吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5362|回复: 19
收起左侧

[Web逆向] 17track接口逆向分析

  [复制链接]
领域 发表于 2020-7-6 13:34

没有放修改后的完整代码,纯粹的学习,谁有更好方法找到_0x4f3f里内存暴破,请指教啊!

调试

17track的快递查询接口,可以通过调试工具看到请求,但是直接通过POST工具是没有结果的,最后测试需要加上Last-Event-ID这个cookie
1.jpg " alt="在这里插入图片描述" />
看了网页加载的js文件,最终只有一个加密的track.min.js,而且发现非常可疑的setCookie,还有Last-Event-ID字符。第一行是个数组,接下一共两个自执行的匿名函数。

(function(_0x2297ee, _0x5f41f3) {
......
}(_0x50c7, 0x9f));
......
(function() {
    var _0x10f375
    ......
    _0x4cec2b();
}());

对这两个函数下断点,clear storage刷新然后一步一步调试。这里只要调用了函数的我们都对函数下断点。当跟到_0x4f3f这个函数的时候,发现很多地方都调用了这个函数,对返回下断点发现是返回的字符串。就把断点取消了继续跟,不然手要按软。第二个自执行函数最后调用的_0x4cec2b,_0x4cec2b最后又调用_0x3966d3,当断到_0x3966d3的时候已经能看到请求信息了,_0x164a16就是post的json,_0x152eb7就是一个ajax请求
3.jpg " alt="在这里插入图片描述" />
跟到_0x3966d3的时候,可以看到前两个参数是函数,最后是一个数字。继续一步一步走,注意_0x126b58 这个值是在变化的。
4.jpg " alt="在这里插入图片描述" />
最后在这里找到了Last-Event-ID,拿去post试一试,成功。

分析代码

我们还原设置Last-Event-ID的代码。

document[_0x4f3f('0x67', 'x3Lg')] = _0x2ec18e[_0x4f3f('0x68', '^p2Z')](_0x316f08, '=') + _0x472ff2[_0x4f3f('0x4d', 'uFIh')]('') + _0x2ec18e[_0x4f3f('0x69', 'aeh^')] + _0x1720d7[_0x4f3f('0x6a', 'LaH7')](); 

直接在控制台调用_0x4f3f函数得到

document["cookie"] = _0x2ec18e["GAOJi"]('Last-Event-ID', '=') + _0x472ff2["join"]('') + _0x2ec18e["FPaVy"] + _0x1720d7["toGMTString"](); 

_0x472ff2["join"]('')//就是我们要的Last-Event-ID

_0x472ff2是重要变量,复制所有加密代码,格式化,放到新网页执行。哈哈哈,崩溃了。
5.jpg " alt="在这里插入图片描述" />
看来是有检测代码。这里我不知道怎么才能下断点,只有一步一步故意写错代码,看是先崩溃还是先报错确定了检测代码位置。有大佬有好方法没?

_0x3184d0['prototype']['yzecjS'] = function() {
                var _0x5e1a47 = new RegExp(this['IbesCh'] + this['kRbSMK']);
                var _0x44235e = _0x5e1a47['test'](this['ZDEFCw']['toString']()) ? --this['LoqXko'][0x1] : --this['LoqXko'][0x0];//这里是一个正则匹配,把_0x44235e 设为-1就跳过了
                return this['NUSOYG'](_0x44235e);
            }

刷新执行,又报新的错误,这个错误直接显示了位置,下断点跟原网页对比

var _0xd2c455 = function(_0x570d92) {
                var _0x6d545d = ~-0x4 >> 0x1 + 0xff % 0x0;
                if (_0x570d92['\x69\x6e\x64\x65\x78\x4f\x66']((!![] + '')[0x3]) !== _0x6d545d) { //这个判断改为不成立即可跳过
                    _0x10cf6b(_0x570d92);
                }
            };

