3.多条件 if 语句执行流程

文章目录

一、先把原始代码和汇编摆在桌面上

原始 C 代码(不改)

c 复制代码
int checkNumber(int num)
{
    int result;

    if (num > 1000)
        result = 10000;
    else if (num > 500)
        result = 5000;
    else if (num > 100)
        result = 1000;
    else if (num > 50)
        result = 500;
    else if (num > 0)
        result = 100;
    else if (num == 0)
        result = 0;
    else if (num > -50)
        result = -100;
    else if (num > -100)
        result = -500;
    else if (num > -500)
        result = -1000;
    else
        result = -5000;

    return result;
}

对应的关键汇编(不改,仅截取核心逻辑)

asm 复制代码
002F1576  cmp         dword ptr [ebp+8],3E8h
002F157D  jle         002F158B
002F157F  mov         dword ptr [ebp-4],2710h
002F1586  jmp         002F1610

002F158B  cmp         dword ptr [ebp+8],1F4h
002F1592  jle         002F159D
002F1594  mov         dword ptr [ebp-4],1388h
002F159B  jmp         002F1610

002F159D  cmp         dword ptr [ebp+8],64h
002F15A4  jle         002F15AF
002F15A6  mov         dword ptr [ebp-4],3E8h
002F15AD  jmp         002F1610

002F15AF  cmp         dword ptr [ebp+8],32h
002F15B6  jle         002F15C1
002F15B8  mov         dword ptr [ebp-4],1F4h
002F15BF  jmp         002F1610

002F15C1  cmp         dword ptr [ebp+8],0
002F15C5  jle         002F15CF
002F15C7  mov         dword ptr [ebp-4],64h
002F15CE  jmp         002F1610

002F15CF  cmp         dword ptr [ebp+8],0
002F15D3  jne         002F15D9
002F15D5  mov         dword ptr [ebp-4],0
002F15DC  jmp         002F1610

002F15D9  cmp         dword ptr [ebp+8],0FFFFFFCEh
002F15DD  jle         002F15E8
002F15DF  mov         dword ptr [ebp-4],0FFFFFF9Ch
002F15E6  jmp         002F1610

002F15E8  cmp         dword ptr [ebp+8],0FFFFFF9Ch
002F15EC  jle         002F15F7
002F15EE  mov         dword ptr [ebp-4],0FFFFFE0Ch
002F15F5  jmp         002F1610

002F15F7  cmp         dword ptr [ebp+8],0FFFFFE0Ch
002F15FB  jle         002F1606
002F15FD  mov         dword ptr [ebp-4],0FFFFFC18h
002F1604  jmp         002F1610

002F1606  mov         dword ptr [ebp-4],0FFFFEC78h
002F1610  mov         eax,dword ptr [ebp-4]

二、第一眼扫过去:这不是 switch,是一条 if-else 链

我在 IDA 里第一眼看到这段的时候,并没有逐条翻译,而是先看结构:

  • [ebp+8] 被反复 cmp

  • 每次 cmp 后面紧跟条件跳转

  • 每个分支一旦命中,都会:

    • mov [ebp-4], 常量

    • jmp 002F1610

  • 002F1610所有路径都会汇合的统一出口

这在逆向里基本是一个信号:

这是"线性 if → else if → else"的经典编译形态。


三、从第一个 if 开始,对着汇编"反着读逻辑"

asm 复制代码
cmp dword ptr [ebp+8],3E8h
jle 002F158B

这里非常关键的一点是:

  • C 里写的是 if (num > 1000)

  • 汇编里判断的是 "不满足就跳走"

也就是说:

  • jle 跳走 → 条件失败 → 去试下一个 else if

  • 不跳 → 条件成立 → 执行赋值

asm 复制代码
mov dword ptr [ebp-4],2710h  ; result = 10000
jmp 002F1610

到这里,第一个 if 分支已经完全闭合


四、else if 的本质:上一个条件失败后,立刻 cmp 下一个阈值

