news 2026/8/28 17:17:24

JS逆向不用头秃:用大模型自动分析混淆代码完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JS逆向不用头秃:用大模型自动分析混淆代码完整流程

做了五六年前端逆向与协议分析,最常被问的问题就是:这段混淆JS怎么解?控制流拆得七零八落、字符串全是十六进制拼接、变量名全是无意义的乱码、还插了一堆反调试死代码,新人看了直接懵,老手也要抠上大半天。

传统的JS逆向,本质上是「人工肉眼分析 + 动态调试验证」的体力劳动:格式化、找入口、打断点、单步跟、抠字符串、还原逻辑,大量时间都花在机械性的清理和梳理上。遇到强混淆的代码,分析核心逻辑的时间甚至不到20%,80%的精力都消耗在和混淆器的对抗上。

而随着代码大模型的成熟,这套工作模式完全可以重构。不是说直接把整段混淆代码扔给大模型就能出结果——那样大概率会得到一段看起来对但功能不对的“幻觉代码”。真正工程化的方案,是「预处理工程化 + 大模型语义还原 + 动态校验闭环」:把机械性的清理、梳理、还原工作交给AI,人只做核心决策、边界约束和结果校验,效率提升数倍的同时,保证结果的准确性。

本文就完整拆解这套自动化分析流程,从预处理、分块、语义还原到动态校验,每一步都附带实现逻辑和实战脚本,看完就能落地属于自己的AI辅助逆向工具链。

混淆代码样本

工程化预处理

功能分块拆解

逐块语义还原

动态校验闭环

可读逻辑输出

格式化标准化

对抗代码剥离

常量字符串还原

死代码初步过滤

核心入口锚定

功能模块划分

依赖关系标注

大模型逐块还原

锚点约束防跑偏

变量语义重命名

多组用例输入

输出结果对比

差异块重还原


一、先讲清楚:传统逆向的痛点与AI的定位

1.1 传统JS逆向的核心痛点

  1. 混淆手段迭代快,特征匹配失效
    早期的混淆简单,写个AST遍历脚本就能批量还原变量名、字符串。现在的混淆器都是生成式的,每次混淆结果都不一样,特征匹配脚本用几次就失效了。

  2. 机械性工作占比高,效率极低
    控制流平坦化、死代码插入、字符串拆分,这些混淆手段本身没有技术难度,但就是费时间。几千行的混淆代码,真正核心的逻辑可能就几百行,大部分时间都在剔垃圾、理结构。

  3. 经验依赖强,新人上手慢
    同样一段混淆代码,老手可能一小时定位核心逻辑,新人可能三天都找不到入口。大量的技巧、经验、坑点,都靠人工积累,没法批量复制。

  4. 强对抗场景下,人工分析成本极高
    遇到虚拟机保护、代码虚拟化、环境检测这类强混淆,人工分析的成本会指数级上升,一个核心算法抠一周都是常事。

1.2 AI的定位:辅助工具,不是替代

很多人觉得AI逆向就是“扔代码进去出结果”,这是最大的误区。

  • AI擅长的是:语义理解、结构梳理、代码翻译、规律总结
  • AI不擅长的是:精确的逻辑还原、边界条件处理、对抗性识别

正确的定位是:人做策略和决策,AI做执行和体力活。人负责找入口、定边界、做校验;AI负责清理死代码、还原控制流、重命名变量、补充注释。把人从80%的机械劳动里解放出来,专注核心的20%。


二、第一步:工程化预处理,先把代码“洗干净”

直接把混淆代码扔给大模型,效果最差。就像你要翻译一篇乱码的文章,得先把污渍擦掉、把字符认全,再翻译。预处理的目标,就是把混淆代码里的噪声尽量去掉,还原成语法正确、结构清晰的基础代码,大幅提升后续AI还原的准确率。

2.1 格式化与语法标准化

第一步永远是格式化。混淆代码一般都是压缩成一行或者乱缩进的,先统一格式化,变成正常的缩进结构。

推荐用js-beautify,比编辑器自带的格式化更强大,能处理各种变形语法。

