基于Ghidra分析x86汇编内联函数的优化与逆向识别
无源码逆向中识别被编译器优化的加法操作
场景复现
原始C++代码
#include <iostream> int addition(int a, int b) { int funcA = a; int funcB = b; return funcA + funcB; }; int main() { volatile int count1 = 8; volatile int count2 = 9; volatile int anotherRandomVar = 0; volatile int result = addition(count1, count2); std::printf("main func is here"); return 0; }
x64 Release编译后的汇编(加法被优化)
************************************************************** * FUNCTION * ************************************************************** int __cdecl main(int _Argc, char * * _Argv, char * * _Env) assume GS_OFFSET = 0xff00000000 int EAX:4 <RETURN> int ECX:4 _Argc char * * RDX:8 _Argv char * * R8:8 _Env int Stack[0x18]:4 anotherRandomVar XREF[1]: 14000108b(W) int Stack[0x10]:4 count1 XREF[2]: 140001074(W), 140001097(R) int Stack[0x8]:4 count2 XREF[2]: 140001083(W), 140001093(R) main XREF[2]: __scrt_common_main_seh:1400012cb 14000400c(*) 140001070 48 83 ec 28 SUB RSP,0x28 140001074 c7 44 24 MOV dword ptr [RSP + count1],0x8 38 08 00 00 00 14000107c 48 8d 0d LEA _Argc,[s_main_func_is_here] = "main func is here" cd 11 00 00 140001083 c7 44 24 MOV dword ptr [RSP + count2],0x9 30 09 00 00 00 14000108b c7 44 24 MOV dword ptr [RSP + anotherRandomVar],0x0 40 00 00 00 00 140001093 8b 44 24 30 MOV EAX,dword ptr [RSP + count2] 140001097 8b 44 24 38 MOV EAX,dword ptr [RSP + count1] 14000109b e8 70 ff CALL printf int printf(char * _Format, ...) ff ff 1400010a0 33 c0 XOR EAX,EAX 1400010a2 48 83 c4 28 ADD RSP,0x28 1400010a6 c3 RET
x64 Release反编译结果(无加法逻辑)
int __cdecl main(int _Argc,char **_Argv,char **_Env) { int count2; int count1; int anotherRandomVar; printf("main func is here"); return 0; }
x86 Release编译后的汇编(加法指令保留)
************************************************************** * FUNCTION * ************************************************************** int __cdecl main(int _Argc, char * * _Argv, char * * _Env) assume GS_OFFSET = 0xff00000000 int EAX:4 <RETURN> int ECX:4 _Argc char * * RDX:8 _Argv char * * R8:8 _Env int Stack[0x18]:4 local_res18 XREF[1]: 140001084(W) int Stack[0x10]:4 local_res10 XREF[2]: 140001074(W), 140001090(R) int Stack[0x8]:4 local_res8 XREF[3]: 14000107c(W), 14000108c(R), 140001096(W) main XREF[2]: __scrt_common_main_seh:1400012cb 14000400c(*) 140001070 48 83 ec 28 SUB RSP,0x28 140001074 c7 44 24 MOV dword ptr [RSP + local_res10],0x8 38 08 00 00 00 14000107c c7 44 24 MOV dword ptr [RSP + local_res8],0x9 30 09 00 00 00 140001084 c7 44 24 MOV dword ptr [RSP + local_res18],0x0 40 00 00 00 00 14000108c 8b 4c 24 30 MOV _Argc,dword ptr [RSP + local_res8] 140001090 8b 44 24 38 MOV EAX,dword ptr [RSP + local_res10] 140001094 03 c8 ADD _Argc,EAX 140001096 89 4c 24 30 MOV dword ptr [RSP + local_res8],_Argc 14000109a 48 8d 0d LEA _Argc,[s_main_func_is_here] = "main func is here" af 11 00 00 1400010a1 e8 6a ff CALL printf int printf(char * _Format, ...) ff ff 1400010a6 33 c0 XOR EAX,EAX 1400010a8 48 83 c4 28 ADD RSP,0x28 1400010ac c3 RET
识别被优化加法操作的实用方法
- 检查变量的引用链路:如果某个变量被赋值后,只有读取操作但没有后续的存储、参数传递或参与其他计算,大概率对应的计算逻辑被优化了。比如x64汇编里的count1和count2,被加载到寄存器后直接被覆盖,没有产生任何实际输出,说明原本的加法被跳过。
- 对比不同版本的二进制:找同一程序的x86/x64版本、Debug/Release版本,对比汇编差异。Debug版本优化少,能看到完整计算流程;不同架构的优化策略也有区别,像例子里x86版本就保留了加法指令,对比后能快速定位被优化的逻辑。
- 追踪寄存器的生命周期:观察寄存器的值变化,如果寄存器被连续加载多个变量但没有运算就被覆盖,那中间可能存在被优化的计算。比如x64里EAX先加载count2,紧接着被count1覆盖,没有ADD指令,说明加法被优化掉了。
- 结合业务逻辑推断:从上下文判断变量的用途,比如两个计数类变量,通常会有求和、比较等操作,如果汇编里没有对应指令,就要考虑是编译器优化了这部分逻辑。
- 利用逆向工具的交叉引用功能:用Ghidra查看变量的XREF,对比有计算和无计算版本的引用差异。比如x86里的local_res8有读取、运算、存储的引用,而x64里的count2只有赋值和读取,这种差异就是优化的痕迹。
内容的提问来源于stack exchange,提问作者sb99
相关产品推荐
相关产品推荐

