좀 열심히 쓴 글

커널 디버깅 중 USER-MODE 프로세스에 디버거 붙이기

ch4rli3kop 2022. 5. 27. 01:28
반응형

커널 디버깅 중 USER-MODE 프로세스에 디버거 붙이기

Windbg로 윈도우 커널 디버깅 중에 유저모드 프로세스를 디버깅하는 방법이 몇 가지 있는데, 일단 이 글에서는 다음과 같은 네 가지의 방법을 정리해볼까 한다.

  1. 실행 중인 프로세스에 붙기 (EPROCESS)
  2. 프로세스 실행하면서 붙기 (ntsd.exe)
  3. 프로세스 로드하면서 붙기 (sxe ld)
  4. 프로세스 생성할 때 붙기 (nt!PspInsertProcess)

 

0. Windbg kernel debugging Setting

https://docs.microsoft.com/ko-kr/windows-hardware/drivers/debugger/setting-up-a-network-debugging-connection-automatically

가장 먼저, 위의 msdn을 참고해서 커널 디버깅 환경 세팅한다.

내 경우에는 hyper-V 로 Windows 10 Version 10.0.19043.1706에 해당하는 wdk sdk 등을 설치했다.

hevd 드라이버에 간단한 ioctl을 보내는 프로그램을 예제로 사용할 타겟 프로그램으로 설정했다. 내 경우 host 환경에 예제 프로그램 빌드 환경을 구축해놓았다.

1. 실행 중인 프로세스에 붙기 (EPROCESS)

첫 번째 방법은 !process 명령어로 EPROCESS 주소를 확인하고 switch 하는 방법이다. 이미 실행 중인 프로세스에 붙는 방법이기 때문에, 다음의 예제 코드에 system("pause") 를 추가하여 프로세스가 유지되도록 진행했다.

...
  
int main() {
  printf("process start\n");
  system("pause");   //
  
  HANDLE H =
      CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver",
                  GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  if (H == INVALID_HANDLE_VALUE) {
    printf("CreateFileA failed.\n");
    return EXIT_FAILURE;
  }
​
  ...
    
  return EXIT_SUCCESS;
}

프로그램을 빌드하고, 해당 exe 파일을 vm 에 집어넣고 실행한다.

C:\Users\pch21\Desktop\Fuzz\hevd>.\hevd_client.exe
process start
계속하려면 아무 키나 누르십시오 . . .

이제 vm 내에서 위와 같이 타겟 프로세스가 실행되면, 다음과 같이 host의 windbg에서 타겟 프로세스의 주소를 확인할 수 있다.

kd> !process 0 0 hevd_client.exe
PROCESS ffffcc899f14e080
    SessionId: 2  Cid: 1bc4    Peb: 1a47ad2000  ParentCid: 10a0
    DirBase: 11049000  ObjectTable: ffffb80469015a00  HandleCount:  45.
    Image: hevd_client.exe

이제 해당 Process로 switch 한다.

kd> .process /i /r /p ffffcc899f14e080
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.

타겟 프로세스의 pdb 심볼 파일이 존재하는 경우, sympath 명령어로 경로를 추가해준다. 내 경우에는 host 환경 내의 pdb 파일이 존재하는 디렉토리 경로를 추가했다.

kd> .sympath+ D:\Tools\wtf\src\build_msvc\RelWithDebInfo
DBGHELP: Symbol Search Path: cache*;SRV*https://msdl.microsoft.com/download/symbols;d:\tools\wtf\src\build_msvc\relwithdebinfo
SYMSRV:  BYINDEX: 0x2
         C:\ProgramData\Dbg\sym
         ntkrnlmp.pdb
         84A84F4D2218BC053913B1204942618D1
SYMSRV:  PATH: C:\ProgramData\Dbg\sym\ntkrnlmp.pdb\84A84F4D2218BC053913B1204942618D1\ntkrnlmp.pdb
SYMSRV:  RESULT: 0x00000000
DBGHELP: nt - public symbols  
        C:\ProgramData\Dbg\sym\ntkrnlmp.pdb\84A84F4D2218BC053913B1204942618D1\ntkrnlmp.pdb
Symbol search path is: srv*;D:\Tools\wtf\src\build_msvc\RelWithDebInfo
Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols;d:\tools\wtf\src\build_msvc\relwithdebinfo
​
************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
OK                                             D:\Tools\wtf\src\build_msvc\RelWithDebInfo

경로를 추가한 뒤 reload 명령어로 symbol 파일을 다시 로딩해준다. /f 옵션은 lazy 하지 않게 바로 로딩하는 옵션인데, 해당 옵션과 /user 옵션을 추가해주면 된다.

kd> .reload /f /user
Loading User Symbols
.SYMSRV:  BYINDEX: 0x4
         C:\ProgramData\Dbg\sym
         hevd_client.pdb
         ABF75D5451C74049864E0307D295930F6
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pdb - path not found
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pd_ - path not found
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\file.ptr - path not found
SYMSRV:  RESULT: 0x80070003
SYMSRV:  BYINDEX: 0x5
         C:\ProgramData\Dbg\sym*https://msdl.microsoft.com/download/symbols
         hevd_client.pdb
         ABF75D5451C74049864E0307D295930F6
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pdb - path not found
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pd_ - path not found
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\file.ptr - path not found
SYMSRV:  HTTPGET: /download/symbols/index2.txt
SYMSRV:  HttpQueryInfo: 80190194 - HTTP_STATUS_NOT_FOUND
SYMSRV:  HTTPGET: /download/symbols/hevd_client.pdb/ABF75D5451C74049864E0307D295930F6/hevd_client.pdb
SYMSRV:  HttpQueryInfo: 80190194 - HTTP_STATUS_NOT_FOUND
SYMSRV:  HTTPGET: /download/symbols/hevd_client.pdb/ABF75D5451C74049864E0307D295930F6/hevd_client.pd_
SYMSRV:  HttpQueryInfo: 80190194 - HTTP_STATUS_NOT_FOUND
SYMSRV:  HTTPGET: /download/symbols/hevd_client.pdb/ABF75D5451C74049864E0307D295930F6/file.ptr
SYMSRV:  HttpQueryInfo: 80190194 - HTTP_STATUS_NOT_FOUND
SYMSRV:  RESULT: 0x80190194
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pdb - path not found
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pd_ - path not found
SYMSRV:  UNC: C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\file.ptr - path not found
DBGHELP: d:\tools\wtf\src\build_msvc\relwithdebinfo\hevd_client.pdb cached to C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pdb
*** WARNING: Unable to verify checksum for hevd_client.exe
DBGHELP: hevd_client - private symbols & lines 
        C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pdb
.SYMSRV:  BYINDEX: 0x6
         C:\ProgramData\Dbg\sym

이제 lm 명령어로 확인해보면 hevd_client.exe 에 대한 심볼이 로드된 것을 확인할 수 있다.

kd> lm
start             end                 module name
00007ff7`47b00000 00007ff7`47b09000   hevd_client C (private pdb symbols)  C:\ProgramData\Dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pdb
00007ffa`24380000 00007ffa`2439b000   VCRUNTIME140   (private pdb symbols)  C:\ProgramData\Dbg\sym\vcruntime140.amd64.pdb\1FE44F1573B246029EAFFD19C4B144671\vcruntime140.amd64.pdb
00007ffa`2b0f0000 00007ffa`2b0fc000   VCRUNTIME140_1   (private pdb symbols)  C:\ProgramData\Dbg\sym\vcruntime140_1.amd64.pdb\02D66622C7D04ADBB93F52B802FD3E001\vcruntime140_1.amd64.pdb
00007ffa`36b20000 00007ffa`36c20000   ucrtbase # (pdb symbols)          C:\ProgramData\Dbg\sym\ucrtbase.pdb\152B3C4F5E1CE0FE6BC36E9F0F2B10E61\ucrtbase.pdb
00007ffa`37000000 00007ffa`372cd000   KERNELBASE   (pdb symbols)          C:\ProgramData\Dbg\sym\kernelbase.pdb\BFA648CE3D974430D6F69BCCC300FC391\kernelbase.pdb
00007ffa`37400000 00007ffa`374bd000   KERNEL32 # (pdb symbols)          C:\ProgramData\Dbg\sym\kernel32.pdb\BF9567320871B7B8741ED4FF2369DC5C1\kernel32.pdb
00007ffa`37660000 00007ffa`37785000   RPCRT4   # (pdb symbols)          C:\ProgramData\Dbg\sym\rpcrt4.pdb\A381203AEB2EE18A33EC95033DA488A81\rpcrt4.pdb
00007ffa`38e70000 00007ffa`38f0c000   sechost  # (pdb symbols)          C:\ProgramData\Dbg\sym\sechost.pdb\F0CCAF8276CE8711A7E0E92AD742F0701\sechost.pdb
00007ffa`39390000 00007ffa`39585000   ntdll      (pdb symbols)          C:\ProgramData\Dbg\sym\ntdll.pdb\094B224BC5297445CF29F9C9BB588DC91\ntdll.pdb
fffff804`1aa00000 fffff804`1ba46000   nt         (pdb symbols)          C:\ProgramData\Dbg\sym\ntkrnlmp.pdb\84A84F4D2218BC053913B1204942618D1\ntkrnlmp.pdb
​
Unloaded modules:
fffff804`21130000 fffff804`21143000   IndirectKmd.sys

이제 bp를 걸고 실행하면 된다.

kd> bp hevd_client!main+0xaf
kd> g

2. 프로세스 실행하면서 붙기 (ntsd.exe)

실행하면서 붙기위해 ntsd.exe를 이용한다. 커널 디버깅 중에 vm 내에서 다음과 같이 ntsd를 실행시키면 새로운 window 에서 타겟 프로세스가 새로 spawn 되면서 host의 windbg에 붙게된다.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>ntsd.exe -s -d  C:\Users\pch21\Desktop\Fuzz\hevd\hevd_client.exe

host의 windbg를 보면 다음과 같은 상태가 되는데, 앞서 시도했던 방법과 다르게 windbg에 kd> 가 아니라 Input> 이 되게 된다. 커널모드가 아니라 유저모드 상태로 붙기 때문이다. 다시 커널모드로 넘어가려면 .breakin 명령어를 사용하면 되는데, privilege 때문에 안된다면 break 버튼을 누르고 Input> .sleep 1000 명령어로 커널모드로 넘어가는 방법이 있다.

