您的位置:首页 > 编程语言 > C语言/C++

inline hook【001】

2014-10-11 15:11 351 查看
什么是inline hook呢?图像解释下:



程序本来是要调用左边的目标函数,但是,我们在有没源码的情况下,想要在调用这个函数的时候做点其他事情,就需要插进去我们的函数,这个实现方式就是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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ dll hook