- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
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 |
|