C 为什么LD_预加载技巧对librt不起作用?
我试图将LD_预加载技巧应用于一些专有二进制文件。我以前也做过类似的事情,但这次运气不好。我试图拦截的调用是timer_settime() Strace清楚地显示了二进制文件调用了timer_settime():C 为什么LD_预加载技巧对librt不起作用?,c,linux,gcc,linker,ld,C,Linux,Gcc,Linker,Ld,我试图将LD_预加载技巧应用于一些专有二进制文件。我以前也做过类似的事情,但这次运气不好。我试图拦截的调用是timer_settime() Strace清楚地显示了二进制文件调用了timer_settime(): [pid 30500] timer_settime(0x2, 0, {it_interval={30, 0}, it_value={30, 0}}, {it_interval={0, 0}, it_value={0, 0}}) = 0 它以不同的时间间隔被多次调用。我想以30秒的间隔
[pid 30500] timer_settime(0x2, 0, {it_interval={30, 0}, it_value={30, 0}}, {it_interval={0, 0}, it_value={0, 0}}) = 0
它以不同的时间间隔被多次调用。我想以30秒的间隔准确地捕捉上面的一个
这是我的代码timerwrap.c:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <time.h>
#include <stdio.h>
int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value)
{
printf("Enter timer.\n");
if((new_value->it_interval).tv_sec == 30) {
printf("Catched!\n");
return 0;
}
int (*real_timer_settime)(timer_t, int, const struct itimerspec *, struct itimerspec *);
real_timer_settime = dlsym(RTLD_NEXT, "timer_settime");
return real_timer_settime(timerid, flags, new_value, old_value);
}
运行程序:
export LD_PRELOAD=/home/Work/C/timerwrap.so
./the_program
但它没能截获电话
我使用LD_DEBUG=all再次运行它以进一步调查。事实证明,对于许多其他符号,timerwrap.so已被查找,例如,dlsym的查找路径在调试输出中如下所示:
2006: symbol=dlsym; lookup in file=/.../the_program [0]
2006: symbol=dlsym; lookup in file=/home/Work/C/timerwrap.so [0]
2006: symbol=dlsym; lookup in file=./lib/libssl.so.6 [0]
2006: symbol=dlsym; lookup in file=/lib/i686/cmov/libdl.so.2 [0]
2006: binding file /.../the_program [0] to /lib/i686/cmov/libdl.so.2 [0]: normal symbol `dlsym' [GLIBC_2.0]
但是,对于timer_settime,查找只需一步,直接转到/usr/lib/librt.so,绕过timerwrap.so:
2006: symbol=timer_settime; lookup in file=/usr/lib/librt.so [0]
2006: binding file /usr/lib/librt.so [0] to /usr/lib/librt.so [0]: normal symbol `timer_settime'
那么这里发生了什么?为什么librt.com这么特别?有什么想法吗
这是我的第一个问题。提前感谢您的帮助 一个简单的示例程序向我展示了一切正常运行 您尝试使用的应用程序可能通过
dlsym
加载timer\u settime
执行dlsym(dlopen(“librt.so”),“timer\u settime”)
解决这个问题不应该那么难,只需在源代码中添加类似的内容:
extern void *_dl_sym (void *handle, const char *name, void *who);
void *dlsym(void *handle, const char *symbol)
{
printf("Enter dlsym.\n");
void* result = _dl_sym(handle, symbol, 0); // the replacement we are going to use
if ((handle != RTLD_NEXT) || (handle != RTLD_DEFAULT))
if(!strcmp(symbol, "timer_settime")) {
printf("Return our timer_settime");
return timer_settime;
}
return result;
}
extern void *_dl_sym (void *handle, const char *name, void *who);
void *dlsym(void *handle, const char *symbol)
{
printf("Enter dlsym.\n");
void* result = _dl_sym(handle, symbol, 0); // the replacement we are going to use
if ((handle != RTLD_NEXT) || (handle != RTLD_DEFAULT))
if(!strcmp(symbol, "timer_settime")) {
printf("Return our timer_settime");
return timer_settime;
}
return result;
}