Microsoft (R) Windows Debugger Version 10.0.19041.685 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
​
CommandLine: C:\Users\pch21\Desktop\Fuzz\hevd\hevd_client.exe
​
************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
Symbol search path is: srv*
Executable search path is: 
*** WARNING: Unable to verify checksum for hevd_client.exe
*** ERROR: Module load completed but symbols could not be loaded for hevd_client.exe
ModLoad: 00007ff6`a6d70000 00007ff6`a6d79000   hevd_client.exe
ModLoad: 00007ffa`39390000 00007ffa`39585000   ntdll.dll
ModLoad: 00007ffa`37400000 00007ffa`374bd000   C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ffa`37000000 00007ffa`372cd000   C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ffa`36b20000 00007ffa`36c20000   C:\Windows\System32\ucrtbase.dll
ModLoad: 00007ffa`2b0f0000 00007ffa`2b0fc000   C:\Windows\SYSTEM32\VCRUNTIME140_1.dll
ModLoad: 00007ffa`2aad0000 00007ffa`2aaeb000   C:\Windows\SYSTEM32\VCRUNTIME140.dll
(64.2228): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffa`394606b0 cc              int     3

어쨋든 이 상태에서 심볼을 추가한다. 주의할 점은 이 경우 심볼 파일의 경로가 host 기준이 아니라, ntsd를 실행시킨 vm 기준으로 입력해야 한다는 점이다.

0:000> .sympath
NOTE: The symbol path for this ntsd is relative to where
ntsd.exe is running, not where kd.exe is running.
Symbol search path is: srv*
Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols
​
************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
0:000> .sympath+ C:\Users\pch21\Desktop\Fuzz\hevd\
NOTE: The symbol path for this ntsd is relative to where
ntsd.exe is running, not where kd.exe is running.
*** WARNING: Unable to verify checksum for hevd_client.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\System32\ucrtbase.dll
*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\System32\KERNEL32.DLL
*** ERROR: Module load completed but symbols could not be loaded for ntdll.dll
Symbol search path is: srv*;C:\Users\pch21\Desktop\Fuzz\hevd\
Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols;c:\users\pch21\desktop\fuzz\hevd\
​
************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
OK                                             C:\Users\pch21\Desktop\Fuzz\hevd\

.reloadlm으로 다시 살펴보면 심볼이 정상적으로 로드된 것을 확인할 수 있다.

​
0:000> .reload
Reloading current modules
.*** WARNING: Unable to verify checksum for hevd_client.exe
...*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\System32\ucrtbase.dll
.*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\System32\KERNELBASE.dll
.*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\System32\KERNEL32.DLL
.*** ERROR: Module load completed but symbols could not be loaded for ntdll.dll
​
​
************* Symbol Loading Error Summary **************
Module name            Error
SharedUserData         No error - symbol load deferred
​
You can troubleshoot most symbol related issues by turning on symbol loading diagnostics (!sym noisy) and repeating the command that caused symbols to be loaded.
You should also verify that your symbol search path (.sympath) is correct.
​
0:000> lm
start             end                 module name
00007ff6`a6d70000 00007ff6`a6d79000   hevd_client M (private pdb symbols)  C:\ProgramData\dbg\sym\hevd_client.pdb\ABF75D5451C74049864E0307D295930F6\hevd_client.pdb
00007ffa`2d0c0000 00007ffa`2d0db000   VCRUNTIME140 M (private pdb symbols)  C:\ProgramData\dbg\sym\vcruntime140.amd64.pdb\1FE44F1573B246029EAFFD19C4B144671\vcruntime140.amd64.pdb
00007ffa`2f6e0000 00007ffa`2f6ec000   VCRUNTIME140_1 M (private pdb symbols)  C:\ProgramData\dbg\sym\vcruntime140_1.amd64.pdb\02D66622C7D04ADBB93F52B802FD3E001\vcruntime140_1.amd64.pdb
00007ffa`36b20000 00007ffa`36c20000   ucrtbase M (pdb symbols)          C:\ProgramData\dbg\sym\ucrtbase.pdb\152B3C4F5E1CE0FE6BC36E9F0F2B10E61\ucrtbase.pdb
00007ffa`37000000 00007ffa`372cd000   KERNELBASE M (pdb symbols)          C:\ProgramData\dbg\sym\kernelbase.pdb\BFA648CE3D974430D6F69BCCC300FC391\kernelbase.pdb
00007ffa`37400000 00007ffa`374bd000   KERNEL32 M (pdb symbols)          C:\ProgramData\dbg\sym\kernel32.pdb\BF9567320871B7B8741ED4FF2369DC5C1\kernel32.pdb
00007ffa`39390000 00007ffa`39585000   ntdll    M (pdb symbols)          C:\ProgramData\dbg\sym\ntdll.pdb\094B224BC5297445CF29F9C9BB588DC91\ntdll.pdb
0:000> 

이제 브포를 걸고 실행하면 된다.

0:000> bp hevd_client!main
0:000> g
Breakpoint 0 hit
hevd_client!main:
00007ff6`a6d710c0 48895c2408      mov     qword ptr [rsp+8],rbx ss:0000002f`1b4ffde0=0000000000000000
0:000> 

3. 실행파일 로드하면서 붙기 (sxe ld)

sxe ld 명령어를 이용해서 프로그램이 로드될 때, breakpoint를 걸 수 있다. 다만 sxe 자체가 첫 번째 로드시에만 적용이 되기 때문에, 로드 시 브포가 걸렸을 때 반드시 bu hevd_client!main 형태로 따로 브포를 걸어야 한다. 따로 또 브포를 걸지않으면 다시 브포를 걸기위해 OS를 껏다 켜야한다. [+추가] 프로그램 del 했다가 ctrl^z 로 다시 복구해주면 다시 sxe ld 부분에 걸린다고 함. 
그리고 sxe ld 전에 꼭 gflag로 커널 디버깅 심볼 로딩을 활성화시키자!

Microsoft (R) Windows Debugger Version 10.0.25111.1000 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
​
Using NET for debugging
Opened WinSock 2.0
Waiting to reconnect...
Connected to target 172.27.180.66 on port 50001 on local IP 172.27.176.1.
You can get the target MAC address by running .kdtargetmac command.
Connected to Windows 10 19041 x64 target at (Fri May 27 00:58:07.236 2022 (UTC + 9:00)), ptr64 TRUE
Kernel Debugger connection established.
​
************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
OK                                             D:\Tools\wtf\src\build_msvc\RelWithDebInfo
Symbol search path is: srv*;D:\Tools\wtf\src\build_msvc\RelWithDebInfo
Executable search path is: 
Windows 10 Kernel Version 19041 MP (1 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Edition build lab: 19041.1.amd64fre.vb_release.191206-1406
Machine Name:
Kernel base = 0xfffff805`4b600000 PsLoadedModuleList = 0xfffff805`4c22a2b0
Debug session time: Fri May 27 00:58:04.486 2022 (UTC + 9:00)
System Uptime: 0 days 0:00:01.993
KDTARGET: Refreshing KD connection
Break instruction exception - code 80000003 (first chance)
*******************************************************************************
*                                                                             *
*   You are seeing this message because you pressed either                    *
*       CTRL+C (if you run console kernel debugger) or,                       *
*       CTRL+BREAK (if you run GUI kernel debugger),                          *
*   on your debugger machine's keyboard.                                      *
*                                                                             *
*                   THIS IS NOT A BUG OR A SYSTEM CRASH                       *
*                                                                             *
* If you did not intend to break into the debugger, press the "g" key, then   *
* press the "Enter" key now.  This message might immediately reappear.  If it *
* does, press "g" and "Enter" again.                                          *
*                                                                             *
*******************************************************************************
nt!DbgBreakPointWithStatus:
fffff805`4b9ffc00 cc              int     3
​
kd> !gflag +ksl
New NtGlobalFlag contents: 0x00040000
    ksl - Enable loading of kernel debugger symbols