到这里,继续,还是报错,这个错误简单明了缺少jquery,在网页加上。搜索_0x3966d3 找到调用它的地方。

        _0x2ec18e[_0x4f3f('0x86', 'oD72')]($, document)[_0x4f3f('0x87', 'tG@(')](function(_0x2c3354, _0x28d1d7, _0x152eb7) {
            if (_0x152eb7[_0x4f3f('0x88', 'Ho1%')][_0x4f3f('0x89', 'klod')](_0x4f3f('0x8a', 'L*ZS')) && _0x152eb7['data']) {
                _0x567d6b = _0x152eb7[_0x4f3f('0x8b', 'oD72')];
                var _0x164a16;
                try {
                    _0x164a16 = JSON['parse'](_0x567d6b);
                } catch (_0x198faf) {
                    if (_0x2ec18e[_0x4f3f('0x8c', 'bv*^')](_0x2ec18e[_0x4f3f('0x8d', '!nz(')], _0x4f3f('0x8e', 'PGF('))) {
                        var _0x574153 = _0x56b4ca[_0x4f3f('0x8f', 'qd7c')](_0x3df0c1, str, seed);
                        if (tag) {
                            _0x472ff2[0x5] = _0x56b4ca[_0x4f3f('0x90', 'm^Gz')](_0x2c724a, _0x574153[_0x4f3f('0x91', 'x3Lg')](0x10));
                            return;
                        }
                        _0x472ff2[0x4] = _0x2c724a(_0x574153['toString'](0x10));
                    } else {
                        _0x164a16 = null;
                    }
                }
                if (_0x164a16 && _0x2ec18e[_0x4f3f('0x92', 'x3Lg')](_0x164a16[_0x4f3f('0x93', 'H0Sy')], '')) {
                    try {
                        _0x2ec18e[_0x4f3f('0x94', '!nz(')](_0x9ff66b, _0x567d6b, _0x567d6b[_0x4f3f('0x95', 'l3oQ')], !![]);
                        var _0x3fd2d0 = _0x4f3f('0x96', '7la!') + _0x4f3f('0x97', 'ttkq') + ']';
                        var _0x3a6885 = _0x2ec18e[_0x4f3f('0xe', '#C9L')]($, _0x3fd2d0);
                        _0x3966d3(_0x28d1d7, _0x3a6885, _0x1a395d(_0x3a6885[_0x4f3f('0x98', 'QKX0')]));
                    } catch (_0x1739bd) {}
                }
            }
        });

还原后

        $(document).ajaxSend(function (_0x2c3354, _0x28d1d7, _0x152eb7) {
            if (_0x152eb7['url']['match']('(//[a-z]+.17track.net/restapi/track)') && _0x152eb7['data']) {
                _0x567d6b = _0x152eb7['data']; //post的数据 {"data":[{"num":"***","fc":0,"sc":0}],"guid":"","timeZoneOffset":-480}
                var _0x164a16; 
                try {
                    _0x164a16 = JSON['parse'](_0x567d6b);//执行JSON.parse获得对象
                } catch (_0x198faf) {
                    //这里省略掉
                }
                if (_0x164a16 && _0x2ec18e['ZIKlo'](_0x164a16['guid'], '')) { //guid参数为空
                    try {
                        //_0x2ec18e['WaYmY'](_0x9ff66b, _0x567d6b, _0x567d6b.length, true);
                        _0x9ff66b(_0x567d6b, _0x567d6b.length, true);//这句跟上面句相等,调用了_0x9ff66b传了data数据和长度,去看_0x9ff66b函数实际对_0x472ff2关键变量作了设置
                        var _0x3fd2d0 = _0x4f3f('0x96', '7la!') + _0x4f3f('0x97', 'ttkq') + ']';//_0x3fd2d0 = "[class*='yq-']";
                        var _0x3a6885 = _0x2ec18e[_0x4f3f('0xe', '#C9L')]($, _0x3fd2d0);//_0x3a6885 = $("[class*='yq-']");
                        _0x3966d3(_0x28d1d7, _0x3a6885, _0x1a395d(_0x3a6885[_0x4f3f('0x98', 'QKX0')]));//调用_0x3966d3传入的参数,_0x28d1d7是XMLHttpRequest,_0x3a6885 = $("[class*='yq-']"),_0x3a6885[_0x4f3f('0x98', 'QKX0')] = _0x3a6885['length'] = $("[class*='yq-']").length,实际等于21,接下来是_0x1a395d函数传入了$("[class*='yq-']").length,
                    } catch (_0x1739bd) { }
                }
            }
        });

