作者:yueji0j1anke
首发于公号:剑客古月的安全屋
字数:3814
阅读时间: 25min
声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。合法渗透,本文章内容纯属虚构,如遇巧合,纯属意外
目录
-
前言
-
前置知识
-
实例分析
-
总结
0x00 前言
笔者研究VMP已经一段时间了,无论是web端还是移动端,其实成型的vmp商业框架不少,但大多数在互联网上没有详细介绍与入门。所以从今天开一篇文章,打算与读者们好好唠嗑一下VMP与ollvm相关分析与实践
本期入门篇
0x01 前置知识
1.vmp
vmp是一种代码保护方案,将要保护的代码编译后,交由给具备特定指令集的虚拟机进行执行
简单来说,vmp可以将受保护的代码放入内置的虚拟机执行,从而防止反编译和破解。
除此之外,vmp还具备混淆、反调试等功能。
2.虚拟化原理
vmp虚拟机是一款栈机,同jvm一般,虚拟机和被保护的代码处于栈空间中,虚拟指令集通过操作栈顶元素完成。
之前我们讲过DVM便是基于寄存器的虚拟机,前者访问内存频繁涉及简单,后者执行效率更快,这种基于寄存器的虚拟机又被叫做LVM
3.虚拟化流程
这里列举x86架构的vmp标准
1.将被保护的代码编译后转换成虚拟指令集,每个虚拟指令对应一个处理程序,即handler,也相当于一个小型的解释器,在转换过程中,还会涉及到混淆和加密
2.插入VstartVM,将程序从真实环境切换至虚拟环境,将寄存器的状态保存,切换至堆栈空间
3.VMDispatcher读取虚拟指令,解码确定对应的handler,调用对应handler进行模拟执行
4.使用虚拟堆栈和真实堆栈进行数据存储,前者供虚拟机使用,后者是线程原有堆栈。当虚拟指令需要修改真实寄存器时,真实寄存器值会被保存在原有堆栈,虚拟寄存器的值则保存在真实寄存器上。不同线程通过维护vmcontext进行隔离
5.执行完毕,通过vret退出虚拟环境。
4.分析虚拟化流程
首先需要知道四个重要概念
VM_DATA -> 虚拟字节码,即要被执行的虚拟指令VM_EIP -> 指向VM_DATA的地址,虚拟机从这里获取指令VM_CONTEXT -> 虚拟机寄存器VM_STACK -> 虚拟栈
分析时一般需要分析以下
1.虚拟寄存器在哪里2.dispatcher在哪里,找到vm_eip3.解析每条handler
0x02 示例分析
分析相关参考文章
https://www.52pojie.cn/thread-713219-1-1.html
分析一款较老的vmp样本,vmprotect 1.81 Demo
是对如下代码vm获得
sub_401000 proc nearmov eax, dword_403000add eax, 12345678hsub eax, 12345678hmov dword_403000, eaxretnsub_401000 endp
1.基本结构
接下来我们打开被保护的vmp样本
看到对应地址
对应call的目的地址以及在.vmp0中了
对应逻辑,保存寄存器,分配堆栈空间
jmp ds:off_40409C[eax*4]
这一步跳转,很像dispatcher处理虚拟指令集,jmp到对应handler
那就关注对应eax寄存器,值来自于esi寄存器,esi寄存器的值来自于esp+2Ch+arg_0
对应的就是栈顶元素
看看404781偏移是什么东东
初始化有值的数据,那这里存储的就是VM_DATA,那对应来说ESI寄存器就等同于VM_EIP
对应的jmp就是一个dispacher
2.handler
那下面的这些块,就是handler了,我们来分析一下(取典型
这里,寄存器压栈
将EBP寄存器的值增加4,将EDX寄存器中的值存储到由EDI寄存器和EAX寄存器之和指向的内存地址
3.还原字节码
首先确认每个handler的功能位置,这里不展现完全了
.vmp0:0040409C off_40409C dd offset vPushReg4 .vmp0:004040A0 dd offset vshl2.vmp0:004040A4 dd offset loc_404058.vmp0:004040A8 dd offset loc_40464D.vmp0:004040AC dd offset loc_4045AF.vmp0:004040B0 dd offset loc_404041.vmp0:004040B4 dd offset loc_404058.vmp0:004040B8 dd offset loc_4045C0.vmp0:004040BC dd offset loc_4045AF.vmp0:004040C0 dd offset loc_404670.vmp0:004040C4 dd offset loc_404058.vmp0:004040C8 dd offset loc_40454E.vmp0:004040CC dd offset loc_4045AF.vmp0:004040D0 dd offset loc_404041.vmp0:004040D4 dd offset loc_404058.vmp0:004040D8 dd offset loc_40457C.vmp0:004040DC dd offset loc_4045AF.vmp0:004040E0 dd offset loc_40451A.vmp0:004040E4 dd offset loc_404058.vmp0:004040E8 dd offset loc_40449C.vmp0:004040EC dd offset loc_4045AF.vmp0:004040F0 dd offset loc_4046BF.vmp0:004040F4 dd offset loc_404058.vmp0:004040F8 dd offset loc_4044F6.vmp0:004040FC dd offset loc_4045AF.vmp0:00404100 dd offset loc_40449C.vmp0:00404104 dd offset loc_404058.vmp0:00404108 dd offset loc_4046EF.vmp0:0040410C dd offset loc_4045AF.vmp0:00404110 dd offset loc_4046EF.vmp0:00404114 dd offset loc_404058.vmp0:00404118 dd offset loc_40475E.vmp0:0040411C dd offset loc_4045AF.vmp0:00404120 dd offset loc_404069.vmp0:00404124 dd offset loc_404058.vmp0:00404128 dd offset loc_404591.vmp0:0040412C dd offset loc_4045AF.vmp0:00404130 dd offset loc_404077.vmp0:00404134 dd offset loc_404058.vmp0:00404138 dd offset loc_40454E.vmp0:0040413C dd offset loc_4045AF.vmp0:00404140 dd offset loc_4044D0.vmp0:00404144 dd offset loc_404058.vmp0:00404148 dd offset loc_4044D0.vmp0:0040414C dd offset loc_4045AF.vmp0:00404150 dd offset loc_404077.vmp0:00404154 dd offset loc_404058.vmp0:00404158 dd offset loc_404610.vmp0:0040415C dd offset loc_4045AF.vmp0:00404160 dd offset loc_40449C.vmp0:00404164 dd offset loc_404058.vmp0:00404168 dd offset loc_4046BF.vmp0:0040416C dd offset loc_4045AF.vmp0:00404170 dd offset loc_40457C.vmp0:00404174 dd offset loc_404058.vmp0:00404178 dd offset loc_40449C.vmp0:0040417C dd offset loc_4045AF.vmp0:00404180 dd offset loc_40453B.vmp0:00404184 dd offset loc_404058.vmp0:00404188 dd offset loc_4044AE.vmp0:0040418C dd offset loc_4045AF.vmp0:00404190 dd offset loc_40454E.vmp0:00404194 dd offset loc_404058.vmp0:00404198 dd offset loc_404719.vmp0:0040419C dd offset loc_404680.vmp0:004041A0 dd offset loc_404719.vmp0:004041A4 dd offset loc_4044F6.vmp0:004041A8 dd offset loc_404532.vmp0:004041AC dd offset loc_404706.vmp0:004041B0 dd offset loc_4045D8.vmp0:004041B4 dd offset loc_40475E.vmp0:004041B8 dd offset loc_404610.vmp0:004041BC dd offset loc_404610.vmp0:004041C0 dd offset loc_40449C.vmp0:004041C4 dd offset loc_4046BF.vmp0:004041C8 dd offset loc_404591.vmp0:004041CC dd offset loc_4046B2.vmp0:004041D0 dd offset loc_404069.vmp0:004041D4 dd offset loc_404591.vmp0:004041D8 dd offset loc_404591.vmp0:004041DC dd offset loc_4045C0.vmp0:004041E0 dd offset loc_4045C0.vmp0:004041E4 dd offset loc_4044AE.vmp0:004041E8 dd offset loc_40464D.vmp0:004041EC dd offset loc_404069.vmp0:004041F0 dd offset loc_40457C.vmp0:004041F4 dd offset loc_404610.vmp0:004041F8 dd offset loc_404077.vmp0:004041FC dd offset loc_4044D0.vmp0:00404200 dd offset loc_404610.vmp0:00404204 dd offset loc_404069.vmp0:00404208 dd offset loc_404680.vmp0:0040420C dd offset loc_404000.vmp0:00404210 dd offset loc_40457C.vmp0:00404214 dd offset loc_4045C0.vmp0:00404218 dd offset loc_40454E.vmp0:0040421C dd offset loc_404069.vmp0:00404220 dd offset loc_4044E4.vmp0:00404224 dd offset loc_404719.vmp0:00404228 dd offset loc_40476F.vmp0:0040422C dd offset loc_404532.vmp0:00404230 dd offset loc_40465F.vmp0:00404234 dd offset loc_404591.vmp0:00404238 dd offset loc_4046BF.vmp0:0040423C dd offset loc_4045D8.vmp0:00404240 dd offset loc_40462B.vmp0:00404244 dd offset loc_4044AE.vmp0:00404248 dd offset loc_40451A.vmp0:0040424C dd offset loc_40463B.vmp0:00404250 dd offset loc_404532.vmp0:00404254 dd offset loc_4044E4.vmp0:00404258 dd offset loc_4044D0.vmp0:0040425C dd offset loc_4044D0.vmp0:00404260 dd offset loc_404698.vmp0:00404264 dd offset loc_404680.vmp0:00404268 dd offset loc_40449C.vmp0:0040426C dd offset loc_404706.vmp0:00404270 dd offset loc_4044AE.vmp0:00404274 dd offset loc_40476F.vmp0:00404278 dd offset loc_4044BE.vmp0:0040427C dd offset loc_40451A.vmp0:00404280 dd offset loc_404584.vmp0:00404284 dd offset loc_404000.vmp0:00404288 dd offset loc_4044E4.vmp0:0040428C dd offset loc_404610.vmp0:00404290 dd offset loc_404069.vmp0:00404294 dd offset loc_40100A.vmp0:00404298 dd offset loc_404680.vmp0:0040429C dd offset loc_40100A.vmp0:004042A0 dd offset loc_404041.vmp0:004042A4 dd offset loc_40408E.vmp0:004042A8 dd offset loc_4046EF.vmp0:004042AC dd offset loc_404591.vmp0:004042B0 dd offset loc_404591.vmp0:004042B4 dd offset loc_4045D8.vmp0:004042B8 dd offset loc_40463B.vmp0:004042BC dd offset loc_4045C0.vmp0:004042C0 dd offset loc_40449C.vmp0:004042C4 dd offset loc_4046DA.vmp0:004042C8 dd offset loc_404706.vmp0:004042CC dd offset loc_404698.vmp0:004042D0 dd offset loc_40463B.vmp0:004042D4 dd offset loc_4044AE.vmp0:004042D8 dd offset loc_404584.vmp0:004042DC dd offset loc_40463B.vmp0:004042E0 dd offset loc_40464D.vmp0:004042E4 dd offset loc_40100A.vmp0:004042E8 dd offset loc_404077.vmp0:004042EC dd offset loc_4044D0.vmp0:004042F0 dd offset loc_40100A.vmp0:004042F4 dd offset loc_40475E.vmp0:004042F8 dd offset loc_4046B2.vmp0:004042FC dd offset loc_404591.vmp0:00404300 dd offset loc_4046B2.vmp0:00404304 dd offset loc_40465F.vmp0:00404308 dd offset loc_40449C.vmp0:0040430C dd offset loc_4045E9.vmp0:00404310 dd offset loc_404706.vmp0:00404314 dd offset loc_404706.vmp0:00404318 dd offset loc_404584.vmp0:0040431C dd offset loc_4045D8.vmp0:00404320 dd offset loc_4044F6.vmp0:00404324 dd offset loc_4044D0.vmp0:00404328 dd offset loc_4046B2.vmp0:0040432C dd offset loc_4045FC.vmp0:00404330 dd offset loc_4044AE.vmp0:00404334 dd offset loc_40457C.vmp0:00404338 dd offset loc_4045FC.vmp0:0040433C dd offset loc_404069.vmp0:00404340 dd offset loc_404568.vmp0:00404344 dd offset loc_40453B.vmp0:00404348 dd offset loc_404000.vmp0:0040434C dd offset loc_40475E.vmp0:00404350 dd offset loc_40465F.vmp0:00404354 dd offset loc_404584.vmp0:00404358 dd offset loc_4045FC.vmp0:0040435C dd offset loc_40476F.vmp0:00404360 dd offset loc_4044F6.vmp0:00404364 dd offset loc_404568.vmp0:00404368 dd offset loc_4044E4.vmp0:0040436C dd offset loc_4045FC.vmp0:00404370 dd offset loc_40475E.vmp0:00404374 dd offset loc_4046B2.vmp0:00404378 dd offset loc_404041.vmp0:0040437C dd offset loc_40453B.vmp0:00404380 dd offset loc_4044E4.vmp0:00404384 dd offset loc_404508.vmp0:00404388 dd offset loc_4044E4.vmp0:0040438C dd offset loc_404508.vmp0:00404390 dd offset loc_4044BE.vmp0:00404394 dd offset loc_4044D0.vmp0:00404398 dd offset loc_4046EF.vmp0:0040439C dd offset loc_404698.vmp0:004043A0 dd offset loc_404077.vmp0:004043A4 dd offset loc_404041.vmp0:004043A8 dd offset loc_4045D8.vmp0:004043AC dd offset loc_4044D0.vmp0:004043B0 dd offset loc_4046EF.vmp0:004043B4 dd offset loc_40464D.vmp0:004043B8 dd offset loc_40453B.vmp0:004043BC dd offset loc_404610.vmp0:004043C0 dd offset loc_4045C0.vmp0:004043C4 dd offset loc_404680.vmp0:004043C8 dd offset loc_40463B.vmp0:004043CC dd offset loc_4045FC.vmp0:004043D0 dd offset loc_404532.vmp0:004043D4 dd offset loc_40453B.vmp0:004043D8 dd offset loc_4046DA.vmp0:004043DC dd offset loc_404591.vmp0:004043E0 dd offset loc_404069.vmp0:004043E4 dd offset loc_404680.vmp0:004043E8 dd offset loc_404610.vmp0:004043EC dd offset loc_404069.vmp0:004043F0 dd offset loc_404610.vmp0:004043F4 dd offset loc_40476F.vmp0:004043F8 dd offset loc_4046DA.vmp0:004043FC dd offset loc_404508.vmp0:00404400 dd offset loc_40408E.vmp0:00404404 dd offset loc_404719.vmp0:00404408 dd offset loc_4044BE.vmp0:0040440C dd offset loc_4045E9.vmp0:00404410 dd offset loc_4044D0.vmp0:00404414 dd offset loc_4044F6.vmp0:00404418 dd offset loc_4044E4.vmp0:0040441C dd offset loc_40465F.vmp0:00404420 dd offset loc_40408E.vmp0:00404424 dd offset loc_4044D0.vmp0:00404428 dd offset loc_404670.vmp0:0040442C dd offset loc_404532.vmp0:00404430 dd offset loc_40464D.vmp0:00404434 dd offset loc_404584.vmp0:00404438 dd offset loc_404698.vmp0:0040443C dd offset loc_40462B.vmp0:00404440 dd offset loc_4044BE.vmp0:00404444 dd offset loc_404508.vmp0:00404448 dd offset loc_4044BE.vmp0:0040444C dd offset loc_404041.vmp0:00404450 dd offset loc_404670.vmp0:00404454 dd offset loc_404706.vmp0:00404458 dd offset loc_40465F.vmp0:0040445C dd offset loc_404508.vmp0:00404460 dd offset loc_404041.vmp0:00404464 dd offset loc_40453B.vmp0:00404468 dd offset loc_4046B2.vmp0:0040446C dd offset loc_404706.vmp0:00404470 dd offset loc_404568.vmp0:00404474 dd offset loc_40100A.vmp0:00404478 dd offset loc_404000.vmp0:0040447C dd offset loc_40465F.vmp0:00404480 dd offset loc_404532.vmp0:00404484 dd offset loc_4045E9.vmp0:00404488 dd offset loc_40475E.vmp0:0040448C dd offset loc_40464D.vmp0:00404490 dd offset loc_4045E9.vmp0:00404494 dd offset loc_4046EF.vmp0:00404498 dd offset loc_40100A
接下来看vm_data
第一个字节0E,跳转的位置即是0040409C + 0x0E *4
即0x4040D4
.vmp0:004045AF and al, 3Ch.vmp0:004045B2 mov edx, [edi+eax].vmp0:004045B5 sub ebp, 4.vmp0:004045B8 mov [ebp+0], edx
0x0E & 0x3C = 0x0C
。 4 字节一个寄存器,0x0C/4 = 3
。因此这里是将栈中的值写入第3个寄存器(记为R3)。
整条指令就可以记为 vPushReg4 R3
。
对应整个vmdata如下
0E E8 81 A9 5D 76 5C 1E 1A 0A 3E 2E 26 36 3A 2A 12 02 06 22 E8 00 30 40 00 79 16 69 78 56 34 12 14 7A 1E 36 E8 78 56 34 12 34 97 4D 6B 06 5C 3E 97 21 11 22 06 3C 4C 21 11 16 EB EA F7 11 1E 20 20 6B 32 77 15 08 78 32 5C 32 36 04 69 00 30 40 00 ED 00 10 20 38 04 24 2C 34 08 1C 00 E1 00
写个python脚本进行匹配即可
# 字节数组byte_array = [0x0E, 0xE8, 0x81, 0xA9, 0x5D, 0x76, 0x5C, 0x1E, 0x1A, 0x0A, 0x3E, 0x2E, 0x26, 0x36,0x3A, 0x2A, 0x12, 0x02, 0x06, 0x22, 0xE8, 0x00, 0x30, 0x40, 0x00, 0x79, 0x16, 0x69,0x78, 0x56, 0x34, 0x12, 0x14, 0x7A, 0x1E, 0x36, 0xE8, 0x78, 0x56, 0x34, 0x12, 0x34,0x97, 0x4D, 0x6B, 0x06, 0x5C, 0x3E, 0x97, 0x21, 0x11, 0x22, 0x06, 0x3C, 0x4C, 0x21,0x11, 0x16, 0xEB, 0xEA, 0xF7, 0x11, 0x1E, 0x20, 0x20, 0x6B, 0x32, 0x77, 0x15, 0x08,0x78, 0x32, 0x5C, 0x32, 0x36, 0x04, 0x69, 0x00, 0x30, 0x40, 0x00, 0xED, 0x00, 0x10,0x20, 0x38, 0x04, 0x24, 0x2C, 0x34, 0x08, 0x1C, 0x00, 0xE1, 0x00]base_address = 0x40409C# 基础地址# 读取映射文件到字典中address_map = {}withopen('mapping.txt', 'r', encoding='utf-8') asfile:forlineinfile:# 提取地址和标识符parts = line.split()iflen(parts) == 4:addr = int(parts[0][6:], 16) # 从 ".vmp0:0040409C" 获取 "0040409C" 并转换为整数identifier = parts[3] # 获取最后一个部分,偏移标识符address_map[addr] = identifier# 计算地址和输出相应的标识符forbyteinbyte_array:ifbyte == 0x00:continueoffset = byte*4calculated_address = base_address+offsetidentifier = address_map.get(calculated_address, "未知")print(f'字节: {byte:02X}, 地址: {calculated_address:08X}, 对应执行: {identifier}')
然后分析具体handler,打标记即可
0x03 总结
核心是掌握VMP执行流程,在反汇编中准确找到 dispatcher等关键执行步骤。该vmp无反混淆花指令,第一次分析起来都还蛮吃力的。现在工业级的应用都加入大量ollvm+花指令,分析起来将会更加复杂。。
参考文章:https://www.52pojie.cn/thread-713219-1-1.html#19342079_%E5%AE%9E%E4%BE%8B%E5%88%86%E6%9E%90-vmprotect-1.81-demo
原文始发于微信公众号(剑客古月的安全屋):移动端VMP攻防-如何分析VMP&入门篇
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论