我正在尝试实现一个 ELF .text 感染示例,如“学习 Linux 二进制分析”中所述。我目前遇到了一个问题,我成功地将我的数据注入到 .text 部分,readelf 没有显示任何错误,但程序在启动期间终止。
到目前为止,我的流程是:
- 根据我要注入的数据的大小增加 .text 部分标题的 sh_size。
- 根据注入数据的大小移动 .text 部分之后的所有部分(修改部分标题中的 sh_offset 和 sh_addr)。
- 通过检查p_type、p_flags和p_offset,找到.text段所在的程序头;然后通过注入数据的大小增加 p_filesz 和 p_memsz。
- 对于之后的所有其他程序头,将注入数据的大小添加到 p_offset。
文件的入口点没有被修改。
当我尝试在radare2 中调试生成的文件时,它输出:
[0x7fd315665007]> aa
[Cannot find function 'entry0' at 0xffffffffff600530(aa)
[x] Analyze all flags starting with sym. and entry0 (aa)
[0x7fd315665007]>
如果我列出功能的数量,我会发现很多功能缺失:
[0x7f05c7bff007]> afl
0xffffffffff600000 1 10 sym.imp..6
0xffffffffff600800 1 10 fcn.ffffffffff600800
[0x7f05c7bff007]>
与原始文件对比:
[0x7f3700c6dea0]> afl
0x55daca36a000 3 73 -> 75 sym.imp.__libc_start_main
0x55daca36a4e8 3 23 sym._init
0x55daca36a510 1 6 sym.imp.puts
0x55daca36a520 1 6 fcn.55daca36a520
0x55daca36a530 1 43 entry0
0x55daca36a560 4 50 -> 40 sym.deregister_tm_clones
0x55daca36a5a0 4 66 -> 57 sym.register_tm_clones
0x55daca36a5f0 4 49 sym.__do_global_dtors_aux
0x55daca36a630 1 10 entry1.init
0x55daca36a63a 1 34 sym.main
0x55daca36a660 4 101 sym.__libc_csu_init
0x55daca36a6d0 1 2 sym.__libc_csu_fini
0x55daca36a6d4 1 9 sym._fini
0x55daca56afe0 1 1020 reloc.__libc_start_main
[0x7f3700c6dea0]>
使用 readelf 列出部分标题还表明缺少某些部分:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data
04
05 .note.gnu.build-id
06
07
08 .init_array .fini_array .dynamic
与原始文件相比:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
我认为移动部分标题的方式存在问题,但我还没有发现问题。
更新 我发现过程中存在一个错误,即使它在 .text 部分之后也会编辑部分/程序标题偏移量。修复此问题后,radare2 能够找到包括 entry0 在内的所有函数。但是,一个函数的名称是不同的:
0x00000510 1 6 sym.imp.puts
变成:
0x00000510 1 6 fcn.00000510
这显然是对 puts() 函数的调用。也许我也需要在这里修改偏移量。
即使进行了修复,丢失部分的问题仍然会发生。
更新 2 我发现程序头的 p_vaddr 值也应该与 p_offset 一起增加。这解决了 readelf -l 中缺少部分的问题。生成的程序现在将成功启动,但在运行时遇到分段错误。
更新 3 我添加了通过病毒大小增加每个 rel 的偏移量来更新 .rel* 部分的程序。这使得 r2 正确列出所有函数名称。可执行文件启动,但在运行时遇到另一个分段错误。