_0x1a395d函数

    function _0x1a395d(_0x3e48ff) { //传过来的21
        var _0x402f82 = _0x3e48ff;
        if (window && document && window['innerHeight'] && window[_0x4f3f('0x19', 'VMDb')] > 0x0) {//这里判断了innerHeight,我们要把这个判断去掉
            var _0x5027d7 = window[_0x4f3f('0x1a', 'klod')]['random']();//_0x5027d7 = Math.random();
            _0x402f82 = window[_0x4f3f('0x1b', 'DYwS')]['round'](_0x2ec18e[_0x4f3f('0x1c', '0BWm')](_0x5027d7, _0x3e48ff));//Math.round(_0x5027d7 * _0x3e48ff);//生成了一个随机数_0x402f82 
        }
        //设置了关键变量_0x472ff2
        _0x472ff2[0x1] = _0x402f82[_0x4f3f('0x1d', 'sge9')](0x10);//_0x402f82.toString(16);
        _0x472ff2[0x2] = _0x402f82[_0x4f3f('0x1e', 'PGF(')](0x10)['length'];//_0x402f82.toString(16).length;
        return _0x402f82;//返回了这个数
    }

_0x3966d3函数

    function _0x3966d3(_0x8517d0, _0xae9512, _0x1e1c09) { //_0x1e1c09 = _0x1a395d生成的数字,
        var _0x126b58 = _0x4f3f('0x56', '#C9L');//_0x126b58  = "yq-";
        var _0x316f08 = _0x4f3f('0x57', 'tG@(');//_0x316f08 = 'Last-Event-ID';
        if (_0xae9512[_0x4f3f('0x58', 'V91Y')] > _0x1e1c09 && document && document[_0x4f3f('0x59', 'Tbb9')]) {//$("[class*='yq-']").length > _0x1e1c09 && document && document['removeEventListener'],_0xae9512['length'] = $("[class*='yq-']").length;
            _0x126b58 = _0xae9512[_0x1e1c09]['className'];//这里修改了_0x126b58值,最后我把_0x1a395d生成的数字设置为固定值,_0x126b58也设置成对应的className,可以去掉这个判断了。
        }
        _0x126b58 = _0x126b58 + '/' + window[_0x4f3f('0x5a', 'fxzh')]['now']()[_0x4f3f('0x5b', 'VMDb')](0x10) + '/' + window[_0x4f3f('0x5c', 'MtlY')][_0x4f3f('0x5b', 'VMDb')](0x10) + '/' + _0x4ba351(); //_0x126b58 + '/' + Date.now().toString(16) + '/' + window.innerHeight.toString(16)+ '/' + _0x4ba351(); 最后咱是要脱离浏览器运行的,window.innerHeight.toString(16)可以设置为一个固定值,最后是_0x4ba351这个函数
        _0x9ff66b(_0x126b58, _0x1e1c09);//_0x9ff66调用了_0x3df0c1,_0x3df0c1调用了_0x5e7be4,_0x5e7be4又有检测函数
        _0x126b58 = _0x2ec18e[_0x4f3f('0x5d', 'H0Sy')](_0x3c4889, _0xd74c71(_0x126b58));
        _0x472ff2[0x0] = _0x126b58;
        //后面的代码已经没有用了,目的只为得到Last-Event-ID
        var eid = _0x472ff2.join("");
        return eid;
        ......
    }

