news 2026/5/26 4:58:46

猿人学第三届-第二题-滑块缺口之涟漪 纯算

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
猿人学第三届-第二题-滑块缺口之涟漪 纯算

猿人学第三届-第二题-滑块缺口之涟漪

1. 网络包分析

1.1 目标API

https://match2025.yuanrenxue.cn/match2025/topic/2_captcha_jpg

1.2 关键载荷参数

  • 参数名:mmc
  • 作用: 这是我们需要还原的加密参数


2. JS代码解混淆

2.1 初始分析

通过启动器进入JS代码后,发现代码经过了严重混淆:

  • 变量名使用了大量隐藏字符(Unicode特殊字符)
  • 代码结构被打乱
  • 如果不解混淆,代码几乎无法阅读

2.2 解混淆工具

使用在线工具进行解混淆:

https://js-deobfuscator.ve

重要设置

  • ✅ 勾选"变量优化"
  • ✅ 点击"清理代码"按钮,移除无用代码

2.3 解混淆后的问题修复

第一个报错

解混淆后替换原JS代码,浏览器报错:

2:1015 Uncaught ReferenceError: yrx_ﱞﱞﱞﱞﱞﱞﱞﱞﱞ is not defined at 2:1015:13 at 2:1166:11 at 2:1181:11 (匿名) @ 2:1015 (匿名) @ 2:1166 (匿名) @ 2:1181

报错位置代码

{try{g=yrx_ﱞﱞﱞﱞﱞﱞﱞﱞﱞ(f,newTextEncoder().encode(Navigator.prototype.userAgent.call(navigator))+"_|_");}catch(a){g=yrx_ﱞﱞﱞﱞﱞﱞﱞﱞﱞ(f,newTextEncoder().encode(navigator.userAgent+Date.now("r")));}}

定位原始代码

搜索关键字TextEncoder,找到解混淆前的代码:

try{yrx_ﱞﱞﱞﱞﱞﱞﱞ=yrx_ﱞﱞﱞﱞﱞﱞﱞﱞﱞ(yrx_ﱞﱞﱞﱞﱞﱞ,(newTextEncoder)["encode"](Navigator["prototype"]["userAgent"]["call"](navigator))+"_|_")}catch(yrx_ﱞ){yrx_ﱞﱞﱞﱞﱞﱞﱞ=yrx_ﱞﱞﱞﱞﱞﱞﱞﱞﱞ(yrx_ﱞﱞﱞﱞﱞﱞ,(newTextEncoder)["encode"](navigator["userAgent"]+Date["now"]("r")))}yrx_ﱞﱞﱞﱞ-=6132+7*-122+-10*527

解决方案

通过对比解混淆前后的代码,发现函数定义在下方:

