Ceroler 发表于 2025-7-8 23:16:07

考古——逆向16位DOS程序

学校作业要求用一个历代学生传承的祖传软件,是16位DOS可执行程序,在现今的电脑上还得安装DOSBox才能用,遂有逆向之用高级语言重新编写的想法。
奈何本人也是一个萌新,目前正在突击小甲鱼的8086汇编视频,已经突击一半左右。
该程序用DIE检测后发现为Pascal编写,无壳

然后我打开IDA开始硬着头皮分析,由于是16位程序,无法使用OD等进行动态调试,用debug跟踪会导致没有用户输入,程序一直在某个块内打转,所以只能静态分析,IDA各种辅助插件也用不了
程序名叫ABR.EXE,是光学领域的相差计算和人工修改程序,虽然程序运行的过程很简单,就是读取存储有用户写好的数据的txt文件,进行运算,并输出存有运算结果的txt文件,但是其运算过程却非常复杂
我的目标是分析出程序是如何运算的,目前是找到了程序利用int 21h中断读取文件的相关指令,但是这些指令后面指向了一个retf,我想请问各位大佬如何定位这些retf将程序又指向了哪里?逆向究竟应该遵循一个怎样的过程?

FishC 发表于 2025-7-8 23:20:37

对于16位DOS程序的逆向分析,特别是遇到`retf`指令后的定位问题,以下是详细解答和逆向步骤建议:

### 一、关于`retf`指令的定位方法
`retf`是远返回指令,会从栈中弹出**CS:IP**两个值作为返回地址。定位方法:
1. **静态分析栈操作**:
   - 在`retf`前的代码中,观察`push`指令(尤其是`push cs`/`push offset`)
   - 例如:
   
   push cs       ; 将CS压栈
   push offset loc_1234 ; 将偏移地址压栈
   call sub_proc ; 调用子程序
   ...
   sub_proc proc far
       ...
       retf ; 此时会弹出CS和offset_loc_1234
   - 返回地址就是`push`的两个值组合(CS:offset)

2. **IDA交叉引用**:
   - 在IDA中选中`retf`所在函数
   - 按`Ctrl+X`查看交叉引用(Xrefs),找到所有`call`这个函数的位置
   - 重点关注`call far ptr`指令(远调用)

3. **栈帧回溯**:
   - 在函数开头找典型序言:
   
   push bp
   mov bp, sp
   - 计算栈中参数/返回地址的位置:
   返回地址IP =
   返回段CS =

### 二、DOS程序逆向标准流程
#### 阶段1:前期准备
1. **运行程序观察行为**
   - 在DOSBox中运行,记录输入/输出文件格式
   - 尝试不同输入数据触发分支

2. **基础分析工具**
   - IDA(静态反汇编)
   - DOS调试器:DEBUG.EXE(动态跟踪)
   - 二进制查看器:WinHex/HxD

#### 阶段2:关键功能定位
1. **定位文件I/O**
   - 搜索`int 21h`中断:
   - 文件打开:`mov ah, 3Dh`
   - 文件读取:`mov ah, 3Fh`
   - 文件关闭:`mov ah, 3Eh`
   - 示例代码特征:
   
   mov dx, offset filename ; 文件名指针
   mov al, 0 ; 只读模式
   mov ah, 3Dh ; 打开文件
   int 21h

2. **定位核心算法**
   - 搜索浮点指令(Pascal常用):
   - `FADD`/`FSUB`/`FMUL`/`FDIV`
   - `FLD`/`FSTP`
   - 搜索数据转换指令:
   - `AAM`/`AAD`(BCD运算)
   - `CBW`/`CWD`(符号扩展)

#### 阶段3:动态调试技巧(DEBUG.EXE)
1. **关键断点设置**:
   
   -g 程序入口点; 先运行到入口
   -b CS:IP       ; 在文件读取函数设断点
   -g             ; 执行到断点

2. **绕过输入阻塞**:
   - 在文件读取函数后断点
   - 手动修改AX寄存器为文件句柄
   - 提前准备输入文件到虚拟磁盘

#### 阶段4:Pascal程序特征
1. **函数识别**:
   - 标准序言:`push bp` + `mov bp,sp`
   - 参数访问:起(16位near call)

2. **运行时库函数**:
   - 文件操作:`Assign`/`Reset`/`Rewrite`
   - 数学函数:`Sqrt`/`Sin`等(搜索`call far ptr`到固定地址)

### 三、针对你的任务建议
1. **优先破解文件格式**
   - 用不同数据生成输入文件
   - 对比输出文件变化
   - 逆向解析比逆向算法更简单

2. **分模块逆向**
   主流程 → 文件读取 → 数据解析 → 计算核心 → 结果输出
   从两端(文件I/O)向中间(算法)推进

3. **实用技巧**:
   - 在IDA中标记所有`int 21h`调用
   - 对文件读写函数重命名(如`FileRead`)
   - 记录浮点寄存器状态变化(`ST(0)-ST(7)`)

> 逆向本质:通过**数据流跟踪**(输入→处理→输出)和**控制流还原**(函数调用链)重建逻辑。遇到复杂算法时,先用黑盒测试推测数学关系,再验证反汇编结果。

建议从文件读取函数向后追踪,重点关注数据如何从文件缓冲区传递到计算模块。Pascal程序通常有清晰的模块边界,坚持每天分析2-3个函数,很快就能掌握全貌!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

快速收敛 发表于 2025-7-9 10:11:59

{:10_257:}
页: [1]
查看完整版本: 考古——逆向16位DOS程序