当前位置: 首页 > news >正文

1.线性switch case语句逆向特征

文章目录

  • 逆向实战:我是怎么从这段汇编一眼看出它是 `switch`,而不是一串 `if/else`
    • 1. 先把源码和目标放在脑子里
    • 2. 第一眼看到的异常感:**比较链太“整齐”了**
      • 2.1 同一个变量,被连续拿来和多个“干净的常量”比较
    • 3. 再往下看:每个分支都“自己干完事就跳走”
      • 为什么?
    • 4. 最后一个确认点:那个“兜底的 jmp”
    • 5. 到这里,我在脑子里已经还原出完整结构了
    • 6. 顺手对照一下完整示例代码(你给的)
    • 7. 我自己在逆向里总结的“线性 switch 判断口诀”

逆向实战:我是怎么从这段汇编一眼看出它是switch,而不是一串if/else

有时候在逆向里,最关键的不是“会不会写 C”,而是看到一坨汇编时,你脑子里第一反应是什么结构

这篇就直接拿你这段汇编来说:我是怎么一步步判断它是switch-case,而不是普通if / else if / else的。


1. 先把源码和目标放在脑子里

源码是一个非常简单的 switch:

intvar=10;switch(var){case1:printf("1\r\n");break;case2:printf("2\r\n");break;case3:printf("3\r\n");break;default:printf("default\r\n");break;}

逆向时我并不是一开始就假设它是 switch,而是先看汇编在“干什么”。

关键汇编如下(无关代码已省略):

; var = 10; 00C114FE mov dword ptr [ebp-4],0Ah ; switch (var) 00C11505 mov eax,dword ptr [ebp-4] 00C11508 mov dword ptr [ebp-8],eax ; 依次比较 1 / 2 / 3 00C1150B cmp dword ptr [ebp-8],1 00C1150F je 00C1151F ; case 1 00C11511 cmp dword ptr [ebp-8],2 00C11515 je 00C1152E ; case 2 00C11517 cmp dword ptr [ebp-8],3 00C1151B je 00C1153D ; case 3 00C1151D jmp 00C1154C ; default

2. 第一眼看到的异常感:比较链太“整齐”了

我在逆向里看到这段时,第一个感觉是:

这不像人手写的 if/else,更像编译器生成的结构。

为什么?

2.1 同一个变量,被连续拿来和多个“干净的常量”比较

cmp [ebp-8], 1 je case_1 cmp [ebp-8], 2 je case_2 cmp [ebp-8], 3 je case_3

注意几个细节:

  • 比较对象完全一样:全是[ebp-8]
  • 比较值非常规整:1、2、3
  • 每次 cmp 后立刻 je 跳走

这在逆向里是一个非常强的信号。

如果是普通 if/else:

  • 有可能是<><=
  • 有可能中途就return
  • 有可能比较对象变来变去

但这里是一模一样的比较模板重复 N 次,只是立即数不同。

👉这非常像 switch 的 case 常量。


3. 再往下看:每个分支都“自己干完事就跳走”

我顺着je跳到每个目标地址去看:

; case 1: 00C1151F push 0C17B30h ; "1\r\n" 00C11524 call printf 00C11529 add esp,4 00C1152C jmp 00C11559 ; ← 关键 ; case 2: 00C1152E push 0C17B34h ; "2\r\n" 00C11533 call printf 00C11538 add esp,4 00C1153B jmp 00C11559 ; case 3: 00C1153D push 0C17B38h ; "3\r\n" 00C11542 call printf 00C11547 add esp,4 00C1154A jmp 00C11559

这一步我基本已经 80% 确认是 switch 了。

为什么?

因为它们全部在做一件事

执行各自的 case 代码 →无条件跳到同一个地址

这在 C 里只有一个非常典型的来源:

caseX:...break;

也就是说:

  • jmp 00C11559break;
  • 00C11559≈ switch 之后的统一出口

如果是 if/else,很多时候:

  • 不需要手动jmp
  • 可以顺着自然流控制流往下走

switch + break 的汇编特征就是:多个分支 → 多个 jmp → 同一出口


4. 最后一个确认点:那个“兜底的 jmp”

回头再看比较链的结尾:

cmp [ebp-8], 3 je case_3 jmp default

这条jmp default非常关键。

因为它说明一件事:

