Linux下C++中可使用的3种Hook方法
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方法相关推荐
- linux 设备数 of,linux下devicetree中惯用的of函数
linux下devicetree中常用的of函数 从device_node中获取信息: int of_property_read_u8_array(const struct device_node * ...
- [转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法
[转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法 参考文章: (1)[转] linux下shell ...
- Linux下 QT中 log4cplus 最基本配置及使用
Linux下 QT中 log4cplus 最基本配置及使用 鉴于网上很多使用方法不是很详细,对小白不友好,并且以此作为记录,方便下次配置. 本文是基于我自己下载的版本写的,请各位根据自己下载的版本更改 ...
- Linux下scp无密码上传 下载 文件 目录的方法
这篇文章主要介绍了Linux下scp无密码上传 下载 文件 目录的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在Linux下远程备份的时候,需要配置scp的 无密码复制文件.目录.就把这个 ...
- Linux 下查看某一个程序所使用的内存方法介绍
Linux 下查看某一个程序所使用的内存方法介绍 在 Linux 上进行开发和运营维护的时候,免不了要查看某一个程序所占用内存的情况.常用方法总结如下(注意第四种方法): 第一种:ps -aux | ...
- linux 网络路径中网络协议栈有几种,linux网络路径中网络协议栈有几种
网络路径有很多种,其中的linux网络路径是最常用的,也是最需要关注的.linux网络路径中网络协议栈有几种?电脑新装系统漏洞应不应该修复?了解网络安全常识,首先就要了解计算机网络安全有哪些基本注意事 ...
- linux程序运行段错误,Linux下的段错误产生的原因及调试方法
Linux下的段错误产生的原因及调试方法 简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址. 一般来 说,段错误就是指访问的内存超出 ...
- linux下grep同时匹配多个单词,Linux下使用grep命令搜索多个单词的方法
摘要 腾兴网为您分享:Linux下使用grep命令搜索多个单词的方法,篆刻字典,中国知网,虚拟机,微博等软件知识,以及掌上公交app,尚书ocr,汇博企业,强密码,支付宝,mh,海融易,我的世界火影忍 ...
- linux下查看文件的权限,Linux下查看文件权限、修改文件权限的方法
查看权限命令查看目录的相关权限可以采用命令ls -lD,或者直接用ls -la 如 ls -l www.jb51.net //这里表示查看www.jb51.net目录 修改权限命令 chmod 77 ...
最新文章
- 6招识破翻新iPhone
- 使用tab键分割的文章能快速转换成表格。( )_无需按空格键,就能将Word文字对齐,3种方法了解一下...
- PMP知识点(七、资源管理)
- 登陆xp系统,无法显示桌面
- php datetime 对象,PHP DateTime 对象和 Date 函数的 Demo
- C++ delete删除动态分配的内存
- WinForm与WPF下跨线程调用控件
- MyBaits动态sql语句
- python json转换与处理
- 求求你了,不要再自己实现这些逻辑了,开源工具类不香吗?
- 存储ic载板_【行业亮点】看好载板供不应求趋势,深南/兴森/越亚积极布局
- 开源物联网云平台 Thingsboard入门
- python安装win32com模块
- golang读取EXIF orientation标记
- 求不规则立方体表面积java_求立方体的体积、表面积(c++)
- 诺顿杀毒软件22010最新注册码
- 杂记——贝叶斯可信区间与频率置信区间的区别
- Oracle analytics server(OAS) 支持 mysql 社区版配置
- 百川云旺客服申请测试流程
- 60 Linux 常用 命令