constbeautify=require('js-beautify').js;constfs=require('fs');letcode=fs.readFileSync('obfuscated.js','utf-8');letformatted=beautify(code,{indent_size:2,space_in_empty_paren:true,wrap_line_length:120});fs.writeFileSync('formatted.js',formatted);

2.2 对抗代码剥离

混淆代码里通常会有反调试、反格式化、环境检测的代码,这些代码不影响核心逻辑,但会干扰分析和调试。
常见的对抗特征:

  • debugger语句无限循环
  • 检测控制台打开,死循环或者报错
  • 检测代码缩进变化,执行假逻辑
  • 检测开发者工具,跳转错误分支

处理方法:通过特征匹配+AST识别,找到这些代码块,直接注释或者替换掉。
比如最常见的无限debugger:

// 识别并替换所有debugger语句code=code.replace(/debugger;/g,'/* debugger removed */');

复杂的对抗逻辑,可以用AST遍历识别特定模式,批量处理。

2.3 常量字符串还原

这是最常见的混淆手段:把明文字符串拆成十六进制、Unicode编码,或者放在数组里通过索引取值。

比如:

// 混淆前leturl="/api/sign";// 混淆后leta=["\x2f\x61\x70\x69\x2f\x73\x69\x67\x6e"];leturl=a[0];

还原方法

  1. 简单的十六进制、Unicode转义,直接正则替换还原
  2. 数组取值类的,通过AST遍历,把常量数组的取值直接替换成字面量
  3. 加密的字符串,先找到解密函数,批量解密替换

还原之后,大模型才能看懂代码里的字符串含义,准确理解逻辑。

2.4 死代码初步过滤

混淆器会插入大量永远执行不到的死代码、只赋值不使用的变量、无效的表达式,用来干扰阅读。

初步过滤可以用简单的数据流分析:

  • 识别从未使用的变量
  • 识别条件永远为真/假的分支
  • 识别没有副作用的表达式

这一步不用追求100%干净,去掉大部分明显的死代码就行,剩下的交给大模型处理。


三、第二步:功能分块拆解,化整为零逐个击破

预处理完的代码还是有几千行,直接喂给大模型,要么上下文不够,要么语义漂移,效果极差。正确的做法是分而治之:把大段代码按功能拆成小块,逐块还原。

3.1 先锚定核心入口

不要从头开始读,先找核心逻辑的入口。逆向的核心目标一般是签名、加密、验证这些,直接搜特征关键词定位。

常用锚点

  • 网络请求:fetchXMLHttpRequestsend
  • 加密算法:CryptoJSMD5SHAAES
  • Canvas指纹:getContexttoDataURL
  • 关键参数:signtokenpasswordkey

找到核心入口点之后,向上回溯调用链,就能梳理出完整的逻辑链路,不用在无关代码里浪费时间。

3.2 按功能模块切块

锚定核心之后,把代码按功能拆成独立的块,每块负责一个功能:

  • 初始化模块:环境检测、参数初始化
  • 工具函数模块:加密、编码、字符串处理
  • 核心逻辑模块:签名生成、算法实现
  • 请求模块:接口调用、参数拼接
  • 验证模块:结果校验、反爬验证

切块原则

  • 每块控制在100~300行,保证大模型的上下文能完整覆盖
  • 每个块尽量独立,减少跨块依赖
  • 标注清楚每个块的输入、输出、依赖的外部函数

3.3 依赖关系标注

切块不是随便切,要标注清楚块之间的依赖关系。比如B块依赖A块的函数,就要先还原A块,再还原B块。

可以简单梳理依赖顺序,从底层工具函数开始,逐层向上还原,还原好的函数可以直接作为下一块的上下文。


四、第三步:大模型语义还原,核心步骤的正确姿势

这是最核心的一步,但也是最容易踩坑的一步。很多人直接扔代码说“帮我还原”,结果出来的代码看起来很漂亮,功能完全不对。正确的还原,必须有明确的约束和校验。

4.1 还原提示词的正确写法

提示词是决定还原质量的关键。核心原则是:明确目标、划定边界、强制约束、指定格式

错误的写法:

帮我把这段代码还原成可读的。

正确的写法:

你是一名资深JavaScript逆向工程师。请分析下面的混淆代码,还原成可读性强的等价代码。