kd> sxe ld hevd_client.exe
kd> g

이제 vm에서 타겟 프로그램을 실행시킨다.

C:\Users\pch21\Desktop\Fuzz\hevd>.\hevd_client.exe
process start
계속하려면 아무 키나 누르십시오 . . .

이제 브포가 걸린다. 미리 sympath에 pdb 경로를 추가해놨기 때문에, bu 명령어 시 pdb 심볼 파일이 로드된다.

kd> 
nt!DebugService2+0x5:
fffff805`4b9ffc55 cc              int     3
kd> bu hevd_client!main
*** WARNING: Unable to verify checksum for hevd_client.exe
kd> .sympath 
Symbol search path is: srv*;D:\Tools\wtf\src\build_msvc\RelWithDebInfo
Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols;d:\tools\wtf\src\build_msvc\relwithdebinfo
​
************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
OK                                             D:\Tools\wtf\src\build_msvc\RelWithDebInfo
kd> g
Breakpoint 0 hit
hevd_client!main:
0033:00007ff6`d12110c0 48895c2408      mov     qword ptr [rsp+8],rbx

이제 매 프로세스 시작마다 브포가 걸린다!

[+추가]

4. 프로세스 생성할 때 붙기 (nt!PspInsertProcess)

Reference : https://vimalshekar.github.io/walkthroughs/Activating-Windbg-on-process-launch

커널 라이브 디버깅 중이기 때문에, 프로세스 생성하는 함수에서부터 디버깅이 가능하다. 위 사이트를 참고했는데, 현재 windows 10 과는 offset이 조금 다르다.

우선, Windows 에서 프로세스 시작 시 동작을 간단히 설명하자면, 먼저 커널에서 프로세스의 정보가 담긴 _EPROCESS커널 오브젝트를 생성하고 이를 프로세스 연결리스트에 추가하여 관리한다. 유저모드에서는 프로세스 정보를 PEB 형태로 관리하다가 필요시 syscall을 통해 이 커널 오브젝트에 접근하여 추가 정보를 가져온다는 정도로 알면 될 것 같다.

아무튼, 생성한 커널 오브젝트를 프로세스 연결리스트에 추가할 때 nt!PspInsertProcess 함수를 호출한다. 이 함수의 첫 번째 매개변수가 _EPROCESS주소이며, 따라서 이 시점에서 첫 번째 매개변수를 살펴봄으로써 해당 커널 오브젝트의 실행 이미지 파일 이름, ImageBase 주소 등을 알 수 있다. 실제로 해당 함수 진입점에서 브포를 걸고 첫 번째 인자인 rcx 레지스터를 살펴보면 다음과 같다. 이번 경우의 타겟 프로세스는 "test_wtf_harness.exe"이다.

