将其他代码合并到可执行文件中(arm-linux)

时间:2011-04-22 16:20:42

标签: linux arm elf binutils objcopy

我正在尝试将一些额外的日志记录代码合并到一个静态链接(android arm linux)可执行文件中。

(正常的跟踪方法似乎不起作用,因为它是一个守护进程,克隆()就在做任何有趣的事情之前 - 告诉strace遵循它只是崩溃它。)

Hex编辑现有代码以将跳转指令插入到新代码中进行测试和工作,问题是将新代码合并到可执行文件中,使其不会干扰现有段,并且加载到可执行页面。

我已经能够将所有附加代码压缩到单个目标文件部分,但无法弄清楚如何使用objcopy(甚至ld)以这样的方式合并它以便正确加载它 - 似乎我需要调整大小和移动现有的加载段,或添加一个将被尊重的加载段。

在共享库中添加代码可能是另一种选择,如果有一种方法可以将必要的存根添加到已经链接且当前是静态的可执行文件中(我会在跳转指令中对存根的已知位置进行十六进制编辑,然后运行时链接器将指向添加的代码

1 个答案:

答案 0 :(得分:0)

这是不优雅的,所以我对更好的想法感兴趣,但这里总结了我能够做的基本工作。

这是一个插入原始精灵填充的小引导有效负载的两个方法,然后mmap()是一个任意大的二进制blob来完成实际工作。

第一部分:自举有效载荷

基本上我在.ARM.exidx部分(在代码段的顶部加载)和.preinit_array部分之间的一些填充中插入少量代码。这段代码只打开另一个二进制blob和mmap(),它只读,可以在硬编码的虚拟地址执行,我希望是安全的。

为了让我插入的代码作为主可执行文件的一部分加载,我不得不修改elf文件中加载段的大小,在这种情况下,它是第二个phdr结构,从0x54开始。 p_filesz在0x64(0x54 + 0x20)和p_memsz在0x68(0x54 + 0x24)都被更改。

我还将偏移量为0x18的elf标头中的e_entry起始地址更改为指向插入的代码。我插入的代码在完成设置时跳转到旧的起始地址(实际上它首先跳转到更大的有效负载中的第二阶段设置,然后跳转到原始地址)。

最后,我更改了静态链接的系统调用存根,我想要捕获的函数指向我在mmap()处理的较大有效负载的加载地址处的替换。

第二部分:大负载

这实现了正在进行的任何修改 - 在我的例子中,用满足某些条件时记录的函数替换系统调用。由于主可执行文件是静态链接的,因此必须这样 - 或者更简单地说,它不能使用C库。相反,它使用汇编语言来发出基本I / O的系统调用。我意识到没有作为可执行文件加载我没有持久的本地变量存储,所以在启动时我mmap()一个匿名页面来保存局部变量 - 主要是我正在登录的文件的fd和设备驱动程序fd的操作应记录下来。

编译这部分有点不优雅。我正在使用-S开关编译汇编到gcc,然后删除所有部分关键字。然后我通过gcc传回它来组装并生成一个对象。我通过链接器运行它,指定我的第一个函数的名称作为入口点(-e)并使用通常的链接器脚本的自定义删除0x8000起始偏移量。但由于标题仍有一些偏移,在这种情况下为128字节。为了保存修正,我将链接的精灵的内容对象转换为二进制blob,dd自己从/ dev / 0开始128字节,并将cat放在开头....

正如我所说......这是不优雅的,所以我愿意接受更好的想法