一、 战场环境
[兵工场]:VC6.0
[兵器谱]: Detours Express 2.1、Windbg6.11、OllyDBG
二、 战术分析
Hook从字面上理解就是钩子的意思,当然这个钩子不是用来钓鱼的。它是用来挂钩程序用的,程序一但被挂钩就可以改变程序原有的流程。例如Hook之前的流程如下:
Hook后的流程如下:
拦截XX聊天信息的基本原理就是挂钩XX的聊天记录函数,使得我们可以中途处理聊天记录。
要改变程序的流程有很多汇编指令可以使用,常用的有两种:JMP、CALL
下面是用OllyDBG反汇编MessageBox得到的头部代码:
77D5050B > 8BFF MOV EDI,EDI
77D5050D /. 55 PUSH EBP
77D5050E |. 8BEC MOV EBP,ESP
这五个字节的指令是保护堆栈用的。我们要攻击的地方就是这5个字节。
Hook后那5个字节是怎么样的呢?在调试过程中发现Hook后OD不稳定,Hook的5个字节变成了下面的样子:
77D5050B >- E9 FA0A2B98 JMP HookDll.1000100A
77D50510 833D 1C04D777 0>CMP DWORD PTR DS:[77D7041C],0
77D50517 74 24 JE SHORT USER32.77D5053D
77D50519 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
跟进跳转看看做了什么……
一个很大的跳转,继续跟进跳转到下面,我们自己写的代码
100010C0 55 PUSH EBP
100010C1 8BEC MOV EBP,ESP
100010C3 83EC 44 SUB ESP,44
100010C6 53 PUSH EBX
100010C7 56 PUSH ESI
100010C8 57 PUSH EDI
100010C9 8D7D BC LEA EDI,DWORD PTR SS:[EBP-44]
100010CC B9 11000000 MOV ECX,11
100010D1 B8 CCCCCCCC MOV EAX,CCCCCCCC
100010D6 F3:AB REP STOS DWORD PTR ES:[EDI]
100010D8 8BF4 MOV ESI,ESP
100010DA 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14]
100010DD 50 PUSH EAX
100010DE 68 30E00210 PUSH HookDll.1002E030
100010E3 68 1CE00210 PUSH HookDll.1002E01C
100010E8 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8]
100010EB 51 PUSH ECX
100010EC FF15 306C0310 CALL DWORD PTR DS:[10036C30]
100010F2 3BF4 CMP ESI,ESP
100010F4 E8 971D0000 CALL HookDll.10002E90
100010F9 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
100010FC 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
100010FF 5F POP EDI
10001100 5E POP ESI
10001101 5B POP EBX
10001102 83C4 44 ADD ESP,44
10001105 3BEC CMP EBP,ESP
10001107 E8 841D0000 CALL HookDll.10002E90
1000110C 8BE5 MOV ESP,EBP
1000110E 5D POP EBP
1000110F C2 1000 RETN 10
看到红色那句没?执行后后回到了原调用MessageBox后面的代码,也就是上面的代码段B
这里提下windbg调试器,掌握了它,windows的秘密再也就是秘密了
下面是对程序的分析结果:
看到没有加载了两个DLL,Hook要成功的一个重要前提是能够读写进程的内存,否则没办法写任何字节。通常的方法是写一个DLL注意的进程的空间。网上有一大堆这种DLL注入器,这里就不一一介绍了。
一、 实弹演练
我八成猜到看到这的人已经云里雾里了,放心微软放出了Detours Express 2.1(XX聊天拦截我没用这玩意,根据原理自己实现的)专门干这事的。由于我国有明确的法律规定,不能发行恶意代码,所以XX聊天记录拦截代码就不放出来了。下面以我写的一个Demo为例来介绍。DEMO的功能是通过加载HookDll.dll实例挂钩USER32.DLL里的MessageBox. HookDll里实现所有的挂钩操作。
1.加载DLL前,弹框内容如下:
2。加载DLL后,弹框内容如下:
MessageBox弹框内容已经被修改。
3.卸载DLL后,弹框内容如下:
下面讲解一下Detours Express 2.1库的使用:
Detours的几个核心API如下:
用到的几个API简要说明下:
DetourTransactionBegin: 开始一个新的detours事务。
DetourUpdateThread:一个线程入队等待更新
DetourAttach:将目标进程(MessageBox)和替换它的函数NEW_MessageBox绑定。第一个参数是一个指针,这个指针指向目标函数的指针(有点绕…)。
DetourTransactionCommit: 事务提交,如果不提交之前的更改是不会生效的。这个函数会返回一个值,如果是NO_ERROR 表明是成功,如果是其他的表示失败。
DetourDetach:解除目标进程和替换函数的绑定,参数和DetourDetach一摸一样。
下面是Hook代码:
VOID Hook()
{
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
//这里可以连续多次调用DetourAttach,表明HOOK多个函数
DetourAttach(&(PVOID&)TrueMessageBox,NEW_MessageBoxA);
DetourTransactionCommit();
OutputDebugString("Hook Success!\n");
}
原始函数MessageBoxA由windows.h声名了,直接用下面的方式使用
static int (WINAPI* TrueMessageBox)(HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType)=MessageBoxA;
我们定义的新MessageBoxA如下:
int WINAPI NEW_MessageBoxA(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
{
//修改输入参数,调用原函数
int ret=TrueMessageBox(hWnd,"该函数已经被Hook","[测试]",uType);
return ret;
}
在完成了任务之后一定要把钩子摘掉:
VOID UnHook()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
//这里可以连续多次调用DetourDetach,表明撤销多个函数HOOK
DetourDetach(&(PVOID&)TrueMessageBox,NEW_MessageBoxA);
DetourTransactionCommit();
OutputDebugString("UnHook Success!\n");
}
注意:我们如果要拦截非windows API的话,通常用下面两个函数实现原有函数地址的导出:
LoadLibrary()
GetProcAddress()
程序下载地址:
http://pan.baidu.com/netdisk/singlepublic?fid=434312_4232810461