如何向已编译的ELF文件中插入汇编指令
简便向ELF二进制插入汇编指令的实用方法
嘿,我太懂手动改十六进制的糟心了——不仅容易搞错字节顺序,还得对着指令集手册查编码,效率极低!下面是几个我日常用的、不用碰十六进制编辑器的简便方案,亲测靠谱:
方法一:用GDB实时修改并导出新二进制
GDB不仅能调试,还能直接在内存里汇编指令,最后导出修改后的二进制:
- 先加载目标ELF:
gdb ./your_target_binary - 定位到你想修改的位置:比如要改
main函数开头,就用break main然后run停在断点,或者直接用x/i main查看指令地址(比如0x401120) - 如果目标内存段是只读的,先临时修改权限:
call mprotect(0x401000, 0x1000, 7)(这里0x401000是段起始地址,0x1000是长度,7代表可读可写可执行) - 直接汇编指令:输入
assemble 0x401120,然后逐行敲你要插入的汇编,比如:
敲完空回车结束汇编push rbx mov rbx, 0xdeadbeef pop rbx - 导出修改后的二进制:
dump binary memory modified_binary 0x400000 0x403000(这里的地址范围要覆盖整个ELF的代码段和数据段,你可以用readelf -l your_target_binary查程序头的地址范围)
方法二:用汇编文件+objcopy插入独立代码段
如果要插入的代码比较长,写个独立汇编文件更方便:
- 写一个带跳转的汇编文件(比如
insert_code.s),要注意跳回原执行流程:.global my_custom_code my_custom_code: ; 这里写你的自定义汇编 mov rax, 0x1234 ; 跳回原来的指令地址,比如原来的main函数开头是0x401125 jmp 0x401125 - 编译成目标文件:
as -o insert_code.o insert_code.s - 把这个目标文件作为新段插入到ELF:
objcopy --add-section .custom_code=insert_code.o \ --set-section-flags .custom_code=code,alloc,exec \ your_target_binary modified_binary - 最后用GDB或者逆向工具,把原来的指令改成跳转到
my_custom_code的地址(用readelf -s modified_binary能查到这个符号的地址)
方法三:用逆向可视化工具(Ghidra/Binary Ninja/IDA)
如果不想敲命令,可视化工具是最省心的:
- 比如用Ghidra:加载ELF后,找到要修改的指令位置,右键选择「Edit > Patch Instruction」,直接输入汇编指令
- 如果要插入新代码(不是替换原有指令),可以在空闲内存区域(比如
readelf -S查到的空闲段,或者程序末尾的空白区)右键「Edit > Patch Instruction」写新代码 - 然后把原来的指令改成跳转,指向新代码的起始地址,再在新代码末尾加跳转回原流程的指令
- 全部改完后,选择「File > Export Program」导出修改后的二进制,一键搞定
避坑提醒
- 指令长度匹配:如果是替换原有指令,要确保新指令的字节数和原来的一致,不然会破坏后续指令的地址偏移。如果字节数不一样,一定要用跳转(trampoline)到空闲空间执行新代码
- PIE文件注意:如果是位置无关可执行文件(PIE),不能用绝对地址跳转,要用
rip相对寻址,比如jmp my_custom_code(%rip) - 权限问题:修改前确认目标段有可写可执行权限,不然GDB或者工具会报错,用
patchelf或者objcopy可以调整段权限
内容的提问来源于stack exchange,提问作者Dylan Göpel




