我是靠谱客的博主 大意水壶,最近开发中收集的这篇文章主要介绍JS 逆向 --- 过无限debugge、hook、js混淆还原、控制流混淆,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 

访问这个网站的时候,cookie 里面会有一个 sign 值,这个sign 值是通过 JavaScript 代码生成的,JS 代码是用 ob 混淆的,

当打开 "开发者工具" 时,会直接进入 "无限 debugger" 模式,过无限debugger 模式这里有三种方法

  • 方法 1.  直接 "从不在此处断点"
  • 方法 2.  查看调用堆栈,把进入无限 debugger 的那个函数在console中重新定义,把函数置空
  • 方法 3.  通过中间人攻击,替换 JavaScript 代码文件成本地文件,在本地文件中把 无限debugger 功能去掉( 注释掉 )。
        这种方法可以进行本地断点调试,和实时验证逆向的代码逻辑

这里使用 方法 3,把网站返回的混淆后的JS代码拿下来,放到 demo.html 文件里面,并用 <script></script>  包括,同时,把 hook cookie 的代码和框架代码也放里面,并放在 混淆代码之前

hook cookie 的代码:

(function () {
    'use strict';
    var cookie_cache = document.cookie;
    Object.defineProperty(document, 'cookie', {
        get: function () {
            console.log(cookie_cache);
            return cookie_cache;
        },
        set: function (val) {
            debugger;
            var cookie = val.split(";")[0];
            var ncookie = cookie.split("=");
            var flag = false;
            var cache = cookie_cache.split(";");
            cache = cache.map(function (a) {
                if (a.split("=")[0] === ncookie[0]) {
                    flag = true;
                    return cookie;
                }
                return a;
            })
            cookie_cache = cache.join(";");
            if (!flag) {
                cookie_cache += cookie + ";";
            }
        },
    });
})();

hook 框架的代码:

  • hook 和 AOPHooker JShttps://gitee.com/HGJing/hooker-js

 

demo.html 文件构造好后,打开 fiddler ---> AutoResponder,添加规则,

chrome 打上 script 断点,然后访问目标网站,即可断下

可以看到访问 JS 时,已经变成我们本地的 demo.html 文件了。然后去掉 script 断点,继续运行,会进入 无限debugger 模式,可以在本地文件中找到无限 debugger 的函数,直接注释掉,或者删除即可,也可以在console直接置空,更简单的是直接 "never pause here",这里使用 "never pause here" 然后继续运行,等待一会会直接进入 hook cookie 的 set 函数中,查看调用堆栈,即可找到关键位置

关键 JS 代码:_0x521302[$_0x5780('x30x78x37x38', 'x4fx71x6cx44') + 'x65x4c'](_0x30c194, _0x521302['x48x43x54' + 'x65x4c'](_0x451a25, _0x521302['x55x64x79' + 'x56x42'](_0x1af341)))

  • $_0x5780('x30x78x37x38', 'x4fx71x6cx44') + 'x65x4c' 放到 console 里面执行得到 "HCTeL"
  • 'x48x43x54' + 'x65x4c' 放到 console 里面执行得到 "HCTeL"
  • 'x55x64x79' + 'x56x42' 放到 console 里面执行得到 "UdyVB"

所以关键代码可以还原为:_0x521302["HCTeL"](_0x30c194, _0x521302["HCTeL"](_0x451a25, _0x521302["UdyVB"](_0x1af341)))

继续还原 _0x1af341,在 console 中执行,可以发现 是一个函数,执行 toString() 方法,打印方法内容。

function _0x1af341(_0x250d81){return new Date()[$_0x5780('x30x78x37x65','x64x24x75x57')+$_0x5780('x30x78x63x30','x69x7ax39x37')+'x66']();}

上面函数继续进行还原:$_0x5780('x30x78x37x65','x64x24x75x57')+$_0x5780('x30x78x63x30','x69x7ax39x37')+'x66' 执行后得到 "valueOf",

所以上面方法可以还原为:function _0x1af341(_0x250d81){return new Date().valueOf();}

现在还原 _0x521302["UdyVB"] 方法:执行 _0x521302["UdyVB"].toString()

可以看到这个函数传递了一个参数,这个参数执行了一个函数,函数体是返回函数执行后的结果。

所以 _0x521302["HCTeL"](_0x30c194, _0x521302["HCTeL"](_0x451a25, _0x521302["UdyVB"](_0x1af341)))

可以还原为  _0x521302["HCTeL"](_0x30c194, _0x521302["HCTeL"](_0x451a25, _0x1af341()))

再进一步还原:_0x521302["HCTeL"](_0x30c194, _0x521302["HCTeL"](_0x451a25, new Date().valueOf()))  ,验证还原结果:

