Linux下C++中可使用的3种Hook方法

x33g5p2x  于2021-12-05 转载在 C/C++  
字(4.2k)|赞(0)|评价(0)|浏览(439)

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

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

    测试代码如下:

  1. #include <malloc.h>
  2. #include <stdio.h>
  3. /* reference:
  4. http://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html
  5. https://stackoverflow.com/questions/11356958/how-to-use-malloc-hook
  6. */
  7. void* (*old_malloc_hook)(size_t, const void*);
  8. void (*old_free_hook)(void* __ptr, const void*);
  9. void my_free_hook(void* ptr, const void* caller);
  10. void* my_malloc_hook(size_t size, const void* caller)
  11. {
  12. void *result;
  13. // Restore all old hooks
  14. __malloc_hook = old_malloc_hook;
  15. __free_hook = old_free_hook;
  16. // Call recursively
  17. result = malloc(size);
  18. // Save underlying hooks
  19. old_malloc_hook = __malloc_hook;
  20. old_free_hook = __free_hook;
  21. // printf might call malloc, so protect it too.
  22. printf("malloc (%u) returns %p\n", (unsigned int) size, result);
  23. // Restore our own hooks
  24. __malloc_hook = my_malloc_hook;
  25. __free_hook = my_free_hook;
  26. return result;
  27. }
  28. void my_free_hook(void *ptr, const void *caller)
  29. {
  30. // Restore all old hooks
  31. __malloc_hook = old_malloc_hook;
  32. __free_hook = old_free_hook;
  33. // Call recursively
  34. free(ptr);
  35. // Save underlying hooks
  36. old_malloc_hook = __malloc_hook;
  37. old_free_hook = __free_hook;
  38. // printf might call free, so protect it too.
  39. printf("freed pointer %p\n", ptr);
  40. // Restore our own hooks
  41. __malloc_hook = my_malloc_hook;
  42. __free_hook = my_free_hook;
  43. }
  44. void my_init(void)
  45. {
  46. old_malloc_hook = __malloc_hook;
  47. old_free_hook = __free_hook;
  48. __malloc_hook = my_malloc_hook;
  49. __free_hook = my_free_hook;
  50. }
  51. int main()
  52. {
  53. my_init();
  54. void* p = malloc(10);
  55. free(p);
  56. fprintf(stdout, "test finish\n");
  57. return 0;
  58. }

   build.sh内容如下:

  1. #! /bin/bash
  2. g++ test.cpp
  3. echo -e "**** start run ****\n"
  4. ./a.out

    执行结果如下:


 

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

**     **测试代码test.cpp如下:

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

**     **测试代码hook.cpp如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int rand()
  5. {
  6. fprintf(stdout, "_^_ set rand function to a constant: 88 _^_\n");
  7. return 88;
  8. }
  9. int strcmp(const char* str1, const char* str2)
  10. {
  11. fprintf(stdout, "_^_ set strcmp function to a constant: 0 _^_\n");
  12. return 0;
  13. }

**     **build.sh内容如下:

  1. #! /bin/bash
  2. g++ -shared -fPIC -o libhook.so hook.cpp
  3. g++ test.cpp
  4. echo -e "**** start run ****\n"
  5. 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如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. extern "C" {
  4. void* __real_malloc(size_t size);
  5. void __real_free(void* ptr);
  6. extern void foo();
  7. void __real_foo();
  8. void* __wrap_malloc(size_t size)
  9. {
  10. fprintf(stdout, "_^_ call wrap malloc function _^_\n");
  11. return __real_malloc(size);
  12. }
  13. void __wrap_free(void* ptr)
  14. {
  15. fprintf(stdout, "_^_ call wrap free function _^_\n");
  16. __real_free(ptr);
  17. }
  18. void __wrap_foo()
  19. {
  20. fprintf(stdout, "_^_ call wrap foo function _^_\n");
  21. }
  22. } // extern "C"
  23. int main()
  24. {
  25. foo();
  26. __real_foo();
  27. void* p1 = malloc(10);
  28. free(p1);
  29. fprintf(stdout, "test finish\n");
  30. return 0;
  31. }

**     **测试代码foo.cpp如下:

  1. #include <stdio.h>
  2. extern "C" {
  3. void foo()
  4. {
  5. fprintf(stdout, "call foo function\n");
  6. }
  7. } // extern "C"

**     **build.sh内容如下:

  1. #! /bin/bash
  2. g++ foo.cpp test.cpp -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--wrap=foo
  3. echo -e "**** start run ****\n"
  4. ./a.out

**     **执行结果如下:


 

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

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

相关文章

最新文章

更多