asm 复制代码
002F158B  cmp dword ptr [ebp+8],1F4h
002F1592  jle 002F159D

我在这里通常会做一件事:

看上一个 jle 的目标地址,是不是正好跳到这里。

一对上,结构就彻底清楚了:

  • 失败 → 跳到下一个 cmp

  • 成功 → 赋值 → 跳统一出口

asm 复制代码
mov dword ptr [ebp-4],1388h  ; result = 5000
jmp 002F1610

这就是:

c 复制代码
else if (num > 500)

后面的 num > 100 / 50 / 0 分支,全都是同一个套路,只是阈值和结果不同。


五、看到补码就要警觉:开始进入负数区间判断

asm 复制代码
cmp dword ptr [ebp+8],0FFFFFFCEh
jle 002F15E8

0xFFFFFFCE 是什么?

  • 补码

  • 转成有符号:-50

再看赋值:

asm 复制代码
mov dword ptr [ebp-4],0FFFFFF9Ch  ; -100

这一步在逆向时非常"顺":

结构没变,只是常量换成了负数。

说明 C 里的逻辑大概是:

c 复制代码
else if (num > -50)
    result = -100;

后面的 -100 / -500 分支,完全同理。


六、没有 cmp 的那一段:这就是 else

asm 复制代码
002F1606  mov dword ptr [ebp-4],0FFFFEC78h

这里有两个非常明显的信号:

  • 前面没有任何比较

  • 执行完就自然落到返回点

这说明:

这是所有条件都失败之后的兜底分支

也就是:

c 复制代码
else
    result = -5000;

七、把整个 if-else 链"反推"成一张逻辑表

这是我在逆向里经常做的最后一步,用来确认自己没有看漏条件:

条件 result
num > 1000 10000
num > 500 5000
num > 100 1000
num > 50 500
num > 0 100
num == 0 0
num > -50 -100
num > -100 -500
num > -500 -1000
else -5000

如果这张表能完整整理出来,说明这个函数已经被你完全逆向成功


八、一句话总结这类结构的"逆向直觉"

只要在反汇编里看到:同一个变量被一串 cmp 连续比较,每个分支内部"赋值 + jmp 同一个出口",最后还有一个自然落地的分支,那它几乎一定是一个多条件 if-else if-else。

cpp 复制代码
#include<iostream>

int checkNumber(int num) {
    int result;

    // 多条件 if-else if-else 语句
    if (num > 1000) {
        result = 10000;
    }
    else if (num > 500) {
        result = 5000;
    }
    else if (num > 100) {
        result = 1000;
    }
    else if (num > 50) {
        result = 500;
    }
    else if (num > 0) {
        result = 100;
    }
    else if (num == 0) {
        result = 0;
    }
    else if (num > -50) {  // 负数的判断,从靠近0的开始
        result = -100;
    }
    else if (num > -100) {
        result = -500;
    }
    else if (num > -500) {
        result = -1000;
    }
    else {
        result = -5000;
    }

    return result;
}

int main() {
    // 测试不同的数字
    int testNumbers[] = { 1500, 750, 200, 75, 25, 0, -25, -75, -150, -300, -1000 };
    int size = sizeof(testNumbers) / sizeof(testNumbers[0]);

    std::cout << "多条件判断测试结果:" << std::endl;
    std::cout << "====================" << std::endl;

    for (int i = 0; i < size; i++) {
        int result = checkNumber(testNumbers[i]);
        std::cout << "checkNumber(" << testNumbers[i] << ") = " << result << std::endl;
    }

 

    return 0;
}
相关推荐
CHANG_THE_WORLD3 个月前
switch语句在汇编层面的几种优化方式 ,为什么能进行优化
汇编·算法·switch·汇编分析·switch case·switch case 汇编·switch case 语句
CHANG_THE_WORLD3 个月前
if条件语句 三目运算符 汇编分析
汇编·算法·条件语句·if 语句·汇编分析·条件语句汇编分析