[原创]CTF 逆向:基础 VM 的三大解法剖析
namename123 CTF 136浏览 · 2025-03-03 14:54

前几天,一位学弟发了道很基础的vm题目给我,我自己想用多种思路来解,中间碰壁多次,于是想着写一篇博客分享下碰壁过程以及关于vm题型我自己的一些解法

一、VM 核心原理速览

vm题型简介

程序大多会有自己一套循环的执行程序流 大致长相为

Plain Text
复制代码
这样的

其中opcode一般情况是由操作数和操作组成的一大串数据(通常由成百上千个byte组成) 说白了就是其中的加密过程很多,我们需要模拟执行流

破局思路

关键定位:虚拟指令分发器(opcode) 加密逻辑:找到他的循环加密 模拟重建:模拟执行流进行爆破或者解密

二、三种解法

解法一:传统手撕

将整个执行流程保存下来,倒着用enc去回到flag

解法二:正向Z3

模拟加密过程,使用Z3约束求解来得到flag

解法三:通过gbd或者frida插桩爆破

因为单字节或者双字节的缘故,所有可能也不过那么几样,我们通过一些手段可以实现爆破程序得到flag

高难度vm

2024年强网杯就有一道vm,对我来说很难 找不到opcode和中间的执行流 这种题我目前的想法也只会无脑的爆破程序,不出也不会了,硬看经常大脑卡死 (大佬轻松手撕)

三、解题

前言

解题前放两位大佬关于vm的博客,我也是跟着学的~ upsw1ng佬关于vm的博客 swdd佬关于利用frida去插桩爆破的博客

前面两种方法

因为前面两种方法都要去提取opcode,所以放一起了 我们以isctf2022年的一道很基础的vm来进行讲解 (题目已经上传了)

image.png
很纯粹的vm,不带任何杂质 一眼看见了程序加密逻辑


同时可以看见i是我们的opcode,i是由v8赋值而来,我们再看一眼v8



双击进去

image.png


基本上是opcode无疑 这里我们可以选择第一个变量,shift+8提取opcode 一共24个变量,一个变量16 byte
image.png


这里多提取一点以防万一 当然这里也可以使用idapython来提取,我就不过多赘述了 贴个脚本



提取了opcode我们再去复现执行流 这里有个坑了,我贴上最后的代码片段大家可以对比下


可以看见很多地方不一样,至于原理我就不是很懂了,有佬知道可以解答下吗~ 具体解密流程建议大家去看汇编代码 比如这里写的[1]

image.png


image.png


其实是[i-1]

现在opcode和执行流程有了,就是我们的求解方法了 这里衍生出了两张,一种是直接手撕逆回去,因为+-^都是可以逆的

解法一逆向手撕

先贴exp

这里因为异或优先级的原因,所以我选择把opcode存起来,然后从后往前进行解密 中间打印的那些,只是为了我当时方便去调试

解法二 Z3约束

这里有两个异曲同工的解法 首先推荐的是第一种

这里有个巨大的坑,卡了我十个小时,因为约束求解多项式的原因,优先级问题,我们在用flag去进行encode的时候,必须要创建一个副本,不然会因为符号变量原因什么的,导致中间那个&0xff和^的优先级会混乱 像下面这样


所以一定要encoded_flag = encode(flag, opcode) flag副本去solver

当然你也可以一个一个去打印出来,这样方便你去调试,这道题的wp就是这样做的,我也不水字数了,大家可以自己去看看

解法三frida插桩爆破

这里不会的师傅一定去看看上面给大家推荐的swdd的博客,我就直接贴脚本了

frida代码

报告大帅!解题完毕!
image.png




0 条评论
某人
表情
可输入 255