软件逆向工程——混淆指令序列分析报告
初始状态说明
分析对象为以下指令序列,涉及栈操作、寄存器操作及条件转移相关逻辑:
push addr_branch_default ; 压入默认分支地址
push ebx ; 压入ebx寄存器值
push edx ; 压入edx寄存器值
mov ebx, [esp+8] ; 从栈中读取默认分支地址到ebx
mov edx, addr_branch_jmp ; 将目标跳转地址存入edx
cmovz ebx, edx ; 若ZF=1,ebx更新为addr_branch_jmp;否则ebx保持不变
mov [esp+8], ebx ; 将ebx的值写回栈中(覆盖原默认分支地址位置)
pop edx ; 恢复edx寄存器
pop ebx ; 恢复ebx寄存器
ret ; 从栈顶弹出地址并跳转
栈偏移说明:假设初始栈顶为esp0,每条指令执行后栈顶地址变化如下(esp值随push减4,pop加4)。
指令执行过程详解(按步骤)
push addr_branch_default
- 栈状态:
[esp0-4] = addr_branch_default,栈顶esp = esp0 - 4。 - 寄存器:无变化。
- 栈状态:
push ebx
- 栈状态:
[esp0-8] = ebx,栈顶esp = esp0 - 8。 - 寄存器:无变化。
- 栈状态:
push edx
- 栈状态:
[esp0-12] = edx,栈顶esp = esp0 - 12。 - 寄存器:无变化。
- 栈状态:
mov ebx, [esp+8]
- 计算
esp+8 = (esp0-12) + 8 = esp0 - 4,即栈中addr_branch_default的位置。 - 寄存器:
ebx = addr_branch_default。 - 栈状态:无变化,栈顶仍为
esp0 - 12。
- 计算
mov edx, addr_branch_jmp
- 寄存器:
edx = addr_branch_jmp(目标跳转地址)。 - 栈状态:无变化。
- 寄存器:
cmovz ebx, edx
- 条件:若
ZF=1(零标志位为1),则ebx = edx = addr_branch_jmp;否则ebx保持addr_branch_default。 - 寄存器:
ebx值根据ZF状态更新。 - 栈状态:无变化。
- 条件:若
mov [esp+8], ebx
- 计算
esp+8 = esp0 - 4(同步骤4),将ebx的值写回该位置。 - 栈状态:若
ZF=1,[esp0-4] = addr_branch_jmp;否则[esp0-4] = addr_branch_default。 - 寄存器:无变化。
- 计算
pop edx
- 栈顶
[esp0-12]的值恢复到edx,栈顶esp = esp0 - 8。 - 寄存器:
edx恢复为初始值(步骤3压入的值)。 - 栈状态:栈顶元素变为
ebx(步骤2压入的值)。
- 栈顶
pop ebx
- 栈顶
[esp0-8]的值恢复到ebx,栈顶esp = esp0 - 4。 - 寄存器:
ebx恢复为初始值(步骤2压入的值)。 - 栈状态:栈顶元素为步骤7更新后的地址(
addr_branch_jmp或addr_branch_default)。
- 栈顶
ret
- 从栈顶弹出地址(
[esp0-4])并跳转,栈顶esp = esp0。 - 最终跳转目标:若
ZF=1,跳转至addr_branch_jmp;否则跳转至addr_branch_default。
- 从栈顶弹出地址(
问题解答
问题(1):若addr_branch_default为ret下一条指令的地址, 以下混淆结果等价于什么指令?
答:当addr_branch_default是ret下一条指令的地址时,若跳转至 addr_branch_default,等价于“不跳转”(继续执行原流程)。
分情况讨论(从cmovz开始):
- 若
ZF=1:ebx更新为addr_branch_jmp,ret跳转至addr_branch_jmp(执行跳转)。 - 若
ZF=0:ebx保持addr_branch_default,ret跳转至ret的下一条指令(不跳转,继续执行)。
- 若
结论:
该混淆序列等价于一条条件跳转指令:jz addr_branch_jmp(若ZF=1,则跳至addr_branch_jmp;否则继续执行下一条指令)。
问题(2):若addr_branch_default为任一其他指令地址, 以下混淆结果等价于什么指令序列?
答:当addr_branch_default是其他地址时,跳转至该地址会执行新的流程,而非继续原流程。
分情况讨论(从cmovz开始):
- 若
ZF=1:ret跳转至addr_branch_jmp(执行目标跳转)。 - 若
ZF=0:ret跳转至addr_branch_default(执行默认分支跳转)。
- 若
结论:
该混淆序列等价于一条条件分支指令序列:jz addr_branch_jmp(若ZF=1跳至addr_branch_jmp);jmp addr_branch_default(若ZF=0跳至默认地址)。
最终结论
- 当
addr_branch_default为ret下一条指令的地址时,等价于:jz addr_branch_jmp。 - 当
addr_branch_default为其他地址时,等价于:jz addr_branch_jmp;jmp addr_branch_default。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 just.ok的个人博客!






