들어가며
1. 들어가며
- 프로그램을 개발하다 보면 오타 같은 사소한 실수부터 복잡한 시스템이 얽혀서 발생하는 중대한 오류까지 여러 가지 문제 상황과 마주치게 된다.
- 이렇게 프로그램이 개발자의 의도대로 동작하지 않고, 예기치 않은 오류나 잘못된 결과를 낳게 하는 코드를 버그(Bug)라고 부른다.
버그(Bug)의 유래
1947년 마크 II 컴퓨터에서 실제 곤충이 릴레이 사이에 끼어 고장을 일으킨 사건이 기록되면서 버그(Bug)라는 용어가 널리 쓰이게 되었다고 전해진다. 버그는 컴퓨터 과학에서 공식적인 학명은 아니지만 이후 소프트웨어상의 결함 전반을 가리키는 말로 확장되었다.
- 디버깅(Debugging)은 용어의 의미 그대로 발생한 버그를 제거하기 위한 행위를 의미한다.
- 개발자들은 코드 상의 버그를 잡기 위해서 작성된 코드를 다시 점검하고 여러 번 실행해보지만, 이것으로 디버깅을 성공적으로 달성하기까지는 상당한 시간이 소요되곤 한다.
- 다음 예시를 살펴본다. 주어진 숫자가 2의 거듭제곱임을 확인하기 위해, 아래와 같이
n과n-1을 AND 비트 연산한 결과가 0인지 확인하는 함수를 작성했다.- 하지만 이 함수를 실제로 실행하면 기대한 것과 다른 결과를 반환한다.
#include <stdio.h>
// 이 함수는 주어진 숫자가 2의 거듭제곱인지 확인하려고 합니다.
// 예: 2, 4, 8, 16, 32...
int is_power_of_two(unsigned int n) {
if (n == 0) {
return 0; // 0은 2의 거듭제곱이 아님
}
// n과 n-1을 AND 비트 연산하면 2의 거듭제곱일 경우 항상 0이 나와야 합니다.
return (n & (n - 1) == 0);
}
- 그 이유는
&연산의 우선순위보다==연산의 우선순위가 높기 때문으로, 실제로는n과(n - 1) == 0을 AND
비트 연산한 결과를 반환한다.- 이와 같이 짧은 코드임에도 버그를 찾고 없애는 과정이 쉽지 않음을 볼 수 있다.
- 이를 해결하기 위해 디버깅을 돕는 도구인 디버거(Debugger)가 개발되었다.
- 디버거는 프로그램을 실행 도중의 프로그램의 내부 상황을 사용자가 모니터링할 수 있게 도와준다.
- 덕분에 개발자들은 본인의 코드를 직접 읽어보면서 한 줄마다 실행 결과가 어떻게 될 지 상상하는 것에서 벗어나, 한 줄 단위의 실행 결과를 직접 명시적으로 확인할 수 있게 되어 원활하게 디버깅을 수행할 수 있게 되었다.
- 디버거의 사용이 보편화된 오늘날에는 디버깅이라는 용어가 “디버거를 사용하는 행위”라는 좁은 의미로도 종종 사용된다.
- 비록 디버거는 버그를 없애기 위한 용도로 만들어졌지만, 디버거의 기능 자체는 버그를 찾는 것 외에도 많은 활용도를 갖추고 있다.
- 특히 프로그램을 직접 실행시키며 프로그램의 용이한 분석을 돕기에 리버스 엔지니어링 행위에 사용되거나 해커들이 프로그램의 취약점을 유발하는 버그를 찾기 위해 사용하기도 한다.

