[#] Windows GDB Stub
[0x00] Overview
Windows Kernel 디버깅에 있어서 windbg
는 정말 가장 강력한 도구입니다. 때문에 해당 포스트가 필요 없을 수 있습니다. 다만 IDA
에서는 GDB
를 이용한 디버깅이 가능하고 이를 이용하여 Windows Kernel 디버깅이 가능합니다.
windbg
의 전통적인 디버깅 방법과는 다르게 동작하기 때문에 꽤 유용하게 사용될 수 있습니다. 예를 들어 PatchGuard 우회 시 사용되는 기법 중 하나인 HalNotifyProcessorFreeze
후킹의 경우에도 windbg
는 BSOD를 발생시킵니다.
어쨋든 여러가지 이유로 GDB Stub
은 유용합니다.
[0x01] Enable VMware GDB Stub
가상머신 파일이 존재하는 디렉토리에 가서 .vmx
파일을 아래와 같이 수정해야 합니다.
- x86 Local Debugging :
debugStub.listen.guest32 = "TRUE"
- x64 Local Debugging :
debugStub.listen.guest64 = "TRUE"
- x86 Remote Debugging :
debugStub.listen.guest32.remote = "TRUE"
- x64 Remote Debugging :
debugStub.listen.guest64.remote = "TRUE"
다음은 호스트와 통신할 디버깅 포트에 대한 설정을 해줘야 합니다. 기본적으로 x64 guest는 8864 포트, x86 guest는 8832 포트를 사용합니다. 변경하려면 아래와 같이 수정합니다.
- x86 :
debugStub.port.guest32 = "33333"
- x64 :
debugStub.port.guest64 = "33333"
BIOS 로드 시 즉시 디버깅을 사용하는 경우 아래와 같이 추가합니다.
- x86 :
monitor.debugOnStartGuest32 = "TRUE"
- x64 :
monitor.debugOnStartGuest64 = "TRUE"
마지막으로 브레이크 포인트를 하드웨어 브레이크포인트를 이용하려는 경우 아래와 같이 추가합니다.
debugStub.hideBreakpoints = "TRUE"
위에서 필요한 내용들을 .vmx
마지막 줄에 추가하고 저장합니다.
[0x02] IDA Setup
이제 IDA에서 설정이 필요합니다. Debugger -> Attach -> Remote GDB debugger
를 선택하고 아래와 같이 설정해야 합니다.
모든 준비가 완료되었습니다. VM을 시작하면 멈춰있게 되며 이 때 IDA gdb
를 attach 하게 되면 디버깅이 가능하게 됩니다.
하지만 심볼도 존재하지 않으며 모두 원시코드입니다. 때문에 매우 불편할 수 있으며 현재 메모리 영역이 정리되어 있지 않기 때문에 제대로 보이지 않습니다. 아래와 같이 IDA에서 설정이 필요합니다.
[Debugger]->[Manual memory regions]
탭을 열어 아래와 같이 설정합니다.
이후 다시 시작하고 suspend
시 정상적으로 메모리가 보이게 됩니다. 이제 심볼 로드를 통해 좀 더 정확한 코드를 확인해봅니다.
[0x03] Load symbol
매우 간단합니다. Guest OS 내에 %SystemRoot%\System32\ntoskrnl.exe
파일을 Host로 가져옵니다.
여기서 WKE
와 같은 로컬 커널 메모리 에디터 도구가 있다면 더 쉽게 가능합니다. 그 외에도 Process Hacker
와 같은 도구를 이용하여 ntoskrnl.exe
모듈의 이미지 베이스를 구해야 합니다.
위와 같이 ntoskrnl.exe
이미지는 0xFFFFF80648A00000
메모리에 로드되어 있습니다. 이를 복사해둡시다.
다음 IDA
에서 [File] -> [Load file] -> [PDB file...]
을 이용하여 아래와 같이 심볼을 로드합니다.
다소 시간이 소모됩니다. 이제 제법 디버거 다워지는 모습을 볼 수 있습니다.
그래도 역시 기능적인 면으로만 봤을 때 windbg
를 따라올 수는 없습니다. 약간의 편의성과 디버깅 방식의 차이로 인해 몇 가지 이점이 존재합니다.
먼저 KdDebuggerEnabled
와 KdDebuggerNotPresent
와 같은 전역변수에서 알아채지 못합니다.
[0x04] Conclusion
어떤 경우에 있어서 해당 디버깅 기법은 참신하며 강력한 기능으로 동작할 수 있습니다. 본인의 경우 Patch Guard
라고 잘 알려져 있는 KPP(Kernel Patch Protection)
을 우회하기 위한 다양한 기법 중 예외 기반의 기법을 시연하기 위해 해당 GDB stub
을 이용했습니다.