kd> dt nt!_EPROCESS @rcx
   +0x000 Pcb              : _KPROCESS
   +0x438 ProcessLock      : _EX_PUSH_LOCK
   +0x440 UniqueProcessId  : 0x00000000`00002060 Void
   +0x448 ActiveProcessLinks : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
   +0x458 RundownProtect   : _EX_RUNDOWN_REF
   +0x460 Flags2           : 0x5000
   +0x460 JobNotReallyActive : 0y0
   +0x460 AccountingFolded : 0y0
   +0x460 NewProcessReported : 0y0
   +0x460 ExitProcessReported : 0y0
   +0x460 ReportCommitChanges : 0y0
   +0x460 LastReportMemory : 0y0
   +0x460 ForceWakeCharge  : 0y0
   +0x460 CrossSessionCreate : 0y0
   +0x460 NeedsHandleRundown : 0y0
   +0x460 RefTraceEnabled  : 0y0
   +0x460 PicoCreated      : 0y0
   +0x460 EmptyJobEvaluated : 0y0
   +0x460 DefaultPagePriority : 0y101
   +0x460 PrimaryTokenFrozen : 0y0
   +0x460 ProcessVerifierTarget : 0y0
   +0x460 RestrictSetThreadContext : 0y0
   +0x460 AffinityPermanent : 0y0
   +0x460 AffinityUpdateEnable : 0y0
   +0x460 PropagateNode    : 0y0
   +0x460 ExplicitAffinity : 0y0
   +0x460 ProcessExecutionState : 0y00
   +0x460 EnableReadVmLogging : 0y0
   +0x460 EnableWriteVmLogging : 0y0
   +0x460 FatalAccessTerminationRequested : 0y0
   +0x460 DisableSystemAllowedCpuSet : 0y0
   +0x460 ProcessStateChangeRequest : 0y00
   +0x460 ProcessStateChangeInProgress : 0y0
   +0x460 InPrivate        : 0y0
   +0x464 Flags            : 0x10050c00
   +0x464 CreateReported   : 0y0
   +0x464 NoDebugInherit   : 0y0
   +0x464 ProcessExiting   : 0y0
   +0x464 ProcessDelete    : 0y0
   +0x464 ManageExecutableMemoryWrites : 0y0
   +0x464 VmDeleted        : 0y0
   +0x464 OutswapEnabled   : 0y0
   +0x464 Outswapped       : 0y0
   +0x464 FailFastOnCommitFail : 0y0
   +0x464 Wow64VaSpace4Gb  : 0y0
   +0x464 AddressSpaceInitialized : 0y11
   +0x464 SetTimerResolution : 0y0
   +0x464 BreakOnTermination : 0y0
   +0x464 DeprioritizeViews : 0y0
   +0x464 WriteWatch       : 0y0
   +0x464 ProcessInSession : 0y1
   +0x464 OverrideAddressSpace : 0y0
   +0x464 HasAddressSpace  : 0y1
   +0x464 LaunchPrefetched : 0y0
   +0x464 Background       : 0y0
   +0x464 VmTopDown        : 0y0
   +0x464 ImageNotifyDone  : 0y0
   +0x464 PdeUpdateNeeded  : 0y0
   +0x464 VdmAllowed       : 0y0
   +0x464 ProcessRundown   : 0y0
   +0x464 ProcessInserted  : 0y0
   +0x464 DefaultIoPriority : 0y010
   +0x464 ProcessSelfDelete : 0y0
   +0x464 SetTimerResolutionLink : 0y0
   +0x468 CreateTime       : _LARGE_INTEGER 0x01d87401`40966b6a
   +0x470 ProcessQuotaUsage : [2] 0x5d8
   +0x480 ProcessQuotaPeak : [2] 0x5d8
   +0x490 PeakVirtualSize  : 0x58f000
   +0x498 VirtualSize      : 0x58f000
   +0x4a0 SessionProcessLinks : _LIST_ENTRY [ 0xffff9081`87afe010 - 0xffffdc07`a39ae520 ]
   +0x4b0 ExceptionPortData : (null) 
   +0x4b0 ExceptionPortValue : 0
   +0x4b0 ExceptionPortState : 0y000
   +0x4b8 Token            : _EX_FAST_REF
   +0x4c0 MmReserved       : 0
   +0x4c8 AddressCreationLock : _EX_PUSH_LOCK
   +0x4d0 PageTableCommitmentLock : _EX_PUSH_LOCK
   +0x4d8 RotateInProgress : (null) 
   +0x4e0 ForkInProgress   : (null) 
   +0x4e8 CommitChargeJob  : (null) 
   +0x4f0 CloneRoot        : _RTL_AVL_TREE
   +0x4f8 NumberOfPrivatePages : 0x22
   +0x500 NumberOfLockedPages : 0
   +0x508 Win32Process     : (null) 
   +0x510 Job              : (null) 
   +0x518 SectionObject    : 0xffffa505`c91025d0 Void
   +0x520 SectionBaseAddress : 0x00007ff7`1fd20000 Void
   +0x528 Cookie           : 0
   +0x530 WorkingSetWatch  : (null) 
   +0x538 Win32WindowStation : (null) 
   +0x540 InheritedFromUniqueProcessId : 0x00000000`00001fcc Void
   +0x548 OwnerProcessId   : 0x1fcc
   +0x550 Peb              : 0x00000004`161ec000 _PEB
   +0x558 Session          : 0xffff9081`87afe000 _MM_SESSION_SPACE
   +0x560 Spare1           : (null) 
   +0x568 QuotaBlock       : 0xffffdc07`9ce09cc0 _EPROCESS_QUOTA_BLOCK
   +0x570 ObjectTable      : 0xffffa505`c9d05c80 _HANDLE_TABLE
   +0x578 DebugPort        : (null) 
   +0x580 WoW64Process     : (null) 
   +0x588 DeviceMap        : (null) 
   +0x590 EtwDataSource    : (null) 
   +0x598 PageDirectoryPte : 0
   +0x5a0 ImageFilePointer : 0xffffdc07`a4543500 _FILE_OBJECT
   +0x5a8 ImageFileName    : [15]  "test_wtf_harne"
   +0x5b7 PriorityClass    : 0x2 ''
   +0x5b8 SecurityPort     : (null) 
   +0x5c0 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x5c8 JobLinks         : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
   +0x5d8 HighestUserAddress : 0x00007fff`ffff0000 Void
   +0x5e0 ThreadListHead   : _LIST_ENTRY [ 0xffffdc07`a3ab66a0 - 0xffffdc07`a3ab66a0 ]
   +0x5f0 ActiveThreads    : 0
   +0x5f4 ImagePathHash    : 0
   +0x5f8 DefaultHardErrorProcessing : 1
   +0x5fc LastThreadExitStatus : 0n0
   +0x600 PrefetchTrace    : _EX_FAST_REF
   +0x608 LockedPagesList  : (null) 
   +0x610 ReadOperationCount : _LARGE_INTEGER 0x0
   +0x618 WriteOperationCount : _LARGE_INTEGER 0x0
   +0x620 OtherOperationCount : _LARGE_INTEGER 0x0
   +0x628 ReadTransferCount : _LARGE_INTEGER 0x0
   +0x630 WriteTransferCount : _LARGE_INTEGER 0x0
   +0x638 OtherTransferCount : _LARGE_INTEGER 0x0
   +0x640 CommitChargeLimit : 0
   +0x648 CommitCharge     : 0x6f
   +0x650 CommitChargePeak : 0x6f
   +0x680 Vm               : _MMSUPPORT_FULL
   +0x7c0 MmProcessLinks   : _LIST_ENTRY [ 0xfffff802`3704dc68 - 0xffffdc07`a39ae840 ]
   +0x7d0 ModifiedPageCount : 0
   +0x7d4 ExitStatus       : 0n259
   +0x7d8 VadRoot          : _RTL_AVL_TREE
   +0x7e0 VadHint          : 0xffffdc07`9e9cb890 Void
   +0x7e8 VadCount         : 0xa
   +0x7f0 VadPhysicalPages : 0
   +0x7f8 VadPhysicalPagesLimit : 0
   +0x800 AlpcContext      : _ALPC_PROCESS_CONTEXT
   +0x820 TimerResolutionLink : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
   +0x830 TimerResolutionStackRecord : (null) 
   +0x838 RequestedTimerResolution : 0
   +0x83c SmallestTimerResolution : 0
   +0x840 ExitTime         : _LARGE_INTEGER 0x0
   +0x848 InvertedFunctionTable : (null) 
   +0x850 InvertedFunctionTableLock : _EX_PUSH_LOCK
   +0x858 ActiveThreadsHighWatermark : 0
   +0x85c LargePrivateVadCount : 0
   +0x860 ThreadListLock   : _EX_PUSH_LOCK
   +0x868 WnfContext       : (null) 
   +0x870 ServerSilo       : (null) 
   +0x878 SignatureLevel   : 0 ''
   +0x879 SectionSignatureLevel : 0 ''
   +0x87a Protection       : _PS_PROTECTION
   +0x87b HangCount        : 0y000
   +0x87b GhostCount       : 0y000
   +0x87b PrefilterException : 0y0
   +0x87c Flags3           : 0
   +0x87c Minimal          : 0y0
   +0x87c ReplacingPageRoot : 0y0
   +0x87c Crashed          : 0y0
   +0x87c JobVadsAreTracked : 0y0
   +0x87c VadTrackingDisabled : 0y0
   +0x87c AuxiliaryProcess : 0y0
   +0x87c SubsystemProcess : 0y0
   +0x87c IndirectCpuSets  : 0y0
   +0x87c RelinquishedCommit : 0y0
   +0x87c HighGraphicsPriority : 0y0
   +0x87c CommitFailLogged : 0y0
   +0x87c ReserveFailLogged : 0y0
   +0x87c SystemProcess    : 0y0
   +0x87c HideImageBaseAddresses : 0y0
   +0x87c AddressPolicyFrozen : 0y0
   +0x87c ProcessFirstResume : 0y0
   +0x87c ForegroundExternal : 0y0
   +0x87c ForegroundSystem : 0y0
   +0x87c HighMemoryPriority : 0y0
   +0x87c EnableProcessSuspendResumeLogging : 0y0
   +0x87c EnableThreadSuspendResumeLogging : 0y0
   +0x87c SecurityDomainChanged : 0y0
   +0x87c SecurityFreezeComplete : 0y0
   +0x87c VmProcessorHost  : 0y0
   +0x87c VmProcessorHostTransition : 0y0
   +0x87c AltSyscall       : 0y0
   +0x87c TimerResolutionIgnore : 0y0
   +0x87c DisallowUserTerminate : 0y0
   +0x880 DeviceAsid       : 0n0
   +0x888 SvmData          : (null) 
   +0x890 SvmProcessLock   : _EX_PUSH_LOCK
   +0x898 SvmLock          : 0
   +0x8a0 SvmProcessDeviceListHead : _LIST_ENTRY [ 0xffffdc07`a3ab6960 - 0xffffdc07`a3ab6960 ]
   +0x8b0 LastFreezeInterruptTime : 0
   +0x8b8 DiskCounters     : 0xffffdc07`a3ab6b00 _PROCESS_DISK_COUNTERS
   +0x8c0 PicoContext      : (null) 
   +0x8c8 EnclaveTable     : (null) 
   +0x8d0 EnclaveNumber    : 0
   +0x8d8 EnclaveLock      : _EX_PUSH_LOCK
   +0x8e0 HighPriorityFaultsAllowed : 0
   +0x8e8 EnergyContext    : 0xffffdc07`a3ab6b28 _PO_PROCESS_ENERGY_CONTEXT
   +0x8f0 VmContext        : (null) 
   +0x8f8 SequenceNumber   : 0
   +0x900 CreateInterruptTime : 0x00000003`eca0dc41
   +0x908 CreateUnbiasedInterruptTime : 0x00000003`eca0dc41
   +0x910 TotalUnbiasedFrozenTime : 0
   +0x918 LastAppStateUpdateTime : 0x00000003`eca0dc41
   +0x920 LastAppStateUptime : 0y0000000000000000000000000000000000000000000000000000000000000 (0)
   +0x920 LastAppState     : 0y000
   +0x928 SharedCommitCharge : 0x51
   +0x930 SharedCommitLock : _EX_PUSH_LOCK
   +0x938 SharedCommitLinks : _LIST_ENTRY [ 0xffffa505`c7f48d68 - 0xffffa505`c7f49c18 ]
   +0x948 AllowedCpuSets   : 0
   +0x950 DefaultCpuSets   : 0
   +0x948 AllowedCpuSetsIndirect : (null) 
   +0x950 DefaultCpuSetsIndirect : (null) 
   +0x958 DiskIoAttribution : (null) 
   +0x960 DxgProcess       : (null) 
   +0x968 Win32KFilterSet  : 0
   +0x970 ProcessTimerDelay : _PS_INTERLOCKED_TIMER_DELAY_VALUES
   +0x978 KTimerSets       : 0
   +0x97c KTimer2Sets      : 0
   +0x980 ThreadTimerSets  : 0
   +0x988 VirtualTimerListLock : 0
   +0x990 VirtualTimerListHead : _LIST_ENTRY [ 0xffffdc07`a3ab6a50 - 0xffffdc07`a3ab6a50 ]
   +0x9a0 WakeChannel      : _WNF_STATE_NAME
   +0x9a0 WakeInfo         : _PS_PROCESS_WAKE_INFORMATION
   +0x9d0 MitigationFlags  : 0x20
   +0x9d0 MitigationFlagsValues : <anonymous-tag>
   +0x9d4 MitigationFlags2 : 0x40000000
   +0x9d4 MitigationFlags2Values : <anonymous-tag>
   +0x9d8 PartitionObject  : 0xffffdc07`9bcbbea0 Void
   +0x9e0 SecurityDomain   : 0x00000001`00000069
   +0x9e8 ParentSecurityDomain : 0x00000001`00000069
   +0x9f0 CoverageSamplerContext : (null) 
   +0x9f8 MmHotPatchContext : (null) 
   +0xa00 DynamicEHContinuationTargetsTree : _RTL_AVL_TREE
   +0xa08 DynamicEHContinuationTargetsLock : _EX_PUSH_LOCK
   +0xa10 DynamicEnforcedCetCompatibleRanges : _PS_DYNAMIC_ENFORCED_ADDRESS_RANGES
   +0xa20 DisabledComponentFlags : 0
   +0xa28 PathRedirectionHashes : (null) 