约束规则

  1. 功能完全等价:还原后的代码和原代码输入输出必须完全一致,不能修改任何逻辑
  2. 保留核心API:所有底层浏览器API、加密函数、网络调用必须保留,不能修改
  3. 语义化重命名:所有无意义的变量名、函数名,根据功能重命名成有意义的英文名称
  4. 结构还原:把平坦化的控制流还原成正常的顺序、分支、循环结构
  5. 剔除死代码:删除所有不影响逻辑的死代码、无效变量、冗余表达式
  6. 补充中文注释:关键逻辑、函数功能、参数含义都要加注释
  7. 只输出完整的还原代码,不要任何解释、说明、markdown标记

代码

{code}

4.2 逐块还原,上下文接力

从最底层的工具函数开始,逐块向上还原。

  • 还原第一层工具函数,验证正确
  • 还原第二层的时候,把第一层还原好的函数作为上下文一起喂进去
  • 逐层向上,直到核心逻辑

这样每一步的上下文都足够精准,还原准确率远高于整段处理。

4.3 不同混淆类型的针对性策略

  • 变量名混淆:重点是语义化重命名,根据函数功能推测变量含义
  • 控制流平坦化:重点是梳理状态变量,还原成标准的分支循环结构
  • 字符串加密:结合上下文和功能,还原字符串的实际含义
  • 死代码插入:识别并剔除不影响逻辑的冗余代码
  • 虚拟机保护:先还原指令集和调度逻辑,再还原具体操作

五、第四步:动态校验闭环,保证结果100%准确

AI还原的代码,哪怕看起来再对,也不能直接信。语义漂移是大模型的固有问题,特别是复杂的位运算、加密逻辑,很容易细节出错。必须通过动态校验,形成闭环。

5.1 输入输出对比法

最核心的校验方法:同样的输入参数,分别运行原混淆代码和还原后的代码,对比输出结果是否完全一致。

实现脚本示例

constvm=require('vm');constfs=require('fs');// 加载原代码和还原代码constoriginalCode=fs.readFileSync('obfuscated.js','utf-8');constrestoredCode=fs.readFileSync('restored.js','utf-8');// 测试用例consttestCases=[{input:'test123',key:'abc'},{input:'',key:''},{input:'1234567890',key:'xyz123'},{input:'中文测试',key:'密钥'}];functionrunCode(code,input,key){constsandbox={result:null,input,key};vm.runInNewContext(code+`result = sign(input, key);`,sandbox);returnsandbox.result;}// 对比测试console.log('开始校验...');letallPass=true;testCases.forEach((tc,i)=>{constr1=runCode(originalCode,tc.input,tc.key);constr2=runCode(restoredCode,tc.input,tc.key);if(r1===r2){console.log(`用例${i+1}: 通过`);}else{console.log(`用例${i+1}: 失败`);console.log('原输出:',r1);console.log('还原输出:',r2);allPass=false;}});console.log(allPass?'全部校验通过':'存在差异,需重新还原');

5.2 多维度覆盖

测试用例要覆盖多个维度:

  • 正常输入
  • 空输入
  • 超长输入
  • 特殊字符、中文
  • 边界值

覆盖的场景越多,校验越可靠。加密算法这类精确逻辑,必须所有用例全部通过才算还原正确。

5.3 差异定位与重还原

如果校验不通过,不要整段重新还原。先定位到具体哪个函数、哪个块输出不一致,针对有问题的块重新还原,给出更明确的约束和提示。

反复迭代,直到所有用例全部通过。


六、工程化封装:打造自己的AI逆向工具链

单步操作熟练之后,可以把整个流程封装成自动化工具链,批量处理混淆代码。

6.1 完整自动化链路

输入混淆代码 ↓ 自动预处理(格式化、去对抗、还原字符串) ↓ 自动识别入口点,按功能切块 ↓ 调用大模型API逐块还原 ↓ 自动运行测试用例校验 ↓ 输出还原后的可读代码 + 校验报告

6.2 批量处理能力

对于大量相似的混淆代码,可以批量处理。比如同一个站点的多个页面、同一个混淆器生成的多份代码,统一预处理、统一还原策略,批量输出结果。

