WinDbg 시작(사용자 모드)

  • 아티클
  • 2023. 04. 14.
  •  

이 문서의 내용

  1. 메모장을 열고 WinDbg 연결
  2. 사용자 고유의 애플리케이션을 열고 WinDbg 연결
  3. 명령 요약
  4. 추가 정보

WinDbg는 Windows용 디버깅 도구에 포함된 커널 모드 및 사용자 모드 디버거입니다. 다음 실습 연습은 WinDbg를 사용자 모드 디버거로 사용하기 시작하는 데 도움이 될 수 있습니다.

Windows용 디버깅 도구를 가져오는 방법에 대한 자세한 내용은 WinDbg Windows 디버거 다운로드 및 설치를 참조하세요.

디버깅 도구를 설치한 후 64비트(x64) 및 32비트(x86) 버전의 도구에 대한 설치 디렉터리를 찾습니다. 예:

  • C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
  • C:\Program Files (x86)\Windows Kits\10\Debuggers\x86

메모장을 열고 WinDbg 연결

  1. 설치 디렉터리로 이동하여 WinDbg.exe엽니다.
  2. 파일 메뉴에서 실행 파일 열기를 선택합니다. 실행 파일 열기 대화 상자에서 notepad.exe 포함된 폴더로 이동합니다. (notepad.exe 파일은 일반적으로 C:\Windows\System32에 있습니다. 파일 이름notepad.exe를 입력합니다. 열기를 선택합니다.
  3. WinDbg 창 아래쪽에 있는 명령줄에서 다음 명령을 입력합니다.출력은 다음 예제와 유사합니다.
  4. dbgcmd
  5. .sympath srv*

 

  • Symbol search path is: srv*
    Expanded Symbol search path is: cache*;SRV
    
    기호 검색 경로는 WinDbg에 기호(PDB) 파일을 찾을 위치를 알려줍니다. 디버거는 함수 이름 및 변수 이름과 같은 코드 모듈에 대한 정보를 가져오기 위해 기호 파일이 필요합니다..새로고침
  • 명령은 .reload WinDbg에 기호 파일을 찾고 로드하기 위해 초기 검색을 수행하도록 지시합니다.
  • 그런 다음, 다음 명령을 입력합니다.
  • notepad.exe 모듈의 기호를 보려면 다음 명령을 입력합니다.

    참고

    출력이 표시되지 않으면 를 다시 입력 .reload 합니다.

    를 포함하는 mainnotepad.exe 모듈에서 기호를 보려면 기호 검사 명령을 사용하여 마스크와 일치하는 모듈을 나열합니다.출력은 다음 예제와 유사합니다.
  • dbgcmd
  • x notepad!wWin*
  • x 메모장!*
  • 00007ff6`6e76b0a0 notepad!wWinMain (wWinMain)
    00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)
    
  • 에 notepad!wWinMain중단점을 배치하려면 다음 명령을 입력합니다.중단점이 설정되었는지 확인하려면 다음 명령을 입력합니다.출력은 다음 예제와 유사합니다.
  • dbgcmd
  • Bl
  • bu notepad!wWinMain
  • 0 e Disable Clear  00007ff6`6e76b0a0     0001 (0001)  0:**** notepad!wWinMain
    
  • 메모장 프로세스를 시작하려면 다음 명령을 입력합니다.메모장 은 함수에 WinMain 올 때까지 실행된 다음 디버거에 침입합니다.
  • dbgcmd
  • g

 

Breakpoint 0 hit
notepad!wWinMain:
00007ff6`6e76b0a0 488bc4          mov     rax,rsp

메모장 프로세스에 현재 로드된 코드 모듈 목록을 보려면 다음 명령을 입력합니다.

Lm

출력은 다음 예제와 유사합니다.

dbgcmd
0:000> lm
start             end                 module name
00007ff6`6e760000 00007ff6`6e798000   notepad    (pdb symbols)          C:\ProgramData\Dbg\sym\notepad.pdb\BC04D9A431EDE299D4625AD6201C8A4A1\notepad.pdb
00007ff8`066a0000 00007ff8`067ab000   gdi32full   (deferred)             
00007ff8`067b0000 00007ff8`068b0000   ucrtbase   (deferred)             
00007ff8`06a10000 00007ff8`06aad000   msvcp_win   (deferred)             
00007ff8`06ab0000 00007ff8`06ad2000   win32u     (deferred)             
00007ff8`06b40000 00007ff8`06e08000   KERNELBASE   (deferred)             
00007ff8`07220000 00007ff8`072dd000   KERNEL32   (deferred)             
00007ff8`07420000 00007ff8`07775000   combase    (deferred)             
00007ff8`07820000 00007ff8`079c0000   USER32     (deferred)             
00007ff8`079c0000 00007ff8`079f0000   IMM32      (deferred)             
00007ff8`07c00000 00007ff8`07c2a000   GDI32      (deferred)             
00007ff8`08480000 00007ff8`085ab000   RPCRT4     (deferred)             
00007ff8`085b0000 00007ff8`0864e000   msvcrt     (deferred)             
00007ff8`08c40000 00007ff8`08cee000   shcore     (deferred)             
00007ff8`08db0000 00007ff8`08fa5000   ntdll      (pdb symbols)          C:\ProgramData\Dbg\sym\ntdll.pdb\53F12BFE149A2F50205C8D5D66290B481\ntdll.pdb
00007fff`f8580000 00007fff`f881a000   COMCTL32   (deferred)    

스택 추적을 보려면 다음 명령을 입력합니다.

k

출력은 다음 예제와 유사합니다.

dbgcmd

 

  • 0:000> k
    00 000000c8`2647f708 00007ff6`6e783d36     notepad!wWinMain
    01 000000c8`2647f710 00007ff8`07237034     notepad!__scrt_common_main_seh+0x106
    02 000000c8`2647f750 00007ff8`08e02651     KERNEL32!BaseThreadInitThunk+0x14
    03 000000c8`2647f780 00000000`00000000     ntdll!RtlUserThreadStart+0x21
    
  • 메모장 실행을 다시 시작하려면 다음 명령을 입력합니다.
  • g
  • 메모장에 침입하려면 파일 메뉴에서 중단을 선택합니다.
  • 에서 ZwWriteFile중단점을 설정하고 확인하려면 다음 명령을 입력합니다.Bl
  • bu ntdll! ZwWriteFile
  • 메모장 실행을 다시 시작하려면 g를 입력 합니다. 메모장 창에서 텍스트를 입력합니다. 파일 메뉴에서 저장을 선택합니다. 실행 중인 코드는 에 관해서 에서 중단됩니다 ZwCreateFile. k 명령을 입력하여 스택 추적을 확인합니다.명령줄 왼쪽의 WinDbg 창에 프로세서 및 스레드 번호가 표시됩니다. 이 예제에서 현재 프로세서 번호는 0이고 현재 스레드 번호는 11(0:011>)입니다. 프로세서 0에서 실행되는 스레드 11의 스택 추적이 창에 표시됩니다.
  • 메모장 프로세스의 모든 스레드 목록을 보려면 이 명령(타일)을 입력합니다.출력은 다음 예제와 유사합니다.
  • dbgcmd
  • ~
  • 0:011> ~
       0  Id: 5500.34d8 Suspend: 1 Teb: 000000c8`262c4000 Unfrozen
       1  Id: 5500.3960 Suspend: 1 Teb: 000000c8`262c6000 Unfrozen
        2  Id: 5500.5d68 Suspend: 1 Teb: 000000c8`262c8000 Unfrozen
        3  Id: 5500.4c90 Suspend: 1 Teb: 000000c8`262ca000 Unfrozen
        4  Id: 5500.4ac4 Suspend: 1 Teb: 000000c8`262cc000 Unfrozen
        5  Id: 5500.293c Suspend: 1 Teb: 000000c8`262ce000 Unfrozen
        6  Id: 5500.53a0 Suspend: 1 Teb: 000000c8`262d0000 Unfrozen
        7  Id: 5500.3ca4 Suspend: 1 Teb: 000000c8`262d4000 Unfrozen
        8  Id: 5500.808 Suspend: 1 Teb: 000000c8`262da000 Unfrozen
       10  Id: 5500.3940 Suspend: 1 Teb: 000000c8`262dc000 Unfrozen
     . 11  Id: 5500.28b0 Suspend: 1 Teb: 000000c8`262de000 Unfrozen
       12  Id: 5500.12bc Suspend: 1 Teb: 000000c8`262e0000 Unfrozen
       13  Id: 5500.4c34 Suspend: 1 Teb: 000000c8`262e2000 Unfrozen
    
    이 예제에서는 14개의 스레드에 인덱스가 0~13개 있습니다.
  • 스레드 0에 대한 스택 추적을 보려면 다음 명령을 입력합니다.k
    dbgcmd
  • 출력은 다음 예제와 유사합니다.
  • ~0s

 

  1. 0:011> ~0s
    0:011> ~0s
    win32u!NtUserGetProp+0x14:
    00007ff8`06ab1204 c3              ret
    0:000> k
     # Child-SP          RetAddr               Call Site
    00 000000c8`2647bd08 00007ff8`07829fe1     win32u!NtUserGetProp+0x14
    01 000000c8`2647bd10 00007fff`f86099be     USER32!GetPropW+0xd1
    02 000000c8`2647bd40 00007ff8`07d12f4d     COMCTL32!DefSubclassProc+0x4e
    03 000000c8`2647bd90 00007fff`f8609aba     SHELL32!CAutoComplete::_EditWndProc+0xb1
    04 000000c8`2647bde0 00007fff`f86098b7     COMCTL32!CallNextSubclassProc+0x9a
    05 000000c8`2647be60 00007ff8`0782e858     COMCTL32!MasterSubclassProc+0xa7
    06 000000c8`2647bf00 00007ff8`0782de1b     USER32!UserCallWinProcCheckWow+0x2f8
    07 000000c8`2647c090 00007ff8`0782d68a     USER32!SendMessageWorker+0x70b
    08 000000c8`2647c130 00007ff8`07afa4db     USER32!SendMessageW+0xda
    
  2. 디버깅을 종료하고 메모장 프로세스에서 분리하려면 다음 명령을 입력합니다.
  3. Qd

사용자 고유의 애플리케이션을 열고 WinDbg 연결

예를 들어 이 작은 콘솔 애플리케이션을 작성하고 빌드한 것으로 가정합니다.

C++
...
void MyFunction(long p1, long p2, long p3)
{
    long x = p1 + p2 + p3;
    long y = 0;
    y = x / p2;
}

void main ()
{
    long a = 2;
    long b = 0;
    MyFunction(a, b, 5);
}

이 연습에서는 빌드된 애플리케이션(MyApp.exe)과 기호 파일(MyApp.pdb)이 C:\MyApp\x64\Debug에 있다고 가정합니다. 또한 애플리케이션 소스 코드가 C:\MyApp\MyApp에 있고 대상 컴퓨터가 컴파일된 MyApp.exe 가정합니다.

  1. WinDbg를 엽니다.
  2. 파일 메뉴에서 실행 파일 열기를 선택합니다. 실행 파일 열기 대화 상자에서 C:\MyApp\x64\Debug로 이동합니다. 파일 이름MyApp.exe를 입력합니다. 열기를 선택합니다.
  3. 다음 명령을 입력합니다..sympath+ C:\MyApp\x64\Debug
  4. 명령은 WinDbg에 애플리케이션에 대한 기호 및 소스 코드를 찾을 수 있는 위치를 알려줍니다. 이 경우 기호에 원본 파일에 대한 정규화된 경로가 있으므로 .srcpath 를 사용하여 소스 코드 위치를 설정할 필요가 없습니다.
  5. .symfix
  6. 다음 명령을 입력합니다.bu MyApp! 기본애플리케이션은 해당 함수와 관련하여 디버거에 침입합니다 main .
  7. WinDbg는 소스 코드와 명령 창을 표시합니다.
  8. g
  9. .새로고침
  10. 디버그 메뉴에서 한 단계씩 실행(또는 F11 선택)을 선택합니다. 으로 한 단계씩 들어갈 때까지 계속 단계별로 MyFunction진행합니다. 줄을 y = x / p2한 단계씩 실행하면 애플리케이션이 충돌하고 디버거로 나뉩니다.
    dbgcmd
  11. 출력은 다음 예제와 유사합니다.

 

  • (1450.1424): Integer divide-by-zero - code c0000094 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    MyApp!MyFunction+0x44:
    00007ff6`3be11064 f77c2428    idiv  eax,dword ptr [rsp+28h] ss:00000063`2036f808=00000000
    
  • 다음 명령을 입력합니다.WinDbg는 문제의 분석을 표시합니다(이 경우 0으로 나누기).
  • dbgcmd
  • !analyze -v

 

  1. FAULTING_IP:
    MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7]
    00007ff6`3be11064 f77c2428        idiv    eax,dword ptr [rsp+28h]
    
    EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
    ExceptionAddress: 00007ff63be11064 (MyApp!MyFunction+0x0000000000000044)
       ExceptionCode: c0000094 (Integer divide-by-zero)
      ExceptionFlags: 00000000
    NumberParameters: 0
    ...
    STACK_TEXT:  
    00000063`2036f7e0 00007ff6`3be110b8 : ... : MyApp!MyFunction+0x44
    00000063`2036f800 00007ff6`3be1141d : ... : MyApp!main+0x38
    00000063`2036f840 00007ff6`3be1154e : ... : MyApp!__tmainCRTStartup+0x19d
    00000063`2036f8b0 00007ffc`b1cf16ad : ... : MyApp!mainCRTStartup+0xe
    00000063`2036f8e0 00007ffc`b1fc4629 : ... : KERNEL32!BaseThreadInitThunk+0xd
    00000063`2036f910 00000000`00000000 : ... : ntdll!RtlUserThreadStart+0x1d
    
    STACK_COMMAND: dt ntdll!LdrpLastDllInitializer BaseDllName ;dt ntdll!LdrpFailureData ;.cxr 0x0 ;kb
    
    FOLLOWUP_IP:
    MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7]
    00007ff6`3be11064 f77c2428        idiv    eax,dword ptr [rsp+28h]
    
    FAULTING_SOURCE_LINE:  c:\myapp\myapp\myapp.cpp
    
    FAULTING_SOURCE_FILE:  c:\myapp\myapp\myapp.cpp
    
    FAULTING_SOURCE_LINE_NUMBER:  7
    
    FAULTING_SOURCE_CODE:  
         3: void MyFunction(long p1, long p2, long p3)
         4: {
         5:     long x = p1 + p2 + p3;
         6:     long y = 0;
    >    7:  y = x / p2;
         8: }
         9:
        10: void main ()
        11: {
        12:     long a = 2;
    ...
    

명령 요약

추가 정보

WinDbg 시작(커널 모드)

디버거 작업

디버깅 기술

WinDbg Windows 디버거 다운로드 및 설치

WinDbg 기능

Posted by gurupia
,