[原创]我写的一个查看MFC消息工具
很多年前已经有人写出来了MFCSPY 我发现少个静态release支持 所以我重写了下
大致思路:
使用dll钩子获取被spy程序的MFC窗口类,然后获得消息映射表,遍历即可
有几个注意地方:
(1)dll需要用mfc dll来写,获取消息映射表MFC现成有GetMessageMap()虚函数,直接可以拿来用,
因为GetMessageMap()是保护函数,所以共有继承CWnd,类里调用GetMessageMap()即可
(静态release版本需要特殊处理下 CWnd虚表中GetMessageMap()的偏移不是0x30而是0x28)
(2)获取当前运行程序的编译方式,这点我没想到方法,知道的麻烦指教下,我只用了
if (GetModuleHandle("mfc42d.dll") != NULL)
{
return MFC42D;
}
if (GetModuleHandle("mfc42.dll") != NULL)
{
return MFC42;
}
return STATIC;
来获取编译方式,用此方法dll的编译方式不能为动态链接,因为我总感觉这种方式不好,所以MFC DLL窗口程序的特征码也没找,只处理了exe, 我使用的是VC6. 更高版本MFC因为没有安装,所以没有测试
具体实现:
测试发现,mfc动态debug方式下 直接在dll钩子函数使用CWnd::FromHandlePermanent便能获得对应的类信息,而其他编译方式都获得不了,所以我使用特征码来找被SPY的窗口CWnd::FromHandlePermanent函数的入口,因为CWnd::FromHandlePermanent在MFC框架的窗口消息处理函数中前几行就调用,所以可以找到4种不同编译方式下的窗口消息处理函数特征,
找到CWnd::FromHandlePermanent函数入口(我最后发现mfc dll中的特征和exe的并不一样,如果想处理dll,则必须再把mfc dll窗口消息处理函数的特征给弄全)
mfc static release: 00418787 55 push ebp 00418788 8B EC mov ebp,esp 0041878A 81 7D 0C 60 03 00 00 cmp dword ptr [ebp+0Ch],360h 00418791 56 push esi 00418792 75 05 jne 00418799 00418794 6A 01 push 1 00418796 58 pop eax 00418797 EB 34 jmp 004187CD 00418799 8B 75 08 mov esi,dword ptr [ebp+8] 0041879C 56 push esi 0041879D E8 5F FF FF FF call 00418701 ;CWnd::FromHandlePermanent mfc static debug: 0047FFE8 55 push ebp 0047FFE9 8B EC mov ebp,esp 0047FFEB 51 push ecx 0047FFEC 53 push ebx 0047FFED 56 push esi 0047FFEE 57 push edi 0047FFEF 81 7D 0C 60 03 00 00 cmp dword ptr [nMsg],360h 0047FFF6 75 0A jne AfxWndProc+1Ah (00480002) 0047FFF8 B8 01 00 00 00 mov eax,1 0047FFFD E9 93 00 00 00 jmp AfxWndProc+0ADh (00480095) 00480002 8B 45 08 mov eax,dword ptr [hWnd] 00480005 50 push eax 00480006 E8 5D FE FF FF call CWnd::FromHandlePermanent (0047fe68) mfc share Debug: AfxWndProcBase: 5F492613 55 push ebp 5F492614 8B EC mov ebp,esp 5F492616 6A FF push 0FFh 5F492618 68 D1 97 4A 5F push offset $L89118 (5f4a97d1) ;171B8 5F49261D 64 A1 00 00 00 00 mov eax,fs:[00000000] 5F492623 50 push eax 5F492624 64 89 25 00 00 00 00 mov dword ptr fs:[0],esp 5F49262B 83 EC 0C sub esp,0Ch 5F49262E B9 10 48 4D 5F mov ecx,offset _afxBaseModuleState (5f4d4810) 5F492633 E8 28 03 00 00 call CProcessLocal<_AFX_BASE_MODULE_STATE>::GetData(5f492960) 5F492638 50 push eax 5F492639 8D 4D EC lea ecx,[_ctlState] 5F49263C E8 72 F8 FF FF call AFX_MAINTAIN_STATE2::AFX_MAINTAIN_STATE2 (5f491eb3) 5F492641 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0 5F492648 8B 45 14 mov eax,dword ptr [lParam] 5F49264B 50 push eax 5F49264C 8B 4D 10 mov ecx,dword ptr [wParam] 5F49264F 51 push ecx 5F492650 8B 55 0C mov edx,dword ptr [nMsg] 5F492653 52 push edx 5F492654 8B 45 08 mov eax,dword ptr [hWnd] 5F492657 50 push eax 5F492658 E8 EB C9 F9 FF call AfxWndProc (5f42f048) AfxWndProc: 5F42F048 55 push ebp 5F42F049 8B EC mov ebp,esp 5F42F04B 51 push ecx 5F42F04C 53 push ebx 5F42F04D 56 push esi 5F42F04E 57 push edi 5F42F04F 81 7D 0C 60 03 00 00 cmp dword ptr [nMsg],360h 5F42F056 75 0A jne AfxWndProc+1Ah (5f42f062) 5F42F058 B8 01 00 00 00 mov eax,1 5F42F05D E9 93 00 00 00 jmp AfxWndProc+0ADh (5f42f0f5) 5F42F062 8B 45 08 mov eax,dword ptr [hWnd] 5F42F065 50 push eax 5F42F066 E8 5D FE FF FF call CWnd::FromHandlePermanent (5f42eec8) mfc share release: AfxWndProcBase: 73DBE443 B8 EC 41 DC 73 mov eax,73DC41ECh ;0x5DA8 73DBE448 E8 A3 BB FF FF call 73DB9FF0 73DBE44D 51 push ecx 73DBE44E 51 push ecx 73DBE44F 68 89 FD DB 73 push 73DBFD89h ;0x1939 73DBE454 B9 50 26 E0 73 mov ecx,73E02650h ;0x441FB 73DBE459 E8 BF FE FF FF call 73DBE31D 73DBE45E 50 push eax 73DBE45F 8D 4D EC lea ecx,[ebp-14h] 73DBE462 E8 B5 FF FF FF call 73DBE41C 73DBE467 FF 75 14 push dword ptr [ebp+14h] 73DBE46A 83 65 FC 00 and dword ptr [ebp-4],0 73DBE46E FF 75 10 push dword ptr [ebp+10h] 73DBE471 FF 75 0C push dword ptr [ebp+0Ch] 73DBE474 FF 75 08 push dword ptr [ebp+8] 73DBE477 E8 20 35 F7 FF call 73D3199C ;AfxWndProc AfxWndProc: 73D3199C 55 push ebp 73D3199D 8B EC mov ebp,esp 73D3199F 81 7D 0C 60 03 00 00 cmp dword ptr [ebp+0Ch],360h 73D319A6 75 05 jne 73D319AD 73D319A8 33 C0 xor eax,eax 73D319AA 40 inc eax 73D319AB EB 36 jmp 73D319E3 73D319AD 56 push esi 73D319AE 8B 75 08 mov esi,dword ptr [ebp+8] 73D319B1 56 push esi 73D319B2 E8 22 F8 FF FF call 73D311D9 ;CWnd::FromHandlePermanent mfc share release dll 00BC1B70 55 PUSH EBP 00BC1B71 8BEC MOV EBP,ESP 00BC1B73 6A FF PUSH -1 00BC1B75 68 5935BC00 PUSH MfcDll1.00BC3559 00BC1B7A 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] 00BC1B80 50 PUSH EAX 00BC1B81 64:8925 0000000>MOV DWORD PTR FS:[0],ESP 00BC1B88 83EC 0C SUB ESP,0C 00BC1B8B 68 9869BD00 PUSH MfcDll1.00BD6998 00BC1B90 8D4D EC LEA ECX,DWORD PTR SS:[EBP-14] 00BC1B93 E8 FEFDFFFF CALL <JMP.&MFC42D.#284> 00BC1B98 C745 FC 0000000>MOV DWORD PTR SS:[EBP-4],0 00BC1B9F 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14] 00BC1BA2 50 PUSH EAX 00BC1BA3 8B4D 10 MOV ECX,DWORD PTR SS:[EBP+10] 00BC1BA6 51 PUSH ECX 00BC1BA7 8B55 0C MOV EDX,DWORD PTR SS:[EBP+C] 00BC1BAA 52 PUSH EDX 00BC1BAB 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 00BC1BAE 50 PUSH EAX 00BC1BAF E8 7A060000 CALL <JMP.&MFC42D.#1192> 00BC1BB4 8945 E8 MOV DWORD PTR SS:[EBP-18],EAX
因为静态release的GetMessageMap()偏移为0x28 所以
我单独做了处理(这样就无关dll编译版本)
if (g_isStaticRelase == true)
{
__asm
{
mov eax,this
mov eax,[eax]
mov ecx,this
call [eax + 028h]
}
}
