【原创】抽丝剥茧InlineHook
这是一篇我自己学习InlineHook的笔记,网上代码很多,但都没详细解释细节,于是了这篇文章算是给自己复习用.自学编程,有不对的地方请指正.
//首先我们不Hook系统API函数,写2个函数一个加法,一个减法。
int add(int a,int b)
{
printf("这里是加法");
return a+b;
}
int sub(int a,int b)
{
printf("这里是减法");
return a-b;
}
//把hook 操作封装在这个函数下
void Inlinehook()
{
//取到2个函数地址
DWORD addrAdd= (DWORD)add;
DWORD addrSub =(DWORD)sub;
*(BYTE *)addrAdd = 0xE9; //!!!!!
*(DWORD *)addrAdd = (DWORD) (addrSub - addrAdd - 5);//!!!!!
//下面通过调试一个函数看看上面2步的意思
//void main()
//{
// add(10,20); 这里下断点进行调试 ==》转到反汇编
//}
//004115B5 push 20 ==>跟进
//004115B7 push 10 ==>跟进
//004115B9 call add (4110A0h) ==>跟进 调用add函数
//004110A0 jmp add (4113E0h) ==>jmp 到add 地址
//看到了吗?
//函数首5字节是jmp指令, jmp xxxx , jmp 的机器码为:0xE9 ,
//剩下的4个字节是相对偏移地址 计算方式:【我们的函数地址 - 被hook函数地址 - 5】
//那么-5 干什么,因为jmp指令要占用5个字节
}
//开始写程序测试下 ,看看调用 add 函数能不能进入sub函数
void main()
{
add(10,20);
}
//运行是不是报错了?因为我们是跑在保护模式下的,内存是不能随意改变的
//因此需要改变内存的保护属性改为PAGE_EXECUTE_READWRITE
//把Inlinehook 函数改成下面形式
void Inlinehook()
{
DWORD addrAdd= (DWORD)add;
DWORD addrSub =(DWORD)sub;
//修改add函数0偏移处5字节为PAGE_EXECUTE_READWRITE
MEMORY_BASIC_INFORMATION mbi;
VirtualProtect((LPVOID)addrAdd,5,PAGE_EXECUTE_READWRITE,&(mbi.Protect));
*(BYTE *)addrAdd = 0xE9;
*(DWORD *)addrAdd = (DWORD) (addrSub - addrAdd - 5);
}
//再次测试下
void main()
{
add(10,20);
//输出结果为:这里是减法
}
//结果成功进入sub函数 说明InlineHook成功了
//*********************************************如果上面你能成功测试,就可以去hook一下系统api了,**************************************************
//测试函数FindWindowA,原理是一样的我就不赘述了
贴上代码
#include "stdafx.h"
#include "windows.h"
#include "Winnt.h"
struct FIVE
{
unsigned int first;
unsigned long four;
}five;
typedef HWND (*RealFindWindowA)(LPCSTR clsName,LPCSTR winName);
RealFindWindowA realFindWindowA;
DWORD g_old_addr;
HWND My_FindWindowA(LPCSTR clsName,LPCSTR winName)
{
*(BYTE *)g_old_addr = (BYTE)five.first;
*(DWORD *)(g_old_addr+1) = (DWORD)five.four;
realFindWindowA = (RealFindWindowA)g_old_addr;
if(strcmp(winName,"无标题 - 记事本") ==0)
{
MessageBoxA(NULL,"FindWindowA被成功InlineHook","xx",MB_OK);
return (HWND)-1;
}
return realFindWindowA(clsName,winName);
}
void main()
{
DWORD addr = (DWORD)add;
DWORD old_addr = (DWORD)GetProcAddress(LoadLibraryA("user32.dll"),"FindWindowA");
g_old_addr = old_addr;
DWORD my_addr = (DWORD)My_FindWindowA;
MEMORY_BASIC_INFORMATION mbi;
VirtualProtect((LPVOID)old_addr,5,PAGE_EXECUTE_READWRITE,&(mbi.Protect));
five.first = *(BYTE *)old_addr;
five.four = *(DWORD *)(old_addr+1);
*(LPBYTE)old_addr= 0xE9;
*(LPDWORD)(old_addr+1) = (DWORD)(my_addr-old_addr-5);
FindWindowA(NULL,"无标题 - 记事本");
}
//这些都是简单的操作,毕竟这样的函数都是公开的,对未公开的函数就要定位内存来进行hook了
//有不对的地方请指正
[ 本帖最后由 五当家 于 2011-12-22 13:43 编辑 ]