我想攔截應用程序對dlsym的調用,我已經嘗試在.so中聲明我正在預加載dlsym,並使用dlsym本身來獲取它的真實地址,但是由於相當明顯的原因,這種行爲並不起作用。如何攔截使用LD_PRELOAD的dlsym調用?
有沒有一種方法比採取進程的內存映射更容易,並且使用libelf來查找加載的libdl.so中dlsym的真實位置?
我想攔截應用程序對dlsym的調用,我已經嘗試在.so中聲明我正在預加載dlsym,並使用dlsym本身來獲取它的真實地址,但是由於相當明顯的原因,這種行爲並不起作用。如何攔截使用LD_PRELOAD的dlsym調用?
有沒有一種方法比採取進程的內存映射更容易,並且使用libelf來查找加載的libdl.so中dlsym的真實位置?
http://www.linuxforu.com/2011/08/lets-hook-a-library-function/
從文本:
,一定要提防的函數,稱自己的dlsym(),當你需要調用__libc_dlsym(手柄,符號)的鉤。
extern void *__libc_dlsym (void *, const char *);
void *dlsym(void *handle, const char *symbol)
{
printf("Ha Ha...dlsym() Hooked\n");
void* result = __libc_dlsym(handle, symbol); /* now, this will call dlsym() library function */
return result;
}
這似乎是段錯誤,我甚至試圖單獨編譯這個代碼,結果相同 – user1588911 2013-03-24 14:03:07
我碰到了同樣的問題絆倒與hdante的答案,作爲評論者:調用__libc_dlsym()
直接與段錯誤崩潰。閱讀一些glibc的來源後,我想出了下面的技巧作爲一種解決方法:
extern void *_dl_sym(void *, const char *, void *);
extern void *dlsym(void *handle, const char *name)
{
/* my target binary is even asking for dlsym() via dlsym()... */
if (!strcmp(name,"dlsym"))
return (void*)dlsym;
return _dl_sym(handle, name, dlsym);
}
注意兩件事情本「解決方案」:
(__libc_)dlsym()
內部完成鎖定,所以爲了使這個線程安全,你應該添加一些鎖定。_dl_sym()
的第三個參數是調用者的地址,glibc似乎通過堆棧展開來重建此值,但我只是使用函數本身的地址。在內部使用調用者地址來查找調用者所處的鏈接映射,以獲得像RTLD_NEXT
這樣的東西(並且,使用NULL作爲thrid參數將使調用失敗,並使用RTLD_NEXT
時發生錯誤)。然而,我沒有看過glibc的unwindind功能,所以我不能100%確定上面的代碼會做正確的事情,並且它可能恰好偶然發生。解決方案到目前爲止存在一些重大缺點:在某些情況下,_dl_sym()
與預期的dlsym()
的行爲完全不同。例如,試圖解析不存在的符號會退出程序,而不是返回NULL。要解決這個問題,可以使用_dl_sym()
剛剛得到的指針原來dlsym()
和使用,對於其他一切(如在「標準」 LD_PRELOAD
鉤計算策略不掛鉤dlsym
在所有):
extern void *_dl_sym(void *, const char *, void *);
extern void *dlsym(void *handle, const char *name)
{
static void * (*real_dlsym)(void *, const char *)=NULL;
if (real_dlsym == NULL)
real_dlsym=_dl_sym(RTLD_NEXT, "dlsym", dlsym);
/* my target binary is even asking for dlsym() via dlsym()... */
if (!strcmp(name,"dlsym"))
return (void*)dlsym;
return real_dlsym(handle,name);
}
是爲代碼問題的一部分還是答案?你可以編輯你的問題或張貼它作爲答案。 – ChrisF 2013-03-28 10:32:36