今天我们来研究下,某头条的jsvmp逻辑层加密算法,其主要的目的是想在大家在接触此类算法时,给出点实质性的建议和思路。
0x01 分析加密
进入到目标网站通过分析请求会发现一个动态的 _signature 加密参数
0x02 定位加密
不同于以往,我们这次使用 ajax 请求拦截方式,来对这个参数进行拦截
通过堆栈的调用信息,得出以下结果
打上断点实现最终定位
换一种形式调用
0x03 window被赋予的属性
我们分析得知: _signature 参数由 window.byted_arawler.sign 方法实现,然而这个方法指向 acrawler.js 文件中一个莫名其妙的位置
所以我们目的也有了初步的明确:只要让 window 对象拥有 byted_acrawler 属性,那么整套算法就会被我们完全击破
0x04 惯用的方法
我们在本地新建一个 HTML 文件把代码整体拷贝过来,然后用浏览器打开
我们惊奇的发现,这个 byted_acrawler 属性已经存在于 window 对象之中,但是当我们借用 node 去执行它的时候,却秒被现实打脸
0x05 如何分析
我们先整体看下代码,除了 if-else 就是 else-if 活活的一个无限套娃形式,而且里面的逻辑,只用单一的字母表示,根本没有任何阅读性
虽然通篇都是 if-else 但它肯定也符合一定的逻辑规律,如若不然,它一定会报错。只不过官方这样做的目的,让它失去可读性,从而导致我们无法对分析。试想,我们可不可以,把它换一种形式进行表示出来,从而恢复它的可读性呢?
0x06 平坦化流程
这是一个全新的概念,也是对抗 jsvmp 算法必会的概念,虽然方式比较简单,但工程量比较庞大。我们需要将代码中所有的 if-else 替换成 switch-case 但问题在于 switch 哪个变量 case 那种情况?
观察一下这段代码:
var j = parseInt("" + b[O] + b[O + 1], 16);
验证一下,整体流程会不会因为j 变量的动态变化,进入到不同的逻辑分支?
不妨我们通过开篇所讲的条件断点试一下,每次 j=16 时会不会进入同一个逻辑分支中,如果能,说明 j 所有 if-else 的动态参数。如果不能,那就再去验证其他参数。
经验证,我们可以确定 j=16 时都会进入到上述的分支,所以我们不妨可以这样将它表示出来
switch (j) {
case 0:
// todo somethind
break;
case 16:
q = S[R--],
w = S[R--],
(A = S[R--]).x === G