我怎样才能使用LD_ preLOAD拦截对dlsym电话? [英] How can i intercept dlsym calls using LD_PRELOAD?

查看:357
本文介绍了我怎样才能使用LD_ preLOAD拦截对dlsym电话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要拦截应用程序调用的dlsym,我试过,我是preloading对dlsym中的.so内声明,并使用dlsym本身得到它的真实地址,但相当明显的原因没有的工作。

I want to intercept application's calls to dlsym, i've tried declaring inside the .so that i'm preloading dlsym , and using dlsym itself to get it's real address, but that for quite obvious reasons didn't work.

有没有办法不是采取进程的内存映射,并使用了libelf找到加载libdl.so内对dlsym的真实位置更容易?

Is there a way easier than taking process' memory maps, and using libelf to find the real location of dlsym inside loaded libdl.so?

推荐答案

我碰到了同样的问题绊倒与hdante的回答作为评论者:调用 __ libc_dlsym()直接崩溃,段错误。阅读一些glibc的源后,我想出了下面的技巧作为一种解决方法:

I stumbled across the same problem with hdante's answer as the commenter: calling __libc_dlsym() directly crashes with a segfault. After reading some glibc sources, I came up with the following hack as a workaround:

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);
}

请注意两件事情本解决方案:

NOTE two things with this "solution":


  1. 这code绕过这是由内部进行锁定(__ libc_)的dlsym(),所以做出这个线程,你应该添加一些锁定。

  2. _dl_sym()的THRID参数是调用者的地址,glibc的似乎重建所栈展开此值,但我只是用函数本身的地址。主叫方地址用于内部找到链接映射来电者是要得到这样 RTLD_NEXT事情权(并使用NULL作为THRID参数将使调用失败,错误当使用 RTLD_NEXT )。不过,我没有看过的glibc的unwindind功能,所以我不是100%肯定的是,上述code会做正确的事情,它可能发生在单独的机会只是工作...

  1. This code bypasses the locking which is done internally by (__libc_)dlsym(), so to make this threadsafe, you should add some locking.
  2. The thrid argument of _dl_sym() is the address of the caller, glibc seems to reconstruct this value by stack unwinding, but I just use the address of the function itself. The caller address is used internally to find the link map the caller is in to get things like RTLD_NEXT right (and, using NULL as thrid argument will make the call fail with an error when using RTLD_NEXT). However, I have not looked at glibc's unwindind functionality, so I'm not 100% sure that the above code will do the right thing, and it may happen to work just by chance alone...

到目前为止psented解决方案$ P $有一些显著的缺点: _dl_sym()的作用完全不同比预期的则dlsym()在某些情况下。例如,试图解决它不存在不退出程序,而不是仅仅返回NULL的象征。要解决这个问题,我们可以使用 _dl_sym()刚刚得到的指针原始则dlsym()和使用对于一切(如在标准 LD_ preLOAD 挂钩计算策略不挂钩则dlsym 在所有)

The solution presented so far has some significant drawbacks: _dl_sym() acts quite differently than the intended dlsym() in some situations. For example, trying to resolve a symbol which does not exist does exit the program instead of just returning NULL. To work around that, one can use _dl_sym() to just get the pointer to the original dlsym() and use that for everything else (like in the "standard" LD_PRELOAD hook approch without hooking dlsym at all):

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);
}

这篇关于我怎样才能使用LD_ preLOAD拦截对dlsym电话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