2010-10-27 37 views
9

假設我有一個動態鏈接的ELF二進制文件,並且我想覆蓋/重定向某些庫調用。我知道我可以用LD_PRELOAD來做到這一點,但我想要一個在二進制文件中永久存在的獨立於環境的解決方案,它適用於setuid/setgid二進制文件,其中沒有一個可以實現。將代碼/符號修補爲動態鏈接的ELF二進制文件

我想要做的是從其他目標文件(可能在新的部分,如有必要)添加代碼,並將這些目標文件中的符號添加到二進制符號表中,以便新添加的代碼版本獲取用於代替共享庫代碼。我相信這應該是可能的,而不需要在現有代碼中實際執行任何重定位;即使它們在同一個文件中,它們也應該能夠在運行時以通常的PLT方式解決(因爲它值得我只關心函數,而不關心數據)。

請不要給我答案,沿着「你不想這樣做!」或者「那不是便攜的!」我正在處理的是一種連接二進制文件與ABI不兼容的備用共享庫實現的方式。有問題的平臺是i386-linux(即32位)。除非我誤解了什麼是可能的,否則我可以編寫一些工具來解析ELF文件並執行我的黑客攻擊,但我懷疑有一種奇特的方式使用GNU鏈接器和其他工具來完成此操作,而無需編寫新代碼。

+0

我不知道這是不是爲你工作,但檢查'nm'系統命令(你可能已經知道它)。給出了相當多的關於這樣的信息。 – Marm0t 2010-10-27 04:32:36

+0

哇,LD_PRELOAD技巧看起來很有趣!我也在尋找一種在二進制文件中執行它的方法。我的問題是我的二進制文件有一個象徵,表示我的BeagleBone的鏈接程序無法解析。 – CJxD 2015-09-28 00:22:10

回答

5

我建議elfsh等人。 ERESI項目中的工具,如果您想自行測試ELF文件。與i386-linux的兼容性不是問題,因爲我自己也用於相同的目的。

相關的操作方法是here

+0

看起來它需要一些閱讀,但我認爲這是我正在尋找的工具。謝謝! – 2010-10-27 06:40:29

+0

ERESI有*任何*文件嗎?我找不到任何「入門」,例子等。 – 2010-10-29 04:41:07

+0

嗯,看起來像沒有(所有鏈接指向svn?)。 – 2010-10-29 07:43:21

0

您可以在程序本身中處理一些動態鏈接。特別是閱讀dlsym(3)的手冊頁,併爲動態鏈接接口的其餘部分閱讀dlopen(3),dlerror(3)和dlclose(3)。

一個簡單的例子 - 說我想覆蓋從libc dup2(2)。我可以用下面的代碼(姑且稱之爲 「dltest.c」):

#define _GNU_SOURCE 

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

int (*prev_dup2)(int oldfd, int newfd); 

int dup2(int oldfd, int newfd) { 
    printf("DUP2: %d --> %d\n", oldfd, newfd); 
    return prev_dup2(oldfd, newfd); 
} 

int main(void) { 
    int i; 

    prev_dup2 = dlsym(RTLD_NEXT, "dup2"); 
    if (!prev_dup2) { 
     printf("dlsym failed to find 'dup2' function!\n"); 
     return 1; 
    } 
    if (prev_dup2 == dup2) { 
     printf("dlsym found our own 'dup2' function!\n"); 
     return 1; 
    } 

    i = dup2(1,3); 
    if (i == -1) { 
     perror("dup2() failed"); 
    } 

    return 0; 
} 

編譯:

gcc -o dltest dltest.c -ldl 

靜態鏈接DUP2()函數將覆蓋從庫中DUP2()。即使該函數在另一個.c文件中(並且被編譯爲單獨的.o),也是如此。

如果您的覆蓋函數本身是動態鏈接的,您可能需要使用dlopen()而不是信任鏈接器以正確的順序獲取庫。

編輯:我懷疑如果重寫的庫內的一個不同的函數調用重寫的函數,原始函數被調用,而不是覆蓋。我不知道如果一個動態庫調用另一個庫會發生什麼。

+0

我想修改二進制文件,而不是源文件。 – 2010-10-27 05:48:26

2

ld可以選擇--wrap,它可以讓您用符號malloc代替給定的符號,您可以將其稱爲__wrap_malloc。因此,您可以爲您感興趣的功能編寫一些存根,並將其鏈接到相關庫。

+0

再次,這個問題是關於修補二進制文件,而不是在我編譯的程序中包裝庫調用。 – 2010-10-27 06:38:45

+0

R .:我不明白爲什麼你不能在你提出的問題中問你提出的問題。 '__wrap_malloc'不需要調用舊的'malloc',它只是用另一個符號替換一個符號。 'ld'是處理我知道的二進制文件,便攜式,靈活的所有你需要的最好的工具。但是你似乎在你的腦海中有某些類型的答案,這並不一定反映在你的問題中。 – 2010-10-27 06:54:32

+0

如果您的意思是有一種方法可以使用現有的可執行ELF文件並添加代碼來定義一些符號,否則這些符號將被解析爲共享庫代碼,只使用GNU'ld',我很想知道如何。但請注意,這需要應用的輸入程序是可執行的ELF文件,而不是'.o'文件或源文件。 – 2010-10-27 08:23:19

1

我似乎不能僅僅爲此問題添加評論,因此將其張貼爲「答案」。很抱歉,這樣做只是希望幫助其他搜索答案的人。

所以,我似乎也有類似的用例,但我明確地找到任何修改不能接受(對我來說)現有的二進制文件,所以我在尋找獨立代理方式:Proxy shared library (sharedlib, shlib, so) for ELF?

相關問題