首页
社区
课程
招聘
[旧帖] [原创][原创]抽丝剥茧Inline Hook 学习笔记 0.00雪花
发表于: 2011-12-20 11:11 1832

[旧帖] [原创][原创]抽丝剥茧Inline Hook 学习笔记 0.00雪花

2011-12-20 11:11
1832
// InlinkHook.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "windows.h"

//抽丝剥茧Inline Hook 学习笔记

//网上有很多inline hook 的例子,但是都是嵌在大量代码中,而且基本没有对inline hook 代码进行详细解释
//我刚学的时候对很多东西都很陌生,忽然明白了,觉得应该写点东西给还不会的人
//写的不好的地方请别见笑

// 首先我们不hook 系统的函数,我们自己写个函数进行一下hook 这样才比较清晰

void add(int a,int b)
{
        printf("加法的结果:%d",a+b);

}

void sub(int a,int b)
{
        printf("减法的结果%d",a-b);
}

//我们把对自己函数的hook封装在这个函数里
void my_simple_hook()
{
        //首先我们要对某个函数进行hook  ,肯定要获取他的地址
        DWORD addr_old = (DWORD)add;
        //获取我们要进行hook 替换的函数
        DWORD addr_new= (DWORD)sub;
        //接下来,我想我们因该看一下汇编代码了,看看call add函数的时候干了什么事情
        //首先进行函数参数压站 然后call add(4110Dh)
        //***这里有2张图片不知道怎么传上来**//
//4110DCh 后 用了一个jmp 指令 跳转到add 处 ==》这里我不明白为什么不直接call 到函数 ,知道的告诉一下

//学过汇编因该知道 jmp 指令 占5  字节  就是说我们定位到这里 修改jmp 的地址就可以进行hook
//解释下:这里为什么用addr_new – addr_old -5
//jmp 取地址 其实不是真正的函数地址,而是他们某个地址的相对偏移
// 2个函数 地址想减就是他们之间的相对偏移
//-5 是干什么的:因为jmp 指令时5字节的

*(LPBYTE)addr_old = 0xE9; //0xE9是jmp的机器码
*(LPWORD)(addr_old +1) = (DWORD)(addr_new – addr_old - 5);

}

//下面进行一下测试
int _tmain(int argc, _TCHAR* argv[])
{
        ///hook();
        //现在我们来调用一下系统的FindWindowA
        //FindWindowA(NULL,"calc.exe");
        my_simple_hook();
        add(10,20);

        return 0;
}
//呵呵报错了,为什么呢?
//大家知道我们操作系统运行在保护模式下,内存怎么能随意修改呢
//但是Microsoft 为我们提供了解决方案 :VirtualProtect函数可以修改指定内存的权限

//修改后的因该是这样

void my_simple_hook()
{
        //首先我们要对某个函数进行hook  ,肯定要获取他的地址
        DWORD addr_old = (DWORD)add;
        //获取我们要进行hook 替换的函数
        DWORD addr_new= (DWORD)sub;
       
        MEMORY_BASIC_INFORMATION mbi;
        VirtualProtect((LPVOID)addr_old,5,PAGE_EXECUTE_READWRITE,&(mbi.Protect));

        *(LPBYTE)addr_old = 0xE9;
        *(LPDWORD)(addr_old+1) = (DWORD)(addr_new- addr_old -5);

}

//结果:我们执行的时加法,却运行了我们的加法

///////////////////////////////////////////////////////////////////////////
///如果上面你理解了,那下面你就可以进行hook 系统函数来完成某个功能了
//目标函数是 FindWindowA

//同样我们需要写 自己的FindWindowA 用来替换系统函数
HWND My_FindWindowA(LPCSTR clsName,LPCSTR winName)
{
        //对我们的计算器程序进行保护
        if(strcmp(winName,"无标题 – 记事本") == 0)
        {
                MessageBoxA(NULL,"被hook了","title",MB_OK);
               
        }
//这里我直接全部返回NULL 其实是不正确的
//我们达到自己目的的同时一定要确保不破坏其他程序正常运行
//因该再次调用原FindWindow 但是这个函数被HOOK 了 ,所以因该先保存原函数地址 然后重新调用
        return NULL;
}

void hook()
{
        HMODULE hModule = LoadLibraryA("user32.dll");
        //获取源FindWindowA的地址
        DWORD addr_old = (DWORD)GetProcAddress(hModule,"FindWindowA");
        //获取自己的FindWindowA的地址
        DWORD addr_new = (DWORD)My_FindWindowA;
       
        //修改系统那个函数的前五个字节的属性为可读写可执行

        MEMORY_BASIC_INFORMATION mbi;
        VirtualProtect((LPVOID)addr_old,5,PAGE_EXECUTE_READWRITE,&(mbi.Protect));

        //使用间接寻址修改原函数前个字节

        *(LPBYTE)addr_old= 0xE9;   //0xE9 对应的汇编指令时JMP

        *(LPDWORD)(addr_old+1) = (DWORD)(addr_new - addr_old - 5);

       
}

//进行下测试
int _tmain(int argc, _TCHAR* argv[])
{
       
        //my_simple_hook();
        //add(10,20);
hook();
FindWindowA(NULL,”无标题 – 记事本”);

        return 0;
}

//运行结果

//不好意思,本来有几张截图,不知道怎么传上来
//教程到这里就结束了,自学点东西不容易,说的不对的地方请指教,希望对还不会的人有帮助

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 39
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
浅显易懂。
2011-12-20 11:32
0
雪    币: 409
活跃值: (182)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
不错很容易理解!
2011-12-20 11:42
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
我懂的东西太少,看完后有点晕。
2011-12-20 14:34
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
“因该再次调用原FindWindow 但是这个函数被HOOK 了 ,所以因该先保存原函数地址 然后重新调用“不矛盾么
2012-11-13 21:51
0
雪    币: 154
活跃值: (91)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
6
其实很多Inline Hook的文章,都用JMP的5字节来做讲解,我感觉这样会更让新手头大。。。特别是我这种只上过小学的人来说,开始的时候那个偏移、RVA啊,为什么要-5啊,全部不懂。。。然后就头大的抄啊抄的。。。
其实对新手,我感觉用JMP DWORD PTR:[xxx]给新手看不是更容易理解么。。。
2012-11-13 23:22
0
雪    币: 6366
活跃值: (4336)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
7
我是新手,我头大
2012-11-14 11:41
0
游客
登录 | 注册 方可回帖
返回
//