- 시중에는 디버깅 환경, 분석 대상과 필요성에 따라 다양한 디버거가 존재한다.
- 그 중, 윈도우 운영체제에서는 WinDbg가 대표적인 위치를 차지하고 있다.
- 비록 윈도우 디버거 중에서는 입문하기 어려운 편에 속하지만, 윈도우 운영체제를 개발한 마이크로소프트사에서 공식적으로 지원하는 디버거인 만큼 가장 다양하고 강력한 기능들을 지원하기에 윈도우 생태계에서 해킹을 하는 사람들에게 필수적인 도구로 취급된다.
- 이번 유닛에서는 WinDbg의 기초적인 사용법 및 명령어들과 함께, 기능을 응용하여 효율적으로 디버깅 작업을
수행하는 방법을 학습한다.
- 이 밖에도 실제 디버깅 실습을 진행하며 실행 파일 분석 과정에서 디버깅을 효율적으로 활용할 수 있는 사례들을 살펴본다.
본 유닛에서 기준으로 삼는 강의 환경은 아래와 같다. 강의의 환경과 일치하지 않더라도, Window 10 이상의 환경을 갖추고 있다면 강의 수강에 큰 어려움은 없다.
- 윈도우 버전
- Window 11 Pro - 24H2 (OS 빌드 26100.4351)
- WinDbg Preview 버전
- Debugger client version: 1.2506.12002.0
- Debugger engine version: 10.0.27829.1001
WinDbg 환경 구축
1. WinDbg Preview 설치
- WinDbg Preview는 기존 CLI 형태로 서비스하던 WinDbg Classic의 기능에 다양한 UI가 더해진 최신 WinDbg
앱으로, Microsoft Store 혹은 이 링크에서 설치할 수 있다.
- 설치 후 WinDbg 실행 시 아래와 같은 화면이 나타난다면 성공적으로 설치된 것이다.

2. WinDbg UI 살펴보기

- WinDbg의 인터페이스를 살펴보면, 빨간색, 초록색, 노란색 네모 박스로 표시한 3개의 영역을 확인할 수 있다.
- 이 영역들을 뷰(View)라고 한다.
- WinDbg는 이런 뷰들을 통해 여러 GUI 환경과 기능들을 제공한다.
- 위 화면에 보여지는 뷰 외에도 Disassembly, Memory, Registers 등 여러 종류의 뷰가 있으며 어떤 뷰가 어디에 위치할 지 사용자 입맛대로 설정할 수 있다.
- 상단 메뉴 바의 파란색 네모로 표시된 “View” 메뉴에서 원하는 것을 선택하면 그에 상응하는 뷰가 생성되고, 드래그를 통해 원하는 위치로 옮길 수 있다.
- 아래는 뷰를 사용자 지정하여 설정한 예시이다.
- 이어지는 강의들은 아래 화면과 같이 좌측 상단에는
Disassembly, 좌측 하단은Command, 우측에는 위에서부터 순서대로Registers,Breakpoints그리고Memory뷰 구성으로 진행된다.

- 지금 당장 각 뷰들의 기능과 사용 방법을 이해하려 할 필요는 없다.
- 추후 강의를 따라오면서 뷰들의 사용법을 익히고 본인의 입맛에 맞게 뷰들을 배치해도 좋다.
- 다만 본래 WinDbg가 CLI 기반 앱인 만큼, Command 뷰는 WinDbg의 명령어를 입력할 수 있는 아주 중요한 뷰이기 때문에 화면에 배치해 두시는 것을 권장한다. 종종 WinDbg의 콘솔이라고 부르기도 한다.
- 이렇게 가꾼 WinDbg 뷰들의 배치를 워크스페이스(Workspace)라고 부른다.
- WinDbg는 워크스페이스를 저장하고 불러오는 기능을 지원하고 있다.
- 상단 메뉴 바의 “파일”을 클릭하면 아래 화면의 메뉴가 등장하며, 좌측의 “Save workspace”를 눌러 현재 워크스페이스를 원하는 경로에 파일 형태로 저장할 수 있다.

