我正在尝试将一些编译的代码注入到 elf 可执行文件中。该策略是在“代码”段的末尾写入一些字节。我选择该段的原因是因为我也需要执行我的有效负载。当段之间的填充太小时,我想将段扩展所需的量,以便它可以承载我的有效负载。
objcopy
与 objcopy <exec> --update-section <name>=<file>
一起就可以做到这一点。
我的主持人将是第
.fini
部分,该部分之后的部分是.rodata
。执行 objcopy 后,代码段的文件大小和内存映像大小是正确的大小。部分和段偏移也会在需要时进行修补。并且代码出现在预期的偏移处(由 objdump
确认)。
我的问题是没有对任何段的虚拟地址进行修补,这会导致代码段与下一个段/段重叠,从而导致
_dl_start
期间出现段错误,因为代码被认为处于只读状态部分。
以下是 readelf
. 生成的输出的一些片段
在 objcopy 之前:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[16] .fini PROGBITS 00000000000a3e84 000a3e84
0000000000000009 0000000000000000 AX 0 0 4
[17] .rodata PROGBITS 00000000000a4000 000a4000
000000000003b488 0000000000000000 A 0 0 32
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000063000 0x0000000000063000 0x0000000000063000
0x0000000000040e8d 0x0000000000040e8d R E 0x1000
LOAD 0x00000000000a4000 0x00000000000a4000 0x00000000000a4000
0x0000000000043ccc 0x0000000000043ccc R 0x1000
及之后:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[16] .fini PROGBITS 00000000000a3e84 000a3e84
00000000000002bd 0000000000000000 AX 0 0 4
[17] .rodata PROGBITS 00000000000a4000 000a5000
000000000003b488 0000000000000000 A 0 0 32
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000063000 0x0000000000063000 0x0000000000063000
0x0000000000041141 0x0000000000041141 R E 0x1000
LOAD 0x00000000000a5000 0x00000000000a4000 0x00000000000a4000
0x0000000000043ccc 0x0000000000043ccc R 0x1000
我的系统:
Linux 6.1.0-13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.55-1 (2023-09-29) x86_64 GNU/Linux
有人知道如何进一步修补二进制文件以使其发挥作用,同时最终仍然拥有有效的精灵吗?
有人知道如何进一步修补二进制文件以使其正常工作吗
这是行不通的——你有一个linked二进制文件,这意味着链接器已将数据地址“烘焙”到代码中。
您希望将数据移动到不同的地址,但这需要更新所有“内置”地址,并且执行此类更新所需的信息(重定位)已被丢弃。
您需要做的是添加一个new可执行段(这些段在运行时并不重要),并将您的有效负载放入该新段中。