按照上面方法在进一步还原:_0x30c194(_0x451a25(new Date().valueOf()))

现在只需要分析 _0x30c194、_0x451a25 ,先看下 _0x451a25 函数的 toString() :function _0x451a25(_0x787271){return _0x521302[$_0x5780('x30x78x31x33x65','x52x5ax77x72')+'x66x4d'](_0x521302[$_0x5780('x30x78x34x35','x4bx73x48x58')+'x66x4d'](_0x521302[$_0x5780('x30x78x31x33x65','x52x5ax77x72')+'x66x4d'](_0x521302[$_0x5780('x30x78x61x31','x29x72x71x78')+'x72x6d'],_0x787271)+'x7e',_0x521302[$_0x5780('x30x78x31x32','x71x75x31x47')+'x41x75'](_0x5b6292,_0x787271)),_0x521302[$_0x5780('x30x78x66x33','x30x33x4ex46')+'x45x71']);}

按上面步骤还原:

function _0x451a25(_0x787271) {
    return "sign=" + _0x787271 + "~" + _0x5b6292(_0x787271) + "; path=/";
}

所以整体逻辑可以变为

function _0x451a25(_0x787271) {
    return "sign=" + _0x787271 + "~" + _0x5b6292(_0x787271) + "; path=/";
}

var timestamp = new Date().valueOf()
_0x30c194(_0x451a25(timestamp))

//等价于
_0x30c194("sign=" + timestamp + "~" + _0x5b6292(timestamp) + "; path=/")

****************** 关键逻辑部分 ******************

这里只需要 分析 _0x5b6292(timestamp) 即可。

看下 _0x5b6292 的 toString():function _0x5b6292(_0x141932){return _0x521302[$_0x5780('x30x78x62x34','x41x6fx23x33')+'x41x75'](_0x2e58ec,_0x141932);} 

还原后等价于:_0x2e58ec(timestamp)

再继续分析  _0x2e58ec 。看下 _0x2e58ec 的 toString():"function _0x2e58ec(_0x2dd05e,_0x2bf8cf,_0x597aa3){return _0x2bf8cf?_0x597aa3?_0x521302[$_0x5780('x30x78x62x39','x4bx73x48x58')+'x6cx75'](_0x5b6292,_0x2bf8cf,_0x2dd05e):_0x521302[$_0x5780('x30x78x31x31x30','x43x34x4ex62')+'x44x44'](_0x1af341,_0x2bf8cf,_0x2dd05e):_0x597aa3?_0x521302[$_0x5780('x30x78x63x32','x69x65x46x51')+'x4dx6d'](_0x1091df,_0x2dd05e):_0x521302['x75x6dx74'+'x4ex65'](_0x289aa2,_0x2dd05e);}"

还原后等价于:_0x289aa2(timestamp)

继续分析 _0x289aa2 。看下 _0x289aa2 的 toString():function _0x289aa2(_0x22d83d){return _0x521302[$_0x5780('x30x78x33x37','x5dx57x5ax62')+'x4dx6d'](_0x554ed6,_0x1091df(_0x22d83d));}

还原后等价于:_0x554ed6(_0x1091df(timestamp))

总体逻辑等价于:_0x554ed6(_0x3f26c9(_0x161382(timestamp)))

_0x161382.toString():function _0x161382(_0x3dad10){return unescape(_0x521302[$_0x5780('x30x78x34x62','x52x5ax77x72')+'x4dx6d'](encodeURIComponent,_0x3dad10));}

还原后等价于:function _0x161382(timestamp){return unescape(encodeURIComponent(timestamp));}

整体逻辑等价于:_0x554ed6(_0x3f26c9(unescape(encodeURIComponent(timestamp))))

var timestamp = new Date().valueOf()
var encode_timestamp = unescape(encodeURIComponent(timestamp))
_0x554ed6(_0x3f26c9(encode_timestamp))

_0x3f26c9.toString():function _0x3f26c9(_0x4b9199){return _0x2b5e04(_0x1cb205(_0x17d11d(_0x4b9199),_0x521302[$_0x5780('x30x78x64x39','x5ex74x58x6a')+'x43x73'](0x8,_0x4b9199[$_0x5780('x30x78x65x30','x55x74x46x4b')+$_0x5780('x30x78x35x30','x39x2ax79x29')])));}

还原后等价于:

 

后面就是 抠  _0x554ed6  和 _0x3f26c9 的代码,然后执行 js 即可得到。。。。。。

 

 

 

 

 

最后

以上就是大意水壶为你收集整理的JS 逆向 --- 过无限debugge、hook、js混淆还原、控制流混淆的全部内容,希望文章能够帮你解决JS 逆向 --- 过无限debugge、hook、js混淆还原、控制流混淆所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部