首页
论坛
课程
招聘
[原创]RING3代码HOOK的原理实现 (学习笔记1)
2008-12-10 14:13 19323

[原创]RING3代码HOOK的原理实现 (学习笔记1)

2008-12-10 14:13
19323
最初看见俄国一份DELPHI代码这样实现,他的优点在于
  1, 在代理函数的内部不用先UNHOOK,再调用,再重新HOOK,否则多线程下会出问题
  2, 没有硬编码,结构性比较好。

bool AfxHookCode(void* TargetProc, void* NewProc,void ** l_OldProc, int bytescopy = 5)
{

        DWORD dwOldProtect;

        ::VirtualProtect((LPVOID)TargetProc, bytescopy, PAGE_EXECUTE_READWRITE, &dwOldProtect);

        *l_OldProc = new unsigned char[bytescopy+5];          // 为拷贝执行被覆盖的指令申请空间

        memcpy(*l_OldProc, TargetProc, bytescopy);           // 事先保存被破坏的指令

        *((unsigned char*)(*l_OldProc) + bytescopy) = 0xe9;    // 我的内存的代码执行完 跳到原来的 代码 + 破坏的代码的长度 上去

                                                                                                    //被破坏指令的长度           //E9 opcode长度                                        //算出偏移的OPCODE    = 被HOOK函数地址的地址 + 破坏指令的长度 - 我分配内存的结束地址                                 
    *(unsigned int *)((unsigned char*)(*l_OldProc) +bytescopy          +     1)          =   (unsigned int)(TargetProc) + bytescopy - ( (unsigned int)((*l_OldProc)) + 5 + bytescopy ) ;  // 我内存代码跳到原来代码上的偏移

        *(unsigned char*)TargetProc =(unsigned char)0xe9;             //被HOOK的函数头改为jmp

                                                                                                                                  //算出偏移的OPCODE  = 代理函数地址 - 被HOOK函数地址
        *(unsigned int*)((unsigned int)TargetProc +1) = (unsigned int)NewProc - ( (unsigned int)TargetProc + 5) ; //被HOOK的地方跳到我的新过程 接受过滤

        ::VirtualProtect((LPVOID)TargetProc, bytescopy, dwOldProtect, 0);
        return true;
}

bool AfxUnHookCode(void* TargetAddress, void * l_SavedCode, unsigned int len)
{
                DWORD dwOldProtect;

                ::VirtualProtect((LPVOID)TargetAddress, len, PAGE_EXECUTE_READWRITE, &dwOldProtect);   

                // 恢复被破坏处的指令
                memcpy(TargetAddress, l_SavedCode, len);

                ::VirtualProtect((LPVOID)TargetAddress, len, dwOldProtect, 0);

          return true;
}

unsigned int *  OldProc;
typedef
int
(__stdcall * MYMESSAGEBOX)     //用于调用自己分配内存处的代码强制转换
   (
    IN HWND hWnd,
    IN LPCSTR lpText,
    IN LPCSTR lpCaption,
    IN UINT uType);

int
__stdcall       // 这里不声明成stdcall的话 编译器认为是C声明方式 要自己平衡堆栈  
MyMessageBox(
    IN HWND hWnd,
    IN LPCSTR lpText,
    IN LPCSTR lpCaption,
    IN UINT uType)
{

        // 这里可以执行一些过滤行为 比如改变参数 或者 直接模拟返回正确的结果
        if ( strcmp(lpText, "sample") == 0)
        {
                printf("filter");
                return 1;
        }

      //强制转换成API函数类型 调用原来的函数
   return ( (MYMESSAGEBOX) OldProc)(hWnd, lpText, lpCaption, uType);

}

int main()
{
        MessageBox(0, "sample", "caption", MB_OK);   //正常调用MSG

                                                                // 这里一定要传地址变量的地址  直接传地址的话 地址变量是一份拷贝 根本不能保存分配的内存的地址(在我看来 指针就是地址变量)
                                                                                                                            //当初写的时候调了3遍才知道这个原因- -
        AfxHookCode((void*)MessageBox, (void*)MyMessageBox, (void**)&OldProc, 5);

        MessageBox(0, "sample", "caption", MB_OK);  //被过滤掉了

        AfxUnHookCode((void*)MessageBox, OldProc, 5); // 恢复被hook的代码

        getchar();

        return 0;
}

[培训] 优秀毕业生寄语:恭喜id咸鱼炒白菜拿到远超3W月薪的offer,《安卓高级研修班》火热招生!!!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (28)
雪    币: 250
活跃值: 活跃值 (63)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 活跃值 10 2008-12-10 14:51
2
0
虽然比较老了……不过还是顶下
雪    币: 370
活跃值: 活跃值 (121)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
bzhkl 活跃值 5 2008-12-10 14:57
3
0
谢谢~  
  基础最重要嘛= =  基础懂了 研究别的也就容易了哈
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Xusually 活跃值 2008-12-11 21:04
4
0
别的不说,收藏代码,
顶lz
雪    币: 459
活跃值: 活跃值 (54)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 活跃值 9 2008-12-11 21:07
5
0
header inline太没意思了,又麻烦又容易出问题,指针替换最爽了,又安全又快捷
雪    币: 5398
活跃值: 活跃值 (339)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
lollipop 活跃值 2008-12-11 23:42
6
0
跟MS的Detour差不多吧?
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
clide2000 活跃值 7 2008-12-11 23:46
7
0
还有delphi版的吗?
雪    币: 370
活跃值: 活跃值 (121)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
bzhkl 活跃值 5 2008-12-12 00:46
8
0
to 5楼:  
             1 个人认为这种模式非常方便 看过很多方式HOOK 这种模式很方便 代码结构非常好
             2 这不一定只能用在header 是 CODE HOOK 随便在哪里HOOK 不一定在函数头
