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.html
https://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 recursively
result = malloc(size);
// Save underlying hooks
old_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 recursively
free(ptr);
// Save underlying hooks
old_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/bash
g++ 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/bash
g++ -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/bash
g++ 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
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/fengbingchun/article/details/121730082
内容来源于网络,如有侵权,请联系作者删除!