6.3 知识库沉淀

把常见的混淆模式、还原策略、校验方法沉淀成知识库,不断优化提示词和处理流程。用的越多,准确率越高,速度越快。


七、踩坑与最佳实践

坑1:直接整段代码扔给大模型

后果:上下文不够、语义漂移、逻辑错误,还原出来的代码中看不中用。
正确:分块处理,从底层到上层,逐块还原,逐步验证。

坑2:只看代码美观,不做动态校验

后果:看起来还原得很漂亮,实际跑起来结果不对,关键逻辑错了都不知道。
正确:所有还原的代码必须经过动态校验,输入输出完全一致才算通过。

坑3:完全依赖AI,自己不看逻辑

后果:遇到对抗性代码、假逻辑,AI会直接当真逻辑还原,结果完全跑偏。
正确:人把控核心方向和边界,AI做体力活,关键逻辑人工复核。

坑4:提示词太简单,没有约束

后果:AI自由发挥,删改关键逻辑,添加自己的想象。
正确:提示词明确约束规则,哪些不能改、哪些必须保留、输出什么格式,都写清楚。

最佳实践

  • 先动态调试找入口,再AI还原,效率最高
  • 越小的块,还原准确率越高,不要贪大
  • 核心加密算法,一定要多组用例校验
  • 还原过程结合AST工具做预处理,比纯AI效果好
  • 常用的混淆模式,沉淀成固定的处理模板

最后

JS逆向这个领域,从来不是比谁能扛、谁能熬,而是比谁的方法更高效、工具链更强大。

大模型没有替代逆向工程师,但它重构了这个工种的工作模式:从以前的「从头到尾人工抠」,变成现在的「策略+工具+AI辅助」。人从体力劳动里解放出来,专注于核心逻辑、对抗策略和流程设计,效率和产出都完全不是一个量级。

说到底,工具在进化,人的能力也要进化。善用AI,把重复的工作交给机器,把精力放在真正有价值的地方,才是技术人的核心竞争力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/28 17:16:18

地铁ISCS采集层为什么行业普遍不用Java?面试高频问题深度分析

标签:#地铁ISCS #工控采集 #OPCUA #C #Java选型 #实时工控 摘要 面试轨交综合监控开发岗时,几乎都会问到同一个核心问题:为什么地铁设备采集服务几乎全部用C/C,很少用Java? 很多开发只笼统知道“Java有GC卡顿”&#x…

作者头像 李华
网站建设 2026/8/28 17:14:45

数学建模必备:灰色关联分析原理、MATLAB实现与实战技巧

1. 项目概述:为什么灰色关联分析是建模的“万金油”?如果你正在备战数学建模,尤其是国赛、美赛这类时间紧、任务重的比赛,那你一定在寻找那些既高效又实用的“杀手锏”算法。灰色关联分析,就是这样一个常被低估的宝藏工…

作者头像 李华
网站建设 2026/8/28 17:10:33

Agent 操作电脑能力评测与实战:从原理到数据

从“会聊天”到“会用电脑”:Agent 的 Computer Use 能力到底行不行?我们拿数据说话最近和几个做 AI 应用的同学聊到一个很现实的问题:大模型驱动的 Agent 已经能写代码、能查资料、能调 API,但让它像一个真人一样“操作电脑”——…

作者头像 李华
网站建设 2026/8/28 17:10:06

C++模板编程:从函数模板到类模板的工业级实践指南

1. 项目概述:为什么C模板是“工业级”代码的基石 如果你写过一些C代码,尤其是在处理数据结构、算法或者需要编写通用库的时候,大概率会碰到一个场景:你需要为不同的数据类型(比如 int , double , string &#x…

作者头像 李华
网站建设 2026/8/28 17:07:33

CodeX CLI使用笔记

.md文件:待补充安装 Codex Cli# 1. 确保 Node ≥ 22 node -v # v22.5.1# 2. 一行命令搞定 npm i -g openai/codex# 3. 验证 codex --version # 0.36.0使用模式codex# 直接带 prompt codex "帮我重构这个函数"# 完整自动模式(无需确认&…

作者头像 李华