​
kd> db @rcx+0x5a8
ffffdc07`9e8a1668  74 65 73 74 5f 77 74 66-5f 68 61 72 6e 65 00 02  test_wtf_harne..
ffffdc07`9e8a1678  00 00 00 00 00 00 00 00-e0 1c 7d 9e 07 dc ff ff  ..........}.....
ffffdc07`9e8a1688  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffdc07`9e8a1698  00 00 ff ff ff 7f 00 00-a0 16 8a 9e 07 dc ff ff  ................

rcx+0x5a8위치를 살펴보면 다음과 같이 ImageFileName이 존재하는 것을 확인할 수 있다.

+0x5a8 ImageFileName    : [15]  "test_wtf_harne"

OS 백그라운드 상에서 지속적으로 다양한 프로세스가 시작되기 때문에, 타겟 프로세스를 찾기위해 다음과 같은 스크립트를 이용하는 것이 신상에 이롭다.

Debugger.txt 이름으로 다음과 같은 스크립트를 생성한다. 간단히 내용을 살펴보면, 브레이크 포인트가 걸릴 때마다 rcx+0x5a8 주소에 있는 문자열을 가져와서 ImageName이라는 변수에 저장하고, 타겟 프로세스의 이름 "*test_wtf_har*"가 맞는지 비교하면서, 맞으면 콜 스택을 출력하고 틀리면 그냥 계속 실행하는 코드이다.

