没有放修改后的完整代码,纯粹的学习,谁有更好方法找到_0x4f3f里内存暴破,请指教啊!
调试
17track的快递查询接口,可以通过调试工具看到请求,但是直接通过POST工具是没有结果的,最后测试需要加上Last-Event-ID这个cookie
" 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请求
" alt="在这里插入图片描述" />
跟到_0x3966d3的时候,可以看到前两个参数是函数,最后是一个数字。继续一步一步走,注意_0x126b58 这个值是在变化的。
" 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是重要变量,复制所有加密代码,格式化,放到新网页执行。哈哈哈,崩溃了。
" 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}'));