所有 case 都没命中 → 强制跳到某一个固定分支

这在 C 里,只能是:

default:

而且这个default块:

00C1154C push 0C17B3Ch ; "default\r\n" 00C11551 call printf 00C11556 add esp,4
  • 没有被任何je直接命中
  • 只通过这一条 fallbackjmp进来

👉100% 的 default 分支形态。


5. 到这里,我在脑子里已经还原出完整结构了

在没看源码前,我在逆向里已经可以直接写出这样的伪代码:

if(v==1){printf("1");}elseif(v==2){printf("2");}elseif(v==3){printf("3");}else{printf("default");}

然后再结合:

  • 比较对象完全一致
  • 常量是离散整数
  • 所有分支都有 break 行为

👉这不是人手写的 if/else,而是编译器生成的线性 switch。


6. 顺手对照一下完整示例代码(你给的)

#include<stdio.h>voidfunc(){intvar=10;switch(var){case1:printf("1\r\n");break;case2:printf("2\r\n");break;default:printf("default\r\n");break;}}intmain(){func();return0;}

和汇编一一对应,没有任何矛盾点。


7. 我自己在逆向里总结的“线性 switch 判断口诀”

最后用人话总结一下这类 switch,我在逆向时脑子里的判断流程是这样的:

  1. 同一个变量被连续 cmp 多次
  2. cmp 的都是干净的常量(1、2、3…)
  3. 每个 cmp 后面都是 je,直接跳走
  4. 比较链最后有一个无条件 jmp → 兜底分支
  5. 每个分支末尾都 jmp 到同一个地址

只要这五条同时出现,我几乎不会再怀疑:

这是 switch,而且是 case 数量少、没用跳转表的那种。


如果你愿意,下一步我们可以直接接着写一篇:

  • “从汇编里区分:线性 switch vs 跳转表 switch”
  • 或者“switch 没有 break(fall-through)在汇编里的真实样子”

这些在真实逆向里,比语法本身更容易踩坑。

http://www.jsqmd.com/news/226180/

相关文章:

  • 实时数据异常检测模块
  • HY-MT1.5-7B A/B测试:不同参数版本效果对比部署方案
  • 实时日志分析:ELK Stack深度优化指南
  • MoE(Mixture of Experts)架构十年演进(2015–2025)
  • HY-MT1.5如何接入现有系统?API接口调用实战教程
  • Fine-tuning十年演进(2015–2025)
  • 导师推荐!8款一键生成论文工具测评:本科生毕业论文高效写作指南
  • HY-MT1.5-1.8B模型微调教程:特定领域适应性训练步骤
  • 9个降AI率工具推荐!继续教育学员高效避坑指南
  • 提示工程架构师实战:Agentic AI可追溯性的技术实现
  • Agent十年演进(2015–2025)
  • HY-MT1.5-7B支持哪些民族语言?方言翻译实测与部署说明
  • LangChain十年演进(2015–2025)
  • HY-MT1.5如何保护隐私?完全离线翻译系统搭建
  • Llama十年演进(2015–2025)
  • 土木工程生就业难?靠远程工作,我找到了高薪稳定工作
  • 土木工程生就业难?靠远程工作,我找到了高薪稳定工作
  • Hunyuan翻译模型多场景落地:医疗文档翻译系统搭建案例
  • Hunyuan翻译模型多场景落地:医疗文档翻译系统搭建案例
  • HY-MT1.5-7B批量翻译:高吞吐量任务调度部署策略
  • HY-MT1.5-7B翻译优化实战:上下文感知功能部署完整指南
  • Hunyuan翻译系统监控怎么做?Prometheus集成实战
  • Hunyuan翻译系统监控怎么做?Prometheus集成实战
  • HY-MT1.5-1.8B vs Google Translate API:开源模型部署性价比全面对比
  • Python 编程中 21 个最基础且核心的功能与概念
  • Python 编程中 21 个最基础且核心的功能与概念
  • HY-MT1.5-1.8B部署教程:3步完成GPU算力适配,边缘设备实时翻译实战
  • 用N-BEATS稳住医疗时序预测不卡顿
  • 开源翻译模型安全性:HY-MT1.5数据隐私保护机制解析
  • HY-MT1.5-7B vs HY-MT1.5-1.8B实战对比:选型建议与部署优化