当然HOOK API有另外的函数比这个还方便 具体见附件
             另外这种构架用了几年了 用的人多了 没出过问题  = =

to 7楼: 有 在附件 使用方法参考我一楼的吧~
上传的附件:
雪    币: 1
活跃值: 活跃值 (205)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
crazybug 活跃值 2 2008-12-12 10:09
9
0
1.header inline 存在着无法解决的安全性问题,不管如何同步操作,都会导致问题,只是概率较低,你没碰到而已,原因是HOOK的指令不是一条,原理自己去想吧,指针替换就没这个问题

2.用的人多就说明没问题了?微软怎么不推荐用这个呢?

3.比起指针替换,这种HOOK操作起来的繁琐 性、包括多次HOOK、同其他人HOOK的冲突上,都存在很大的弊端

4.如果不在HEADER上,这种HOOK还存在被跳走的可能~所以无法通用

总之CODE INLINE很挫很垃圾~
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
devilfire 活跃值 2008-12-12 10:48
10
0
虽然不懂,也顶一下!
雪    币: 88
活跃值: 活跃值 (151)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
frozenrain 活跃值 2008-12-12 11:26
11
0
标记下,自己上次准备写个全局的,正好学习楼主的代码
雪    币: 395
活跃值: 活跃值 (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
fishjam 活跃值 2008-12-19 21:57
12
0
大概看了一下,个问题没有想懂:
  按照一楼的写法,原函数的头五个字节的汇编必须组成完整的命令,否则汇编命令可能出错,这部是否是Delphi代码中SizeOfProc的起的作用?
雪    币: 123
活跃值: 活跃值 (11)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
qydao 活跃值 2008-12-21 10:23
13
0
大家都各说各的,我认为不错的,初级时只会HOOK——MYAPI——UNHOOK——MYFUN——HOOK,我觉得这个应该高级些,实用!
雪    币: 370
活跃值: 活跃值 (121)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
bzhkl 活跃值 5 2008-12-21 23:39
14
0
bool AfxHookCode(void* TargetProc, void* NewProc,void ** l_OldProc, int bytescopy = 5)

注意看函数声明 = =  第五个是参数 传进去的 可以是7字节 8字节等等 = =
雪    币: 123
活跃值: 活跃值 (11)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
qydao 活跃值 2008-12-24 09:11
15
0
改成全局的出错了,提示内存不能为写,想法可以,我需要进一步调试,哎调试半天还不行,明明都可以,不知道怎么了!
算了不如使用临界区来保护那段内在,不不知道行不!
雪    币: 123
活跃值: 活跃值 (11)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
qydao 活跃值 2008-12-24 15:47
16
0
改成全局的不行,经调试在这一句*((unsigned char*)(*l_OldProc)+bytescopy) = 0xe9;有问题,为什么?
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jhb 活跃值 2009-2-19 02:28
17
0
好,喜欢. 辛苦了。  呵呵。
雪    币: 197
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ben中文 活跃值 2009-2-19 11:13
18
0
能給個指針替換方法的文章鏈接嗎?我google了一下,沒有找到相關的文章。

另外,除了header inline和指針替換之外,還有別的hook方法嗎?

謝謝!
雪    币: 3650
活跃值: 活跃值 (1014)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
sunsjw 活跃值 1 2009-2-20 16:08
19
0
inline hook最好是能有一个小的反汇编引擎.计算出前面几个要hook是多少个字节...
不然的话还是有可能会出错...
雪    币: 326
活跃值: 活跃值 (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
快雪时晴 活跃值 4 2009-2-20 18:42
20
0
TAG:RING3代码HOOK的原理实现 INLINE / HEADER HOOK API SRC 源码 C++ DELPHI
雪    币: 193
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kingcom 活跃值 2009-3-21 12:52
21
0
很多时候没法替换指针的,只能hook函数体。并且微软有个detours库,是官方的实现
雪    币: 601
活跃值: 活跃值 (23)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Second 活跃值 1 2009-11-8 17:46
22
0
哈哈。找了半天,才找到。
收藏了。
雪    币: 231
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
starskywh 活跃值 2009-12-3 11:43
23
0
  我觉着很好.
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhyong 活跃值 2009-12-12 09:24
24
0
楼主能整理一份DELPHI版本的吗,你的思路值得学习!
雪    币: 24
活跃值: 活跃值 (11)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
skymelai 活跃值 2009-12-12 11:43
25
0
什么是指针替换,给讲讲?好像这个方法很利害。
游客
登录 | 注册 方可回帖
返回