Hook即钩子,截获API调用的技术,是将执行流程重定向到你自己的代码,类似于hack。如使程序运行时调用你自己实现的malloc函数代替调用系统库中的malloc函数。这里介绍下Linux下C++中可使用的3中Hook方法:

1. GNU C库允许你通过指定适当的钩子函数(hook function)来修改malloc、realloc和free的行为,钩子函数的声明在malloc.h文件中,如__malloc_hook, __free_hook,你可以使用这些钩子来帮助你调试使用动态内存分配的程序,但是用GCC编译时会提示这些接口已被废弃。

测试代码如下:

#include <malloc.h>
#include <stdio.h>/* reference:http://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.htmlhttps://stackoverflow.com/questions/11356958/how-to-use-malloc-hook
*/
void* (*old_malloc_hook)(size_t, const void*);
void (*old_free_hook)(void* __ptr, const void*);
void my_free_hook(void* ptr, const void* caller);void* my_malloc_hook(size_t size, const void* caller)
{void *result;// Restore all old hooks__malloc_hook = old_malloc_hook;__free_hook = old_free_hook;// Call recursivelyresult = malloc(size);// Save underlying hooksold_malloc_hook = __malloc_hook;old_free_hook = __free_hook;// printf might call malloc, so protect it too.printf("malloc (%u) returns %p\n", (unsigned int) size, result);// Restore our own hooks__malloc_hook = my_malloc_hook;__free_hook = my_free_hook;return result;
}void my_free_hook(void *ptr, const void *caller)
{// Restore all old hooks__malloc_hook = old_malloc_hook;__free_hook = old_free_hook;// Call recursivelyfree(ptr);// Save underlying hooksold_malloc_hook = __malloc_hook;old_free_hook = __free_hook;// printf might call free, so protect it too.printf("freed pointer %p\n", ptr);// Restore our own hooks__malloc_hook = my_malloc_hook;__free_hook = my_free_hook;
}void my_init(void)
{old_malloc_hook = __malloc_hook;old_free_hook = __free_hook;__malloc_hook = my_malloc_hook;__free_hook = my_free_hook;
}int main()
{my_init();void* p = malloc(10);free(p);fprintf(stdout, "test finish\n");return 0;
}

build.sh内容如下:

#! /bin/bashg++ test.cpp
echo -e "**** start run ****\n"
./a.out

执行结果如下:

2. 使用LD_PRELOAD环境变量:可以设置共享库的路径,并且该库将在任何其它库之前加载,即这个动态库中符号优先级是最高的。如果系统库函数使用内联优化,如strcmp,则在编译程序时,可能需添加-fno-builtin-strcmp。

      测试代码test.cpp如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>int main()
{srand(time(NULL));for (int i = 0; i < 2; ++i)fprintf(stdout, "value: %02d\n", rand() % 100);const char* str1 = "https://blog.csdn.net/fengbingchun";const char* str2 = "https://github.com/fengbingchun";fprintf(stdout, "are they equal: %d\n", strcmp(str1, str2));fprintf(stdout, "test finish\n");return 0;
}

      测试代码hook.cpp如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>int rand()
{fprintf(stdout, "_^_ set rand function to a constant: 88 _^_\n");return 88;
}int strcmp(const char* str1, const char* str2)
{fprintf(stdout, "_^_ set strcmp function to a constant: 0 _^_\n");return 0;
}

      build.sh内容如下:

#! /bin/bashg++ -shared -fPIC -o libhook.so hook.cpp
g++ test.cpp
echo -e "**** start run ****\n"
LD_PRELOAD=${PWD}/libhook.so ./a.out

      执行结果如下:

      3. 使用GCC的--wrap选项:对symbol使用包装函数(wrapper function),任何对symbol未定义的引用(undefined reference)会被解析成__wrap_symbol,而任何对__real_symbol未定义的引用会被解析成symbol。即当一个名为symbol符号使用wrap功能时,程序中任何用到symbol符号的地方实际使用的是__wrap_symbol符号,任何用到__real_symbol的地方实际使用的是真正的symbol。注意:当__wrap_symbol是使用C++实现时,一定要加上extern “C”,否则将会出现”undefined reference to __wrap_symbol”。

      测试代码test.cpp如下:

#include <stdio.h>
#include <stdlib.h>extern "C" {void* __real_malloc(size_t size);
void __real_free(void* ptr);
extern void foo();
void __real_foo();void* __wrap_malloc(size_t size)
{fprintf(stdout, "_^_ call wrap malloc function _^_\n");return __real_malloc(size);
}void __wrap_free(void* ptr)
{fprintf(stdout, "_^_ call wrap free function _^_\n");__real_free(ptr);
}void __wrap_foo()
{fprintf(stdout, "_^_ call wrap foo function _^_\n");
}} // extern "C"int main()
{foo();__real_foo();void* p1 = malloc(10);free(p1);fprintf(stdout, "test finish\n");return 0;
}

      测试代码foo.cpp如下:

