首页
社区
课程
招聘
[原创]RING3代码HOOK的原理实现 (学习笔记1)
发表于: 2008-12-10 14:13 21520

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

2008-12-10 14:13
21520

最初看见俄国一份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;
}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

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

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

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

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

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

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

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

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

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