- 이제 WinDbg를 이용해 본격적으로 디버깅할 준비가 완료되었다.
- 다음 주제부터 실습용 바이너리를 직접 디버깅해보며 WinDbg의 기초적인 사용법을 익혀보겠다.
WinDbg 사용해보기
1. WinDbg 사용해보기
- 이번에는 WinDbg로 바이너리를 디버깅해보겠다.
- 강의에서 실습하는 바이너리는 링크에서 다운로드 받을 수 있다.
본래 디버거를 사용하는 환경인 개발 환경에서 WinDbg를 활용할 경우 디버깅 정보에 해당하는 pdb 확장자를 가진 심볼 파일과 소스 코드를 가지고 있는 상태에서 디버깅한다. 하지만 리버스 엔지니어링을 비롯하여 해커들이 마주치는 환경은 pdb 파일 및 소스 코드가 없는 상황이 대부분이기에, 해당 상황에서 비롯된 정보의 결함을 정적 분석으로 보완한다. 이번 강의는 정적 분석이 아닌 WinDbg의 사용법 학습에 초점이 맞추어져 있으므로 pdb 심볼 파일을 제공하여 진행된다.
2. Launch Executable
- 디버깅을 하는 가장 첫 단계는 디버깅할 프로그램을 디버거 위에서 실행하거나 이미 실행 중인 프로세스의 제어권을 디버거가 가지게끔 하는 것이다.
- WinDbg는 디버깅할 프로그램을 디버거 위에서 실행해주는 Launch Executable 기능을 지원하고 있다.

- 상단 메뉴 바의 “파일”을 클릭한 후 위 화면의 “Start debugging”에서 빨간색 박스로 표시한 “Launch executable”을 클릭하면 컴퓨터에 저장된 실행 파일을 선택하여 디버깅을 시작할 수 있다.
- Launch executable을 이용해 강의 실습 바이너리를 열어본다.

