LD_PRELOAD トリックを独自のバイナリに適用しようとしていました。以前にも似たようなことをしたことがありますが、今回はうまくいきませんでした。私がインターセプトしようとした呼び出しは、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秒間隔で正確にキャッチしたい。
ここに私のコード、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 の場合、ルックアップは 1 ステップだけで済み、timerwrap.so をバイパスして /usr/lib/librt.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 は特別なのですか? 何かご意見は?
これは私の最初の質問です。助けてくれてありがとう!