如何读取嵌入到程序自身 ELF 中的数据?

How to read data embedded into the program's own ELF?

提问人:Matheus Moreira 提问时间:11/12/2023 最后编辑:Matheus Moreira 更新时间:11/15/2023 访问量:123

问:

该工具可以很容易地将任意文件嵌入到 ELF 可执行文件中:objcopy

objcopy --add-section program.file1=file1.dat \
        --add-section program.file2=file2.dat \
        program program+files

在我看来,应该可以在不打开和读取任何外部文件的情况下以编程方式访问。但是,似乎没有简单的方法可以从正在运行的程序中获取此信息。program+filesfile1file2

这些文件已添加为 ELF 可执行文件的命名部分。但是,Linux 仅加载 ELF 程序头表描述的段。这些部分永远不会出现在该集中,因为它们对于执行不是必需的。

因此,虽然可以获取指向当前正在运行的程序的 ELF 标头的指针,但这毫无意义,因为根本没有加载这些部分。

uintptr_t address = getauxval(AT_PHDR) & -4096;
Elf64_Ehdr *elf = (Elf64_Ehdr *) address;

// dangling pointer, sections aren't loaded by the OS
Elf64_Shdr *sections = ((unsigned char *) elf) + elf->e_shoff;

我的目的是在运行时按名称搜索这些部分,找到以它们为前缀的部分并计算指向它们的指针,以便我的代码可以像普通内存块一样使用它们。program.

我不能为此使用预定义的符号,因为我想支持任意数量的嵌入文件,包括根本没有嵌入文件。我需要在运行时查找这些部分。

Linux 将仅加载标有 .这些部分可以以某种方式放置在段中吗? 似乎无法编辑程序标题表并添加新段。如何去做呢?PT_LOADPT_LOADobjcopyPT_LOAD

c linux 链接器 elf 嵌入式资源

评论

0赞 KamilCuk 11/13/2023
您是否考虑过仅使用数据链接或使用 xxd?
0赞 Matheus Moreira 11/14/2023
@KamilCuk是的。该解决方案似乎不适用于我的用例。我希望我的用户能够在编译程序后添加新数据。符号必须在某个时候链接到可执行文件中。这是一个独立的 C 应用程序,所以我不能用来获取符号。如果我能以某种方式获得一个新的程序标题条目。dlopen

答:

1赞 Employed Russian 11/15/2023 #1

我的目的是在运行时按名称搜索部分,找到以程序为前缀的部分。并计算指向它们的指针,以便我的代码可以像普通内存块一样使用它们。

您可以在磁盘上找到 (using )、it1、解码部分标题(请参阅此答案),然后计算指向感兴趣部分的指针并根据需要使用它们。program/proc/self/exemmap

这些部分可以以某种方式放置在PT_LOAD段中吗?

否:这将需要重建可执行文件的某些部分,如果不重新链接整个程序,就无法重建。

更新:

如果您不太关心程序的内存使用情况,则可以修改最后一段以“覆盖”整个 ,然后您可以跳过单独的部分 - 文件已经在内存中。LOADprogram+filesmmap

你只需要增加 和 这样..p_filesz.p_memszphdr.p_offset + phdr.p_filesz == file_size

代价是,你将导致通常不会加载到内存中的数据(例如节头、调试节(如果有))占用内存。但是,对于需求分页,价格可能非常小 - 任何东西都不应该访问这些“额外”内存区域,因此不应该导致它们被分页。

P.S. 我知道没有可以更新等的标准实用程序,但是在 或 中编写这样的补丁程序非常容易。.p_fileszCPython


1 您不必全部,只需包含所需部分的部分即可。mmapprogram

评论

0赞 Matheus Moreira 11/15/2023
在我对此进行研究的过程中,我遇到了您的许多答案,它们非常有帮助,谢谢。是否可以使用链接器脚本添加占位符程序标头结构?这可能允许向 ELF 添加数据,然后编辑占位符的大小和偏移量以覆盖它。我刚刚通过电子邮件向 binutils 邮件列表发送了有关这种可能性的信息,但无法让它工作。也许你会知道答案......现在,我正在尝试以这种方式解决它。
1赞 Employed Russian 11/15/2023
@MatheusMoreira我修改了答案并收回了“不,你不能”的部分;-)
0赞 Matheus Moreira 11/15/2023
对于未来的读者:我创建了一个 LLVM lld 问题和模具问题,要求提供占位符程序头文件功能。也许它会成功。
0赞 Matheus Moreira 11/19/2023
mold为此获得了支持。我取得了进步,但遇到了新问题,最终提出了一个新问题。也许你也会知道答案。