簡體   English   中英

如何使用 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);
}

請注意此“解決方案”的兩件事:

  1. 此代碼繞過由(__libc_)dlsym()內部完成的鎖定,因此為了使此線程安全,您應該添加一些鎖定。
  2. _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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM