簡體   English   中英

將代碼/符號修補為動態鏈接的ELF二進制文件

[英]Patching code/symbols into a dynamic-linked ELF binary

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

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

請不要給我答案“你不想這樣做!” 或者“那不便攜!” 我正在研究的是一種將二進制文件與稍微ABI不兼容的備用共享庫實現連接起來的方法。 有問題的平台是i386-linux(即32位),如果重要的話。 除非我弄錯了什么是可能的,否則我可以編寫一些工具來解析ELF文件並執行我的黑客攻擊,但我懷疑有一種奇特的方法可以使用GNU鏈接器和其他工具來完成此操作而無需編寫新代碼。

我建議elfsh等人。 ERESI項目中的工具,如果您想自己檢測ELF文件。 與i386-linux的兼容性不是問題,因為我自己也用它來達到同樣的目的。

相關的方法在這里

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM