You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:12:01