吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4083|回复: 30
上一主题 下一主题
收起左侧

[Web逆向] vmp套vmp之探讨某d的_fingerprint参数生成

[复制链接]
跳转到指定楼层
楼主
utf8 发表于 2025-5-9 16:42 回帖奖励
本帖最后由 utf8 于 2025-5-9 16:42 编辑

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,这个是死值,我刷新了几次都没变

接着向下看,为了方便教学,我将日志一些干扰项全部删除了。日志很长,且听我慢慢分析。

我们分析日志的时候抓住几点:

  1. 入参
  2. 计算
  3. 结果

在下面这个日志,我们初始串 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

其中 qmwhwwpphm33都是通过一个函数生产的。

这个函数直接扣就行,不算难点。代码如下:

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可以私信我,如果有教学意义,并且无风险,我会出详细教程的。

log.zip (28.96 KB, 下载次数: 20)

免费评分

参与人数 10吾爱币 +11 热心值 +9 收起 理由
beihai1314 + 1 + 1 我很赞同!
zeknight + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
ioyr5995 + 1 + 1 我很赞同!
allspark + 1 + 1 用心讨论,共获提升!
抱歉、 + 1 用心讨论,共获提升!
hikz + 1 谢谢@Thanks!
fengbolee + 2 + 1 用心讨论,共获提升!
FitContent + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
helian147 + 1 + 1 热心回复!
1959450071 + 1 + 1 谢谢@Thanks!

查看全部评分

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

沙发
yellowspider 发表于 2025-5-9 17:36
大佬大佬,膜拜膜拜
3#
hackest 发表于 2025-5-9 22:08
4#
amwquhwqas128 发表于 2025-5-9 23:00
5#
twl288 发表于 2025-5-10 00:31
谢谢,虽然我看不懂
6#
xue888 发表于 2025-5-10 00:59
厉害厉害 好好学习
7#
wasm2023 发表于 2025-5-10 11:27
楼主,可以试试猿人学第二届的题目,尤其是第10题
8#
 楼主| utf8 发表于 2025-5-10 17:21 |楼主
wasm2023 发表于 2025-5-10 11:27
楼主,可以试试猿人学第二届的题目,尤其是第10题

好像之前做过,不知道放哪里了
9#
lyyzs7742 发表于 2025-5-10 23:41
配套的题目
10#
wasm2023 发表于 2025-5-11 09:29
utf8 发表于 2025-5-10 17:21
好像之前做过,不知道放哪里了

知乎的vmp套wasm vmp也可以试试
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-6-10 19:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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