Ubuntu下反汇编ELF后fasm重汇编报value out of range错误
错误产生原因
- 基础流程完全不成立:
objdump -D输出的内容是面向人工阅读的反汇编标注文本,不是可直接送入汇编器编译的合法源码。它既没有保留ELF完整的段属性、重定位元数据、符号表定义、加载器配置信息,默认输出的AT&T语法、行首地址标注、符号后缀注释也完全不符合fasm的输入语法要求。就算修正了所有指令的地址问题,fasm默认输出纯二进制格式,不手动编写完整的ELF结构声明的话,根本生成不了可运行的ELF文件。 - 报错的直接触发原因:你看到的
e9操作码对应x86架构的32位相对近跳转指令,其操作数是「当前指令下一条地址到目标地址的32位有符号偏移」,合法寻址范围只有指令前后±2GiB。而objdump反汇编动态链接ELF时,会把指向动态符号(此处为stderr@@GLIBC_2.2.5)的重定位项直接解析成一个加载时才会确定的假绝对地址0x7e734770,这个地址和当前指令位置0x2ab2c的计算偏移远超过32位有符号数的表示范围,fasm在编译阶段计算跳转偏移时自然抛出value out of range错误。
可行的调整方案
- 放弃「全量反汇编后直接重编译」的思路,动态链接的ELF包含大量汇编阶段无法确定的加载期重定位项、编译器生成的元数据(异常处理、栈保护、初始化/析构段等),靠手动修正objdump输出的方式不可能补全所有缺失信息。
- 小范围代码修改优先用二进制补丁方案,稳定性最高:
- 如果自定义代码长度小于等于待替换原有代码的长度,直接用fasm/nasm把自定义汇编编译为纯二进制机器码片段,用十六进制编辑器或者
dd命令直接替换ELF对应偏移的字节即可。 - 如果自定义代码长度超过原有位置的空间,先在ELF的
.text段找代码洞(段末尾用于对齐的0xCC/0x00填充区域),在原修改位置写一条跳转到代码洞的32位相对跳转,把自定义逻辑写在代码洞区域,逻辑执行完后再跳转回原指令位置继续执行。这种方式不需要重编译整个ELF,也不会破坏原有文件的结构和动态链接逻辑。
- 如果自定义代码长度小于等于待替换原有代码的长度,直接用fasm/nasm把自定义汇编编译为纯二进制机器码片段,用十六进制编辑器或者
- 如果需要做大规模代码修改,使用专门支持重编译的逆向工具链:先完整导出ELF的段布局、符号表、重定位项,生成汇编器兼容的合法源码,把所有动态链接符号声明为外部引用,不要写死objdump给出的假绝对地址;汇编时指定和原ELF一致的加载基址、段权限,链接阶段保留原有的动态链接依赖、重定位表,最后修正ELF头、程序头、节表的偏移和校验信息。
内容的提问来源于stack exchange,提问作者ciberneticaDieu
相关产品推荐
相关产品推荐

