2013-11-01 18 views
4

我試圖將LD_PRELOAD技巧應用於某些專有二進制文件。我以前做過類似的事情,但這次沒有運氣。我試圖攔截的電話是timer_settime()。爲什麼LD_PRELOAD技巧不適用於librt?

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秒的間隔完全捕捉上面的那個。

這裏是我的代碼,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); 
} 

GCC命令行:

gcc -Wall -g -shared -fPIC -o timerwrap.so timerwrap.c -ldl -lrt 

運行程序:

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.so特別?有什麼想法嗎?

這是我的第一個問題。預先感謝任何幫助!

回答

2

一個簡單的示例程序向我展示了一切正常。

您嘗試使用的應用程序可能會通過dlsym加載timer_settime

dlsym(dlopen("librt.so"), "timer_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; 
}