如何从elf到我的二进制文件调用和编译功能?

时间:2019-05-08 20:03:23

标签: c gcc elf disassembly

我有一个我不写的二进制文件(ELF),但我想使用此二进制文件中的1个函数(我知道该函数的地址/偏移量),该函数未从二进制文件中导出。

我的目标是从我编写的C代码中调用此函数,并在我的二进制文件中静态编译该函数(我使用gcc进行编译)。

我该怎么办?

1 个答案:

答案 0 :(得分:2)

我要回答

  

从我编写的C代码中调用此函数

部分。

以下内容在某些假设下有效,例如动态链接和位置无关代码。我很久没想过如果它们坏了会发生什么(如果有兴趣,让我们进行实验/讨论)。

$ cat lib.c
int data = 42;
static int foo () { return data; }

gcc -fpic -shared lib.c -o lib.so

$ nm lib.so  | grep foo
00000000000010e9 t foo

以上内容复制了您所知道的地址。我们现在知道的地址是0x10e9。重定位之前它是foo的虚拟地址。我们将通过简单地添加动态加载器进行的重定位建模,只需添加lib.so加载时的基址即可。

$ cat 1.c
#define _GNU_SOURCE
#include <stdio.h>
#include <link.h>
#include <string.h>
#include <elf.h>

#define FOO_VADDR 0x10e9

typedef int(*func_t)();

int callback(struct dl_phdr_info *info, size_t size, void *data)
{
    if (!(strstr(info->dlpi_name, "lib.so")))
        return 0;
    Elf64_Addr addr = info->dlpi_addr + FOO_VADDR;
    func_t f = (func_t)addr;
    int res = f();
    printf("res = %d\n", res);
    return 0;
}

int main()
{
    void *handle = dlopen("./lib.so", RTLD_LAZY);
    if (!handle) {
        puts("failed to load");
        return 1;
    }
    dl_iterate_phdr(&callback, NULL);
    dlclose(handle);
    return 0;
}

现在...

$ gcc 1.c -ldl  && ./a.out
res = 42

Voila-奏效了!很好玩。

信用:this很有帮助。

如果您有任何疑问,请随时阅读此人并在评论中提问。

  

在我的二进制文件中静态编译此函数

我不知道该怎么做。这将比较棘手。你为什么要那样?另外,您是否知道该函数是否依赖原始ELF文件中的某些数据(或者可能调用了其他函数),就像上面的示例一样?

相关问题