3

私の Linux アプリケーション (A) は、ソース コードを持っていないサード パーティの共有ライブラリ (B) にリンクしています。このライブラリは、(C) のソース コードを持っていない別のサード パーティの共有ライブラリを使用します。(B) は直接リンクする代わりに dlopen を使用して (C) にアクセスしていると思います。これについての私の理由は、(B) の 'ldd' は (C) を表示せず、objdump -X (B) は dlopen/dlclose/dlsym への参照を表示することです。

私の要件は、(A) のコードで、(C) にある関数 foo() への関数ポインターを取得する必要があることです。通常、これには dlsym を使用しますが、dlopen から返されたハンドルを渡す必要がありますが、(B) はこれを公開していないため、持っていません。

-

より大きなコンテキストの場合: (C) の関数を変更して、ヘルパー関数 bar() (これも (C) にあります) を呼び出すたびに、(A) にある同じシグネチャを持つ関数も呼び出すようにする必要があります。同じパラメータ (基本的に、(C) foo()->bar() のコードパスにコードを挿入します。gdb を使用してこれを達成する方法を見つけたと思いますが、gdb コマンド リストを移植するために、 「関数ポインタを取得するステップで立ち往生しています.私はまた、上記の正確な問題ではなく、同じタスクを達成するための代替手段を受け入れています.

編集:これを書いた後、私はおそらくコード内のファイルで別の dlopen を実行できることに気付きました。そのハンドルの dlsym を介して返されるシンボルは、元の dlopen を介して受信したものと同じである必要があります。dlopen のマニュアルページを正しく読んでいる場合. しかし、私はまだ、より大きな文脈でのアドバイスや支援に興味があります.これについてもっと良い方法があれば.

4

2 に答える 2

2

関数fooおよびのプロトタイプがわかっている場合barは、アプリ環境で LD_PRELOAD (作成したライブラリ) を実行して、次に使用可能な関数を呼び出すことができます (fooまたはbar必要なタスクを実行した後)。

/*
 * gcc -shared -fPIC my_lib.c -ldl -Wl,-init,init_lib -o lib_my_name.so
 *
 * LD_PRELOAD this library in the environment of the target executable
 *
 */

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

#ifndef RTLD_NEXT
#define RTLD_NEXT ((void *)-1)
#endif

int init_lib(void)
{
    return 0;
}

void *foo (params here...)
{
    /* your required task here */

    return ((void* (*)(size_t))(dlsym(RTLD_NEXT, "foo")))(params here);
}

(これを達成するために gdb を使用したため、何らかのデバッグ目的でこれを行っていると想定しています。それ以外の場合、これはクライアントのマシンでいくつかの機能を変更するための良い方法ではありません)

于 2011-01-05T07:47:57.413 に答える
1

(C) のハンドルを簡単につかむことができます。適切なファイルを dlopen するだけです。dlopen するファイルが既にわかっているか (シンボル "foo" が必要なため)、またはstrace -e open,mmap,mmap2(A) で実行して、たまたま開いた共有ライブラリを確認します。

(C) が作成されたとき、(C) 自体に「bar」があるため、「bar」への参照 (「foo」の jmp 命令からなど) は通常、作成時にすでに部分的に解決されています。したがって、bar の呼び出しは PLT を通過しません。つまり、簡単なハックによる bar のオーバーライドは無効であり、gdb のように asm レベルのパニングが必要です。

これらすべてが過度に作業集約的に聞こえるので、作業する価値があるかどうか、またはクローズド ソース コンポーネントを捨てた方がよいかどうかという疑問が生じます。

于 2011-01-05T00:14:31.410 に答える