[英]Patching code/symbols into a dynamic-linked ELF binary
假設我有一個動態鏈接的ELF二進制文件,我想覆蓋/重定向某些庫調用。 我知道我可以用LD_PRELOAD
做到這一點,但我想要一個在二進制文件中永久存在的解決方案,獨立於環境,並且適用於setuid / setgid二進制文件, LD_PRELOAD
都不能實現。
我想做的是從其他目標文件添加代碼(如果需要,可能在新的部分中),並將這些目標文件中的符號添加到二進制符號表中,以便使用新添加的代碼版本代替共享庫代碼。 我相信這應該是可能的,而不需要在現有代碼中實際執行任何重定位; 即使它們在同一個文件中,它們也應該能夠在運行時以通常的PLT方式解析(因為我只關心函數而不是數據)。
請不要給我答案“你不想這樣做!” 或者“那不便攜!” 我正在研究的是一種將二進制文件與稍微ABI不兼容的備用共享庫實現連接起來的方法。 有問題的平台是i386-linux(即32位),如果重要的話。 除非我弄錯了什么是可能的,否則我可以編寫一些工具來解析ELF文件並執行我的黑客攻擊,但我懷疑有一種奇特的方法可以使用GNU鏈接器和其他工具來完成此操作而無需編寫新代碼。
ld
有一個選項--wrap
,它允許你用一個你稱之為__wrap_malloc
的符號替換像malloc
這樣的給定符號。 有了它,您可以為您感興趣的函數編寫一些存根,並將其鏈接到相關庫。
我似乎無法僅對此問題添加評論,因此將其作為“答案”發布。 抱歉,這樣做只是為了幫助其他搜索答案的人。
所以,我似乎有類似的用例,但我明確地發現對現有二進制文件的任何修改都是不可接受的(對我來說),所以我正在尋找獨立的代理方法: ELF的代理共享庫(sharedlib,shlib,so)?
您可以在程序中處理一些動態鏈接。 特別是閱讀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()而不是信任鏈接器以正確的順序獲取庫。
編輯 :我懷疑如果被覆蓋的庫中的不同函數調用重寫函數,則調用原始函數而不是覆蓋。 我不知道如果一個動態庫調用另一個動態庫將會發生什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.