如何在Windows(PE)/Linux(ELF)可执行文件末尾添加机器码?
问题解答
核心问题:能否在二进制文件末尾添加代码?用什么工具?
完全可以实现,但不是直接往文件末尾追加字节这么简单——你需要修改二进制的格式头部(比如PE/ELF的段表/节表),新增一个可执行的节区,把你的代码放在末尾对应位置,同时更新头部里的加载信息,让系统能识别并正确加载这段新代码。
可用的工具分为两类:
- 可视化工具:
- Windows PE文件:
LordPE、CFF Explorer,这俩能直接编辑PE头的节表,新增节区后把代码写入文件末尾对应的偏移,调整节表的起始偏移、大小、权限(要设为可执行+可读)。Cutter其实也能做,你需要手动编辑段表条目,新增一个节区指向文件末尾的新字节,然后设置权限。 - Linux/macOS ELF文件:
objcopy可以通过--add-section参数新增节区,比如objcopy --add-section .mycode=newcode.bin target.elf,之后用chmod +x确保可执行;Cutter也支持编辑ELF的段表来新增节区。
- Windows PE文件:
- 脚本/编程工具:
- 用
pefile(处理PE)或pyelftools(处理ELF)写脚本,自动化完成新增节区、写入代码、更新头部的操作;逆向常用的pwntools也有封装好的方法来修改二进制文件结构。 - x96dbg可以在内存中把代码注入到进程后,用dump功能导出修改后的文件,但要注意在dump前确保新增的代码段已经被正确映射,并且更新文件的头部信息(不然dump出来的文件可能无法正常运行)。
- 用
次要问题:为什么直接在末尾加不行?读写段的区别?
1. 直接追加字节的问题
二进制文件不是随便的字节流,它有严格的格式规范:比如PE文件有DOS头、PE头、节表,每个节表条目记录了对应段的文件偏移、内存加载地址、大小、权限等信息。你直接往末尾加字节,系统加载时根本不会把这部分当成可执行代码——因为没有对应的节表条目告诉系统“这部分是可执行的,要加载到内存的某个地址”。另外,有些程序会校验文件大小或者用文件偏移来计算资源位置,文件大小变化会直接导致这些逻辑出错。
2. 只读段与读写段的工作原理
它们本质都是文件里的字节,但系统加载到内存时会赋予完全不同的权限:
- 只读段(比如.text):加载后内存页的权限是只读+可执行,目的是保护代码不被意外修改,同时利用操作系统的内存保护机制,防止恶意代码篡改程序逻辑。如果你在内存里尝试修改.text段的内容,会直接触发内存访问异常。
- 读写段(比如.data/.bss):.data是已初始化的全局变量,.bss是未初始化的全局变量,加载后内存页权限是可读可写,用来存储程序运行时需要修改的数据。这些段不会被标记为可执行,防止注入的代码在这里执行(现代系统的NX保护)。
内容的提问来源于stack exchange,提问作者Gabriel Frigo
相关产品推荐
相关产品推荐

