jsvmp逆向实战X-Bogus篇,算法还原
- 前言
- X-Bogus算法逻辑
- 寻找log插桩位置
- 第四步
- 第三步
前言
看过很多大佬关于X-Bogus算法还原的文章,都是通过log插桩,分析日志信息再结合动态调试一步步抽丝剥茧,最终还原算法,但是不同的插桩点带来的工作量是完全不同的。
经过我的不断摸索,找到了一个更加简单高效的逆向方法。jsvmp的特性除了压缩、混淆、大循环之外,还有一个重要的特征,就是通过apply的方式调用方法,那么我们只需要在大循环的代码里面找到apply并打上日志断点,就可以直接在日志里面分析算法逻辑了,而不是依赖大量的动态调试。
X-Bogus算法逻辑
X-Bogus算法的生成过程我把它分为以下四个大步骤,我们实际分析是反正来,从第四步开始逐步分析到第一步。
步骤 | 操作 |
---|---|
一 | 生成canvas,params、data、user-agent转为数组 |
二 | 将第一步生成的canvas和三个数组通过一些位移、&运算并加入时间戳合并成一个数组 |
三 | 将第二步生成的数组转为乱码,乱码再经过多次处理,生成最终的乱码 |
四 | 将乱码经过一系列运算生成X-Bogus |
寻找log插桩位置
打开某音网址,随便找个视频点个赞,然后查看点赞请求的调用堆栈。
点击图中标红位置,直接就会调到第一个apply,前后观察以下,发现这个apply就是在一个大循环中,先在这个apply打上日志断点,这个地方打断点需要注意一下。
断点内容:"function:",_0xc26b5e,"args:",_0x1f1790,"result:",_0x2458f0['apply'](_0xc26b5e, _0x1f1790),"_0x2458f0:",_0x2458f0
搜索一下看看大循环里面还有没有别的apply,这里是还有一个的,找到它,并打上断点。
断点内容:"function:",_0xc26b5e,"args:",_0x1f1790,"result:", _0x2458f0['apply'](_0xc26b5e, _0x1f1790),"_0x2458f0:",_0x2458f0
接下来就可以清空控制台,取消点赞,然后就可以在控制台分析日志了。
第四步
找到日志中第一次出现X-Bogus的位置,下图第一个红框这里调用了一个方法,参数是乱码字符串,生成了X-Bogus,下面的日志是具体的生成过程。
日志简单明了,function里面的乱码调用了charCodeAt方法,传入args生成了result,我们可以在控制台验证一下,如下图所示,传入参数和结果都能对上。
接着往下看,function的字符串、args参数、调用方法都变了,生成的结果也是最终X-Bogus的单个字符,"Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=".charAt()
控制台验证一下,都能对上,唯一不知道的就是0、47、60、45这几个参数哪来的,猜测肯定跟上一步生成的2、255、45有关,中间进行了哪些操作日志中并没有,这里就需要动态调试一下了,动态调试的过程就不说了,太麻烦。
动态调试需要改一下log日志,把整个循环的方法抠出来,折叠一下代码,然后仔细观察一下就会发现,通过_0xf24f2b、_0x3eb330、_0x217611、_0x2458f0,_0xf24f2b就能控制走到哪个分支,我们在前面的日志里面加上这几个参数,这样就知道怎么打条件断点了。
直接给出第四步的代码,传入乱码字符串验证一下
function get_x_bogus(lm){
var pub_key = "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=";
var x_bogus="";
for (let i = 0; i < lm.length; i += 3) {
var a = lm.charCodeAt(i);
var b = lm.charCodeAt(i+1);
var c = lm.charCodeAt(i+2);
const baseNum = c | (b << 8) | (a << 16);
const str1 = pub_key[(baseNum & 0xfc0000) >>> 18];
const str2 = pub_key[(baseNum & 0x3f000) >>> 12];
const str3 = pub_key[(baseNum & 0xfc0) >>> 6];
const str4 = pub_key[(baseNum & 0x3f)];
x_bogus += `${str1}${str2}${str3}${str4}`;
}
return x_bogus
}
可以看到结果和控制台的一模一样。
第三步
第三步就是生成第四步用到的乱码字符串,往上翻日志,如图所示标红位置就是乱码的生成过程,参数,方法都有,这一步是最简单的,直接控制台验证。
可以看到,结果跟控制台是一样的,接下来就得分析这个数组是怎么来的。第二步的逻辑现在的日志完全看不到,需要打条件断点动态调试,这里就不细讲了,两个apply断点就能把第一步、第三步的逻辑还原处理,第四步也需要动态调试。我是先把能还原的先还原,然后再动态调试把整个加密逻辑串联起来。如果你根据文章提示操作到这里,基本上就有了继续下去的动力,不会一头雾水了。