编辑
2025-05-19
jsVmp反编译
00
请注意,本文编写于 46 天前,最后修改于 12 天前,其中某些信息可能已经过时。

目录

一. 构建ast节点
1. 闭包函数的创建
2. try-tatch的处理
3. 跳转指令的处理
4. 最后得到nodeGrapth
二.SSA转化和还原代码结构
三.反编译的代码正确性验证

一. 构建ast节点

思路

hook栈,如果对栈数组某个位置进行赋值,就生成一个用临时变量接收这个值的赋值语句,并生成一个GraphNode节点,并正确连接后驱节点关系,以便后续建立CFG结构还原控制流

image.png

image.png

image.png

1. 闭包函数的创建

第一步找到vmp模拟函数闭包的创建的逻辑。因为我们还原最大的单位是方法,然后是语句,控制流。 腾讯的vmp非常清晰,E变量为pc指针,C指令集,w为栈和堆,也就是每次执行指令的中间值和变量储存的位置都是w。我们需要区分变量和中间值。腾讯用于存储变量的值,是以一个长度为1的数组进行包裹,变量的储存空间为这个数组的0索引,这样就可以把变量存储空间的引用传给新建的闭包函数,以便在闭包函数访问和修改。 db75e493aaf11626fbac8f300d9d0c2.png 图中1处解析:首先闭包函数需要一个栈和堆空间,为图中的A变量。然后把父函数,也就是创建闭包函数的函数中的变量传递给闭包函数。

图中2处解析:初始化闭包函数的变量,K[0]为函数创建上下文this,K[1]为调用闭包函数的参数列表,[2]为闭包函数本身。

图中3处解析: 初始化调用闭包函数的每一个参数,相当于把每一个参数作为闭包函数里的var变量。 所以我们可以改写这个case函数。

image.png push创建的闭包函数的ast到栈里。 image.png genarateFucAst方法调用getBlockAst方法dump出方法的所有语句。

2. try-tatch的处理

try-catch的处理:需要注意的是try和catch的汇合点的寻找。 image.png

3. 跳转指令的处理

image.png

4. 最后得到nodeGrapth

nodeGrapth保存每一个语句节点,和语句节点之间的后驱关系。 image.png

二.SSA转化和还原代码结构

详细见http://dtt666.com/post/3

三.反编译的代码正确性验证

1.直接把还原的代码替换掉原网站原本的vmp,可以正确运行并生成加密参数

2.浏览器直接调用vmp中的加密方法,结果与原vmp一致

原vmp结果:

34e5d132ae97b7f773d82ea2a7e71b9.png

image.png

反编译的vmp结果:

d5ed7feab9147d77d9b924bb3e00102.png

image.png

本文作者:韦峰

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!