#include <stdio.h>extern "C" {void foo()
{fprintf(stdout, "call foo function\n");
}} // extern "C"

      build.sh内容如下:

#! /bin/bashg++ foo.cpp test.cpp -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--wrap=foo
echo -e "**** start run ****\n"
./a.out

      执行结果如下:

      Windwos上的Hook是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其它进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理Windows消息或特定事件。钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。

      GitHub:https://github.com/fengbingchun/Linux_Code_Test

Linux下C++中可使用的3种Hook方法相关推荐

  1. linux 设备数 of,linux下devicetree中惯用的of函数

    linux下devicetree中常用的of函数 从device_node中获取信息: int of_property_read_u8_array(const struct device_node * ...

  2. [转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法

    [转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法 参考文章: (1)[转] linux下shell ...

  3. Linux下 QT中 log4cplus 最基本配置及使用

    Linux下 QT中 log4cplus 最基本配置及使用 鉴于网上很多使用方法不是很详细,对小白不友好,并且以此作为记录,方便下次配置. 本文是基于我自己下载的版本写的,请各位根据自己下载的版本更改 ...

  4. Linux下scp无密码上传 下载 文件 目录的方法

    这篇文章主要介绍了Linux下scp无密码上传 下载 文件 目录的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在Linux下远程备份的时候,需要配置scp的 无密码复制文件.目录.就把这个 ...

  5. Linux 下查看某一个程序所使用的内存方法介绍

    Linux 下查看某一个程序所使用的内存方法介绍 在 Linux 上进行开发和运营维护的时候,免不了要查看某一个程序所占用内存的情况.常用方法总结如下(注意第四种方法): 第一种:ps -aux | ...

  6. linux 网络路径中网络协议栈有几种,linux网络路径中网络协议栈有几种

    网络路径有很多种,其中的linux网络路径是最常用的,也是最需要关注的.linux网络路径中网络协议栈有几种?电脑新装系统漏洞应不应该修复?了解网络安全常识,首先就要了解计算机网络安全有哪些基本注意事 ...

  7. linux程序运行段错误,Linux下的段错误产生的原因及调试方法

    Linux下的段错误产生的原因及调试方法 简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址. 一般来 说,段错误就是指访问的内存超出 ...

  8. linux下grep同时匹配多个单词,Linux下使用grep命令搜索多个单词的方法

    摘要 腾兴网为您分享:Linux下使用grep命令搜索多个单词的方法,篆刻字典,中国知网,虚拟机,微博等软件知识,以及掌上公交app,尚书ocr,汇博企业,强密码,支付宝,mh,海融易,我的世界火影忍 ...

  9. linux下查看文件的权限,Linux下查看文件权限、修改文件权限的方法

    查看权限命令查看目录的相关权限可以采用命令ls -lD,或者直接用ls -la 如 ls -l www.jb51.net  //这里表示查看www.jb51.net目录 修改权限命令 chmod 77 ...

最新文章

  1. 6招识破翻新iPhone
  2. 使用tab键分割的文章能快速转换成表格。( )_无需按空格键,就能将Word文字对齐,3种方法了解一下...
  3. PMP知识点(七、资源管理)
  4. 登陆xp系统,无法显示桌面
  5. php datetime 对象,PHP DateTime 对象和 Date 函数的 Demo
  6. C++ delete删除动态分配的内存
  7. WinForm与WPF下跨线程调用控件
  8. MyBaits动态sql语句
  9. python json转换与处理
  10. 求求你了,不要再自己实现这些逻辑了,开源工具类不香吗?
  11. 存储ic载板_【行业亮点】看好载板供不应求趋势,深南/兴森/越亚积极布局
  12. 开源物联网云平台 Thingsboard入门
  13. python安装win32com模块
  14. golang读取EXIF orientation标记
  15. 求不规则立方体表面积java_求立方体的体积、表面积(c++)
  16. 诺顿杀毒软件22010最新注册码
  17. 杂记——贝叶斯可信区间与频率置信区间的区别
  18. Oracle analytics server(OAS) 支持 mysql 社区版配置
  19. 百川云旺客服申请测试流程
  20. 60 Linux 常用 命令

热门文章

  1. OpenCV中的特征匹配+单应性以查找对象
  2. 机器学习(实战)facebook地址预测
  3. Windows下PCL1.9.1配置(编译源码)
  4. 剑指offer:面试题17. 打印从1到最大的n位数
  5. div自己移除自己/移除div下面的所有子元素
  6. 【1】用命令行搭建Vue项目
  7. addEventListener()与removeEventListener()
  8. Tafficserver旁路接入方案综述
  9. LINUX UMASK详解
  10. Linux系统文本命令快速登录与退出