行业动态

防御吧作为15年知名老牌域名服务商,CNNIC和CANN双认证域名注册商,已经
持续为500多万个域名提供服务,包括智能DNS/自由转移/隐私保护等服务!
反外挂揭秘:hook技术
2021-09-23 14:25:35 【

hook 介绍

hook英文意思是钩子,hook可以在程序已经编译成bin文件,甚至执行时,修改函数流程。先上一段简单代码,让大家对hook有个简单认识。

#define XX_JMP_OPCODE  0xE9#pragma pack(push, 1)struct xxhook_jmp32 {  uint8_t opcode ;  int32_t offset;};#pragma pack(pop)// 设置钩子static bool xx_setjmp(void* src, void* dst) {  xxhook_jmp32* jmp = (xxhook_jmp32*)src;  jmp->opcode = 0xE9;    jmp->offset = (char*)dst - ((char*)src + sizeof(xxhook_jmp32)) ;  return true;}

例子1:hook 用户函数

void func1() {  printf("func1\n");}void func2() {  printf("func2\n");}void test_hook_my_func() {  func1();  // 使代码区可写  DWORD old_pro = 0;  BOOL ret = VirtualProtect(&func1, 4096, PAGE_EXECUTE_READWRITE, &old_pro);  // hook!  xx_setjmp(&func1, &func2);  func1();}

执行后输出

func1func2


例子2:hook C函数

static __inline time_t __CRTDECL my_time(_Out_opt_ time_t* const _Time) {  return 1234;}void test_hook_cfunc() {  printf("time=%u\n",time(NULL));  DWORD old_pro = 0;  BOOL ret = VirtualProtect(&time, 4096, PAGE_EXECUTE_READWRITE, &old_pro);  xx_setjmp(&time, &my_time);  printf("time=%u\n", time(NULL));}

输出

time=1632322864time=1234


可以看出,函数的执行逻辑已经改变了。


hook代码解析

hook的本质,就是修改原代码,在跳转到我们的函数,我们对比一下例子2中hook前后的time函数汇编代码变化。

hook前

        static __inline time_t __CRTDECL time(            _Out_opt_ time_t* const _Time            )        {00007FF6DA4B1290 48 89 4C 24 08       mov         qword ptr [rsp+8],rcx  00007FF6DA4B1295 48 83 EC 28          sub         rsp,28h              return _time64(_Time);00007FF6DA4B1299 48 8B 4C 24 30       mov         rcx,qword ptr [_Time]  00007FF6DA4B129E FF 15 FC 1E 00 00    call        qword ptr [__imp__time64 (07FF6DA4B31A0h)]          }00007FF6DA4B12A4 48 83 C4 28          add         rsp,28h  00007FF6DA4B12A8 C3                   ret

hook后

        static __inline time_t __CRTDECL time(            _Out_opt_ time_t* const _Time            )        {00007FF6DA4B1290 E9 AB FD FF FF       jmp         my_time (07FF6DA4B1040h)  00007FF6DA4B1295 48 83 EC 28          sub         rsp,28h              return _time64(_Time);00007FF6DA4B1299 48 8B 4C 24 30       mov         rcx,qword ptr [_Time]  00007FF6DA4B129E FF 15 FC 1E 00 00    call        qword ptr [__imp__time64 (07FF6DA4B31A0h)]          }00007FF6DA4B12A4 48 83 C4 28          add         rsp,28h  00007FF6DA4B12A8 C3                   ret

可以看出,函数第一行就是跳转到我们的函数的jump语句。

我们再来回顾一下修改的代码,12行就是赋值0xe9代表是跳转语句,接下来4个字节就是跳转的offset,公式为:dst-(src+5)。5是本条jmp语句的长度。

#define XX_JMP_OPCODE  0xE9#pragma pack(push, 1)struct xxhook_jmp32 {  uint8_t opcode ;  int32_t offset;};#pragma pack(pop)static bool xx_setjmp(void* src, void* dst) {  xxhook_jmp32* jmp = (xxhook_jmp32*)src;  jmp->opcode = 0xE9;  jmp->offset = (char*)dst - ((char*)src + sizeof(xxhook_jmp32)) ;  return true;}


hook技术看这一篇为什么不够

有一些问题我们还没解决

  • 原函数已经被破坏,第一句改成了jmp,如果还想调用原函数怎么办?

  • 64bit操作系统,如果原函数和目标函数的offset超过uint32-max怎么办?

  • hook时,有线程正在执行此函数怎么办?

  • linux如何hook?

  • hook还有哪些用处?



】【打印关闭】 【返回顶部
分享到QQ空间
分享到: 
上一篇提升DNS安全 限制DDoS攻击 下一篇如何设置 CC 防护?

立足首都,辐射全球,防御吧专注云防御及云计算服务15年!

联系我们

服务热线:010-56157787 ,010-56159998
企业QQ:4000043998
技术支持:010-56159998
E-Mail:800@fangyuba.com
Copyright ? 2003-2016 fangyuba. 防御吧(完美解决防御与加速) 版权所有 增值许可:京B2-20140042号
售前咨询
公司总机:4000043998 01056155355
24小时电话:010-56159998
投诉电话:18910191973
值班售后/技术支持
售后服务/财务
备案专员
紧急电话:18610088800