- 그 결과로 프로그램이 실행되는 과정에서 중단점에 도달하여 디버거에게 프로세스에 대한 제어권이 넘어온 상태가 된다.
중단점이란?
중단점은 프로그램의 실행을 잠시 멈추고 디버거가 프로세스의 상태를 살펴보고자 하는 지점을 의미한다. 중단점은 디버거의 가장 강력한 기능으로, 디버거에서 디버깅하려는 프로세스의 특정 지점에 중단점을 설정하면 해당 지점의 코드에 int 3 명령어를 삽입한다. int 3 명령어는 중단점을 위해 설계된 명령어로 CPU가 이 명령어를 실행할 경우 즉시 실행을 멈추고 제어권을 디버거에게 넘기게 된다.
이후 실행을 재개하면 디버거는 삽입한 int 3 명령어를 본래의 코드로 되돌려 놓으며, 실행을 재개한 후 프로세스가 정상적으로 동작 할 수 있게 한다.
Launch executable 도중 중단점을 설정한 적이 없는데 어떻게 중단점이 걸리나요?
Launch executable을 이용하는 경우, 디버깅할 프로세스가 실행되기 직전에 자동으로 중단점을 설정해 디버거에게 제어권을 넘겨 원활한 디버깅 작업을 가능하게 한다.
Launch 과정에서 중단점을 거는 원리는 int 3 명령어를 삽입하는 것과는 약간의 차이가 있다. 기본적으로 WinDbg를 통해 프로그램을 실행하면 프로세스가 생성될 때 디버깅 되고 있다는 정보가 로더에 전달된다. 로더는 해당 정보를 전달 받을 경우 프로세스가 실행되기 직전에 int 3 명령어가 있는 함수를 호출하여 중단점이 걸리는 효과를 얻도록 하고 있다.
- 이렇게 중단점에 도달해 디버거가 제어권을 얻은 상태에서는 디버거를 통해 프로세스의 메모리, 레지스터 등의 내부 상태를 확인하고 조작하거나 새로운 중단점을 거는 등 프로그램을 분석하는 것에 도움이 되는 여러 행위들을 수행할 수 있다.
3. Examine Symbols
-
디버그 심볼(Debug Symbol)은 디버깅을 편하게 만들어주는 중요한 정보로 바이너리 파일과 소스 파일을 연결해주는 메타데이터이다.
- 디버그 심볼이 있다면, 디버깅 대상이 기계어로 된 바이너리 파일일지라도 심볼의 정보를 이용하여 소스
코드 수준의 디버깅이 가능하게 된다. WinDbg에서는 이 심볼 정보를
x명령어로 확인할 수 있다.
- 디버그 심볼이 있다면, 디버깅 대상이 기계어로 된 바이너리 파일일지라도 심볼의 정보를 이용하여 소스
코드 수준의 디버깅이 가능하게 된다. WinDbg에서는 이 심볼 정보를
-
x명령어는 기본적으로x [Module]![Symbol]와 같이 사용한다.- 예를 들어서, 주어진 실습 바이너리의 함수인
main()에 대한 정보를 확인하고 싶다면 WinDbg의 Command 뷰에 아래와 같이 입력하면 된다.
0:000> x exercise_lecture!main 00007ff6`72f21330 exercise_lecture!main (void) - 예를 들어서, 주어진 실습 바이너리의 함수인
-
모듈 명은 바이너리 명인 _exercise_lecture_이며, 이후 소스 코드에서 선언된 함수 명인
main을 심볼로 입력하면 소스에서 선언한 함수main()이 바이너리 파일에서 가지는 정보에 대해 표시되게 된다.- 가장 좌측의 16진수 값은 해당 함수의 주소를 의미한다.
-
심볼이 없는 환경에서는
main()의 주소가0x7ff672f21330라는 정보를 직접 분석해 알아내어 디버깅에 활용하게 된다.
WinDbg가 심볼을 인식하지 못하는 경우
WinDbg는 일반적으로 같은 폴더에 심볼 파일(pdb 파일)이 있는 경우 이를 자동으로 인식하지만, 자동으로 인식하지 못하는 경우 수동으로 심볼 파일을 WinDbg에 로드할 수 있다. 이 경우 WinDbg Command 뷰에
.sympath [pdb 파일이 있는 폴더의 경로]를 입력한다. 이때, 상대 경로를 사용하는 경우 디버깅 중인 바이너리 경로가 아닌WinDbg.exe가 있는 경로를 기준으로 탐색하므로 절대 경로를 사용하는 것을 권장한다.
4. Set Breakpoint
-
Launch Executable을 수행한 뒤에는 본격적으로 프로세스 상태를 확인하고 싶은 주소에 중단점을 설정해야 한다.- WinDbg에서는 중단점을 설정하기 위한 기본적인 명령어로
bp를 제공하며,bp [Address]혹은bp [Module]![Symbol]형식으로 사용할 수 있다. - 예를 들어 실습 바이너리의
main()에 중단점을 설정하고 싶다면 디버거 콘솔에 아래와 같이 입력할 수 있다.
0:000> bp exercise_lecture!main - WinDbg에서는 중단점을 설정하기 위한 기본적인 명령어로
-
하지만 심볼이 없는 환경에서는 WinDbg에서
exercise_lecture!main이라는 심볼을 인식할 수 없으므로main()의 주소를 직접 구하여 중단점을 설정해야 한다. -
방금 학습한
x명령어를 활용하여 주소를 얻은 뒤 아래와 같이 중단점을 설정할 수 있다.0:000> bp 00007ff6`72f21330 -
WinDbg에서는 기본적으로 숫자를 16진수로 인식하기에 “0x”와 같은 접두어를 붙이지 않아도 되며, 가독성을 높이기 위해 4바이트 단위를 끊는 용도로 역따옴표(
)를 사용한다.이때 역따옴표()나 접두어 “0x”를 붙이지 않아도 정상적으로 작동한다.- 다만, 10진수로 입력하는 경우에는 반드시 앞에 “0n” 접두어를 붙여야 한다.
exercise_lecture!main의 주소가 다릅니다.
윈도우 운영체제에서 프로그램이 메모리에 로드될 때, 운영체제는 프로그램이 로드되는 시작 주소를 랜덤하게 설정하여 로드하므로 환경에 따라
exercise_lecture!main의 주소가 다른 것은 매우 자연스러운 현상이다. 본인 환경에서x exercise_lecture!main의 실행 결과를 기준으로 강의를 따라오면 된다.
-
중단점을 설정했다면 중단점 목록을
bl명령어로 확인할 수 있다. 혹은, Breakpoints 뷰를 통해서도 확인할 수 있다.0:000> bl 0 e Disable Clear 00007ff6`d0e71330 0001 (0001) 0:**** exercise_lecture!main
5. Go
-
중단점 설정이 완료되었다면 다음 설정한 중단점까지 프로세스를 마저 실행시켜야 한다.
- WinDbg에서는
g명령어로 이 기능을 지원하고 있다. 아래는main()에 중단점을 설정한 후g를 실행한 결과이다.
1:004> g Breakpoint 2 hit exercise_lecture!main: 00007ff6`72f21330 4881ecb8000000 sub rsp,0B - WinDbg에서는
-
이후 Disassembly 뷰에서 하이라이트 된 지점 혹은 Registers 뷰의
rip값을 확인해보면 중단점을 설정한 위치에서 프로세스가 중단되어 있는 모습을 확인할 수 있다.- WinDbg Preview에서는
g명령어 대신 상단 메뉴 바의 “Home”에 있는 “Go” 버튼을 사용할 수 있다.
- WinDbg Preview에서는

