17track接口逆向分析


没有放修改后的完整代码,纯粹的学习,这网站不错,本来就是免费查询,还支持40个单号一起查。谁有更好方法找到_0x4f3f里内存暴破,欢迎指教啊!

调试

17track的快递查询接口,可以通过调试工具看到请求,但是直接通过POST工具是没有结果的,最后测试需要加上Last-Event-ID这个cookie
在这里插入图片描述
看了网页加载的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请求
在这里插入图片描述
跟到_0x3966d3的时候,可以看到前两个参数是函数,最后是一个数字。继续一步一步走,注意_0x126b58 这个值是在变化的。
在这里插入图片描述
最后在这里找到了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是重要变量,复制所有加密代码,格式化,放到新网页执行。哈哈哈,崩溃了。
在这里插入图片描述
看来是有检测代码。这里我不知道怎么才能下断点,只有一步一步故意写错代码,看是先崩溃还是先报错确定了检测代码位置。有大佬有好方法没?

_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}'));

另一个方法

拿出万能的python,使用selenium,就是耗资源,速度慢。话说还要什么Last-Event-ID,直接分析结果就完了。

from selenium import webdriver
import json
import requests

options=webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument('--disable-gpu')
options.add_experimental_option('excludeSwitches', ['enable-automation'])

driver = webdriver.Chrome(executable_path="chromedriver.exe",chrome_options=options)

driver.get("https://t.17track.net/zh-cn#nums=***,***")
cookie = driver.get_cookie('Last-Event-ID')
eid = cookie['value']
driver.quit()
print(eid)
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值