1. 项目概述当JS逆向遇上AI辅助分析最近在爬虫圈子里猿人学的题目一直是检验JS逆向功力的“试金石”。第二届第三题那个绕来绕去的token加密参数相信让不少朋友挠头。传统的逆向方法比如扣代码、补环境、下断点虽然有效但过程繁琐尤其是面对混淆严重、逻辑复杂的代码时往往需要投入大量时间进行人肉分析。这次我想尝试点不一样的引入AI作为辅助分析工具看看能不能提升我们定位关键加密逻辑的效率。这不仅仅是“用AI解题”更是一次探索如何将AI大模型的能力融入我们日常逆向工作流的实战。简单来说这个项目就是利用AI比如ChatGPT、Claude或DeepSeek等代码模型来辅助分析猿人学题目中生成token的JavaScript代码。我们的目标不是让AI全自动破解而是让它充当一个“超级实习生”或“代码解释专家”帮助我们快速理解混淆后的代码结构、识别关键函数、梳理加密流程从而大幅缩短从“看到乱码”到“理清逻辑”的时间。对于爬虫工程师、安全研究人员或是对前端加密感兴趣的朋友来说掌握这套“人机协同”的分析方法能让你在面对复杂JS逆向时更加从容。2. 逆向目标分析与环境准备2.1 目标网站与参数初探首先我们得明确靶子。猿人学第二届第三题通常是一个模拟的榜单数据页面数据通过Ajax动态加载请求参数中携带一个关键的token有时也可能是sign、encrypt等名称。这个token由前端JavaScript生成每次请求都会变化且与请求参数、时间戳或其他页面状态有关用于服务端验证请求的合法性。核心需求我们需要找到生成这个token的JavaScript代码块理解其加密算法和依赖的输入参数最终在Python中复现该算法从而能够构造有效的请求来获取数据。传统难点代码混淆核心逻辑往往被obfuscator等工具混淆变量名变成_0xabc123字符串被编码代码可读性极差。逻辑分散加密逻辑可能分散在多个函数或文件中通过复杂的调用链组织起来。环境依赖代码可能依赖浏览器环境下的特有对象如window、document、navigator或函数直接扣取到Node.js或Python中运行会报错。2.2. AI工具选型与配置工欲善其事必先利其器。选择合适的AI工具至关重要。我们的需求是代码分析与解释因此需要选择在代码理解、逻辑推理方面表现突出的模型。1. 主流AI工具对比OpenAI ChatGPT (GPT-4): 代码理解能力强上下文窗口大能处理较长的代码片段。适合用于分段分析、解释复杂逻辑。需注意使用合规的API。Anthropic Claude (Claude 3 Opus/Sonnet): 在长文本处理和复杂指令遵循上表现优异对代码的逻辑梳理和步骤分解很在行。同样需要注意使用方式。国内大模型 (如DeepSeek Coder, 通义千问CodeQwen): 对中文上下文支持更好在代码生成和理解上也有不俗表现且访问相对便利。DeepSeek Coder专门针对代码训练是不错的选择。本地模型 (如CodeLlama, WizardCoder): 数据完全本地隐私性好但对硬件要求高推理速度可能较慢适合对隐私要求极高的场景。注意使用任何在线AI服务时切勿上传任何涉及真实用户数据、敏感商业逻辑或明显违法违规的代码。我们分析的是公开的、用于技术学习的题目代码。2. 我的配置方案我个人倾向于使用Claude 3 Sonnet或DeepSeek Coder作为主力分析工具。它们的平衡点在于足够强的代码分析能力、较大的上下文窗口可以一次性粘贴较多混淆代码、以及相对清晰的逻辑输出。准备一个能够粘贴大量文本的Web界面或API客户端即可。3. 辅助工具链浏览器开发者工具 (Chrome DevTools): 用于抓包、下载JS文件、调试。Sources面板和Network面板是我们的主战场。代码编辑器 (VS Code): 用于整理、格式化扣下来的JS代码。Node.js环境: 用于本地执行和测试扣出来的JavaScript代码片段验证其输出。Python环境 (requests, execjs等库): 最终算法复现和请求发送的平台。3. 核心逆向流程与AI介入点整个逆向过程可以看作一场“侦查”行动AI在其中扮演了“智能分析员”的角色。以下是结合了AI辅助的标准操作流程。3.1 数据抓包与关键JS定位首先进行手动操作这是AI无法替代的“现场勘查”。打开目标页面进入榜单或数据展示页。开启DevTools的Network面板勾选Preserve log然后触发数据加载如点击查询、翻页。在请求列表中找到携带token的XHR/Fetch请求通常是api、data等路径。查看其Headers和Payload确认token参数名。关键步骤全局搜索。在DevTools的Sources面板中对所有已加载的JS文件进行全局搜索CtrlShiftF。搜索关键词可以是token参数名如token,sign请求的URL路径关键字encrypt、encode、sign等可能的方法名。在搜索结果中找到包含token生成或赋值逻辑的JS文件。通常你会看到类似token: xxxxxx或params[token] encrypt(data)的代码。点击进入该文件。3.2. AI辅助代码清洗与结构梳理现在我们拿到了一个可能被严重混淆的JS文件。直接阅读如同天书。这时请出我们的AI助手。操作步骤代码提取在Sources面板中选中包含可疑逻辑的整个函数或一大段代码通常几百行到上千行复制出来。首次提示工程将代码粘贴给AI并附上清晰的指令。例如“请分析以下经过混淆的JavaScript代码。它很可能是一个用于生成HTTP请求中token或sign参数的加密函数。请你尝试对代码进行反混淆将十六进制字符串如\x65\x6e\x63或Unicode转义符还原为可读字符串。识别出代码中的关键函数特别是那些可能进行哈希如MD5、SHA、AES、RSA加密或进行特定编码Base64、Hex的函数。梳理主要的函数调用链用箭头图或列表说明函数之间的调用关系。指出可能的入口函数即最终生成输出token的那个函数。”AI能做什么字符串还原AI能快速识别并还原\x或\u格式的编码字符串这是提升可读性的第一步。模式识别它能识别出常见的加密库代码模式比如CryptoJS的调用方式、或自定义的位操作逻辑可能是类似MD5的FF/GG/HH/II函数。逻辑摘要即使不能完全理解算法AI也能帮你总结出“这段代码先对输入字符串A做了某种变换B然后调用了函数C最后将结果用Base64编码”这样的高层逻辑。实操心得不要一次性把上万行的整个JS文件扔给AI。模型有上下文长度限制且过多无关代码会干扰分析。应该分段、分功能地提交。先定位到最可能是入口函数的区域比如搜索return最终结果的那几行把这一小段及其直接调用的函数提交给AI分析。3.3. 关键加密逻辑定位与算法推断通过AI的初步梳理我们可能得到了一个或几个关键函数名尽管它们可能叫_0x12a4b5。接下来需要深入核心。追踪参数来源在入口函数中找到生成token所依赖的输入参数。这些参数可能来自页面全局变量如window.page请求的固定参数如page,t当前时间戳Date.now()一个固定的密钥可能被编码后隐藏在代码中甚至是一个之前请求返回的seed。AI辅助算法推断将疑似核心加密的函数代码比如一个包含很多^、、、操作或者有CryptoJS.MD5、btoa等调用的函数单独提出来再次询问AI。提示词示例“以下是疑似加密核心的函数_0x2891cd。请分析其算法逻辑它接收哪些参数每个参数的可能含义是什么例如待加密字符串、密钥、初始向量IV函数内部进行了哪些关键操作例如分组、循环位移、查表S-Box、与常量进行运算它最终返回的结果是什么格式例如十六进制字符串、Base64字符串、字节数组根据其操作它最可能实现了哪种加密或哈希算法例如类似MD5的流程、类似AES的轮函数、自定义的XOR混淆”交叉验证AI的推断不一定100%准确。我们需要用实际数据进行验证。在浏览器控制台Console中尝试直接调用我们定位到的入口函数传入已知的参数看输出的token是否与抓包抓到的一致。如果函数依赖复杂的浏览器环境可以尝试用Proxy或Object.defineProperty“钩住”Hook关键函数在它执行时打印出中间结果和输入参数。这能让我们获得最真实的执行数据流。重要提示AI可能会“幻觉”Hallucination即自信地给出错误的分析。永远要以浏览器中的实际执行结果作为最终判断标准。AI的分析结果是一个强大的“假设”需要我们用实验去证实或证伪。3.4. 本地模拟与算法复现一旦我们通过“AI分析手动验证”确认了加密逻辑下一步就是将其移植到Python中。环境补全如果JS代码依赖CryptoJS等库在Python中我们可以用pycryptodome或hashlib等库对应实现。AI可以帮忙将CryptoJS.MD5(value).toString()翻译成Python的hashlib.md5(value.encode()).hexdigest()。复杂逻辑翻译对于自定义的、位操作繁多的算法手动翻译容易出错。此时可以将清晰的JS函数代码经过AI反混淆和注释的版本再次交给AI。提示词“请将以下JavaScript函数generateToken精确地翻译成Python函数。注意处理所有位运算、整数溢出JavaScript是32位有符号整数按位运算、以及字符串编码问题。确保逻辑完全等价。”单元测试用抓包中获取的多组请求参数和对应的token作为测试用例反复验证Python复现的算法。确保在不同输入下输出都与原始token匹配。4. 实战案例拆解猿人学第三题token分析假设我们通过抓包发现请求的token是一个由数字和字母组成的32位字符串类似f1d2a3b4c5d6e7f8a9b0c1d2e3f4a5b6。每次请求page参数变化时token都不同。4.1. 定位与初步AI分析通过全局搜索token我们定位到一个名为challenge.xxxx.js的文件其中有一行params[token] _0x11bb3c(_0x1a2d4f[page] window[_secret_key]);这很可能是入口。我们查看_0x11bb3c函数发现它是一段约50行、充满^、、运算和魔数如0x5A827999的代码。我们将这段代码丢给AI。AI回复摘要 “这段代码_0x11bb3c是一个自定义的哈希函数其结构模仿了SHA-1算法的压缩函数核心循环。它接收一个字符串输入进行了如下操作将输入字符串转换为UTF-8编码的字节数组。对字节数组进行填充使其长度符合64字节512位分组的规范。定义了四个循环函数F,G,H以及对应的常量K1,K2,K3。进行了80轮的位运算每20轮使用不同的循环函数和常量。最终将五个32位中间变量a,b,c,d,e的状态值拼接并输出为十六进制字符串。注意它与标准SHA-1的初始哈希值h0-h4不同且轮函数可能被微调。你需要验证其输出。”这个分析一下子将我们从“一团乱麻”带到了“疑似SHA-1变种”的清晰假设上。4.2. 手动验证与细节确认我们在浏览器控制台进行验证首先找到window[_secret_key]的值。在Console输入window._secret_key假设得到猿人学secret2024。然后手动调用函数。假设当前page1。// 在Console中执行 _0x11bb3c(1猿人学secret2024)得到输出与Network中page1的请求的token对比完全一致。假设输出是f1d2a3b4c5d6e7f8a9b0c1d2e3f4a5b6。至此AI的假设被证实。加密逻辑是token custom_hash(page window._secret_key)。4.3. Python算法复现现在我们需要在Python中实现这个“魔改SHA-1”。我们可以将AI分析后的、可读性增强的JS代码或者直接就是原混淆代码如果你有信心交给AI进行翻译。向AI提交_0x11bb3c函数的清晰版代码并请求翻译。AI生成的Python代码骨架import struct def left_rotate(n, b): return ((n b) | (n (32 - b))) 0xffffffff def custom_hash(data): # 1. 预处理与填充 (与JS逻辑对齐) if isinstance(data, str): data data.encode(utf-8) original_byte_len len(data) data b\x80 while (len(data) % 64) ! 56: data b\x00 data struct.pack(Q, original_byte_len * 8) # 2. 初始化魔改的初始哈希值 (从JS代码中提取) h0 0x67452301 h1 0xEFCDAB89 h2 0x98BADCFE h3 0x10325476 h4 0xC3D2E1F0 # 注意这个值与标准SHA-1不同 # 3. 定义魔改的轮函数和常量 (从JS代码中提取) def F(b, c, d): return (b c) | ((~b) d) def G(b, c, d): return b ^ c ^ d def H(b, c, d): return (b c) | (b d) | (c d) # 常量K也可能被修改 K1 0x5A827999 K2 0x6ED9EBA1 K3 0x8F1BBCDC K4 0xCA62C1D6 # 4. 主循环 (80轮) for i in range(0, len(data), 64): chunk data[i:i64] w list(struct.unpack(16L, chunk)) for j in range(16, 80): # 扩展消息注意JS中可能使用的位运算方式 w.append(left_rotate(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1)) a, b, c, d, e h0, h1, h2, h3, h4 for j in range(80): if 0 j 20: f F(b, c, d) k K1 elif 20 j 40: f G(b, c, d) k K2 elif 40 j 60: f H(b, c, d) k K3 else: f G(b, c, d) # 注意最后20轮可能用G而不是标准的H k K4 temp (left_rotate(a, 5) f e k w[j]) 0xffffffff e d d c c left_rotate(b, 30) b a a temp h0 (h0 a) 0xffffffff h1 (h1 b) 0xffffffff h2 (h2 c) 0xffffffff h3 (h3 d) 0xffffffff h4 (h4 e) 0xffffffff # 5. 生成最终哈希值 return %08x%08x%08x%08x%08x % (h0, h1, h2, h3, h4) # 测试 if __name__ __main__: token custom_hash(1猿人学secret2024) print(token) # 预期输出: f1d2a3b4c5d6e7f8a9b0c1d2e3f4a5b6关键点你需要从JS代码中精确提取出那些魔数初始哈希h0-h4、常量K1-K4、轮函数的定义可能和标准不同、以及最后20轮使用的是哪个函数。这些细节决定了算法的正确性。AI生成的代码是一个高度可定制的模板。4.4. 完整请求构造与测试算法复现成功后剩下的就是常规的爬虫流程了。import requests import time def get_token(page): secret_key 猿人学secret2024 # 这个值需要从JS中动态提取或固定 input_str f{page}{secret_key} return custom_hash(input_str) def fetch_data(page): url https://match.yuanrenxue.cn/api/match/3 params { page: page, # 可能还有其他固定参数 } headers { User-Agent: Mozilla/5.0..., Referer: https://match.yuanrenxue.cn/, } # 关键动态生成token params[token] get_token(page) resp requests.get(url, paramsparams, headersheaders) if resp.status_code 200: return resp.json() else: print(f请求失败: {resp.status_code}) return None # 遍历页面获取数据 for page in range(1, 6): data fetch_data(page) if data: print(f第{page}页数据: {data}) time.sleep(1) # 礼貌延迟5. AI辅助逆向的常见问题与技巧5.1. 如何应对AI的“幻觉”AI“幻觉”是最大的风险。它可能信誓旦旦地告诉你这是“RSA加密”而实际上只是个简单的XOR。应对策略交叉验证用不同的AI模型如ChatGPT和Claude分析同一段代码对比它们的结论。如果结论差异很大就需要提高警惕。分而治之让AI分析最小的、功能独立的代码块。一个只做Base64编码的函数AI几乎不会分析错。从简单到复杂逐步建立信心。要求提供依据在提示词中要求AI“指出得出这个结论的代码行依据”。这能迫使AI进行更细致的推理有时它能指出来有时它指不出来后者就暴露了其结论的脆弱性。终极验证在浏览器控制台或Node.js中实际运行代码片段。这是唯一真理。你可以构造一个简单的输入让AI认为的“加密函数”运行一下看输出是否符合某种已知模式的长度和字符集。5.2. 如何设计高效的提示词好的提示词是成功的一半。针对JS逆向可以遵循以下结构角色设定“你是一位资深JavaScript逆向工程师和安全研究员。”任务描述“请分析以下经过混淆的JavaScript代码片段它来自一个网络爬虫逆向场景。”具体指令分点、清晰“还原所有可读的字符串。”“识别出所有函数定义并给它们起一个基于功能的、可读的别名如calculateHash,encodeBase64。”“绘制函数调用关系图。”“重点分析函数_0x123abc指出它可能实现了什么算法输入输出是什么。”输出格式“请用Markdown格式输出包含代码块和清晰的步骤说明。”进阶技巧使用少样本学习Few-shot Learning。在提示词中先给一个简单的、你知道答案的混淆代码例子并展示你希望AI如何分析它。然后再给出你要分析的真实复杂代码。这能极大地提升AI输出的格式和质量。5.3. 如何处理复杂的浏览器环境依赖有时生成token的代码严重依赖window、document、navigator.userAgent甚至是一些由其他JS文件生成的全局变量。AI辅助策略环境提取让AI帮你识别代码依赖了哪些浏览器环境下的属性。提示词“列出此代码片段中所有对浏览器全局对象如window,document,navigator,location的引用。”模拟方案根据AI列出的清单在Python的execjs或js2py环境中提前定义这些变量。例如import js2py context js2py.EvalJs() context.window {_secret_key: 猿人学secret2024} context.document {} context.navigator {userAgent: Mozilla/5.0...} # 然后执行扣出来的JS代码 token context.eval(js_code)函数Hook如果依赖过于复杂可以考虑在浏览器中通过重写Function.prototype或使用Proxy在关键函数执行时将其参数、上下文和结果打印出来从而“窥探”到其运行时的真实状态然后直接在Python中硬编码这些状态值。5.4. 效率提升与流程整合将AI分析融入你的逆向工作流建立代码片段库将常见的混淆模式如字符串数组还原、十六进制解码及其AI分析提示词保存下来下次直接复用。使用带代码高亮的笔记软件如Obsidian、Notion将抓取的JS代码、AI的分析结果、自己的验证笔记、最终的Python代码全部记录在一个页面内形成完整的逆向报告。自动化尝试对于简单的、模式固定的混淆如简单的变量名替换可以尝试编写正则表达式或使用de4js等开源工具进行初步反混淆再将结果交给AI减轻AI的负担。6. 总结与个人体会回过头看“JS逆向实战|使用AI分析猿人学第二届第三题的token加密参数”这个项目本质上是一次方法论的升级。AI的加入并没有改变JS逆向的核心——即对JavaScript语言特性、浏览器环境、加密算法和网络协议的深刻理解。它改变的是我们处理“信息噪音”和“认知负荷”的方式。以前面对一堆_0x开头的变量我们需要像侦探一样一点点人肉跟踪、记录、推理耗时耗力。现在AI可以瞬间帮我们完成初步的“现场勘查报告”指出“这里可能是个哈希函数”、“那里可能在进行Base64编码”。这相当于给我们配备了一个拥有海量代码模式记忆的助手极大地加速了假设生成的过程。但必须清醒认识到AI目前只是一个强大的辅助而非主体。它无法替代你在浏览器控制台里亲手调试、下断点、观察调用栈。它无法替代你对密码学基础知识的理解否则你无法判断AI关于“魔改SHA-1”的结论是否合理。它更无法替代你用真实数据去验证算法的最终步骤。我个人的体会是“AI辅助逆向”的最佳模式是“人主机辅”。工程师负责制定侦查策略抓包、定位、设计验证实验、把控方向判断AI的分析是否靠谱、并完成最终的工程化落地Python复现、集成到爬虫框架。AI则负责完成那些重复、繁琐、需要大量模式匹配的初步分析工作将工程师从“阅读天书”的苦力中解放出来让我们能更专注于高层次的逻辑推理和架构设计。这次实战之后我的逆向工具箱里又多了一件趁手的兵器。下次再遇到更复杂的obfuscator打包代码或者wasm加密我知道至少有一个聪明的“伙伴”可以一起商量了。当然最后做决策、写代码、并对结果负责的依然是我自己。