varyrx_ﱞﱞﱞﱞﱞﱞﱞﱞﱞ=function(yrx_ﱞﱞﱞﱞ,yrx_ﱞﱞﱞﱞﱞ){varyrx_ﱞﱞﱞﱞﱞﱞ=yrx_ﱞﱞ(this,(function(){returnyrx_ﱞﱞﱞﱞﱞﱞ["toString"]()["search"]("(((.+)+)+)"+"+$")["toString"]()["constructo"+"r"](yrx_ﱞﱞﱞﱞﱞﱞ)["search"]("(((.+)+)+)"+"+$")}));yrx_ﱞﱞﱞﱞﱞﱞ();varyrx_ﱞﱞﱞﱞﱞﱞﱞ=yrx_ﱞﱞﱞ(this,(function(){varyrx_ﱞ=function(){varyrx_ﱞ;try{yrx_ﱞ=Function("return (fu"+"nction() "+("{}.constru"+'ctor("retu'+'rn this")('+" )")+");")()}catch(yrx_ﱞﱞ){yrx_ﱞ=window}returnyrx_ﱞ}// ... 更多代码}));}

我们需要手动重命名这个函数。将其重命名为Getutf8arry

// 修改后的代码try{g=Getutf8arry(f,newTextEncoder().encode(Navigator.prototype.userAgent.call(navigator))+"_|_");}catch(a){g=Getutf8arry(f,newTextEncoder().encode(navigator.userAgent+Date.now("r")));}d-=8;

同时修改函数定义:

varGetutf8arry=functione(d,f){vari=a||27;for(;;){if(i<16){if(i<8){if(i<4){if(i<2){if(i<1){j[l]=255-l;i+=14;}else{// ... 更多代码}}}}}}}
第二个报错

再次测试后发现还有一个报错位置:

}elseif(c<11){e=document.getElementById("captchaCanvas");c-=3;}else{k=yrx_ﱞﱞﱞﱞﱞﱞﱞﱞﱞ(f,j);// 这里还有一个未重命名的调用c-=7;}

修改为

}elseif(c<11){e=document.getElementById("captchaCanvas");c-=3;}else{k=Getutf8arry(f,j);// 修改函数名c-=7;}

修改完成后,刷新页面,图片正常显示,说明解混淆已完成。


3. 加密逻辑分析

3.1 核心加密函数分析

从我们重命名的Getutf8arry函数入手,分析其返回值:

try{g=Getutf8arry(f,newTextEncoder().encode(Navigator.prototype.userAgent.call(navigator))+"_|_");}catch(a){g=Getutf8arry(f,newTextEncoder().encode(navigator.userAgent+Date.now("r")));}

关键发现

  1. try块是混淆陷阱new TextEncoder().encode(...) + "_|_"会报错,因为 Uint8Array 不能与字符串相加
  2. 真正的加密在catch块:实际执行的是navigator.userAgent + Date.now("r")
  3. 返回值g是一个长度为124的Uint8Array数组

这是典型的RC4 加密算法的特征。

3.2 加密参数还原

参数1:加密数据(data)
// 真正的加密数据生成newTextEncoder().encode(navigator.userAgent+Date.now("r"))

还原为函数:

/** * 生成加密所需的输入数据(UA + 时间戳) * @returns {Uint8Array} 输入数据的字节数组 */functiongenerateInputData(){// 获取浏览器的 UserAgentconstuserAgent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36'// 获取当前时间戳consttimestamp=Date.now().toString();// 将UA和时间戳合并constcombinedString=userAgent+timestamp;// 转换为字节数组returnnewTextEncoder().encode(combinedString);}
参数2:加密密钥(key)

通过调试,将密钥f转换为字符串:

console.log(newTextDecoder().decode(f))// 输出: b31ac05816bb570d

发现是一个16位的随机字符串。向上查找代码,找到密钥生成逻辑:

if(d<12){if(d<10){if(d<9){e=Array.apply(null,Array(16)).map(function(){varb=a||0;for(;;){return"0123456789abcdef0123456789abcdef0123456789abcdef6789abcdef789abcdef6789abcdef".charAt(Math.floor(Math.random()*62));}}).join("");// ... 更多代码}}}

验证

"0123456789abcdef0123456789abcdef0123456789abcdef6789abcdef789abcdef6789abcdef".charAt(Math.floor(Math.random()*62));// 'd'"0123456789abcdef0123456789abcdef0123456789abcdef6789abcdef789abcdef6789abcdef".charAt(Math.floor(Math.random()*62));// 'e'"0123456789abcdef0123456789abcdef0123456789abcdef6789abcdef789abcdef6789abcdef".charAt(Math.floor(Math.random()*62));// 'f'

每次运行生成一个字符,Array(16)生成16个字符,与密钥长度一致:

'b31ac05816bb570d'.length// 16

还原为函数:

/** * 生成16位随机字符串作为加密密钥 * @returns {string} 16位随机字符串 */functiongenerateRandomKey(){constcharset="0123456789abcdef0123456789abcdef0123456789abcdef6789abcdef789abcdef6789abcdef";constkey=Array.apply(null,Array(16)).map(function(){returncharset.charAt(Math.floor(Math.random()*62));}).join("");returnkey;}

将密钥转换为 Uint8Array:

/** * 将密钥字符串转换为Uint8Array * @param {string} key - 密钥字符串 * @returns {Uint8Array} 字节数组 */functionkeyToByteArray(key){returnnewTextEncoder().encode(key);}

3.3 RC4加密算法还原

Getutf8arry函数复制到本地:

/** * RC4变种加密算法 * @param {Uint8Array} key - 加密密钥(16字节) * @param {Uint8Array} data - 待加密数据 * @returns {Uint8Array} 加密后的数据 */functionrc4Encrypt(key,data){vari=27;// 固定为27(通过单步调试确定)//此处省略自行复制}

重要修改

  • i = a || 27改为固定值i = 27(通过单步调试确定)

3.4 Token格式化

找到将加密数组转换为最终token的位置。全局搜索mmc

elseif(d<3){h.data={mmc:Array.from(g).map(function(b){varc=a||0;for(;;){returnb.toString(16).padStart(2,"0");}}).join("")+e};}

单步调试后验证:

h.data// {mmc: '6a014756a723eec83e1ff6bf8e0ad3e420df3c896f60768a70...543f677c3633be4ab9ab1c9dc1c72e7e3d3f3db51a0982988'}

还原为函数:

/** * 将加密结果转换为token格式 * @param {Uint8Array} encryptedData - 加密后的数据 * @param {string} key - 原始密钥 * @returns {object} 包含mmc字段的数据对象 */functionformatToken(encryptedData,key){constresult={data:{mmc:Array.from(encryptedData).map(function(byte){returnbyte.toString(16).padStart(2,"0");}).join("")+key}};returnresult;}

格式说明

  • 将每个字节转换为2位16进制字符串
  • 所有字节拼接后,追加原始密钥
  • 最终形成完整的mmc参数

4. 完整代码实现

constUSER_AGENT='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36'/** * 生成16位随机字符串作为加密密钥 * @returns {string} 16位随机字符串 */functiongenerateRandomKey(){constcharset="0123456789abcdef0123456789abcdef0123456789abcdef6789abcdef789abcdef6789abcdef";constkey=Array.apply(null,Array(16)).map(function(){returncharset.charAt(Math.floor(Math.random()*62));}).join("");returnkey;}/** * 将密钥字符串转换为Uint8Array * @param {string} key - 密钥字符串 * @returns {Uint8Array} 字节数组 */functionkeyToByteArray(key){returnnewTextEncoder().encode(key);}/** * 生成加密所需的输入数据(UA + 时间戳) * @returns {Uint8Array} 输入数据的字节数组 */functiongenerateInputData(){// 获取浏览器的 UserAgentconstuserAgent=typeofnavigator!=='undefined'?navigator.userAgent:USER_AGENT;// 获取当前时间戳consttimestamp=Date.now().toString();// 将UA和时间戳合并constcombinedString=userAgent+timestamp;// 转换为字节数组returnnewTextEncoder().encode(combinedString);}/** * RC4变种加密算法 * @param {Uint8Array} key - 加密密钥(16字节) * @param {Uint8Array} data - 待加密数据 * @returns {Uint8Array} 加密后的数据 */functionrc4Encrypt(key,data){// 此处省略具体实现,请从原始JS中复制完整的rc4Encrypt函数// 记得将 i = a || 27 改为 i = 27}/** * 将加密结果转换为token格式 * @param {Uint8Array} encryptedData - 加密后的数据 * @param {string} key - 原始密钥 * @returns {object} 包含mmc字段的数据对象 */functionformatToken(encryptedData,key){constresult={data:{mmc:Array.from(encryptedData).map(function(byte){returnbyte.toString(16).padStart(2,"0");}).join("")+key}};returnresult;}/** * 生成完整的加密token * @returns {string} 加密后的token字符串 */functiongenerateToken(){// 1. 生成随机密钥constkey=generateRandomKey();console.log("生成密钥:",key);// 2. 将密钥转换为字节数组constkeyBytes=keyToByteArray(key);console.log("密钥字节数组:",keyBytes);// 3. 生成输入数据(UA + 时间戳)constinputData=generateInputData();console.log("输入数据:",inputData);// 4. 执行RC4加密constencryptedData=rc4Encrypt(keyBytes,inputData);console.log("加密结果:",encryptedData);// 5. 格式化为最终tokenconsttokenData=formatToken(encryptedData,key);returntokenData.data.mmc;}// 使用示例consttoken=generateToken();console.log("最终Token:",token);

5. 总结

5.1 加密流程

  1. 生成随机密钥:16位随机字符串(从特定字符集中选择)
  2. 准备加密数据:UserAgent + 当前时间戳
  3. RC4加密:使用密钥对数据进行RC4变种加密
  4. 格式化输出:将加密结果转为16进制字符串,并追加原始密钥

5.2 关键技术点

  • 混淆陷阱:try块中的代码会报错,真正的逻辑在catch块
  • RC4算法:使用了RC4的变种实现
  • 状态机控制:通过变量i控制执行流程(固定为27)
  • Token格式:加密数据的16进制表示 + 原始密钥

5.3 注意事项

  • 时间戳必须与服务器时间同步
  • UserAgent必须与浏览器一致
  • 密钥每次请求都需要重新生成
  • 最终的mmc参数包含加密数据和密钥两部分
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 5:38:37

交通网络仿真软件:TransModeler_(1).TransModeler软件概述

TransModeler软件概述 1. TransModeler简介 TransModeler是一款强大的交通网络仿真软件&#xff0c;广泛应用于交通规划、设计和管理等领域。它能够模拟各种交通网络和交通流情况&#xff0c;帮助用户评估和优化交通系统的性能。TransModeler的主要功能包括交通网络建模、交通流…

作者头像 李华
网站建设 2026/5/24 14:29:57

5个必学的Conda命令实战案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个Jupyter Notebook教程&#xff0c;包含5个Conda命令的实战案例&#xff1a;1. 创建和管理Python虚拟环境&#xff1b;2. 安装特定版本的Python包&#xff1b;3. 导出和共享…

作者头像 李华
网站建设 2026/5/25 7:03:10

F2批量重命名工具终极指南:告别杂乱文件名的7个实战技巧

F2批量重命名工具终极指南&#xff1a;告别杂乱文件名的7个实战技巧 【免费下载链接】f2 F2 is a cross-platform command-line tool for batch renaming files and directories quickly and safely. Written in Go! 项目地址: https://gitcode.com/gh_mirrors/f21/f2 还…

作者头像 李华
网站建设 2026/5/25 14:37:56

5、高级网络分析工具:Wireshark 与 Ettercap 的进阶应用

高级网络分析工具:Wireshark 与 Ettercap 的进阶应用 1. 超越简单捕获的高级 Wireshark 应用 假设你已经对 Wireshark(曾用名 Ethereal)有了一定的使用经验。即使你刚接触渗透测试,在实验环境中也很难避开 Wireshark。如果你对这个出色的数据包分析工具还不熟悉,那你应该…

作者头像 李华
网站建设 2026/5/25 19:33:13

AZ-500云安全架构设计(从Agent部署到实时威胁检测)

第一章&#xff1a;MCP AZ-500 的云 Agent 安全防护在现代云安全架构中&#xff0c;Azure 的 MCP AZ-500 认证所涵盖的云 Agent 安全机制是保障虚拟机工作负载完整性的核心组件。云 Agent 作为运行在 Azure 虚拟机内部的轻量级代理程序&#xff0c;负责与 Azure 控制平面通信&a…

作者头像 李华
网站建设 2026/5/25 14:38:06

Winevdm:在64位Windows上运行16位应用的终极方案

Winevdm&#xff1a;在64位Windows上运行16位应用的终极方案 【免费下载链接】winevdm 16-bit Windows (Windows 1.x, 2.x, 3.0, 3.1, etc.) on 64-bit Windows 项目地址: https://gitcode.com/gh_mirrors/wi/winevdm 你是否遇到过这样的情况&#xff1a;一些经典的16位…

作者头像 李华