windbg - Wow64, x86, x64에서의 커널 구조체(예: TEB) 구조체 확인
일반적으로 커널 구조체는 ntdll.dll에 담겨져 있고, x86 process on x86 system, x64 process on x64 system에서는 단순히 "dt _TEB"라고 하면 해당 구조체를 확인할 수 있습니다.
// x86 windbg / x86 debuggee on x86 windows
// x64 windbg / x64 debuggee on x64 windows
0:000> dt _TEB
ntdll!_TEB
+0x000 NtTib : _NT_TIB
+0x038 EnvironmentPointer : Ptr64 Void
+0x040 ClientId : _CLIENT_ID
+0x050 ActiveRpcHandle : Ptr64 Void
+0x058 ThreadLocalStoragePointer : Ptr64 Void
...[생략]...
+0x180c WowTebOffset : Int4B
+0x1810 ResourceRetValue : Ptr64 Void
+0x1818 ReservedForWdf : Ptr64 Void
+0x1820 ReservedForCrt : Uint8B
+0x1828 EffectiveContainerId : _GUID
이런 규칙이 x86 process on x64 system인 경우에는 살짝 달라집니다. 우선, x64 운영체제에서 x86 버전의 windbg로 x86 프로세스에 연결한 후 _TEB 구조체를 보려는 경우 다음과 같이 오류가 발생합니다.
// x64 Windows 10 1909
// x86 windbg / x86 debuggee
0:000> dt _TEB
*************************************************************************
*** ***
*** ***
*** Either you specified an unqualified symbol, or your debugger ***
*** doesn't have full symbol information. Unqualified symbol ***
*** resolution is turned off by default. Please either specify a ***
*** fully qualified symbol module!symbolname, or enable resolution ***
*** of unqualified symbols by typing ".symopt- 100". Note that ***
*** enabling unqualified symbol resolution with network symbol ***
*** server shares in the symbol path may cause the debugger to ***
*** appear to hang for long periods of time when an incorrect ***
*** symbol name is typed or the network symbol server is down. ***
*** ***
*** For some commands to work properly, your symbol path ***
*** must point to .pdb files that have full type information. ***
*** ***
*** Certain .pdb files (such as the public OS symbols) do not ***
*** contain the required information. Contact the group that ***
*** provided you with these symbols if you need this command to ***
*** work. ***
*** ***
*** Type referenced: _TEB ***
*** ***
*************************************************************************
Symbol _TEB not found.
x86 notepad.exe를 대상으로 테스트해 보면 32비트 _TEB는 다음과 같은 DLL에 정의되어 있는 것을 확인할 수 있습니다.
0:000> dt *!_TEB
combase!_TEB
wintypes!_TEB
ole32!_TEB
또한 x64 시스템의 경우 별도로 _TEB32 구조체를 함께 제공하기 때문에 이것을 사용해도 무방합니다.
// Windows Server 2008 R2
0:000> dt *!_TEB32
ole32!_TEB32
// Windows Server 2012 이상
0:000> dt *!_TEB32
ntdll!_TEB32
ole32!_TEB32
그다음, x64 운영체제에서 x64 버전의 windbg로 x86 프로세스에 연결한 후 _TEB 구조체를 보려는 경우를 정리해 보겠습니다. 우선 이런 경우 "dt _TEB" 명령어가 잘 동작하는 듯하지만,
// x64 Windows 10 1909
// x64 windbg / x86 debuggee
0:000> dt _TEB
ntdll!_TEB
+0x000 NtTib : _NT_TIB
+0x038 EnvironmentPointer : Ptr64 Void
+0x040 ClientId : _CLIENT_ID
+0x050 ActiveRpcHandle : Ptr64 Void
+0x058 ThreadLocalStoragePointer : Ptr64 Void
+0x060 ProcessEnvironmentBlock : Ptr64 _PEB
+0x068 LastErrorValue : Uint4B
...[생략]...
+0x1810 ResourceRetValue : Ptr64 Void
+0x1818 ReservedForWdf : Ptr64 Void
+0x1820 ReservedForCrt : Uint8B
+0x1828 EffectiveContainerId : _GUID
아쉽게도 x64 버전의 _TEB 구조체일 뿐 x86 버전이 아니므로, 32비트 버전은 _TEB32로 구해야 합니다. (혹은, WinTypes.dll, combase.dll, ole32.dll 등에 정의한 _TEB 사용)
0:000> dt _TEB32
ntdll!_TEB32
+0x000 NtTib : _NT_TIB32
+0x01c EnvironmentPointer : Uint4B
+0x020 ClientId : _CLIENT_ID32
+0x028 ActiveRpcHandle : Uint4B
+0x02c ThreadLocalStoragePointer : Uint4B
+0x030 ProcessEnvironmentBlock : Uint4B
...[생략]...
+0xfe0 ResourceRetValue : Uint4B
+0xfe4 ReservedForWdf : Uint4B
+0xfe8 ReservedForCrt : Uint8B
+0xff0 EffectiveContainerId : _GUID
한 가지 더 아쉬운 점이 있다면 _TEB32 구조체는 Windows Server 2012부터 ntdll.dll에 포함되었기 때문에 Windows Server 2008 R2의 경우에는 ole32.dll에 정의된 (_TEB32가 아닌) _TEB를 참조해야 합니다.
0:002> dt ole32!_TEB
ole32!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
...[생략]...
+0xfcc TxnScopeEnterCallback : Ptr32 Void
+0xfd0 TxnScopeExitCallback : Ptr32 Void
+0xfd4 TxnScopeContext : Ptr32 Void
+0xfd8 LockCount : Uint4B
+0xfdc SpareUlong0 : Uint4B
꽤나 복잡하군요. ^^; 이외에도 "dt ntdll32!_TEB"와 같이 "ntdll32"에서도 구하는 것이 가능한데 현재 제가 가진 운영체제에서 재현이 안 되므로 생략합니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]