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方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TorchVision中通过AlexNe
- 下一篇: 使用Windows7上的VS Code打