学习到的知识:
1、知道Handle块生成的套路即可(核心)
2、Esi伪代码加密不需要深入了解,为了完整性我才写下去(无用)
基础知识:
1、熟悉壳的都会发现壳入口都是:
pushad
pushfd
XXXX
popad
popfd
前后基本是固定的套路,主要是中间真正模拟的代码不同
2、如何看Vmp_SetEsiStruct参数对应哪条Handle块
ESI_Matching_Array每一组是8个字节
ESI_Matching_Array[2~3]:VMopcode(助记符)
ESI_Matching_Array[4]: 寻址方式
ESI_Matching_Array[5]: 大小
3、针对ADD系列提供对称的加密流程
加壳后动态解密
加壳前我们应该将数据加密一遍了
正文:
1、ESI伪代码构造的框架简单介绍
按照框架逻辑分为以下三步:
1、处理特殊Opcode (不重要,为了完整性)
2、构造Esi伪代码 (核心,看完这一步即可)
3、加密Esi伪代码与拼接跳转地址 (不重要,为了完整性才写下去)
2、Vmp_DisposeUserSpecialOpcode函数分析
3、Vmp_CreateEsiBytecode函数分析
3、1 构造出基本框架的Handle块
3、2 模拟出实际代替指令,以Push 403000为例
1、执行Vmp_CreateVM_POP_Context函数,构造出VM_POP_CONTEXT框架
我们发现以0x12(PUSH KEY)开始,0x14(push 0)结尾。其中过滤掉ESP
2、执行Vmp_UserOpcodeDisassembly函数,构造Push XXXX指令
首先根据VMopcode选择不同的执行流程
根据类型区别读取不同的数据
如何看Vmp_SetEsiStruct参数对应那条Handle块
ESI_Matching_Array每一组是8个字节
ESI_Matching_Array[2~3]:VMopcode(助记符)
ESI_Matching_Array[4]: 寻址方式
ESI_Matching_Array[5]: 大小
不就是对应我们那一句push 401000吗?
现在我们就已经把push 401000这一条指令模拟成功了
VM_POP_CONTEXT ---->0xB次
VM_PUSH_IMM ---->push 401000
那么我们还剩下构造退出指令的代码,就是VM_PUSH_CONTEXT加VM_RET
3、 剩下代码就是构造出结尾指令的
VMP是将两条指令为一组,在最后一组代码后面加上退出指令操作
执行完毕后如下:
总结:
1、将两组Opcode信息保存为一组的结构是struc_AllBytecode
2、现在ESI伪代码已经构造完成,那么还剩下两个问题 :
ESI代码存在哪里?
ESI代码对应的Index是什么?
3、3 针对struc_UserVmpPEInformationPY_50~54进行初始化或则乱序操作
struc_UserVmpPEInformationPY_50 == 2个Opcode为一组
struc_UserVmpPEInformationPY_54 == 保存特殊Opcode的
3、4 填充补充Esi信息
获取该Esi存放的地址和获取该Handle块的Index
填充前:
填充后:
Index是0,这是未加密的
3、5 蜜汁操作,生成一堆无用的垃圾代码
各位真正逆向分析找到Esi往前跳的即可,感觉这堆指令没什么用
3、6 Vmp_CreateEsiBytecode函数总结
1、其实VMP生成Handle块套路基本都是固定模板
2、假设是mov模拟:push +pop 不就可以了吗
xchg交换:push + pop 或则 xor a,b xor b,a xor a,b
其实自己随便搞也能模拟出来
3、剩下比较复杂的逻辑运算跟模拟cmp指令的我专门写一篇讲解