4

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 は特別なのですか? 何かご意見は?

これは私の最初の質問です。助けてくれてありがとう!

4

1 に答える 1

2

簡単なサンプル プログラムは、すべてが正常に動作することを示しています。

使用しようとしているアプリケーションは、おそらくtimer_settimevia をロードしdlsymます。

やっている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; 
}
于 2013-11-01T08:38:42.267 に答える