我怎样才能使用LD_ preLOAD拦截对dlsym电话? [英] How can i intercept dlsym calls using LD_PRELOAD?
问题描述
我要拦截应用程序调用的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":
- 这code绕过这是由
内部进行锁定(__ libc_)的dlsym()
,所以做出这个线程,你应该添加一些锁定。 -
_dl_sym()
的THRID参数是调用者的地址,glibc的似乎重建所栈展开此值,但我只是用函数本身的地址。主叫方地址用于内部找到链接映射来电者是要得到这样RTLD_NEXT事情
权(并使用NULL作为THRID参数将使调用失败,错误当使用RTLD_NEXT
)。不过,我没有看过的glibc的unwindind功能,所以我不是100%肯定的是,上述code会做正确的事情,它可能发生在单独的机会只是工作...
- This code bypasses the locking which is done internally by
(__libc_)dlsym()
, so to make this threadsafe, you should add some locking. - 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 likeRTLD_NEXT
right (and, using NULL as thrid argument will make the call fail with an error when usingRTLD_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屋!