6. Step Into & Step Over & Step Out
- 디버깅 작업을 수행하다 보면, 프로그램을 한 줄 씩 실행시키고 싶은 경우가 있다.
- 이를 위해 WinDbg에서는 Step Into와 Step Over 기능을 지원한다.
- 그 외에 지금 실행 중인 함수를 전부 실행하여 함수를 빠져나오고 싶은 경우에는 Step Out 기능을 사용할 수 있다.
6.1 Step Into
-
코드를 한 줄 실행하는 기능으로, WinDbg 명령어로는
t에 해당한다.- 함수를 호출하는 코드를 Step Into로 실행할 경우 해당 함수 내부로 들어가게 된다.
-
실습 바이너리의
main()에서gen_flag()를 호출하는 지점에서t명령어를 사용해 보겠다.- 아래는 WinDBG에서 실습 바이너리를 디버깅하여
gen_flag()를 호출하는 지점인call exercise_lecture!gen_flag가 있는 지점까지 도달한 상태에서t명령을 사용하기 전과 후에 해당하는 Disassembly 뷰이다.
- 아래는 WinDBG에서 실습 바이너리를 디버깅하여
-
Step Into 전

-
Step Into 후

-
Step Into를 수행하면 바로 다음 명령어의 주소에 중단되는 것이 아닌 함수 내부로 진입한 것을 확인할 수 있다. -
Step Into 기능은 Command 뷰에서
t명령어로 사용할 수 있지만, 상단 메뉴 바의 “Home”에 있는 Step Into 버튼으로도 이용 가능하다.
6.2 Step Over
-
Step Over도 Step Into와 마찬가지로 한 줄 씩 실행하는 기능이지만, 함수를 호출하는 코드에서 기능을 사용하면 함수 내부로 진입하지 않고 해당 함수를 모두 실행한 뒤 다음 코드로 넘어간다. WinDbg 명령어로는
p에 해당한다.- Step Into와 동일하게
call exercise_lecture!gen_flag에서 Step Over를 수행해 보겠다.
- Step Into와 동일하게
-
Step Over 전

-
Step Over 후

-
Step Into와 다르게 Step Over를 수행하면
exercise_lecture!gen_flag내부로 진입하지 않고 주소 상으로 다음 명령어 위치에서 중단된 것을 확인할 수 있다.- Step Over 또한 Step Into와 마찬가지로 상단 메뉴 바의 “Home”에서 Step Over 버튼으로 이용 가능하다.

6.3 Step Out
-
Step Out은 현재 함수를 빠져나오는 기능이다.
- 이 기능을 사용하면 현재 실행 중인 함수를 모두 실행하고 해당 함수를 호출했던 지점으로 돌아가 중단한다.
- 이에 해당하는 WinDbg 명령어는
gu이다.
-
마찬가지로 상단 메뉴 바의 “Home”에서 Step Out 버튼으로 이용 가능하다.

7. Register
- WinDbg에는 레지스터 값을 쉽게 읽을 수 있는 Registers 뷰가 따로 존재한다.
- 뿐만 아니라
r명령어를 이용해 쉽게 레지스터 값을 읽고 쓸 수 있다.
- 뿐만 아니라

-
r명령어를 입력하면 레지스터 뷰에 표시되는 포맷과 동일하게 레지스터의 값들을 출력한다.0:000> r rax=00000012ca1afae7 rbx=000001d5dcf8ff20 rcx=ea032b257cad0000 rdx=000001d5dce50000 rsi=0000000000000000 rdi=000001d5dcf8d390 rip=00007ff672f21370 rsp=00000012ca1afab0 rbp=0000000000000000 r8=7ffffffffffffffc r9=000001d5dcf8bca0 r10=000001d5dcf8bca0 r11=00000012ca1af970 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 -
이 외에도 특정 레지스터만 출력하고 싶다면
r [Register]형태로 명령어를 사용할 수 있다.- 아래는 예시로
rax레지스터 값을 출력한 것이다.
0:000> r rax rax=00000012ca1afae7 - 아래는 예시로
-
레지스터에 원하는 값을 쓰고 싶다면,
r [Register] = [Value]형태로 원하는 레지스터에 원하는 값을 쓸 수 있다.- 아래는
rax레지스터의 값을0x1337로 변경한 예시이다.
0:000> r rax=0x1337 0:000> r rax rax=0000000000001337 - 아래는
-
이후
rax값을 출력해보면 변경한 값이 적용되어 있음을 확인할 수 있다.
8. Memory
- 메모리 또한 Memory 뷰를 이용하여 GUI로 확인할 수 있다.
- 메모리 뷰의 Address 창에 메모리를 보고 싶은 주소를 입력하면 해당 주소 주변의 메모리 값을 쉽게 확인할 수 있다.
- Command 뷰에서는 Display 계열 명령어들로 메모리 값을 쉽게 확인할 수 있으며 Enter 계열 명령어로 메모리 값을 쉽게 조작할 수 있다.
8.1 Display
- Display는 메모리 값을 출력하는 명령어이다.
da,db,dw,dq등 여러 명령어들이 있으나, 명령어의 형식은 대부분d* [Address] L[Count]로 동일하다.- 이때,
[Address]와[Count]모두 기본 16진수로 인식됨에 주의해야 한다.
da,db,dw등d뒤에 붙는 문자에 따라서 출력 포맷이 달라질 뿐, 역할은 동일하다.- 각 명령어를 정리한 표는 아래와 같다.
| 명령어 | 설명 |
|---|---|
db | 1 byte 단위로 출력한다. |
dw | 2 byte 단위로 출력한다. |
dd | 4 byte 단위로 출력한다. |
dq | 8 byte 단위로 출력한다. |
dp | 포인터 값의 크기 단위로 출력한다. |
| 32비트 아키텍처에서는 4byte, 64비트 아키텍처에서는 8byte 단위로 출력하게 된다. | |
df | 4 byte 단위를 float 형으로 출력한다. |
dD | 8 byte 단위를 float 형으로 출력한다. |
da | ASCII 문자열 형식으로 출력한다. |
| 주어진 개수만큼 다 출력하거나 Null을 마주칠 때까지 출력한다. | |
du | 유니코드 문자열 형식으로 출력한다. |
| 주어진 개수만큼 다 출력하거나 Null을 마주칠 때까지 출력한다. |
-
명령어를 직접 사용해보기 위해서 스택의 데이터를 출력해보겠다.
- 아래는 방금 학습한
r명령어 기능을 이용해 스택의 주소를 담고 있는rsp레지스터의 값을 확인한 뒤, 해당 주소의 데이터를 1 바이트 단위로 16개 출력한 예시이다.
0:000> r rsp rsp=00000012f34ffcf8 0:000> db 00000012f34ffcf8 L10 00000012`f34ffcf8 e0 15 e7 d0 f6 7f 00 00-00 00 00 00 00 00 00 00 ................ - 아래는 방금 학습한
-
출력된 첫 8 바이트는 특정 주소 값을 가리키고 있는 것으로 추측된다.
- 주소를 가리키는 포인터 값 포맷으로 출력하고 싶을 경우
dp를 이용할 수 있다. - 아래는
dp를 이용해 포인터 값의 크기 단위로 출력한 예시이다.
0:000> dp 00000012f34ffcf8 L2 00000012`f34ffcf8 00007ff6`d0e715e0 00000000`00000000 - 주소를 가리키는 포인터 값 포맷으로 출력하고 싶을 경우
-
이때
L뒤에 붙는 숫자는 출력할 데이터의 크기가 아닌 개수라는 점을 주의해야 한다.- 위 예시에서
db를 이용한 1 바이트 단위 데이터 출력에서는L10이 1 바이트 크기 0x10개를 의미하여 총 0x10 바이트를 출력하지만,dp를 이용한 포인터 크기(8 바이트) 단위 데이터 출력에서는L10이 8 바이트 크기 0x10개를 의미하여 총 0x80 바이트를 출력한다.
- 위 예시에서
8.2 Enter
- Enter는 메모리 값을 수정하는 명령어이다.
- Enter 또한 Display 계열 명령어처럼 여러 명령어들이 존재하며,
e뒤에 붙는 문자에 따라 입력 포맷이 달라지는 등 대부분의 명령어 형식을 공유한다. 각 명령어들을 정리한 표는 아래와 같다.
- Enter 또한 Display 계열 명령어처럼 여러 명령어들이 존재하며,
| 명령어 | 설명 |
|---|---|
eb | 1 byte 값을 입력한다. |
ew | 2 byte 값을 입력한다. |
ed | 4 byte 값을 입력한다. |
eq | 8 byte 값을 입력한다. |
ef | float 형으로 입력한다. |
eD | double 형으로 입력한다. |
ea | ASCII 문자열 형식으로 입력한다. |
eu | unicode 문자열 형식으로 입력한다. |
-
마찬가지로 스택의 데이터를 변조해 보겠다.
- 먼저
r명령어로 스택 주소를 얻은 뒤 해당 주소의 값을 살피면 아래와 같다.
0:000> r rsp rsp=00000012f34ffcf8 0:000> db 00000012f34ffcf8 L1 00000012`f34ffcf8 e0 - 먼저
-
현재
0xe0인 값을0xe1로 변조한 뒤 다시 해당 주소의 데이터를 확인하면, 아래와 같이 값이 변조된다.0:000> eb 00000012f34ffcf8 e1 0:000> db 00000012f34ffcf8 L1 00000012`f34ffcf8 e1
마치며
1. 마치며
- 이번 강의에서는 WinDbg의 기본적인 사용법을 익혀 보았다. 디버깅 과정에서 가장 주요한 작업은 프로그램 실행 중 특정 시점에서 프로그램의 상태를 살펴보는 것이기 때문에, 이번 시간에 익힌 기본적인 사용법으로도 일반적인 디버깅 작업들을 수행할 수 있다.
- 다음 강의에서는 WinDbg의 단편적인 사용 방법에서 벗어나, 실습과 함께 WinDbg를 활용해 효과적으로 바이너리를 분석하는 방법을 학습해볼 것이다.