本文所讨论的对象为Code Virtualizer,所描述的方法应该也适用于其它虚拟机,使用的软件为IDA 5.5+IDAPython。
一.Handler还原
用PyEmu虚拟执行,得到Handler解密算法,定义还原脚本模板,再根据解密算法可以生成基本的还原Python脚本,附件的文件已实现该过程,由于是根据以前的老版本的dump_wmimmc.sys的解码脚本改写而成,未进行完整测试,有可能有Bug,附件的测试文件有5个虚拟机,已有一个虚拟机的还原脚本,其它的自行测试。
二.Handler识别
现阶段是根据解码的Handler按需进行助记符手动标记,下面是Handler识别的另一种想法,不一定可行,想法不是太清楚:
1.语义表达式
表达式Expr有这些操作:ExprAssign,ExprId,ExprImm,ExprCond,ExprMem,ExprOp,ExprSlice,ExprCompose,ExprOpt等说不清楚操作,举例说明(python语法):
a=ExprId('eax',32)
b=ExprId('ecx,32)
#输出eax,ecx
print a,b
#输出(eax+ecx)
c=ExprOp('+',a,b)
print c
#输出(eax+ecx)
d=a+b
print d
#输出eax[0:16]
ax=a[:16]
print ax
#输出dword ptr [eax+ecx]
d=ExprMem(c,32)
print d
#输出 d=(c+b)
a=ExprId('a',32)
b=ExprId('b',32)
c=a+b
print ExprAssign(d,c)
#输出((y-0x1)+0x2)
x=(y-ExprImm(uint32(1)))+ExprImm(uint32(2))
print x
#输出(y+0x1)
print ExprOpt(x)
最有用的操作是ExprOpt,用于指令压缩,主要优化是constant fold(常量折叠),ExprSlice主要用于分部寄存器,如标志位,16位寄存器等,ExprCompose用于表达式结合,ExprCond是汇编中jcc的语义转化.
2.虚拟机
该虚拟机是基于语义的,对汇编语言进行语义转化,然后虚拟执行。
假设虚拟机执行前的虚拟机环境为:
esp:init_esp
ebp:init_ebp
eax:init_eax
ebx:init_ebx
ecx:init_ecx
edx:init_edx
esi:init_esi
edi:init_edi
zf:0
.
.
.
在该虚拟机执行的语句为add eax,ebx 则执行完后的虚拟机环境应该为:
esp:init_esp
ebp:init_ebp
eax:init_eax+init_ebx
ebx:init_ebx
ecx:init_ecx
edx:init_edx
esi:init_esi
edi:init_edi
zf:(init_eax+init_ebx)==0
.
.
.
不论是X86代码,还是伪代码,进行语义转化后,虚拟机对指令压缩应该非常有效,并且实现各种Hook:寄存器读写Hook,堆栈读写Hook,内存读写Hook,汇编语句Hook,eip Hook等等,分析各个Hook生成的log,可以大概知道在虚拟机中的指令流程,实际上第一步的Handler解密完全可以用该虚拟机实现。
3.助记符标记
先刨去Handler解密算法,第一步可以实现,预先收集各Handler在该虚拟机执行完毕后的环境,已标记好各个Handler,虚拟执行Handler,用Levenshtein Distance算法比较其相似度,相似度高的就可以进行标记,如需要还要进行模式匹配。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!