本帖最后由 Shocker 于 2021-8-10 10:49 编辑
前言
本文介绍一种根据IDA Python动态调试的OLLVM反混淆方法(基于x86_32指令)
思路
根据之前大佬们给出的ollvm流程图,可知
控制流平坦化
OLLVM的真实逻辑在
那么只要在这些块的头部下断点,记录下之前断点的位置,最后将块中真实块的跳转的地址修改为下一个真实的块的地址即可.
对所有真实块下断点
注意
1.一个真实块的后继真实块可能连接着多个真实块,也可能只有一个真实块
如上图所示,这个块中将一个立即数放入栈中的一个变量里,且该块的后继块中并无cmov指令,意味着该块的后继真实块只有一个.
2.若该块或其后继块中包含cmov指令
意味着该块的后继将会有两个真实块,在此例中,该块的下一个真实块由第一个条指令cmp决定.
若[ebp+var_8]的值小于5,它的下一个真实块由ecx(0D8AAAD2D)决定,反之由eax(140A249C)决定.
找出所有真实块的后继块
用IDA Python脚本记录所有的断点运行的地址
from idaapi import *
class MyDbgHook(DBG_Hooks):
""" Own debug hook class that implementd the callback functions """
def dbg_bpt(self, tid, ea):
print ("Break point at 0x%x pid=%d" % (ea, tid))
# return values:
# -1 - to display a breakpoint warning dialog
# if the process is suspended.
# 0 - to never display a breakpoint warning dialog.
# 1 - to always display a breakpoint warning dialog.
return 0
# Remove an existing debug hook
try:
if debughook:
print("Removing previous hook ...")
debughook.unhook()
except:
pass
# Install the debug hook
debughook = MyDbgHook()
debughook.hook()
debughook.steps = 0
# Stop at the entry point
ep = get_inf_attr(INF_START_IP)
request_run_to(ep)
# Step one instruction
request_step_over()
# Start debugging
run_requests()
将脚本载入IDA 并启动调试
F9直到程序结束.
就可以得到所有真实块的下一个真实块.
0x401600 -> 0x401677
0x401677 (该块包含cmov指令) -> 0x401690,0x4016cc
0x401690 -> 0x4016b3
0x4016b3 -> 0x401677
连接所有真实块
使用IDA的Keypatch插件就可以对代码进行patch
需要注意
结果
将无关的块进行nop后,结果如下
IDA 去混淆后F5的代码
混淆前F5的代码
萌新第一次发帖,如有不足之处请大家多等指教...
本文所用示例
链接:https://pan.baidu.com/s/15k9KQcHChFqMgMt8mFD6sA
提取码:mxnk
|