r $t0 = (rcx+0x5a8)
as /ma ${/v:ImageName} @$t0
.echo ${ImageName}
.if ($spat(@"${ImageName}", "*test_wtf_har*")) {kn; .echo "break at target process!"} .else { g }

다음과 같이 브레이크 포인트를 걸고 실행하고 vm 상에서 타켓 프로세스를 실행하면 된다.

kd> bp nt!PspInsertProcess "$$<C:\\Users\\Charlie\\Desktop\\fuzzing\\Debugger.txt"
kd> g
​
...
​
kd> r $t0 = (rcx+0x5a8)
kd> as /ma ${/v:ImageName} @$t0
kd> .echo ${ImageName}
test_wtf_harne
kd> .if ($spat(@"${ImageName}", "*test_wtf_har*")) {kn; .echo "break at target process!"} .else { g }
 # Child-SP          RetAddr               Call Site
00 ffff8e8d`4908adb8 fffff802`36affac8     nt!PspInsertProcess
01 ffff8e8d`4908adc0 fffff802`368096b5     nt!NtCreateUserProcess+0xd88
02 ffff8e8d`4908ba90 00007ff8`8922e634     nt!KiSystemServiceCopyEnd+0x25
SYMSRV:  BYINDEX: 0xA28
         C:\ProgramData\Dbg\sym
         ntdll.pdb
         094B224BC5297445CF29F9C9BB588DC91
