vmp套vmp之探讨某d的_fingerprint参数生成
本文仅供学习交流,因使用本文内容而产生的任何风险及后果,作者不承担任何责任,一起学习吧
快速定位
直接搜索this._fingerprint = _$XS.get(this._version, this._appId),
便可快速定位到这个参数的生成位置。
传入两个参数this._version = '5.1'
和this._appId = '73806'
。简单记一下,打上断点,步入进去。
我们进入到了这样的一个函数:
var _$XS = {
'get': function(_$Vk, _$Vt) {
var _$VM = {
'gZiAS': function(_$VN, _$Vr, _$Vf) {
return _$VN(_$Vr, _$Vf);
}
}
, _$VI = arguments.length > 0x58a + 0x32a * 0xb + -0x2856 && _$h.hhZxk(void (0x428 + -0xfc3 * -0x2 + 0x1 * -0x23ae), arguments[0x59e + -0x696 * 0x2 + -0x8 * -0xf2]) ? arguments[-0x14f6 + -0x211c + 0x3614] : -0xf * -0x19f + -0x1084 + 0x7cd * -0x1
, _$VH = _$Xl.get(_$Xf.STORAGE_KEY_VK, {
'raw': !(-0x2 * -0x1de + -0x305 * 0x5 + 0xb5e),
'from': _$VI
})
, _$VO = _$h.HsBLR(_$X7, _$VH) ? _$VH : {}
, _$VR = _$XH(_$VO, [_$Vk, _$Vt]);
if (_$Xj(_$VR))
return _$VR.v;
var _$VC = _$Xu();
return _$XI(_$VO, [_$Vk, _$Vt], {
'e': 0x1e13380,
'v': _$VC,
't': Date.now()
}),
function(_$VN) {
if (!_$VN)
return;
var _$Vr = [];
_$h.wtKeL(_$XO, _$VN, function(_$VX, _$VV) {
_$VM.gZiAS(_$XO, _$VX, function(_$VD, _$Vw) {
_$Xj(_$VD) && _$Vr.push({
'v': _$VV,
'appid': _$Vw,
'data': _$VD
});
});
});
var _$Vf = {};
_$Vr.forEach(function(_$VX) {
var _$VV = _$VX.v
, _$VD = _$VX.appid
, _$Vw = _$VX.data;
_$XI(_$Vf, [_$VV, _$VD], _$Vw);
}),
_$Xl.set(_$Xf.STORAGE_KEY_VK, _$Vf);
}(_$VO),
_$VC;
}
}
这里还是一步步取跟,看看这个函数干了什么。
函数分析
我还是按照我的风格来讲解,一步步分析代码
var _$VM = {
'gZiAS': function(_$VN, _$Vr, _$Vf) {
return _$VN(_$Vr, _$Vf);
}
} //这里简单定义了一个对象
, _$VI = arguments.length > 0x58a + 0x32a * 0xb + -0x2856 && _$h.hhZxk(void (0x428 + -0xfc3 * -0x2 + 0x1 * -0x23ae), arguments[0x59e + -0x696 * 0x2 + -0x8 * -0xf2]) ? arguments[-0x14f6 + -0x211c + 0x3614] : -0xf * -0x19f + -0x1084 + 0x7cd * -0x1
, _$VH = _$Xl.get(_$Xf.STORAGE_KEY_VK, {
'raw': !(-0x2 * -0x1de + -0x305 * 0x5 + 0xb5e),
'from': _$VI
}) // 这里去取了一些浏览器的值 但是我们在这里看到一个 v = "dw3gwggga2hpa338" 很像我们的_fingerprint我们直接步出这个函数,看看结果是不是
, _$VO = _$h.HsBLR(_$X7, _$VH) ? _$VH : {}
, _$VR = _$XH(_$VO, [_$Vk, _$Vt]);
if (_$Xj(_$VR))
return _$VR.v;
var _$VC = _$Xu();
return _$XI(_$VO, [_$Vk, _$Vt], {
'e': 0x1e13380,
'v': _$VC,
't': Date.now()
}),
我们步出这个函数发现this._fingerprint = "dw3gwggga2hpa338"
说明这个并且我们多次运行后面方法发现这个是不变的。但是它真的是不变的吗。
如果你详细跟了上面这个函数你就知道,这个_fingerprint
会被存储在本地存储的WQ_dy1_vk
中。
我们还是观察这个代码。这个v
是我们的_fingerprint
,向下看看发现。讲解如下:
var _$VC = _$Xu(); // 说明这个是_fingerprint生成的地方(2)
return _$XI(_$VO, [_$Vk, _$Vt], {
'e': 0x1e13380,
'v': _$VC, // 这里不就表明了吗 (1)
't': Date.now()
}),
还是一样,打上断点步入进去,发现。好家伙,一眼vmp,而且还是vmp套vmp。但是不要慌。还记得我之前文章写的巧用ai和vmp插桩的几点吗。我们将代码扣下来将需要插桩的分支发给ai让他给我们插好桩。这样我们就得到一份完美的插桩代码。这里还要提醒一下,需要把每个vmp的栈和执行分支也打出来。会方便很多。这个插好的代码我会放到附录供大家学习。
我们既然知道这个是存储在本地的,我们清空本地网站数据。重新步入。
执行完这个函数,我们得到一份粗略的日志。我们先简单浏览一下。我们发现一个很奇怪的字符串 0jhqw3pa2m
后面操作都有它的身影。说明这个是个重要参数。
很显然是上面那个函数,直接进入看看。
function a0dbbcbn(_$h, _$n) {
var _$q = a0dbbcbh();
return a0dbbcbn = function(_$p, _$A) {
_$p = _$p - (-0x4 * -0x59d + 0x155f + -0x2ac7);
var _$L = _$q[_$p];
if (a0dbbcbn.TpoVmd === undefined) {
var _$k = function(_$H) {
var _$O = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';
var _$R = ''
, _$C = '';
for (var _$N = -0x1d7 + -0x1438 * -0x1 + 0x1261 * -0x1, _$r, _$f, _$X = 0x23ff + 0x1c9d + -0x409c; _$f = _$H.charAt(_$X++); ~_$f && (_$r = _$N % (-0x87e + -0x1 * -0x9cb + -0x149) ? _$r * (-0x4e9 * 0x1 + -0x1 * -0x6ca + 0x3 * -0x8b) + _$f : _$f,
_$N++ % (0x2 * 0x4f0 + -0x1f9c + 0x4 * 0x570)) ? _$R += String.fromCharCode(-0x3 * -0xca0 + 0x2 * -0x689 + -0x17cf & _$r >> (-(0x28 * 0x2e + -0x11c * 0x1 + -0x612) * _$N & -0x1543 + 0x23a3 + -0xb * 0x14e)) : 0x9ac + 0x23b4 + -0x2d60) {
_$f = _$O.indexOf(_$f);
}
for (var _$V = -0x1ad0 + 0x23c5 + -0x1 * 0x8f5, _$D = _$R.length; _$V < _$D; _$V++) {
_$C += '%' + ('00' + _$R.charCodeAt(_$V).toString(0x11 * 0x8b + 0xbb7 + -0x14e2)).slice(-(0x1f57 + 0x30a + -0x225f));
}
return decodeURIComponent(_$C);
};
a0dbbcbn.SOdwIc = _$k,
_$h = arguments,
a0dbbcbn.TpoVmd = !![];
}
var _$t = _$q[0x600 + 0x16a0 + 0x394 * -0x8].substring(0xd5a + -0x1 * 0x1b12 + 0xdb8, 0xe16 + 0x1c63 + -0x2a77)
, _$M = _$p + _$t
, _$I = _$h[_$M];
return !_$I ? (_$L = a0dbbcbn.SOdwIc(_$L),
_$h[_$M] = _$L) : _$L = _$I,
_$L;
}
,
a0dbbcbn(_$h, _$n);
}
这个你直接丢给gpt分析就行,他这个很明显就是一个字符解析,而且是在传入大数组中取。那么这个值便是一个定值。但是我还是简单还原了一下:
var decodeBase64URIComponent = function(encodedStr) {
var base64Chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';
var decodedBinary = '', percentEncoded = '';
for (var bitCounter = 0, buffer, currentChar, charIndex = 0;
currentChar = encodedStr.charAt(charIndex++);
~currentChar && (
buffer = bitCounter % 4 ? buffer * 64 + currentChar : currentChar,
bitCounter++ % 4
) ? decodedBinary += String.fromCharCode(
255 & buffer >> ((-2 * bitCounter) & 6)
) : 0) {
currentChar = base64Chars.indexOf(currentChar);
}
for (var i = 0, len = decodedBinary.length; i < len; i++) {
percentEncoded += '%' + ('00' + decodedBinary.charCodeAt(i).toString(16)).slice(-2);
}
return decodeURIComponent(percentEncoded);
};
console.log(decodeBase64URIComponent('mgPOCxCZCgeYBq')) // 这个是大数组的第535,这个是死值,我刷新了几次都没变
接着向下看,为了方便教学,我将日志一些干扰项全部删除了。日志很长,且听我慢慢分析。
我们分析日志的时候抓住几点:
- 入参
- 计算
- 结果
在下面这个日志,我们初始串 0jhqw3pa2m
,经历了什么不为人知的计算。关注到了有一个比大小和乘积。而且大量使用了random
函数。最后变成了["0","a","2"]
那么我们着重观察["0","a","2"]这个结果生成的特征,从下向上看。
我们在总结一下就是,循环这个串(指针i),每次参数随机值和这个串的长度 减 i 的乘积 和 一个数 3比大小,比他小就取出这个字符同时让这个数减一
代码简单写一下就是:
str_replace = []
for(let i=0,j=input.length,flag=3;i<input.length;i++,j--){
// console.log(input[i])
a = Math.random() * j // 这里就是随机取三个值
// console.log('随机数乘积结果-->' + a)
if(a < flag){
flag--;
str_replace.push(input[i])
}
}
这部分完整日志如下:
执行分支--o 69 栈r--> ["0jhqw3pa2m"]
执行分支--o 68 栈r--> [10]
执行分支--o 56 栈r--> [10]
执行分支--o -5340 栈r--> []
执行分支--o -275 栈r--> [-5340]
执行分支--o 56 栈r--> [-5340,-275]
执行分支--o 5615 栈r--> [-5615]
执行分支--o 79 栈r--> [-5615,5615]
执行分支--o 68 栈r--> [0]
执行分支--o 29 栈r--> [0]
执行分支--o 43 栈r--> []
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,0]
执行分支--o 75 栈r--> [null,省略,0,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,0,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",0]
执行分支--o 68 栈r--> ["0"]
执行分支--o 12 栈r--> ["0"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.0009489305987293584
执行分支--o 75 栈r--> [null,省略,0.0009489305987293584]
执行分支--o 30 栈r--> [null,省略,0.0009489305987293584,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.0009489305987293584 10
7080 [插桩] 返回值: 0.009489305987293584
执行分支--o 22 栈r--> [0.009489305987293584]
执行分支--o 35 栈r--> [0.009489305987293584,3]
执行分支--o 17 栈r--> [true]
执行分支--o 47 栈r--> []
执行分支--o 2 栈r--> [[]]
执行分支--o 76 栈r--> [null,[]]
执行分支--o 68 栈r--> [null,[],"0"]
7094 [插桩] 分支1 - 调用 i.call
7095 [插桩] 调用函数: ƒ push() { [native code] }
7096 [插桩] 参数: [] 0
7100 [插桩] 返回值: 1
执行分支--o 56 栈r--> [1]
执行分支--o -910 栈r--> []
执行分支--o -5375 栈r--> [-910]
执行分支--o 56 栈r--> [-910,-5375]
执行分支--o 6285 栈r--> [-6285]
执行分支--o 5 栈r--> [-6285,6285]
执行分支--o 32 栈r--> [0]
执行分支--o 72 栈r--> [0,2]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [10]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [0]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,1]
执行分支--o 75 栈r--> [null,省略,1,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,1,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 1 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",1]
执行分支--o 68 栈r--> ["j"]
执行分支--o 12 栈r--> ["j"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.24283588276465118
执行分支--o 75 栈r--> [null,省略,0.24283588276465118]
执行分支--o 30 栈r--> [null,省略,0.24283588276465118,9]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.24283588276465118 9
7080 [插桩] 返回值: 2.1855229448818605
执行分支--o 22 栈r--> [2.1855229448818605]
执行分支--o 35 栈r--> [2.1855229448818605,2]
执行分支--o 17 栈r--> [false]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [9]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [1]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,2]
执行分支--o 75 栈r--> [null,省略,2,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,2,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 2 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",2]
执行分支--o 68 栈r--> ["h"]
执行分支--o 12 栈r--> ["h"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.5844895447176711
执行分支--o 75 栈r--> [null,省略,0.5844895447176711]
执行分支--o 30 栈r--> [null,省略,0.5844895447176711,8]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.5844895447176711 8
7080 [插桩] 返回值: 4.675916357741369
执行分支--o 22 栈r--> [4.675916357741369]
执行分支--o 35 栈r--> [4.675916357741369,2]
执行分支--o 17 栈r--> [false]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [8]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [2]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,3]
执行分支--o 75 栈r--> [null,省略,3,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,3,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 3 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",3]
执行分支--o 68 栈r--> ["q"]
执行分支--o 12 栈r--> ["q"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.5011145080247482
执行分支--o 75 栈r--> [null,省略,0.5011145080247482]
执行分支--o 30 栈r--> [null,省略,0.5011145080247482,7]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.5011145080247482 7
7080 [插桩] 返回值: 3.5078015561732374
执行分支--o 22 栈r--> [3.5078015561732374]
执行分支--o 35 栈r--> [3.5078015561732374,2]
执行分支--o 17 栈r--> [false]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [7]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [3]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,4]
执行分支--o 75 栈r--> [null,省略,4,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,4,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 4 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",4]
执行分支--o 68 栈r--> ["w"]
执行分支--o 12 栈r--> ["w"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.6615523978605656
执行分支--o 75 栈r--> [null,省略,0.6615523978605656]
执行分支--o 30 栈r--> [null,省略,0.6615523978605656,6]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.6615523978605656 6
7080 [插桩] 返回值: 3.9693143871633936
执行分支--o 22 栈r--> [3.9693143871633936]
执行分支--o 35 栈r--> [3.9693143871633936,2]
执行分支--o 17 栈r--> [false]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [6]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [4]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,5]
执行分支--o 75 栈r--> [null,省略,5,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,5,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 5 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",5]
执行分支--o 68 栈r--> ["3"]
执行分支--o 12 栈r--> ["3"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.53692932445542
执行分支--o 75 栈r--> [null,省略,0.53692932445542]
执行分支--o 30 栈r--> [null,省略,0.53692932445542,5]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.53692932445542 5
7080 [插桩] 返回值: 2.6846466222771
执行分支--o 22 栈r--> [2.6846466222771]
执行分支--o 35 栈r--> [2.6846466222771,2]
执行分支--o 17 栈r--> [false]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [5]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [5]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,6]
执行分支--o 75 栈r--> [null,省略,6,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,6,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 6 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",6]
执行分支--o 68 栈r--> ["p"]
执行分支--o 12 栈r--> ["p"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.6613187237589039
执行分支--o 75 栈r--> [null,省略,0.6613187237589039]
执行分支--o 30 栈r--> [null,省略,0.6613187237589039,4]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.6613187237589039 4
7080 [插桩] 返回值: 2.6452748950356155
执行分支--o 22 栈r--> [2.6452748950356155]
执行分支--o 35 栈r--> [2.6452748950356155,2]
执行分支--o 17 栈r--> [false]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [4]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [6]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,7]
执行分支--o 75 栈r--> [null,省略,7,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,7,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 7 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",7]
执行分支--o 68 栈r--> ["a"]
执行分支--o 12 栈r--> ["a"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.5048743044162417
执行分支--o 75 栈r--> [null,省略,0.5048743044162417]
执行分支--o 30 栈r--> [null,省略,0.5048743044162417,3]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.5048743044162417 3
7080 [插桩] 返回值: 1.5146229132487252
执行分支--o 22 栈r--> [1.5146229132487252]
执行分支--o 35 栈r--> [1.5146229132487252,2]
执行分支--o 17 栈r--> [true]
执行分支--o 47 栈r--> []
执行分支--o 2 栈r--> [["0"]]
执行分支--o 76 栈r--> [null,["0"]]
执行分支--o 68 栈r--> [null,["0"],"a"]
7094 [插桩] 分支1 - 调用 i.call
7095 [插桩] 调用函数: ƒ push() { [native code] }
7096 [插桩] 参数: ['0'] a
7100 [插桩] 返回值: 2
执行分支--o 56 栈r--> [2]
执行分支--o -910 栈r--> []
执行分支--o -5375 栈r--> [-910]
执行分支--o 56 栈r--> [-910,-5375]
执行分支--o 6285 栈r--> [-6285]
执行分支--o 5 栈r--> [-6285,6285]
执行分支--o 32 栈r--> [0]
执行分支--o 72 栈r--> [0,1]
执行分支--o 3 栈r--> [false]
执行分支--o 68 栈r--> []
执行分支--o 87 栈r--> [3]
执行分支--o 68 栈r--> []
执行分支--o 12 栈r--> [7]
执行分支--o 47 栈r--> []
执行分支--o 3 栈r--> [省略]
执行分支--o 41 栈r--> [null,省略]
执行分支--o 40 栈r--> [null,省略,8]
执行分支--o 75 栈r--> [null,省略,8,"0jhqw3pa2m"]
执行分支--o 70 栈r--> [null,省略,8,10]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA < _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 8 10
7080 [插桩] 返回值: true
执行分支--o -50 栈r--> [true]
执行分支--o 60 栈r--> []
执行分支--o 3 栈r--> ["0jhqw3pa2m"]
执行分支--o 81 栈r--> ["0jhqw3pa2m",8]
执行分支--o 68 栈r--> ["2"]
执行分支--o 12 栈r--> ["2"]
执行分支--o 47 栈r--> []
执行分支--o 0 栈r--> [省略]
执行分支--o 47 栈r--> [null,省略]
执行分支--o 1 栈r--> [null,省略,{}]
执行分支--o 95 栈r--> [null,省略,null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.1288065950106041
执行分支--o 75 栈r--> [null,省略,0.1288065950106041]
执行分支--o 30 栈r--> [null,省略,0.1288065950106041,2]
7074 [插桩] 调用 i.call
7075 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA * _$VL;
}
7076 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 0.1288065950106041 2
7080 [插桩] 返回值: 0.2576131900212082
执行分支--o 22 栈r--> [0.2576131900212082]
执行分支--o 35 栈r--> [0.2576131900212082,1]
执行分支--o 17 栈r--> [true]
执行分支--o 47 栈r--> []
执行分支--o 2 栈r--> [["0","a"]]
执行分支--o 76 栈r--> [null,["0","a"]]
执行分支--o 68 栈r--> [null,["0","a"],"2"]
7094 [插桩] 分支1 - 调用 i.call
7095 [插桩] 调用函数: ƒ push() { [native code] }
7096 [插桩] 参数: (2) ['0', 'a'] 2
7100 [插桩] 返回值: 3
执行分支--o 56 栈r--> [3]
执行分支--o -910 栈r--> []
执行分支--o -5375 栈r--> [-910]
执行分支--o 56 栈r--> [-910,-5375]
执行分支--o 6285 栈r--> [-6285]
执行分支--o 5 栈r--> [-6285,6285]
执行分支--o 32 栈r--> [0]
执行分支--o 72 栈r--> [0,0]
执行分支--o 3 栈r--> [true]
执行分支--o 14 栈r--> []
执行分支--o 4 栈r--> []
执行分支--o 68 栈r--> [""]
执行分支--o 56 栈r--> [""]
执行分支--o -3847 栈r--> []
执行分支--o -737 栈r--> [-3847]
执行分支--o 56 栈r--> [-3847,-737]
执行分支--o 4584 栈r--> [-4584]
执行分支--o 11 栈r--> [-4584,4584]
执行分支--o 68 栈r--> [0]
执行分支--o 29 栈r--> [0]
执行分支--o 49 栈r--> []
执行分支--o 85 栈r--> []
执行分支--o 40 栈r--> [0]
执行分支--o 22 栈r--> [0,["0","a","2"]]
我们还是接着向下看,我们发现这个短数组["0","a","2"]
不知道参与了什么变成了 02a
,继续向下看,又产生了一个新的字符串 q02amwhwwpphm331
这个字符串你会发现他是由好几部分拼接而成的。q 02a mwhwwpphm33 1
其中 q
和mwhwwpphm33
都是通过一个函数生产的。
这个函数直接扣就行,不算难点。代码如下:
const randomHelper = {
cgmkT(x, y) {
return Math.floor(x * y);
}
};
function generateRandomString(config) {
for (var length = config.size, pool = config.num, result = ''; length--; )
result += pool[randomHelper.cgmkT(Math.random(), pool.length) | 0];
console.log(config)
return result;
}
那么这个size
咋来的,这里就需要断点分析了,这就是为什么我要打出执行分支。这里size也是一个随机数参数的
执行分支-->a 19 栈d--> []
执行分支-->a 44 栈d--> [null]
执行分支-->a 60 栈d--> [null,null]
执行分支-->a 95 栈d--> [null,null,{}]
执行分支-->a 1 栈d--> [null,null,{},1]
执行分支-->a 95 栈d--> [null,null,{"size":1}]
执行分支-->a 2 栈d--> [null,null,{"size":1},"jhqw3pm"]
执行分支-->a 99 栈d--> [null,null,{"size":1,"num":"jhqw3pm"}]
我们看到在分支1第一次出现,那么我们在他的上级95打上断点查看执行了什么。
简单搜一下
很好,将断点设置为46
我们得到如下:
那么很明显了。这个size就是随机数 * 10 | 0 得到的。
那么后面那个size是怎么得到的呢,也很简单。就是固定13-size-1。这里你可以多大几分日志对比。后面那个1也是这个随机的size
现在最难的就是这个02a。
短串分析
准备好,超长日志再次准备出现 ["0","a","2"] --> 02a
这里比较难,需要你自己多打几分日志对比
这里代码我就不给出了,核心点在于计算取数,取数之后更新数组,后面再到新数组取数,再更新。
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.26127766219234505
6921 执行分支--o 40 栈r--> [0.26127766219234505]
6921 执行分支--o 90 栈r--> [0.26127766219234505,["0","a","2"]]
6921 执行分支--o 61 栈r--> [0.26127766219234505,3]
6921 执行分支--o 63 栈r--> [0.26127766219234505,3,0]
6921 执行分支--o 56 栈r--> [0.26127766219234505,3]
6921 执行分支--o -9420 栈r--> [0.7838329865770352]
6921 执行分支--o -126 栈r--> [0.7838329865770352,-9420]
6921 执行分支--o 56 栈r--> [0.7838329865770352,-9420,-126]
6921 执行分支--o 9546 栈r--> [0.7838329865770352,-9546]
6921 执行分支--o 94 栈r--> [0.7838329865770352,-9546,9546]
6921 执行分支--o 67 栈r--> [0.7838329865770352,0]
6921 执行分支--o 68 栈r--> [0]
6921 执行分支--o 13 栈r--> [0]
6921 执行分支--o 85 栈r--> []
6921 执行分支--o 53 栈r--> [""]
6921 执行分支--o 3 栈r--> ["",["0","a","2"]]
6921 执行分支--o 20 栈r--> ["",["0","a","2"],0]
6921 执行分支--o 51 栈r--> ["","0"]
6921 执行分支--o 68 栈r--> ["0"]
6921 执行分支--o 85 栈r--> ["0"]
6921 执行分支--o 53 栈r--> []
6921 执行分支--o 85 栈r--> [["0","a","2"]]
6921 执行分支--o 85 栈r--> [["0","a","2"],0]
6921 执行分支--o 40 栈r--> [["0","a","2"],0,["0","a","2"]]
6921 执行分支--o 90 栈r--> [["0","a","2"],0,["0","a","2"],["0","a","2"]]
6921 执行分支--o 61 栈r--> [["0","a","2"],0,["0","a","2"],3]
6921 执行分支--o 56 栈r--> [["0","a","2"],0,["0","a","2"],3,0]
6921 执行分支--o 1547 栈r--> [["0","a","2"],0,["0","a","2"],3]
6921 执行分支--o 5708 栈r--> [["0","a","2"],0,["0","a","2"],3,1547]
6921 执行分支--o 56 栈r--> [["0","a","2"],0,["0","a","2"],3,1547,5708]
6921 执行分支--o -7254 栈r--> [["0","a","2"],0,["0","a","2"],3,7255]
6921 执行分支--o 61 栈r--> [["0","a","2"],0,["0","a","2"],3,7255,-7254]
6921 执行分支--o 3 栈r--> [["0","a","2"],0,["0","a","2"],3,1]
6921 执行分支--o 84 栈r--> [["0","a","2"],0,["0","a","2"],2]
6921 执行分支--o 68 栈r--> [["0","a","2"],0,"2"]
6921 执行分支--o 14 栈r--> ["2"]
6921 执行分支--o 68 栈r--> []
6921 执行分支--o 90 栈r--> [0]
6921 执行分支--o 85 栈r--> []
6921 执行分支--o 40 栈r--> [1]
6921 执行分支--o 22 栈r--> [1,["2","a","2"]]
6921 执行分支--o 70 栈r--> [1,3]
6921 执行分支--o -53 栈r--> [true]
6921 执行分支--o 47 栈r--> []
6921 执行分支--o 1 栈r--> [{}]
6921 执行分支--o 85 栈r--> [null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.1915809302903172
6921 执行分支--o 40 栈r--> [0.1915809302903172]
6921 执行分支--o 90 栈r--> [0.1915809302903172,["2","a","2"]]
6921 执行分支--o 61 栈r--> [0.1915809302903172,3]
6921 执行分支--o 63 栈r--> [0.1915809302903172,3,1]
6921 执行分支--o 56 栈r--> [0.1915809302903172,2]
6921 执行分支--o -9420 栈r--> [0.3831618605806344]
6921 执行分支--o -126 栈r--> [0.3831618605806344,-9420]
6921 执行分支--o 56 栈r--> [0.3831618605806344,-9420,-126]
6921 执行分支--o 9546 栈r--> [0.3831618605806344,-9546]
6921 执行分支--o 94 栈r--> [0.3831618605806344,-9546,9546]
6921 执行分支--o 67 栈r--> [0.3831618605806344,0]
6921 执行分支--o 68 栈r--> [0]
6921 执行分支--o 13 栈r--> [0]
6921 执行分支--o 85 栈r--> []
6921 执行分支--o 53 栈r--> ["0"]
6921 执行分支--o 3 栈r--> ["0",["2","a","2"]]
6921 执行分支--o 20 栈r--> ["0",["2","a","2"],0]
6921 执行分支--o 51 栈r--> ["0","2"]
6921 执行分支--o 68 栈r--> ["02"]
6921 执行分支--o 85 栈r--> ["02"]
6921 执行分支--o 53 栈r--> []
6921 执行分支--o 85 栈r--> [["2","a","2"]]
6921 执行分支--o 85 栈r--> [["2","a","2"],0]
6921 执行分支--o 40 栈r--> [["2","a","2"],0,["2","a","2"]]
6921 执行分支--o 90 栈r--> [["2","a","2"],0,["2","a","2"],["2","a","2"]]
6921 执行分支--o 61 栈r--> [["2","a","2"],0,["2","a","2"],3]
6921 执行分支--o 56 栈r--> [["2","a","2"],0,["2","a","2"],3,1]
6921 执行分支--o 1547 栈r--> [["2","a","2"],0,["2","a","2"],2]
6921 执行分支--o 5708 栈r--> [["2","a","2"],0,["2","a","2"],2,1547]
6921 执行分支--o 56 栈r--> [["2","a","2"],0,["2","a","2"],2,1547,5708]
6921 执行分支--o -7254 栈r--> [["2","a","2"],0,["2","a","2"],2,7255]
6921 执行分支--o 61 栈r--> [["2","a","2"],0,["2","a","2"],2,7255,-7254]
6921 执行分支--o 3 栈r--> [["2","a","2"],0,["2","a","2"],2,1]
6921 执行分支--o 84 栈r--> [["2","a","2"],0,["2","a","2"],1]
6921 执行分支--o 68 栈r--> [["2","a","2"],0,"a"]
6921 执行分支--o 14 栈r--> ["a"]
6921 执行分支--o 68 栈r--> []
6921 执行分支--o 90 栈r--> [1]
6921 执行分支--o 85 栈r--> []
6921 执行分支--o 40 栈r--> [2]
6921 执行分支--o 22 栈r--> [2,["a","a","2"]]
6921 执行分支--o 70 栈r--> [2,3]
6921 执行分支--o -53 栈r--> [true]
6921 执行分支--o 47 栈r--> []
6921 执行分支--o 1 栈r--> [{}]
6921 执行分支--o 85 栈r--> [null,{}]
6954 [插桩] 分支1 - 调用 i.call
6955 [插桩] 调用函数: ƒ random() { [native code] }
6956 [插桩] 参数: Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
6960 [插桩] 返回值: 0.11069052654495881
6921 执行分支--o 40 栈r--> [0.11069052654495881]
6921 执行分支--o 90 栈r--> [0.11069052654495881,["a","a","2"]]
6921 执行分支--o 61 栈r--> [0.11069052654495881,3]
6921 执行分支--o 63 栈r--> [0.11069052654495881,3,2]
6921 执行分支--o 56 栈r--> [0.11069052654495881,1]
6921 执行分支--o -9420 栈r--> [0.11069052654495881]
6921 执行分支--o -126 栈r--> [0.11069052654495881,-9420]
6921 执行分支--o 56 栈r--> [0.11069052654495881,-9420,-126]
6921 执行分支--o 9546 栈r--> [0.11069052654495881,-9546]
6921 执行分支--o 94 栈r--> [0.11069052654495881,-9546,9546]
6921 执行分支--o 67 栈r--> [0.11069052654495881,0]
6921 执行分支--o 68 栈r--> [0]
6921 执行分支--o 13 栈r--> [0]
6921 执行分支--o 85 栈r--> []
6921 执行分支--o 53 栈r--> ["02"]
6921 执行分支--o 3 栈r--> ["02",["a","a","2"]]
6921 执行分支--o 20 栈r--> ["02",["a","a","2"],0]
6921 执行分支--o 51 栈r--> ["02","a"]
6921 执行分支--o 68 栈r--> ["02a"]
6921 执行分支--o 85 栈r--> ["02a"]
6921 执行分支--o 53 栈r--> []
6921 执行分支--o 85 栈r--> [["a","a","2"]]
6921 执行分支--o 85 栈r--> [["a","a","2"],0]
6921 执行分支--o 40 栈r--> [["a","a","2"],0,["a","a","2"]]
6921 执行分支--o 90 栈r--> [["a","a","2"],0,["a","a","2"],["a","a","2"]]
6921 执行分支--o 61 栈r--> [["a","a","2"],0,["a","a","2"],3]
6921 执行分支--o 56 栈r--> [["a","a","2"],0,["a","a","2"],3,2]
6921 执行分支--o 1547 栈r--> [["a","a","2"],0,["a","a","2"],1]
6921 执行分支--o 5708 栈r--> [["a","a","2"],0,["a","a","2"],1,1547]
6921 执行分支--o 56 栈r--> [["a","a","2"],0,["a","a","2"],1,1547,5708]
6921 执行分支--o -7254 栈r--> [["a","a","2"],0,["a","a","2"],1,7255]
6921 执行分支--o 61 栈r--> [["a","a","2"],0,["a","a","2"],1,7255,-7254]
6921 执行分支--o 3 栈r--> [["a","a","2"],0,["a","a","2"],1,1]
6921 执行分支--o 84 栈r--> [["a","a","2"],0,["a","a","2"],0]
6921 执行分支--o 68 栈r--> [["a","a","2"],0,"a"]
6921 执行分支--o 14 栈r--> ["a"]
6921 执行分支--o 68 栈r--> []
6921 执行分支--o 90 栈r--> [2]
6921 执行分支--o 85 栈r--> []
6921 执行分支--o 40 栈r--> [3]
6921 执行分支--o 22 栈r--> [3,["a","a","2"]]
6921 执行分支--o 70 栈r--> [3,3]
6921 执行分支--o -53 栈r--> [false]
6921 执行分支--o 66 栈r--> []
6921 执行分支--o 80 栈r--> ["02a"]
7177 [插桩] 返回值: 02a
执行分支-->a 71 栈d--> ["02a"]
执行分支-->a 23 栈d--> ["02a"]
后面就简单了,其实你解开上面这段就基本上完成这个逆向了。
我把日志整理一下如下:
7194 [插桩] 参数: ƒ slice() { [native code] } (16) ['q', '0', '2', 'a', 'm', 'w', 'h', 'w', 'w', 'p', 'p', 'h', 'm', '3', '3', '1'] 0 9
7198 [插桩] 返回值: (9) ['q', '0', '2', 'a', 'm', 'w', 'h', 'w', 'w']
这里就是一个简单的切割
6628 [插桩] 调用函数: ƒ pop() { [native code] }
6629 [插桩] 参数: (9) ['q', '0', '2', 'a', 'm', 'w', 'h', 'w', 'w']
6633 [插桩] 返回值: w
这里就是从后面取数
执行分支-->a 36 栈d--> [null,[],null,省略,35,null,null,"w"]
执行分支-->a 85 栈d--> [null,[],null,省略,35,null,null,"w",36]
7171 [插桩] 调用 x.call
7172 [插桩] 调用函数: ƒ parseInt() { [native code] }
7173 [插桩] 参数: null w 36
7177 [插桩] 返回值: 32
执行分支-->a 21 栈d--> [null,[],null,省略,35,32]
7171 [插桩] 调用 x.call
7172 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA - _$VL;
}
7173 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 35 32
7177 [插桩] 返回值: 3
执行分支-->a 10 栈d--> [null,[],3]
执行分支-->a 5591 栈d--> [null,[],null,3]
执行分支-->a -2258 栈d--> [null,[],null,3,5591]
执行分支-->a 23 栈d--> [null,[],null,3,5591,-2258]
执行分支-->a -3297 栈d--> [null,[],null,3,3333]
执行分支-->a 65 栈d--> [null,[],null,3,3333,-3297]
执行分支-->a 65 栈d--> [null,[],null,3,36]
6861 [插桩] 分支1 - 调用 x.call
6862 [插桩] 调用函数: ƒ toString() { [native code] }
6863 [插桩] 参数: 3 36
6867 [插桩] 返回值: 3
执行分支-->a 71 栈d--> [null,[],"3"]
6861 [插桩] 分支1 - 调用 x.call
6862 [插桩] 调用函数: ƒ push() { [native code] }
6863 [插桩] 参数: [] 3
这里就是将 取出的字符通过 parseInt(取出的,36) 然后被35 减去 再通过 toString(36)
6627 [插桩] case 34 - 分支1 - 调用 x.call
6628 [插桩] 调用函数: ƒ pop() { [native code] }
6629 [插桩] 参数: (8) ['q', '0', '2', 'a', 'm', 'w', 'h', 'w']
6633 [插桩] 返回值: w
执行分支-->a 36 栈d--> [null,["3"],null,省略,35,null,null,"w"]
执行分支-->a 85 栈d--> [null,["3"],null,省略,35,null,null,"w",36]
7171 [插桩] 调用 x.call
7172 [插桩] 调用函数: ƒ parseInt() { [native code] }
7173 [插桩] 参数: null w 36
7177 [插桩] 返回值: 32
执行分支-->a 21 栈d--> [null,["3"],null,省略,35,32]
7171 [插桩] 调用 x.call
7172 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA - _$VL;
}
7173 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 35 32
7177 [插桩] 返回值: 3
执行分支-->a 10 栈d--> [null,["3"],3]
执行分支-->a 5591 栈d--> [null,["3"],null,3]
执行分支-->a -2258 栈d--> [null,["3"],null,3,5591]
执行分支-->a 23 栈d--> [null,["3"],null,3,5591,-2258]
执行分支-->a -3297 栈d--> [null,["3"],null,3,3333]
执行分支-->a 65 栈d--> [null,["3"],null,3,3333,-3297]
执行分支-->a 65 栈d--> [null,["3"],null,3,36]
6861 [插桩] 分支1 - 调用 x.call
6862 [插桩] 调用函数: ƒ toString() { [native code] }
6863 [插桩] 参数: 3 36
6867 [插桩] 返回值: 3
执行分支-->a 71 栈d--> [null,["3"],"3"]
6861 [插桩] 分支1 - 调用 x.call
6862 [插桩] 调用函数: ƒ push() { [native code] }
6863 [插桩] 参数: ['3'] 3
一样的
6628 [插桩] 调用函数: ƒ pop() { [native code] }
6629 [插桩] 参数: (7) ['q', '0', '2', 'a', 'm', 'w', 'h']
6633 [插桩] 返回值: h
执行分支-->a 36 栈d--> [null,["3","3"],null,省略,35,null,null,"h"]
执行分支-->a 85 栈d--> [null,["3","3"],null,省略,35,null,null,"h",36]
7171 [插桩] 调用 x.call
7172 [插桩] 调用函数: ƒ parseInt() { [native code] }
7173 [插桩] 参数: null h 36
7177 [插桩] 返回值: 17
执行分支-->a 21 栈d--> [null,["3","3"],null,省略,35,17]
7171 [插桩] 调用 x.call
7172 [插桩] 调用函数: ƒ (_$VA, _$VL) {
return _$VA - _$VL;
}
7173 [插桩] 参数: {QuHhA: 'function', DPusW: ƒ, KzvJS: ƒ, TxipF: ƒ, Ufhnc: ƒ, …} 35 17
7177 [插桩] 返回值: 18
执行分支-->a 10 栈d--> [null,["3","3"],18]
执行分支-->a 5591 栈d--> [null,["3","3"],null,18]
执行分支-->a -2258 栈d--> [null,["3","3"],null,18,5591]
执行分支-->a 23 栈d--> [null,["3","3"],null,18,5591,-2258]
执行分支-->a -3297 栈d--> [null,["3","3"],null,18,3333]
执行分支-->a 65 栈d--> [null,["3","3"],null,18,3333,-3297]
执行分支-->a 65 栈d--> [null,["3","3"],null,18,36]
6861 [插桩] 分支1 - 调用 x.call
6862 [插桩] 调用函数: ƒ toString() { [native code] }
6863 [插桩] 参数: 18 36
6867 [插桩] 返回值: i
执行分支-->a 71 栈d--> [null,["3","3"],"i"]
6861 [插桩] 分支1 - 调用 x.call
6862 [插桩] 调用函数: ƒ push() { [native code] }
6863 [插桩] 参数: (2) ['3', '3'] i
你可以验证一下
最后我们得到["3","3","i","3","d","p","x","z","9"] 这个和之前切割的后面一部分拼接就是我们的_fingerprint
啦
小结一下
这个没有复杂计算基本上全是随机值。所以推理起来不算太难。但是他也不是很简单。只有自己关掉教程搞出来才知道是不是真的简单。
如有错误,还请大佬指出谢谢!!!
最后感谢大佬的观看,也感谢大佬们的支持。如果你有好玩的网站或者app可以私信我,如果有教学意义,并且无风险,我会出详细教程的。