3

特定のアプリケーションに追加し、いくつかの関数の呼び出しを追跡するための小さなパッチを作成しました。その中には、malloc() と open() があります。dlsym を使用して元のシンボルへのポインターを格納し、関数名を独自のものに置き換えています。Linux で完全にコンパイルされ、動作します。コードは次のとおりです。

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dlfcn.h>

/**
 * Interponemos nuestra funcion open
 * 
 * @param   char*    filename
 * @param   int      flags
 **/

int open(char * filename, int flags)
{
    static int (*real_open)(char*, int) = NULL;
    if (!real_open)
        real_open = dlsym(RTLD_NEXT, "open");

    // Entero
    int p = real_open(filename, flags);
    fprintf(stderr, "Abrimos %s) = %i\n", filename, flags);

    // Devolvemos
    return p;
}

//--------------------------------------------------------

/**
 * Interponemos nuestra funcion malloc
 * 
 * @param   size_t    size
 */

void* malloc(size_t size)
{
    static void* (*real_malloc)(size_t) = NULL;
    if (!real_malloc)
        real_malloc = dlsym(RTLD_NEXT, "malloc");

    void *p = real_malloc(size);

    // Memoria reservada
    fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p);

    // Devolvemos
    return p;
}

次に、次の命令でコンパイルし、pi.so を作成します。

gcc -Wall -O2 -fPIC -shared -ldl -o pi.so pi.c 

次に、LD_PRELOAD ディレクティブを使用して、任意のアプリに挿入します。

LD_PRELOAD=/home/.../injection/pi.so <binary>

そして、それは Linux で素晴らしい働きをします! しかし、家に帰って Mac で GCC を使用してコンパイルしようとすると、コンパイルに失敗し、LD_PRELOAd ディレクティブが機能しません。何を変更すればよいですか?どうもありがとうございました。

4

3 に答える 3

4

mach では、プリロードする共有ライブラリのリストを指定するDYLD_INSERT_LIBRARIES代わりに、マクロを使用する必要があります (1...*)。LD_PRELOAD

デフォルトでは、標準関数は、同じ名前を持っているという理由だけで、共有オブジェクトからの関数に置き換えられません。DYLD_INTERPOSEマクロを使用して、どの関数が何をオーバーライドするかを明示的に述べる必要があります。これにより、置換関数を任意の名前 (たとえば、override openwith my_open) で宣言し、オーバーライドしている元の関数を呼び出すことができます。それに加えて、実際の関数のアドレスを手動で解決する必要はありません。

または、Linux のような動作を実現するには、DYLD_FORCE_FLAT_NAMESPACEマクロを定義する必要があります。

詳細については、dyldマニュアルを参照してください。

したがって、コードは次のようになります。

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dlfcn.h>
#include <mach-o/dyld-interposing.h>

/**
 * Interponemos nuestra funcion open
 * 
 * @param   char*    filename
 * @param   int      flags
 **/

int my_open(char * filename, int flags)
{
    // Entero
    int p = open(filename, flags);
    fprintf(stderr, "Abrimos %s) = %i\n", filename, flags);

    // Devolvemos
    return p;
}
DYLD_INTERPOSE(my_open, open)

//--------------------------------------------------------

/**
 * Interponemos nuestra funcion malloc
 * 
 * @param   size_t    size
 */

void* my_malloc(size_t size)
{
    void *p = malloc(size);

    // Memoria reservada
    fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p);

    // Devolvemos
    return p;
}
DYLD_INTERPOSE(my_malloc, malloc)
于 2010-09-28T20:31:29.030 に答える
1

Mac OS X(10.6.4)にはLD_PRELOADへの参照が含まれていないため、無視されるため、コードを挿入しようとして失敗します。全世界がLinuxと同じではありません。

マニュアルページを見ると、次のことがわかりました。

$ man dyld

..。

DYLD_INSERT_LIBRARIESこれは、プログラムで指定されたものの前にロードするダイナミックライブラリのコロンで区切られたリストです。これにより、新しいモジュールだけで一時的な動的共有ライブラリをロードすることにより、フラット名前空間イメージで使用される既存の動的共有ライブラリの新しいモジュールをテストできます。DYLD_FORCE_FLAT_NAMESPACEも使用されていない限り、これは動的共有ライブラリを使用して2レベルの名前空間イメージを構築したイメージには影響しないことに注意してください。

于 2010-09-28T07:12:10.373 に答える
1

OSX の場合、DYLD_INSERT_LIBRARIES 環境を使用する必要があります。LD_PRELOAD の代わりに変数。

ただし、オーバーライドが機能しないことは確かです。私が見つけることができる最も近いことは、誰かがここの mach_override の下のコードにきちんとパッケージ化されているいくつかの魔法のアセンブリトリックを行う必要があるということです: http://extendamac.svn.sourceforge.net/viewvc/extendamac/trunk/code /

于 2010-09-28T07:24:38.913 に答える