本帖最后由 Shocker 于 2021-8-11 14:34 编辑
前言
本文是对上一篇文章
基于IDA Python的OLLVM反混淆(二) 实战腾讯御安全(模拟器)
的补充.
思路
- 合并代码块
- 修复call的偏移地址
- 去除残留的属于控制块的代码
实现过程
实验环境:ida7.5+雷电模拟器(64位)4
由上篇可知
原始指令最终被化简成了许多的代码块,且大多数代码块的结尾以jmp结束
我们就可以将jmp指令去除,将代码块合并在一起
代码块合并
#combine_block.py
import keypatch
from idaapi import *
import capstone
import struct
combine_blocks={}
ea_blcok_map={}
codes_map={}
def nop_block(block):
nop_code=0x90
for i in range(block.end_ea-block.start_ea):
idc.patch_byte(block.start_ea+i,nop_code)
so_base=idaapi.get_imagebase()
fun_offset=0x25D0
f_blocks = idaapi.FlowChart(idaapi.get_func(so_base+fun_offset), flags=idaapi.FC_PREDS)
for block in f_blocks:
if block.start_ea==block.end_ea:
continue
ea_blcok_map[block.start_ea]=block
codes_map[block.start_ea]=get_bytes(block.start_ea,block.end_ea-block.start_ea)
block_end=idc.prev_head(block.end_ea)
if idc.print_insn_mnem(block_end).startswith('j'):
next_block=get_operand_value(block_end,0)
combine_blocks[block.start_ea]=next_block
else:
combine_blocks[block.start_ea]=block.end_ea
# 将所有块nop后再将原始指令连接
nop_block(block)
first_block=so_base+fun_offset
wirte_offect=0
while True:
if wirte_offect==0:
block=ea_blcok_map[first_block]
else:
block=ea_blcok_map[next_block]
codes=codes_map[block.start_ea]
md=capstone.Cs(capstone.CS_ARCH_X86,capstone.CS_MODE_32)
for code in md.disasm(codes,block.start_ea):
if code.mnemonic=='jmp' or code.mnemonic.startswith('cmov') or code.mnemonic=='nop': #排除这些指令
continue
block_bytes=bytes(code.bytes)
if code.mnemonic=='call':
if code.op_str.startswith('0x'):
called_addr=int(code.op_str,16)
fix_addr=called_addr-fun_offset-wirte_offect-5
fix_bytes=struct.pack('i',fix_addr)
block_bytes=bytes(code.bytes[0:1])+fix_bytes
print('combine_block:0x%x'%block.start_ea)
patch_bytes(first_block+wirte_offect,block_bytes)
wirte_offect=wirte_offect+len(block_bytes)
if block.start_ea in combine_blocks:
next_block=combine_blocks[block.start_ea]
if not next_block in ea_blcok_map:
break
else:
break
# print('0x%x,0x%x'%(key,combine_blocks[key]))
合并后的流程图
可以看到,还有许多属于控制块的指令没有去除
去除混淆指令
去除混淆指令原理基于
x86反混淆IDA Python脚本 (一)
反复运行该脚本直到无新指令被patch,手动删除一些无效的内存指令
最后执行combine_block.py脚本去除所有nop指令
去混淆的代码片段如下所示
相关示例代码见
https://github.com/PShocker/de-ollvm/
|