看流星社区

 找回密码
 注册账号
查看: 4256|回复: 0

Mhook_SetHook函数流程

[复制链接]

该用户从未签到

发表于 2015-4-15 15:42:16 | 显示全部楼层 |阅读模式
1.EnterCritSec 互斥进入关键Section

2.SkipJumps 查找 被HOOK函数 或者 HOOK函数的真实入口地址,通过判断函数地址前几个字节是为JMP,机器码为E9/FF25/EB
E9+32位偏移 FF25+绝对地址 EB+8位偏移

3.DisassembleAndSkip 函数 在被HOOK函数中查找修改的地址和长度,过滤RET  JMP/JNE...分支,CALL等指令

4.SuspendOtherThreads 函数 挂起该进程所有线程 ----->SuspendOneThread 通过GetThreadContext获取每个线程的上下文,检查线程是否执行着 被HOOK函数中需要被修改地址的指令,如果是则ResumeThread该线程,令该线程执行过那些指令,然后再挂起该线程,而本线程Sleep一下。

5.TrampolineAlloc 查找分配存储inline信息块的进程虚拟空间

6.通过VirtualProtectEx修改被HOOK函数的虚拟地址页属性,也设置存储inline信息块的空间的页属性,令其为可执行的,因为inline信息块中保存了被HOOK函数被修改的指令和再跳转到被HOOK函数的被修改的地址后的指令。

7.设置inline信息块
struct MHOOKS_TRAMPOLINE {
        PBYTE        pSystemFunction;        //被HOOK的函数地址                               
        DWORD        cbOverwrittenCode;        //需要在被HOOK函数的改写的指令长度                       
        PBYTE        pHookFunction;                //我们的HOOK函数地址                                       
        BYTE        codeJumpToHookFunction[MHOOKS_MAX_CODE_BYTES];//跳转到我们的HOOK函数的指令
        BYTE        codeTrampoline[MHOOKS_MAX_CODE_BYTES];        //跳转到被HOOK函数修改后的指令
        BYTE        codeUntouched[MHOOKS_MAX_CODE_BYTES];        //被修改的指令       
};

7.1 首先把被HOOK函数需要被修改的指令保存在codeUntouched数组中,也保存在codeTrampoline数组中

7.2 然后在codeTrampoline后面加上跳转到原来修改后HOOK函数的指令,通过EmitJump函数完成,从当前codeTrampoline地址跳到修改后HOOK函数的地址,通过地址比较,如果是小于等于0x7fff0000,则用E9+32位偏移,反之,用FF25 + 绝对地址。

7.3 再设置跳转到我们的HOOK函数的指令保存在codeJumpToHookFunction数组,比较被HOOK函数和HOOK函数的真实入口地址,也是通过EmitJump完成。

7.4 FlushInstructionCache 修改指令

8.更新所谓原来被HOOK函数的地址为codeTrampoline,因为codeTrampoline保存了被修改的指令和跳转到原来修改后HOOK函数的指令。

9.ResumeOtherThreads重起所有挂起的线程

10.LeaveCritSec 离开关键Section
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-28 16:47

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表