_0x4ba351

    function _0x4ba351() {  //这个密密麻麻一大片,主要目的是生成XMLHttpRequest返回一个true,咱又不需要XMLHttpRequest。直接return true就好
        if (_0x2ec18e[_0x4f3f('0x39', '4PG(')] === _0x4f3f('0x3a', 'VuqV')) {
            var _0x2371bc = _0x4f3f('0x3b', 'f*#]');
            var _0x135745 = _0x2ec18e[_0x4f3f('0x3c', '1gMZ')];
            if (objs[_0x4f3f('0x3d', 'DYwS')] > rndNo && document && document[_0x4f3f('0x3e', 'V91Y')]) {
                _0x2371bc = objs[rndNo][_0x4f3f('0x3f', 'tG@(')];
            }
            _0x2371bc = _0x2ec18e[_0x4f3f('0x40', 'Ho1%')](_0x2ec18e[_0x4f3f('0x41', 'VuqV')](_0x2371bc + '/' + window[_0x4f3f('0x42', 'sge9')]['now']()['toString'](0x10) + '/', window[_0x4f3f('0x43', 'm^Gz')][_0x4f3f('0x44', 'kG!t')](0x10)), '/') + _0x2ec18e[_0x4f3f('0x45', 'f*#]')](_0x4ba351);
            _0x2ec18e[_0x4f3f('0x46', '4PG(')](_0x9ff66b, _0x2371bc, rndNo);
            _0x2371bc = _0x2ec18e[_0x4f3f('0x47', 'x3Lg')](_0x3c4889, _0xd74c71(_0x2371bc));
            _0x472ff2[0x0] = _0x2371bc;
            if (navigator[_0x4f3f('0x48', 'm48V')]) {
                var _0x55d807 = new Date();
                _0x55d807[_0x4f3f('0x49', 'Tbb9')](_0x2ec18e[_0x4f3f('0x4a', 'H0Sy')](_0x55d807[_0x4f3f('0x4b', 'KKV$')](), 0x12c * 0x3e8));
                document[_0x4f3f('0x4c', 'NJ5J')] = _0x135745 + '=' + _0x472ff2[_0x4f3f('0x4d', 'uFIh')]('') + ';path=/;domain=17track.net;expires=' + _0x55d807[_0x4f3f('0x4e', 'KKV$')]();
                _0x55d807 = new Date();
                _0x55d807[_0x4f3f('0x4f', 'kG!t')](_0x55d807['getTime']() + 0x12c * 0x3e8);
                document['cookie'] = _0x135745 + '=' + _0x472ff2[_0x4f3f('0x50', 'sge9')]('') + ';path=/;domain=17track.net;expires=' + _0x55d807[_0x4f3f('0x51', 'DYwS')]();
            }
            if (!_0x411c47(_0x135745)) {
                xhr[_0x4f3f('0x52', 'x3Lg')](_0x135745, _0x472ff2[_0x4f3f('0x53', 'tG@(')](''));
            }
        } else {
            var _0x47b984;
            try {
                _0x47b984 = new XMLHttpRequest();
            } catch (_0x3ef69c) {
                try {
                    _0x47b984 = new ActiveXObject(_0x4f3f('0x54', 'VMDb'));
                } catch (_0x494a23) {
                    try {
                        _0x47b984 = new ActiveXObject(_0x4f3f('0x55', 'jc9G'));
                    } catch (_0x1f73b5) {
                        return ![];
                    }
                }
            }
            _0x47b984 = null;
            return !![];
        }
    }

_0x5e7be4

    function _0x5e7be4(_0x14393c) {
        if (_0x2ec18e[_0x4f3f('0x27', '#C9L')](_0x4f3f('0x28', '7la!'), _0x4f3f('0x29', 'y*Cp'))) {
            if (window && window[_0x4f3f('0x2a', 'ttkq')] && window[_0x4f3f('0x2b', '#C9L')] > 0x0 && document && document[_0x4f3f('0x2c', 'kG!t')]['hostname'][_0x4f3f('0x2d', '^p2Z')](_0x4f3f('0x2e', 'DYwS'))) { //if (window && window['innerWidth'] && window['innerWidth'] > 0 && document && document['location']['hostname']['match']('.17track.net')) { 让这个判断永远为true吧
                if (!_0x14393c) {  
                    _0x472ff2[0x3] = 0x1;
                } else { //下面可以看到对_0x472ff2做了设置
                    if (_0x4f3f('0x2f', '!nz(') !== _0x4f3f('0x30', 'klod')) {
                        _0x472ff2[0x3] = 0x1;
                    } else {
                        _0x472ff2[0x3] = _0x14393c;
                    }
                }
            } else {
                if (_0x4f3f('0x31', 'm^Gz') !== _0x2ec18e[_0x4f3f('0x32', 'm48V')]) {
                    that['console'] = function(_0x114f36) {
                        var _0x49a662 = {};
                        _0x49a662[_0x4f3f('0x33', 'f*#]')] = _0x114f36;
                        _0x49a662[_0x4f3f('0x34', 'l3oQ')] = _0x114f36;
                        _0x49a662[_0x4f3f('0x35', 'f*#]')] = _0x114f36;
                        _0x49a662['info'] = _0x114f36;
                        _0x49a662[_0x4f3f('0x36', 'V91Y')] = _0x114f36;
                        _0x49a662[_0x4f3f('0x37', 'l3oQ')] = _0x114f36;
                        _0x49a662[_0x4f3f('0x38', 'klod')] = _0x114f36;
                        return _0x49a662;
                    }(func);
                } else {
                    _0x472ff2[0x3] = 0x0;
                }
            }
        } else {
            _0x472ff2[0x3] = _0x14393c;
        }
    }

