Icesword라는 프로그램을 보면 Message Hook Chain을 구하는 기능을 가지고 있습니다. Message Hooking시 타모듈과의 충돌을 분석할때 유용하게 사용하곤합니다. 그렇다면 과연 이러한 Message Hook chain은 어디에 등록되어 있을까 ?
간단히 Win32 Thread의 Teb를 확인하면 추적이 가능합니다.
0: kd> !process 857295a0 3
PROCESS 857295a0 SessionId: 0 Cid: 0788 Peb: 7ffdd000 ParentCid: 06c4
DirBase: 064001e0 ObjectTable: e17d5a30 HandleCount: 45.
Image: notepad.exe
VadRoot 858351f0 Vads 67 Clone 0 Private 202. Modified 17. Locked 0.
DeviceMap e190da40
Token e1f29d48
ElapsedTime 00:00:03.062
UserTime 00:00:00.015
KernelTime 00:00:00.078
QuotaPoolUsage[PagedPool] 63204
QuotaPoolUsage[NonPagedPool] 2680
Working Set Sizes (now,min,max) (926, 50, 345) (3704KB, 200KB, 1380KB)
PeakWorkingSetSize 931
VirtualSize 31 Mb
PeakVirtualSize 36 Mb
PageFaultCount 1007
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 468
THREAD 85775518 Cid 0788.054c Teb: 7ffdf000 Win32Thread: e1ff3008 WAIT: (WrUserRequest) UserMode Non-Alertable
84976d98 SynchronizationEvent
일반적인 Notepad의 Process와 Thread입니다. 이 중에서 우리에게 필요한 부분인 Message Hook Chain에 대한 정보는 Thread의 TEB에 포함되어 있습니다.
0: kd> .process 857295a0
Implicit process is now 857295a0
0: kd> dt _TEB 7ffdf000
ntdll!_TEB
+0×000 NtTib : _NT_TIB
+0×01c EnvironmentPointer : (null)
+0×020 ClientId : _CLIENT_ID
+0×028 ActiveRpcHandle : (null)
+0×02c ThreadLocalStoragePointer : (null)
+0×030 ProcessEnvironmentBlock : 0×7ffdd000 _PEB
+0×034 LastErrorValue : 0
+0×038 CountOfOwnedCriticalSections : 0
+0×03c CsrClientThread : (null)
+0×040 Win32ThreadInfo : 0xe1ff3008
+0×044 User32Reserved : [26] 0
+0×0ac UserReserved : [5] 0
+0×0c0 WOW32Reserved : (null)
+0×0c4 CurrentLocale : 0×412
+0×0c8 FpSoftwareStatusRegister : 0
+0×0cc SystemReserved1 : [54] (null)
+0×1a4 ExceptionCode : 0
+0×1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
… 생략
Thread TEB를 확인하면 Win32ThreadInfo라는 녀석이 존재합니다. 기본적으로 PVOID 형을 가지고 있는데 물론 Undocument 된 부분이라 이렇게 표시 되죠 .
Win32ThreadInfo의 메모리에 있는 데이터는 MessageQueue, KeyboardLayout, Desktop, DesktopInfo, WindowList 등 Win32를 UI를 구동하는데 필요한 데이터들을 포함하고 있습니다.
그리고 Global Message Hook과 Local Message Hook에 대한 정보는 Win32ThreadInfo, DesktopInfo 정보를 통해서 추적이 가능합니다.
0: kd> dt finter!_THREADINFO 0xe1ff3008
+0×000 W32Thread : W32THREAD
+0×028 ptl : (null)
+0×02c ppi : 0xe10531c8
+0×030 pq : 0xe1e4a9e8 _Q
+0×034 spklActive : 0xe147db58
+0×038 pcti : 0xbc638820
+0×03c rpdesk : 0×858afe88
+0×040 pDeskInfo : 0xbc630650 _DESKTOPINFO
+0×044 pClientInfo : 0×7ffdf6cc
+0×048 TIF_flags : 0×1100000
+0×04c pstrAppName : (null)
+0×050 psmsSent : (null)
+0×054 psmsCurrent : (null)
+0×058 psmsReceiveList : (null)
+0×05c timeLast : 2543531
+0×060 idLast : 0xe11bab48
+0×064 cQuit : 0
+0×064 exitCode : 0
+0×068 hdesk : 0×0000002c
+0×06c cPaintsReady : 0
+0×070 cTimersReady : 0
+0×074 pMenuState : (null)
+0×078 ptdb : (null)
+0×078 pwinsta : (null)
+0×07c psiiList : (null)
+0×080 dwExpWinVer : 0×400
+0×084 dwCompatFlags : 0
+0×088 dwCompatFlags2 : 0
… 생략
+0×0e0 fsReserveKeys : 0
+0×0e4 apEvent : (null)
+0×0e8 amdesk : 0xf01ff
+0×0ec cWindows : 6
+0×0f0 cVisWindows : 0
+0×0f4 aphkStart : [16] (null)
간단히 정리한 구조체를 이용해서 Win32ThreadInfo의 데이터를 확인해 봤습니다. 이 중 _DESKTOPINFO의 값을 다시 확인해보죠
0: kd> dt _DESKTOPINFO 0xbc630650
finter!_DESKTOPINFO
+0×000 pvDesktopBase : 0xbc630000
+0×004 pvDesktopLimit : 0xbc930000
+0×008 spwnd : 0xbc6306e8
+0×00c fsHooks : 0×850
+0×010 aphkStart : [16] (null)
+0×050 spwndShell : 0xbc63ead8
+0×054 ppiShellProcess : 0xe1956448
+0×058 spwndBkGnd : 0xbc63f2e0
+0×05c spwndTaskman : 0xbc63e548
+0×060 spwndProgman : (null)
+0×064 pvwplShellHook : 0xe1ce8ea0
+0×068 cntMBox : 0
Win32ThreadInfo의 aphkStart Member는 Local Hook의 데이터를 나타내는 Array고 DesktopInfo의 aphkStart Member는 Global Hook의 데이터를 나타내는 Arrary 입니다. 각각 Array의 인자는 HOOK Structure를 나타내며 각 Index는 Hooking Type을 나타내도록 구성됩니다.
이제 이 Array 안의 데이터를 확인해보겠습니다.
0: kd> dps 0xe1ff3008+0xf4 L16
e1ff30fc 00000000
e1ff3100 00000000
e1ff3104 00000000
e1ff3108 bc636de0
e1ff310c 00000000
e1ff3110 00000000
e1ff3114 00000000
e1ff3118 00000000
e1ff311c bc636e20
e1ff3120 00000000
e1ff3124 00000000
e1ff3128 00000000
e1ff312c 00000000
e1ff3130 00000000
e1ff3134 00000000
e1ff3138 00000000
e1ff313c 00000000
e1ff3140 00000000
e1ff3144 00000000
e1ff3148 00000000
e1ff314c 00000000
e1ff3150 00000000
0: kd> dps 0xbc630650+0×10 L16
bc630660 00000000
bc630664 00000000
bc630668 00000000
bc63066c 00000000
bc630670 bc640530
bc630674 00000000
bc630678 bc640570
bc63067c 00000000
bc630680 00000000
bc630684 00000000
bc630688 00000000
bc63068c bc6404f0
bc630690 00000000
bc630694 00000000
bc630698 00000000
bc63069c 00000000
bc6306a0 bc63ead8
bc6306a4 e1956448
bc6306a8 bc63f2e0
bc6306ac bc63e548
bc6306b0 00000000
bc6306b4 e1ce8ea0
0: kd> dt _HOOK bc636e20
npkfinder!_HOOK
+0×000 head : _THRDESKHEAD
+0×014 phkNext : (null)
+0×018 iHook : 7
+0×01c offPfn : 0×0000ff89
+0×020 flags : 2
+0×024 ihmod : 1
+0×028 ptiHooked : 0xe1ff3008 _THREADINFO
+0×02c rpdesk : (null)
이 중 하나를 열어서 보면 위와 같은 구조로 이루어져 있습니다. phkNexe 인자는 다음 Hook Chain을 가르키는 인자인데 현재는 하나의 Hooking Function만이 등록되어 있는 상태군요 .
IceSword의 경우는 이러한 원리( ?? ) 를 이용해서 아마도 Hook Chain을 보여주는것 같습니다. 위에 설명한 Hook Chain를 잘이용하면 아래와 같은 샘플도 만들수 있죠. ( 샘플소스는 개인적으로 문의해주세요 …)

조금이나마 도움이 되셨으면합니다.
Enjoy Debugging…
최근 답글