![](/img/trans.png)
[英]Overriding 'free' or 'delete' using LD_PRELOAD & dlsym()
[英]How can I intercept dlsym calls using LD_PRELOAD?
我想攔截應用程序對 dlsym 的調用。 我嘗試在 .so 中聲明,以便我預加載 dlsym ,並使用 dlsym 本身來獲取它的真實地址,但是由於很明顯的原因,這不起作用。
有沒有比獲取進程的內存映射並使用 libelf 在加載的 libdl.so 中找到 dlsym 的真實位置更容易的方法?
我在 hdante 的回答中偶然發現了與評論者相同的問題:調用__libc_dlsym()
直接因段錯誤而崩潰。 在閱讀了一些 glibc 源代碼后,我想出了以下 hack 作為解決方法:
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
類的RTLD_NEXT
正確(並且,使用 NULL 作為第三個參數將使調用在使用RTLD_NEXT
時失敗並出現錯誤)。 但是,我沒有看過 glibc 的 unwindind 功能,所以我不能 100% 確定上面的代碼會做正確的事情,而且它可能只是偶然地工作...... 到目前為止提出的解決方案有一些明顯的缺點: _dl_sym()
dlsym()
在某些情況下與預期的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);
}
http://www.linuxforu.com/2011/08/lets-hook-a-library-function/
從文中:
當您需要在鈎子中調用 __libc_dlsym (句柄,符號)時,請注意自身調用 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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.