[备份]一处JS反调试引发的思考

起因

白帽子们挖Web漏洞时,JavaScript信息是至关重要的一环

从JS中可以得到隐藏接口等信息,然后尝试挖掘越权,SQL注入和上传等洞

笔者刚入门时候曾用这种办法挖到了一些CNVD,算是收获颇丰

回到主题,审计JS能够获得重要信息,然而并不是所有JS都能直接拿来看

很多情况下白帽子们将会面临混淆后的JS,这时候就需要尝试逆向调试分析了

最近在研究JS逆向相关的事情,遇到了一处比较有趣的代码

也许对于大佬来说很简单,不过我不太懂JS,第一次遇到感觉挺有趣的

起因是发现调试该JS时候会发现卡死,但目标网站在正常使用该JS脚本

分析

对全局JavaScript做了一定的分析后,最终跟踪到代码如下

注意到其中有类似正则的地方,所以第一印象这里可能是业务逻辑代码,分析后发现并不是

在一开始定义了大函数_0x4b1809

最终这样调用:new _0x4b1809(_0x2ba9)['OsLPar']();

跟入OsLPar函数

化简后为其实就可以看懂了:\w+ *\(\) *{\w+ *['|"].+['|"];? *}

不难猜出,该正则匹配的是:aaa () {aaa'aaa';}这样的字符串,看上去似乎是一个函数调用

照着写一段,验证猜测

得出结论,函数调用的最后分号后可以跟多个空格,但左大括号之后必须跟字符串

这个正则正是导致我卡死的反调试核心代码

回到代码中_0x1403ab['test']等价于上文代码的a.test

函数参数为this['HILIkx']['toString']()

这个参数是正则需要匹配的目标,跟入HILIkx函数发现只是简单的return字符串

注意最后还有一个toString代码,这里的toString不同于Java的方法

这里直接返回的是纯字符串"function () {\n return'newState';\n};"

显然可以得出结论,无法匹配到正则\w+ *\(\) *{\w+ *['|"].+['|"];? *}因此返回false

继续看后面的表达式,如果为true会从NsTJKl数组中移除1否则移除0,暂不分析这里的用途

函数的return会跟入anWLTR函数,传入的_0x26db32一定是false

其中的~是非运算,所以代码最终会进入this['xTDWoN'](this['YlKlnG'])

跟入xTDWoN函数,先不考虑传入的参数,因为参数只会影响到返回值

重点关注for循环内容,次数数组this['NsTJKl']['length']长度为2大于0,所以成功进入for循环

将for循环化简如下,发现for循环内会往数组NsTJKl中push一个随机数

然后将数组长度赋值给length,本来进入for循环的条件i<length是满足的,继续加入随机数导致for循环永远满足,也就是死循环

这里找到了卡死的原因,本质是一处的正则没有匹配到

问题来了,为什么目标网站的正则可以匹配到,但我本地无法匹配到

原因不难,目标网站的JS是压缩后的代码

逆向者在本地尝试做破解的时候,会将代码格式化(无论chrome还是vscode里都会很容易地进行格式化)

格式化后的代码不满足条件,所以会进入死循环

绕过方式其实也简单,还原回压缩格式即可

实现

使用node的babel库

上手写代码

给出一个demo.js文件,简单的一个两数相加函数

经过笔者自制工具处理后代码如下,给末尾添加调用语句add(1,2);执行该JS文件发现卡死

使用babel库的压缩代码功能

得到如下代码,执行代码后发现没问题