c - 如何从另一个可执行文件调用二进制文件的 _start?

标签 c assembly elf

我有一个 elf64 可执行文件 foo,我想“手动”加载和启动它并能够从中调用其他函数。我如何将它加载到内存中,然后设置指令指针与它一起运行。

foo 不是一个共享对象库,它是一个可执行文件,具有像 SO 一样导出的某些功能。

那么,有几个问题:

  1. 我在哪里将二进制文件加载到内存中以便它是可执行的?堆?堆?
  2. 如何设置指令指针以从我的程序更改为 foo 的入口点?

例如,我有以下内容,但它会出现段错误:

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <elf.h>

#define ELF_SIZE 10000

int main(int argc, char **argv)
{

    FILE *fp;
    void *   entry_point ;
    Elf64_Ehdr *elfHdr;
    uint8_t *buffer = malloc(ELF_SIZE);

    fp = fopen("./foo", "rb");

    int read_size = fread(buffer, 1, ELF_SIZE, fp);
    if (read_size == ELF_SIZE)
    {
        printf("loaded ELF onto heap
\n");
    } else
    {
        printf("read failed: %d\n", read_size);
        return 0;
    }
    printf("elf loaded at %x\n", buffer);

    elfHdr = (Elf64_Ehdr*) buffer;

    printf("entry point at %x\n", elfHdr->e_entry);

    entry_point = elfHdr->e_entry + buffer;

    printf("trying to jump to: %x\n", entry_point
            );
        int a;
        __asm__ ("jmp %1;"
                : "=r" (a)
                : "r" (entry_point));

    return 0;

} 

出于各种原因,使用正常方法启动 foo()(如 system())或其他标准操作系统工具不是一种选择。我需要能够调用 _start 来启动它,并在它开始运行后调用“foo_bar()”。我试过使用 dlopen/dlsym 但它不起作用,因为它是可执行文件而不是共享库

最佳答案

printf("loaded ELF onto stack \n");

这是一个谎言:您将可执行文件加载到,而不是堆栈

Where do I load the binary into memory so that is executable? Stack? Heap?

堆和栈都不合适;使用 mmap 将二进制文件放入内存。可能需要多次 mmap 调用(针对目标二进制文件中的每个 PT_LOAD 段调用一次)。

How do I setup the instruction pointer to change from my program to the entry point of foo?

更改指令指针是最少的问题(您已经编码的 jmp 将起作用,或者您可以将地址转换为函数指针,然后简单地调用它——不需要内联汇编)。


您要实现的目标非常重要。查看 UPX 来源以了解涉及的内容。

如果二进制文件是非 PIE 可执行文件,那么您不能将其加载到任意内存位置——它已链接到加载到特定地址,如果在任何其他地址加载。

如果二进制文件是 PIE 可执行文件,它可以在任意地址运行(尽管它仍然有对齐要求,malloc 不太可能满足)。

在旧版本的 GLIBC 中,可以 dlopen() PIE 可执行文件,但新版本不允许这样做。

在 PIE 可执行文件可以运行之前,它必须重新定位,这也是一项非常重要的任务。

TL;DR:您可能真的不想这样做(另请参阅 http://xyproblem.info ),但如果您真的这样做,肯定会比仅仅阅读花费更多的努力将二进制文件放入缓冲区并跳转到其中的 _start 符号。

关于c - 如何从另一个可执行文件调用二进制文件的 _start?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68217885/

相关文章:

c++ - undefined reference 编译 OpenFP

c - 为什么一个字节的大小必须是8位?

assembly - Assembly 中的偏移是什么以及如何使用它们?

c - c中的字符串文字

c++ - 为什么 C 和 C++ 关键字 "#defined"或 "typedefed"也作为它们的大写版本?

从 LLVM 位码编译对象时无法链接到静态库。

c - 如何通过汇编代码找到固定长度的多维数组?

python-2.7 - 在 Heroku 上使用 python 运行tensorflow时出现导入错误?

linux-kernel - 为什么我在运行 readelf -s 时得到这个输出

c - 如何检查程序是否在c中静态编译