Skills Plugins MCP Prompt Model 博客 我的中心

ast-deobfuscate

用 Babel AST 还原混淆的 JS 代码(字符串解密、控制流还原、死代码删除)。

DeepseekModel Curated skill Quality Excellent · 78 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=zhizhuodemao-ai-reverse-toolkit-skills-ast-deobfuscate-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name ast-deobfuscate description 用 Babel AST 还原混淆的 JS 代码(字符串解密、控制流还原、死代码删除)。 ast-deobfuscate 对 $ARGUMENTS 执行 AST 解混淆,最大化还原可读代码。 工具链 : @babel/parser + @babel/traverse + @babel/generator + @babel/types 工作目录约定 project/ ├── source/ │ └── original/ # 原始混淆文件(只读,不修改) │ └── target.js ├── scripts/ # 解混淆脚本(每步一个,一次性,针对目标定制) │ ├── step1_string_decrypt.js │ ├── step2_expr_simplify.js │ └── ... ├── intermediate/ # 中间产物(每步输出,可回退) │ ├── target_step0.js # 格式化 + 去反调试 │ ├── target_step1.js # 字符串解密后 │ ├── target_step2.js # 表达式简化后 │ └── ... └── source/ └── deobfuscated/ # 最终输出 └── target_deobf.js 原则 : 每个步骤读取上一步的中间文件,输出新的中间文件。出错时可从任意中间文件重新开始。 环境初始化 解混淆脚本基于 Babel 工具链运行在 Node.js 中。首次执行前检查并安装依赖: # 在项目根目录检查 package.json,没有则初始化 npm init -y npm install @babel/parser @babel/traverse @babel/generator @babel/types # 如需格式化 npm install prettier 执行策略 整体原则 本 skill 是 百科全书 ,不是固定流水线。执行者根据实际代码灵活选择步骤: 进入计划模式 : 先完成 Step 0 分析,然后进入计划模式,向用户展示分析结果和建议的步骤组合,获得确认后再执行 按需跳步 : 没有字符串数组就跳过 Step 1,没有控制流平坦化就跳过 Step 4 随时调整 : 任何步骤执行后发现新情况,都可以回退或插入额外步骤 MCP 用于分析和验证 : js-reverse MCP 用于获取源码、搜索特征、小规模验证方案可行性;大批量转换和验证通过 Node.js 脚本执行 MCP 使用时机 MCP 的定位是 分析工具和验证探针 ,不是批量执行引擎。 阶段 MCP 用法 分析阶段 search_in_sources 搜索混淆特征; get_script_source 获取目标脚本 方案验证 evaluate_script 执行几个解密调用,确认方案可行后再写批量脚本 中间验证 evaluate_script 抽样对比解混淆前后的函数输出 控制流分析 set_breakpoint + step_over 动态跟踪 switch-case 执行顺序 最终验证 在浏览器中用解混淆后的代码替换原始代码,验证功能正常 大批量字符串解密、表达式简化、死代码移除等转换工作,全部通过 Node.js 脚本 + Babel AST 完成。 Subagent 并行策略 可并行的任务组合: Step 0 中:特征识别 + 反调试代码搜索 Step 2 中:Proxy 函数识别 + 对象字典识别(互不依赖) 验证阶段:多组测试数据可并行验证 技术手册 以下是各类解混淆技术的详细参考。 根据 Step 0 的分析结果,选择需要的章节执行。 Step 0: 预分析与特征识别 目标 : 了解混淆类型和程度,为后续步骤提供参考(非硬性路由)。 0.1 获取源码 本地文件: 直接读取 $ARGUMENTS URL: 下载后保存到 source/original/ 浏览器中(代码尚未下载到本地): - 用 MCP list_scripts → get_script_source 获取 - 可用 search_in_sources 做关键词快速扫描: "_0x" → 确认混淆前缀 "debugger" → 定位反调试 "push" + "shift" → 旋转 IIFE "split('|')" → 控制流平坦化 0.2 格式化 : 用 prettier 或 babel generator 统一缩进,保存为 intermediate/target_step0.js 0.3 AST 体检报告 (可选) 文件较小时直接全文阅读是最快最全面的方式。但即使能读全文,统计脚本的价值在于 把非结构化代码转化为结构化数据 — "callee 频次 Top 5"这类信息,人肉读代码很难准确统计。写一个脚本对 AST 做全局扫描: 统计项: 基础指标: - 文件大小、总行数、AST 总节点数 - FunctionDeclaration / FunctionExpression 数量 - VariableDeclaration 数量 字符串数组特征: - 最大的 ArrayExpression 及其元素数量(>50 个元素大概率是字符串数组) - 该数组所在的行号范围 访问器函数特征: - CallExpression 中 callee 名称频次 Top 5(高频调用的大概率是访问器函数) - 这些函数的参数模式(单参数数字?双参数?) 控制流特征: - WhileStatement 内嵌 SwitchStatement 的数量(>0 说明有控制流平坦化) - SwitchCase 总数量 命名模式: - 标识符前缀分布统计(如 _0x、_0X、a0_、_$、__x 等,取 Top 3 前缀及占比) - 单字符变量占比 - 平均标识符长度 混淆强度: - StringLiteral 数量 vs CallExpression 取字符串的数量(比值越低,字符串混淆越重) - UnaryExpression 中 ! 运算符数量(大量 ![] !![] 说明布尔值混淆) 0.4 特征指纹(仅供参考) 特征 混淆类型 常见处理 高频前缀(如 _0x / a0_ )+ 大字符串数组 + 旋转 IIFE Obfuscator.io 及变种 Step 1→2→3→4→5→6 高频前缀但无字符串数组 轻度混淆 Step 2→3→5→6 while(true){switch} + 顺序数组 控制流平坦化 Step 2→4→5→6 jsjiami.com 标记 sojson 先去壳,再按实际情况选步骤 Webpack/Parcel 模块包裹 打包工具 先 unpack 提取模块,再对单模块解混淆 大量 eval / Function() 代码加密 沙箱执行解密层,再按实际情况选步骤 0.5 移除反调试 (如存在) 搜索并删除: debugger 语句(尤其在定时器/循环中) setInterval(() => { debugger }, ...) constructor("debu") 反格式化检测 console 重写/禁用代码 0.6 进入计划模式 向用户展示: 识别到的混淆特征 建议执行的步骤组合 预估的复杂度 用户确认后开始执行。执行过程中发现新情况随时可调整计划。 产出 : intermediate/target_step0.js + 分析报告 Step 0.5: Webpack/打包工具 Unpack(可选) 适用条件 : 代码是 Webpack/Browserify/Parcel 打包的 bundle。识别特征: Webpack 特征: - 外层 IIFE 接收一个模块数组或对象作为参数 - 内部有 __webpack_require__ 或类似的模块加载函数: function(modules) { function __webpack_require__(moduleId) { if(installedModules[moduleId]) return installedModules[moduleId].exports; var module = installedModules[moduleId] = { exports: {} }; modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); ... } } - 每个模块是 function(module, exports, __webpack_require__) { ... } 处理方向 1. 识别模块数组/对象(IIFE 的参数) 2. 提取每个模块函数,保存为独立文件: intermediate/modules/module_0.js intermediate/modules/module_1.js ... 3. 对 __webpack_require__(N) 调用,添加注释标注引用了哪个模块 4. 识别入口模块(通常是 __webpack_require__(0)) 5. 对每个模块独立执行后续解混淆步骤 Webpack 固定参数重命名(确定性的,不需要猜测): - 第 1 个参数 → module - 第 2 个参数 → exports - 第 3 个参数 → __webpack_require__ - __webpack_require__.p → __webpack_public_path__ - __webpack_require__.m → __webpack_modules__ - __webpack_require__.c → __webpack_module_cache__ 产出 : intermediate/modules/module_N.js (每个模块独立文件) ⚠️ unpack 后,后续步骤对每个模块文件独立执行,而非对整个 bundle。 Step 1: 字符串解密与大数组回填 适用条件 : 代码中存在字符串数组 + 访问器函数模式。若无此模式则跳过。 目标 : 将所有加密/编码的字符串还原为明文。这是后续步骤的基础。 1.1 识别字符串数组结构 典型模式包含三部分(函数名前缀不固定,可能是 _0x 、 a0_ 、 _$ 或任意混淆名): 字符串数组函数 : 返回包含所有字符串的数组 旋转 IIFE : 对数组执行 push/shift 旋转,打乱原始顺序 访问器函数 : 接受索引参数,返回数组中对应字符串(通常有偏移量计算) 识别方法: 通过 AST 体检报告中的"最大 ArrayExpression"和"CallExpression callee 频次 Top 5"定位 1.2 处理方向 流程: 先用 MCP 小规模验证方案,再写 Node.js 脚本批量执行 第一步: 用 MCP 验证方案 1. 用 MCP evaluate_script 调用几个访问器函数,确认能正确返回明文 2. 确认参数模式(单参数?双参数?偏移量?) 3. 方案验证通过后,再写批量脚本 第二步: 批量执行(二选一) 方案 A(推荐): Node.js vm 沙箱 1. 从 AST 中提取字符串数组 + 旋转 IIFE + 访问器函数的源码 2. 在 vm.createContext() 沙箱中执行 3. 遍历 CallExpression,用沙箱函数计算返回值并替换 4. 删除已无用的数组函数、旋转 IIFE、访问器函数 方案 B: 纯静态分析(旋转逻辑简单时) 1. 解析数组元素,静态计算旋转次数 2. 手动应用旋转得到最终数组 3. 直接用索引查表替换 1.3 转义字符串还原 遍历所有 StringLiteral: 删除 node.extra(强制用已解析的 value) \x48\x65\x6c\x6c\x6f → "Hello" \u0048\u0065 → "He" 1.4 数值还原 遍历所有 NumericLiteral: 删除 node.extra 0x12 → 18, 0b1010 → 10 验证 : 用 MCP evaluate_script 抽样对比几个解密结果是否正确 产出 : intermediate/target_step1.js Step 2: 表达式简化 适用条件 : 几乎所有混淆代码都需要此步骤。与 Step 5 循环执行效果最佳。 2.1 常量折叠 (Constant Folding) 遍历 BinaryExpression / UnaryExpression / LogicalExpression / ConditionalExpression: 1. 调用 path.evaluate() 2. 若 confident === true: - 用 t.valueToNode(value) 生成新节点 - 验证结果是 Literal 类型(排除 Infinity/undefined 等边界值) - 所有类型都要处理: string, number, boolean(不要只处理部分类型) - 替换原节点 3. 若 confident === false: - 检查是否为连续字符串拼接(左子树右叶 + 右叶都是 StringLiteral) - 若是,合并相邻字面量 2.2 布尔值还原 遍历 UnaryExpression: ![] → false !![] → true !0 → true !1 → false !"" → true !"x" → false void 0 → undefined 2.3 Proxy 函数内联 识别条件: 函数体只有一条 return 语句,且 return 的是: - 二元运算: function(a,b){ return a + b } - 函数调用: function(a,b){ return a(b) } - 属性访问: function(a,b){ return a[b] } - 逻辑运算: function(a,b){ return a && b } 处理: 1. 找到所有符合条件的 FunctionDeclaration 2. 确认 binding.constant === true(未被重新赋值) 3. 找到所有 CallExpression 引用 4. 将实参代入函数体表达式,替换调用处 5. 引用归零后删除函数声明 2.4 对象属性字典内联 识别条件: 对象仅作为属性字典使用 var map = { 'a': function(x,y){return x+y}, 'b': 'hello' } map['a'](1, 2) → 1 + 2 map['b'] → 'hello' 处理: 1. 找到对象声明,确认所有属性值为 Literal 或简单函数 2. 确认 binding.constant === true 3. 将所有 MemberExpression 访问替换为对应属性值 4. 对函数类属性,同时执行 Proxy 函数内联逻辑 5. 引用归零后删除对象声明 产出 : intermediate/target_step2.js Step 3: 引用与属性访问标准化 适用条件 : 代码中大量使用 obj['prop'] 方括号访问。需在字符串解密(Step 1)之后执行。 3.1 方括号转点号 遍历 MemberExpression: 条件: computed === true 且 property 是 StringLiteral 且属性名是合法标识符(匹配 /^[a-zA-Z_$][a-zA-Z0-9_$]*$/) obj['prop'] → obj.prop obj['forEach'] → obj.forEach 保留: obj['class'](保留字), obj['data-id'](含连字符), obj[variable](变量) 3.2 逗号表达式拆分 逗号表达式不只出现在 ExpressionStatement 中,需覆盖所有位置: 1. ExpressionStatement: (a = 1, b = 2, c()) → a = 1; b = 2; c(); 2. ReturnStatement: return (a = 1, b = 2, result) → a = 1; b = 2; return result; 3. IfStatement test / for init / for update 中的逗号表达式也需拆分 4. 赋值右侧: x = (a(), b(), c) → a(); b(); x = c; 产出 : intermediate/target_step3.js Step 4: 控制流平坦化还原 适用条件 : 代码中存在 while(true){ switch(...) { case... } } 结构。强依赖 Step 2 的常量折叠。 4.1 分析实际结构 不预设固定模式,根据实际代码分析控制流结构: 常见特征(仅供参考,实际变种很多): - WhileStatement,test 恒为 true - 循环体内是 SwitchStatement - 存在某种顺序控制机制(数组索引、状态变量等) - 每个 case 以 continue/break 结尾 分析方法: 1. 阅读具体的 while-switch 代码,理解其控制流逻辑 2. 用 MCP set_breakpoint + step_over 动态跟踪实际执行顺序 3. 判断顺序控制机制是静态可解的还是依赖运行时值 4.2 还原方向 根据分析结果制定还原策略。核心思路: 1. 确定代码块的执行顺序 2. 按顺序提取各 case 的代码块 3. 移除控制流包裹(while/switch/continue) 4. 用 path.replaceWithMultiple() 替换整个结构 ⚠️ 复杂情况(状态变量动态计算、嵌套多层等): - 向用户展示分析结果,请求辅助判断 - 可用 MCP 动态跟踪辅助理解执行流程 - 宁可保留未还原的结构,也不要错误还原 验证 : 用 MCP evaluate_script 执行还原后的函数,对比原始输出 产出 : intermediate/target_step4.js Step 5: 死代码移除 适用条件 : 几乎所有混淆代码都需要。与 Step 2 循环执行效果最佳。 5.1 不可达分支清理 遍历 IfStatement / ConditionalExpression: 1. 用 path.get("test").evaluateTruthy() 求值条件 2. 若结果 === true: 用 consequent 替换整个节点 3. 若结果 === false: 用 alternate 替换(无 alternate 则删除) 4. 注意: BlockStatement 需展开为语句数组再替换 5.2 无用变量/函数剔除 遍历 VariableDeclarator / FunctionDeclaration: 1. 获取 binding = scope.getBinding(name) 2. 若 binding.constant === true 且 binding.referenced === false: - 确认 init 无副作用后删除 3. 若 init 有副作用(函数调用等): 保留 5.3 空语句清理 遍历 EmptyStatement: 直接删除 遍历 BlockStatement: 若 body 为空且不是函数体,删除 5.4 循环策略(Step 2 + Step 5)— 必须实现,不可跳过 单次执行 Step 2 和 Step 5 会遗漏大量可简化代码。原因:死代码移除后暴露新的常量表达式,常量折叠后又暴露新的死代码。 实现方式: 在脚本中用循环包裹 Step 2 和 Step 5 的 visitor let round = 0; do { changed = false 执行 Step 2 全部 visitor(常量折叠 + 布尔值 + Proxy + 对象字典) 执行 Step 5 全部 visitor(不可达分支 + 无用变量 + 空语句) 若本轮有任何节点被替换或删除 → changed = true round++ 保存中间文件: intermediate/target_step5_round{round}.js } while (changed && round < 50) 每轮循环保存中间文件: intermediate/target_step5_round{N}.js 产出 : intermediate/target_step5.js Step 6: 变量重命名与最终整形 适用条件 : 代码中存在无意义的混淆变量名时执行。仅执行确定性的模式化重命名,不做语义推导。 6.1 模式化重命名(确定性的) 某些变量名可以根据代码模式确定性地重命名,不需要猜测: Webpack 模块参数(不管原始名是什么前缀): function(xx1, xx2, xx3) { xx3(69) } → function(module, exports, __webpack_require__) { __webpack_require__(69) } 判断依据: 三参数函数,第三个参数被当作函数调用且参数是数字 常见回调模式:
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。