JSVMP(JavaScript Virtual Machine Protection) 是一种JavaScript代码保护技术,通过模拟虚拟执行环境(自定义指令集、堆栈、寄存器等)来隐藏原始代码逻辑,增加逆向难度。
核心特点:
-
自定义指令集:替换原生JS操作码为虚拟指令。
-
虚拟执行引擎:解析虚拟指令并模拟执行。
-
代码混淆:原始逻辑被转换为难以理解的虚拟指令序列。
示例代码:


目标网站分析


可以发现,传入参数和headers请求头里面有加密参数的痕迹,需要去逆向分析yrx15和yrx-15-jsvmp的生成逻辑,加密参数一定会在send之前生成,所以可以跟踪启动器,一步步跟栈,看作用域来找

可以发现需要的参数都在yrx_e和yrx_t中,接下来就是往上找堆栈,直到在作用域中找不到需要的参数,多半就是在这个堆栈内生成的,随后就是跟栈,直到找到这里


在这里你会发现无论怎么跳转下一个函数最终都会回到这里,这里也符合最开始所述的jsvmp的特征,这里我们需要通过插桩的方法来推测代码的执行结果,通过比对发现this[“nextOperant”]在case中频繁的出现,因此我们可以进入该方法然后进行插桩,同时进入该function我们可以看到type,value,raw,index等信息,这些能更好的帮助我们分析理解代码逻辑

现在获取该页面的js代码,通过fidder的autoresponse进行固定,固定后发现对应的参数还是动态的,可以通过hook方法发现调用了Date.getTime和Math.random方法,这里找一次请求然后获取固定住就行

这里将需要的信息通过console.log输出到控制台中

在网页的控制台中可以看到对应的加密参数已经生成,插桩成功,现在需要将对应的代码在本地运行,通过补环境,文本比对的方法补出浏览器环境
在本地运行时可以通过联调(浏览器和本地一起运行代码)的方法找出环境检测。
node也有自带的浏览器调试指令 node --inspect-brk demo.js, 分析到此结束,开始实操。
直接本地运行代码,将代码通过try catch包裹,在最后输出error可以先后发现window,navigator,document,和document.cookie需要补出,window使用node环境中的global,其他的使用{}即可,cookie需要在浏览器中获取,随后会发现这个报错

这个其实也很明显,需要去构造XMLHttpRequest

XMLHttpRequest 用于发送http请求 open 用于设置请求方法GET/POST send 用于提交表单数据 将这些补全后会报错screen未定义,进入报错会发现这里是获取环境来构造这个keys这里就也没什么好说的从浏览器拿数据补就行了,先后补出screen,createElement,getContext,getExtension,getParameter,loseContext,setRequestHeader,将这些补齐代码就能一路到底运行了 你以为就结束了? 这才刚开始呢老弟,发现最终的结果和真实结果有很大的差距,这种就是陷入了蜜罐,基本上蜜罐得浏览器和本地联调的方法来找,但jsvmp有个缺陷,就是下限高,但上限达不到top。 一般的小几万行顺序执行的js代码找蜜罐能找到天昏地暗,但jsvmp不一样,可以直接比对插桩的输出日志,很快的发现和浏览器的差别
左边是浏览器的插桩输出,右边是本地的插桩输出,可以发现在1688行这里出现了差异,然后往上一看可以发现是调用fingerprint_getfp这里出现了问题,进入代码可以发现问题。 代码调用了window.localStorage和sessionStorage,构造好这两个即可,然后再次比对可以先后找出navigator.plugins,navigator.webdriver,navigator.language等环境检测。 注:node版本尽量降低至18,作者原先node环境22,发现navigator.webdriver和userAgent在高版本中不能被修改,并且navigator似乎也有一些问题,被重写了好像。
补全后再次比对发现该错误,这个看着似乎是调用了new Error,在浏览器中搜索或者联调就可以发现问题,最后还有给小地方就是dum_getvis,检测document里面的visibilityState。 补充即可,至此环境就已经补全。 结果如下:
这里就也没什么好说的从浏览器拿数据补就行了,先后补出screen,createElement,getContext,getExtension,getParameter,loseContext,setRequestHeader,将这些补齐代码就能一路到底运行了
你以为就结束了?
这才刚开始呢老弟,发现最终的结果和真实结果有很大的差距,这种就是陷入了蜜罐,基本上蜜罐得浏览器和本地联调的方法来找,但jsvmp有个缺陷,就是下限高,但上限达不到top。
一般的小几万行顺序执行的js代码找蜜罐能找到天昏地暗,但jsvmp不一样,可以直接比对插桩的输出日志,很快的发现和浏览器的差别
左边是浏览器的插桩输出,右边是本地的插桩输出,可以发现在1688行这里出现了差异,然后往上一看可以发现是调用fingerprint_getfp这里出现了问题,进入代码可以发现问题。
代码调用了window.localStorage和sessionStorage,构造好这两个即可,然后再次比对可以先后找出navigator.plugins,navigator.webdriver,navigator.language等环境检测。
注:node版本尽量降低至18,作者原先node环境22,发现navigator.webdriver和userAgent在高版本中不能被修改,并且navigator似乎也有一些问题,被重写了好像。
补全后再次比对发现该错误,这个看着似乎是调用了new Error,在浏览器中搜索或者联调就可以发现问题,最后还有给小地方就是dum_getvis,检测document里面的visibilityState。
补充即可,至此环境就已经补全。
结果如下:

评论(已关闭)
评论已关闭