【JS逆向学习】猿人学 第五题 js混淆 乱码

本文围绕猿人学逆向目标展开,先分析网络请求,通过跟栈、断点调试等方法,逐步分析加密参数的生成逻辑。在扣代码调试过程中,处理反调试代码、补全变量和函数,最终拿到核心加密参数,完成所有加密分析,并给出猿人学第五题源码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

逆向目标
  • 网址:https://match.yuanrenxue.cn/match/5
  • 接口:https://match.yuanrenxue.cn/api/match/5?page=2&m=1709806560791&f=1709806560000
  • 参数:
    • Cookie(m、RM4hZBv0dDon443M)
    • payload(m、f)
逆向过程

老规矩,上来先分析网络请求
在这里插入图片描述
网页上分析请求有点不太清楚,我们直接转为 python 代码来分析,观察右侧python代码,加密的几个参数就清楚了 cookie(m、RM4hZBv0dDon443M)params(m、f)
在这里插入图片描述

逆向分析

我们先进启动器跟栈观察发现加密参数都已经生成完成了,那我们先随便找个加密参数搜索一下看能不能找到window._$is的赋值语句,直接搜索_$is,返现只有一个匹配结果
在这里插入图片描述
这是一个window的属性,我们又没有搜索到赋值语句,所以可以断定是在某个js语句中执行了这个操作,那我们在当前文件继续查看分析这个文件,可以看到在实际的网络请求的逻辑上面就有一段自执行的函数代码

<script>
    function _$KS() {
   
   

        if (eval["toString"]() === "function eval() { [native code] }") {
   
   
            if ($_zw["length"] === 25) {
   
   
                $_ow = "";

                for (var h = 0; h < window["$$$"]["length"]; h++) {
   
   
                    $_ow += String["fromCharCode"](window["$$$"][h]["charCodeAt"]() - 76);
                }

                eval($_ow);
            } else {
   
   
                $_ow = "";

                for (var h = 0; h < window["$$$"]["length"]; h++) {
   
   
                    $_ow += String["fromCharCode"](window["$$$"][h]["charCodeAt"]() - 76);
                }

                eval($_ow);
            }
        } else {
   
   
            $_ow = "";

            for (var h = 0; h < window["$$$"]["length"]; h++) {
   
   
                $_ow += String["fromCharCode"](window["$$$"][h]["charCodeAt"]() - 2331 - parseInt(h["toString"]()["slice"](0, 1)) * 2);
            }

            eval($_ow);
        }
    }

    _$KS();
</script>

我们简单分析下这段代码,eval["toString"]() === "function eval() { [native code] }"的值为true,然后在控制台看下$_zwlength值为27,所以具体执行的是哪个分支就很清楚了,直接断点调试,发现断住了
在这里插入图片描述
接下来就是大家喜闻乐见的常规hook操作了,既然是 cookie加密 我们就先 hook cookiem参数

(function () {
   
   
    'use strict';
    var cookie_cache = document.cookie;
    Object.defineProperty(document, 'cookie', {
   
   
        get: function () {
   
   
            return cookie_cache;
        },
        set: function (val) {
   
   
            console.log('Setting cookie', val);
            //if (val.indexOf('RM4hZBv0dDon443M') !== -1) {
   
   
            if (val.indexOf('m') !== -1) {
   
   
                debugger;
            }
            var cookie = val.split(";")[0];
            var ncookie = cookie.split("=");
            var flag = false;
            var cache = cookie_cache.split("; ");
            cache = cache.map(function (a) {
   
   
                if (a.split("=")[0] === ncookie[0]) {
   
   
                    flag = true;
                    return cookie;
                }
                return a;
            })
            cookie_cache = cache.join("; ");
            if (!flag) {
   
   
                cookie_cache += cookie + "; ";
            }
            return cookie_cache;
        }
    });
})();

如下图,断点断在了如下位置
在这里插入图片描述
直接跟栈分析就行了

_$Wa = _0x12eaf3();
_0x3d0f3f[_$Fe] = 'm=' + _0x474032(_$Wa) + ';\x20path=/';

控制台打印_$Wa的值为1709864112000,是个 13 位的时间戳,再看_0x12eaf3 的函数定义

function _0x12eaf3() {
   
   
    return _0x35bb1d[_$UH[0xff]](new _0x35bb1d());
}
/* 
	控制台打印观察混淆后的变量值,如下
*/
_$UH[0xff]
>> 'parse'
_0x35bb1d
>> ƒ Date() {
   
    [native code] }

再来看_0x474032这个函数
在这里插入图片描述
一层层跟下去就可以发现具体的调用顺序了,如下图
在这里插入图片描述
调用顺序都有了,接下来我们要开始扣代码了,把上图所有涉及到的调用函数都扣下来,然后我们在本地nodejs中调试

function _0x1ee7ec(_0x206333) {
   
   
    return _0x12b47d(_0x11a7a2(_0x35f5f2(_0x206333), 0x8 * _0x206333[_$UH[0x6c]]));
}


function _0x499969(_0x82fe7e) {
   
   
    var _0x5bdda4, _0x322a73, _0xd0b5cd = '0123456789abcdef', _0x21f411 = '';
    for (_0x322a73 = 0x0; _0x322a73 < _0x82fe7e[_$UH[0x6c]]; _0x322a73 += 0x1)
        _0x5bdda4 = _0x82fe7e[_$UH[0xf]](_0x322a73),
            _0x21f411 += _0xd0b5cd['charAt'](_0x5bdda4 >>> 0x4 & 0xf) + _0xd0b5cd['charAt'](0xf & _0x5bdda4);
    return _0x21f411;
}

function _0x2b8a17(_0x36f847) {
   
   
    return unescape(encodeURIComponent(_0x36f847));
}

function _0x41873d(_0x5a6962) {
   
   
    return _0x1ee7ec(_0x2b8a17(_0x5a6962));
}

function _0x37614a(_0x32e7c1) {
   
   
    return _0x499969(_0x41873d(_0x32e7c1));
}

function _0x474032(_0x233f82, _0xe2ed33, _0x3229f9) {
   
   
    return _0xe2ed33 ? _0x3229f9 ? v(_0xe2ed33, _0x233f82) : y(_0xe2ed33, _0x233f82) : _0x3229f9 ? _0x41873d(_0x233f82) : _0x37614a(_0x233f82);
}

function _0x12b47d(_0x149183) {
   
   
    var _0xabbcb3, _0x1145c3 = '', _0x4fce58 = 0x20 * _0x149183[_$UH[0x6c]];
    for (_0xabbcb3 = 0x0; _0xabbcb3 < _0x4fce58; _0xabbcb3 += 0x8)
        _0x1145c3 += _0x30bc70[_$UH[0x114]](_0x149183[_0xabbcb3 >> 0x5] >>> _0xabbcb3 % 0x20 & 0xff);
    return _0x1145c3;
}

function _0x35f5f2(_0x243853) {
   
   
    var _0x139b8b, _0xa791a1 = [];
    for (_0xa791a1[(_0x243853[_$UH[0x6c]] >> 0x2) - 0x1] = void 0x0,
             _0x139b8b = 0x0; _0x139b8b < _0xa791a1[_$UH[0x6c]]; _0x139b8b += 0x1)
        _0xa791a1[_0x139b8b] = 0x0;
    var _0x41a533 = 0x8 * _0x243853[_$UH[0x6c]];
    for (_0x139b8b = 0x0; _0x139b8b < _0x41a533; _0x139b8b += 0x8)
        _0xa791a1[_0x139b8b >> 0x5] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗雅颂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值