SYMSRV:  PATH: C:\ProgramData\Dbg\sym\ntdll.pdb\094B224BC5297445CF29F9C9BB588DC91\ntdll.pdb
SYMSRV:  RESULT: 0x00000000
DBGHELP: ntdll - public symbols  
        C:\ProgramData\Dbg\sym\ntdll.pdb\094B224BC5297445CF29F9C9BB588DC91\ntdll.pdb
SYMSRV:  BYINDEX: 0xA29
         C:\ProgramData\Dbg\sym
         kernelbase.pdb
         BFA648CE3D974430D6F69BCCC300FC391
SYMSRV:  PATH: C:\ProgramData\Dbg\sym\kernelbase.pdb\BFA648CE3D974430D6F69BCCC300FC391\kernelbase.pdb
SYMSRV:  RESULT: 0x00000000
DBGHELP: KERNELBASE - public symbols  
        C:\ProgramData\Dbg\sym\kernelbase.pdb\BFA648CE3D974430D6F69BCCC300FC391\kernelbase.pdb
03 000000d4`6497d808 00007ff8`86b38e73     ntdll!NtCreateUserProcess+0x14
04 000000d4`6497d810 00007ff8`86b371a6     KERNELBASE!CreateProcessInternalW+0xfe3
SYMSRV:  BYINDEX: 0xA2A
         C:\ProgramData\Dbg\sym
         kernel32.pdb
         BF9567320871B7B8741ED4FF2369DC5C1
SYMSRV:  PATH: C:\ProgramData\Dbg\sym\kernel32.pdb\BF9567320871B7B8741ED4FF2369DC5C1\kernel32.pdb
SYMSRV:  RESULT: 0x00000000
DBGHELP: KERNEL32 - public symbols  
        C:\ProgramData\Dbg\sym\kernel32.pdb\BF9567320871B7B8741ED4FF2369DC5C1\kernel32.pdb
05 000000d4`6497ede0 00007ff8`87fecbb4     KERNELBASE!CreateProcessW+0x66
06 000000d4`6497ee50 00007ff7`a2a84486     KERNEL32!CreateProcessWStub+0x54
07 000000d4`6497eeb0 00000000`00000001     0x00007ff7`a2a84486
08 000000d4`6497eeb8 00000240`6c7e14d0     0x1
09 000000d4`6497eec0 00000240`6c7ec440     0x00000240`6c7e14d0
0a 000000d4`6497eec8 00000000`00000000     0x00000240`6c7ec440
break at target process!
nt!PspInsertProcess:
fffff802`36afd32c 488bc4          mov     rax,rsp

이 시점에서는 아직 연결리스트에 프로세스를 추가하지 않았기 때문에, !process 0 0 명령어로 프로세스를 확인할 수 없다. 따라서, 이제 bp nt!KiStartUserThread로 프로세스를 실행하기 직전 함수에 브포를 걸면 된다.

kd> bp nt!KiStartUserThread
kd> g

nt!KiStartUserThread 에서 멈추면 앞선 과정과 마찬가지로 다음과 같이 진행하면 된다.

kd> !process 0 0 test_wtf_harness.exe
PROCESS ffffcf01ccf6a080
    SessionId: 2  Cid: 1880    Peb: da4e6a4000  ParentCid: 0690
    DirBase: 6e9b7000  ObjectTable: ffffe2090870b780  HandleCount:  44.
    Image: test_wtf_harness.exe
​
kd> .process /i /r /p ffffcf01ccf6a080
kd> g
​
...
​
kd> .sympath+ "{symbol 경로}"
kd> .reload /f /d
kd> bu test_wtf_harness!main
​
...
​
kd> g
반응형

'좀 열심히 쓴 글' 카테고리의 다른 글

WTF(WHAT THE FUZZ) TUTORIAL  (7) 2022.06.03
What The Fuzz 분석  (0) 2021.08.08
Fuzzing software: common challenges and potential solutions 정리  (0) 2021.08.06
House of Husk  (0) 2020.08.09
Bypass SNI Filtering  (1) 2020.06.29