最后我们删掉调用_0x3966d3的代码去掉,对所有使用$的地方已经设置为固定值,去掉第二个自执行函数,然后给_0x4cec2b加一个参数

function _0x4cec2b(_0x567d6b) {
    .....
    _0x8f6309();
    var _0x164a16 = JSON['parse'](_0x567d6b);
    _0x9ff66b(_0x567d6b, _0x567d6b.length, true);
    var eid = _0x3966d3(0, 0, _0x1a395d(21));
    return eid;
}

最后直接调用就可以获得Last-Event-ID拉,拿着python或者nodejs去浪吧!

var eid  = _0x4cec2b('{"data":[{"num":"***","fc":0,"sc":0}],"guid":"","timeZoneOffset":-480}'));

免费评分

参与人数 4威望 +1 吾爱币 +24 热心值 +4 收起 理由
howsk + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Lucifer_BW + 1 + 1 热心回复!
hi566 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

涛之雨 发表于 2020-7-7 08:52
此外就是楼主问的格式化的问题
[JavaScript] 纯文本查看 复制代码
var _0x2333a0=_0x10f375(this,function(){var _0x4d2180=function(){return'\x64\x65\x76';},_0x326747=function(){return'\x77\x69\x6e\x64\x6f\x77';};var _0x2b03ab=function(){var _0x48fa7a=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!_0x48fa7a['\x74\x65\x73\x74'](_0x4d2180['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var _0x209b4b=function(){var _0x1542e8=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return _0x1542e8['\x74\x65\x73\x74'](_0x326747['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var _0x10cf6b=function(_0x10f4d5){var _0x1679be=~-0x1>>0x1+0xff%0x0;if(_0x10f4d5['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===_0x1679be)){_0xd2c455(_0x10f4d5);}};var _0xd2c455=function(_0x570d92){var _0x6d545d=~-0x4>>0x1+0xff%0x0;if(_0x570d92['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==_0x6d545d){_0x10cf6b(_0x570d92);}};if(!_0x2b03ab()){if(!_0x209b4b()){_0x10cf6b('\x69\x6e\x64\u0435\x78\x4f\x66');}else{_0x10cf6b('\x69\x6e\x64\x65\x78\x4f\x66');}}else{_0x10cf6b('\x69\x6e\x64\u0435\x78\x4f\x66');}});
_0x2333a0();

开fd劫持一下页面的那个js,删掉上述正则防格式化部分就行(当然可以格式化后再保存到本地)
涛之雨 发表于 2020-7-7 06:58
本帖最后由 涛之雨 于 2020-7-7 08:48 编辑

额。这是加密了,可以解密后再分析的。。。
我最近在研究这个,等完善了会把源码扔出来。。。
现在有时候会出各种莫名其妙的bug(代码的不规范,版本的不同,抽取规则的不同都是问题)

Screenshot_20200707_065905_com.huawei.browser.jpg
此外他的代码应该是有禁止格式化,所以你格式化会出错(原理是正则表达式)
唔,貌似是买的高级版,方法有点复杂,看一下
有些地方定义的方法不一样。
半自动半手动吧,(变量没有办法还原,而且我也没看流程。。。)
decode.png

截图是加密部分的(仔细看那个代码,前面一半全都是_0x变量,后一半都是没有处理过的。姑且称前面一半为加密部分吧)

变量建议分析后批量重命名。不然很难看懂
geniusxiao 发表于 2020-7-6 17:36
ambo 发表于 2020-7-6 19:45
萌新看不懂哦
魔道书生 发表于 2020-7-6 22:07
image.png 这算不算简单点?  狗头保命
pwp 发表于 2020-7-6 22:19
根本看不懂你所云。
bags 发表于 2020-7-7 00:17
太强了看不懂。。。
allennt 发表于 2020-7-7 00:34
有点厉害>_>
lifz888 发表于 2020-7-7 07:45
非常好的分析,支持原创,支持发帖
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-26 11:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表