inline hook【001】
2014-10-11 15:11
351 查看
什么是inline hook呢?图像解释下:
![](http://img.blog.csdn.net/20141011122300015?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlsZWl5YW5nMTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
程序本来是要调用左边的目标函数,但是,我们在有没源码的情况下,想要在调用这个函数的时候做点其他事情,就需要插进去我们的函数,这个实现方式就是inline hook
操作原理非常简单:
在程序调用目标函数时候,会找到该函数的地址(图里边的head A),通过将这个头信息偷偷的替换:
![](http://img.blog.csdn.net/20141011140937834?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlsZWl5YW5nMTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
通过jmp B跳到head B,调用我们的插入函数,这样只要被HOOK的程序调用目标函数,就一定会先调用我们的插入函数,(比如游戏中,人机对战,电脑偷偷调用某个行动的时候,我们把它的行为打印,甚至改变,来帮助我们实现我们的想法)。
但是不能影响原来函数的操作,我们在插入函数运行结束后,再将目标函数被去掉的头部还给它,然后在指回去:
![](http://img.blog.csdn.net/20141011141106162?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlsZWl5YW5nMTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
然而,在驱动编程的时候,我们往往这样做:http://www.cnblogs.com/Safe3/archive/2008/10/20/1315381.html
HOOK:
UnHook:
但是很多时候我们想要的是一个应用级别的dll,而不是内核级别的sys,可以这样:http://blog.sina.com.cn/s/blog_802a13bc0100qyol.html
同样想实现这个流程,但是在应用级别,没有权限调用cr0,应用级别,可以用这个来做:
HOOK:
_asm
{
pushad //将EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI这8个指令压栈,保存现场
lea edi,OldMessageBoxACode //edi存放的是想要将数据移动到的目标地址,也就是OldMessageBoxACode
mov esi,fpMessageBoxA //esi存放的是数据存放的源地址
cld //cld是来控制重复移动时候的esi 和edi的递增方式。 cld是将方向标志位DF设置为0,每次rep循环的时候,esi和edi自动+1。 std是将方向标志位DF设置为1,每次rep循环的时候,esi和edi自动-1。
movsd //移动字节数,movsd是DWORD,movsw是WORD,movsb是BYTE
movsb
popad //将EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI这8个指令弹出,还原现场
}
参考:http://blog.csdn.net/zhenyongyuan123/article/details/8364011
http://blog.csdn.net/flowshell/article/details/6094184 http://blog.csdn.net/feixiaoxing/article/details/7009911
接下来需要做的:
完整写一个实例。
如何将DLL注入到指定程序:http://blog.csdn.net/beanjoy/article/details/8497307
程序本来是要调用左边的目标函数,但是,我们在有没源码的情况下,想要在调用这个函数的时候做点其他事情,就需要插进去我们的函数,这个实现方式就是inline hook
操作原理非常简单:
在程序调用目标函数时候,会找到该函数的地址(图里边的head A),通过将这个头信息偷偷的替换:
通过jmp B跳到head B,调用我们的插入函数,这样只要被HOOK的程序调用目标函数,就一定会先调用我们的插入函数,(比如游戏中,人机对战,电脑偷偷调用某个行动的时候,我们把它的行为打印,甚至改变,来帮助我们实现我们的想法)。
但是不能影响原来函数的操作,我们在插入函数运行结束后,再将目标函数被去掉的头部还给它,然后在指回去:
然而,在驱动编程的时候,我们往往这样做:http://www.cnblogs.com/Safe3/archive/2008/10/20/1315381.html
HOOK:
KIRQL Irql; //开始inline hook //关闭内存写保护 _asm { push eax mov eax, cr0 mov CR0VALUE, eax and eax, 0fffeffffh mov cr0, eax pop eax } //提升IRQL中断级 Irql=KeRaiseIrqlToDpcLevel(); //函数开头五个字节写JMP RtlCopyMemory((BYTE *)NtOpenProcess,JmpAddress,5); //恢复Irql中断级 KeLowerIrql(Irql); //开启内存写保护 __asm { push eax mov eax, CR0VALUE mov cr0, eax pop eax }
UnHook:
//把五个字节再写回到原函数 KIRQL Irql; //关闭写保护 _asm { push eax mov eax, cr0 mov CR0VALUE, eax and eax, 0fffeffffh mov cr0, eax pop eax } //提升IRQL到Dpc Irql=KeRaiseIrqlToDpcLevel(); RtlCopyMemory((BYTE *)NtOpenProcess,OriginalBytes,5); KeLowerIrql(Irql); //开启写保护 __asm { push eax mov eax, CR0VALUE mov cr0, eax pop eax }
但是很多时候我们想要的是一个应用级别的dll,而不是内核级别的sys,可以这样:http://blog.sina.com.cn/s/blog_802a13bc0100qyol.html
同样想实现这个流程,但是在应用级别,没有权限调用cr0,应用级别,可以用这个来做:
HOOK:
void HookOn() { HANDLE hProc; DWORD dwIdOld = GetCurrentProcessId(); // 得到所属进程的ID // 得到所属进程的句柄 hProc = OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); // 修改所属进程中MessageBoxA的前5个字节的属性为可写 VirtualProtectEx(hProc,NtOpenProcess,5,PAGE_READWRITE,&dwIdOld); // 将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA WriteProcessMemory(hProc,NtOpenProcess,JmpAddress,5,0); //RtlCopyMemory((BYTE *)NtOpenProcess,JmpAddress,5); // 修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 VirtualProtectEx(hProc,NtOpenProcess,5,dwIdOld,&dwIdOld); bHook=true; }UnHook:
void HookOff() { HANDLE hProc; DWORD dwIdOld = GetCurrentProcessId(); // 得到所属进程的ID hProc = OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); VirtualProtectEx(hProc,NtOpenProcess,5,PAGE_READWRITE,&dwIdOld); WriteProcessMemory(hProc,NtOpenProcess,OriginalBytes,5,0); //RtlCopyMemory((BYTE *)NtOpenProcess,OriginalBytes,5); VirtualProtectEx(hProc,NtOpenProcess,5,dwIdOld,&dwIdOld); bHook = false; }有个比较赞的地方:拷贝一个函数体几个字节到指定空间
_asm
{
pushad //将EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI这8个指令压栈,保存现场
lea edi,OldMessageBoxACode //edi存放的是想要将数据移动到的目标地址,也就是OldMessageBoxACode
mov esi,fpMessageBoxA //esi存放的是数据存放的源地址
cld //cld是来控制重复移动时候的esi 和edi的递增方式。 cld是将方向标志位DF设置为0,每次rep循环的时候,esi和edi自动+1。 std是将方向标志位DF设置为1,每次rep循环的时候,esi和edi自动-1。
movsd //移动字节数,movsd是DWORD,movsw是WORD,movsb是BYTE
movsb
popad //将EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI这8个指令弹出,还原现场
}
参考:http://blog.csdn.net/zhenyongyuan123/article/details/8364011
http://blog.csdn.net/flowshell/article/details/6094184 http://blog.csdn.net/feixiaoxing/article/details/7009911
接下来需要做的:
完整写一个实例。
如何将DLL注入到指定程序:http://blog.csdn.net/beanjoy/article/details/8497307
相关文章推荐
- Inline Hook NtQueryDirectoryFile
- Inline Hook NtQueryDirectoryFile
- Inline Hook NtQueryDirectoryFile
- 详谈内核三步走Inline Hook实现
- Ring 0 Inline Hook
- Inline Hook 之(监视任意函数)
- 【原创】详谈内核三步走Inline Hook实现
- SSDT Hook的妙用-对抗ring0 inline hook
- SSDT Hook的妙用-对抗ring0 inline hook
- Inline hook KeyboardClassServiceCallback实现键盘记录
- Android Arm Inline Hook
- 详谈内核三步走Inline Hook实现
- C++ Inline Hook 代码
- Android Inline Hook
- Inline Hook IofCallDriver 截获所有IRP
- 小试X64 inline HOOK,hook explorer.exe--->CreateProcessInternalW监视进程创建
- Inline Hook IofCallDriver 截获所有IRP
- rootkit hook之[三] inline hook
- SSDT Hook的妙用-对抗ring0 inline hook
- SSDT Hook的妙用-对抗ring0 inline hook