Skip to main content

dsl-vm-reverse

Reverse JavaScript-based custom DSL/VM interpreters, non-standard WASM-like runtimes, and risk-control engines. Use when analyzing IIFE or switch-based opcode dispatchers, extracting instruction tables, recovering bytecode semantics, capturing VM state at runtime, or reconstructing execution flow.

Aller à l'installation

Informations de source

Dépôt
SeaOf0/dsh-redteam-model
Dernière activité de la source
18 août 2026 à 15:45
Langue détectée de SKILL.md
chinois
Étoiles
486
Forks
42

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
dsl-vm-reverse
description
Reverse JavaScript-based custom DSL/VM interpreters, non-standard WASM-like runtimes, and risk-control engines. Use when analyzing IIFE or switch-based opcode dispatchers, extracting instruction tables, recovering bytecode semantics, capturing VM state at runtime, or reconstructing execution flow.
# 🔄 DSL 自定义虚拟机逆向(DSL VM Reverse Engineering) > 用于逆向基于 JavaScript 实现的自定义 WASM 虚拟机/风控引擎 --- ## 目录 - [1. 适用范围](#1-适用范围) - [2. DSL VM 识别特征](#2-dsl-vm-识别特征) - [3. 通用逆向工作流](#3-通用逆向工作流) - [4. Opcode 提取与分类](#4-opcode-提取与分类) - [5. 运行时捕获方案](#5-运行时捕获方案) - [6. 常见状态码](#6-常见状态码) - [7. Skill 自检清单](#7-skill-自检清单) --- ## 1. 适用范围 当目标文件符合以下 **任意特征** 时使用本 skill: | # | 特征 | 说明 | |---|------|------| | 1 | IIFE 开头 + 大量单字母变量名 | `!function(){var U=void 0,y=parseInt,E0=Function,...}` | | 2 | 包含 `DG()` 或类似函数含 switch-case 循环 | 解释器主循环,`d[7]&31` 解码 opcode | | 3 | 大文件(500KB+)但零字节占比 < 1% | 非标准 WASM,纯 JS | | 4 | 包含 `C[number]` 常量表引用 | `C[9][xxx]` 函数表/字符串表 | | 5 | 单行压缩代码 | 583KB 单行,混淆变量名 | ### 排除规则 | 条件 | 非本 skill | 转至 | |------|-----------|------| | 文件以 `\x00asm` 开头 | 标准 WASM 二进制 | `reverse-engineering/languages.md` | | 文件以 `Uint8Array([0,97,115,109])` 含 WASM 魔术字 | WASM 嵌入式 | 提取 .wasm 后转 IDA/Ghidra | | 标准 Webpack 打包(`function(e,t,n){...}`) | 普通 JS | `js-reverse/` | | 零字节占比 > 20% | WASM 二进制 | `reverse-engineering/languages.md` | --- ## 2. DSL VM 识别特征 ### 代码特征 ```javascript // 特征 1: IIFE 入口,单字母变量映射数字常量 !function(){ var U=void 0, y=parseInt, E0=Function, AN=Uint8Array; var E=15, l=10, m=12, x=16, S=13, $=11; // 数字常量映射为变量名,替代原始数字 ... } // 特征 2: 解释器主循环 DG() function DG(C, d, ...) { var d = []; // 数组模拟 WASM stack/locals for (d[7] = x; d[7] !== U;) { var aE = d[7] & 31; // 低 5 位 = opcode var O = d[7] >> 5 & 31; // 高 5 位 = sub-operation switch (aE) { case 0: /* ... */ d[7] = 612; break; case 1: /* ... */ // ... N 个 case } } } // 特征 3: 常量表 C[9] 存储函数索引和字符串 // C[9][0] = ["pc"] → 函数参数描述 // C[9][667] = "string" → 字符串常量 // C[9][x] = number → 函数索引 // 特征 4: W(C[index], null, ...) 调用模式 // W = Function.prototype.call.bind(call) // 所有内置函数通过 C[index] 索引调用 // 特征 5: 指令编码格式 // d[7] = opcode(bit 0-4) | subop(bit 5-9) | operand(bit 10+) ``` ### Opcode 编码格式 每条指令编码为 32 位整数: ``` bit 0-4: opcode (0-N) bit 5-9: sub-operation (0-31) bit 10-31: operand/立即数 解码: aE = d[7] & 31 → opcode O = d[7] >> 5 & 31 → sub-operation d[other] = d[7] >> 10 → operand ``` --- ## 3. 通用逆向工作流 ### Phase 1: 文件分类(5 分钟) ```bash # 检查是否为 DSL VM python3 << 'EOF' with open('target.js', 'rb') as f: head = f.read(100) # 1. 检查 WASM 魔术字 if head[:4] == b'\x00asm': print("标准 WASM 二进制") exit() # 2. 检查零字节占比 data = open('target.js', 'rb').read() zero_pct = data.count(b'\x00') / len(data) * 100 print(f"零字节占比: {zero_pct:.1f}%") if zero_pct > 20: print("WASM 二进制") elif head[:2] == b'!f': # 检查单字母变量模式 if b'var U=void 0' in head or b'U=void 0,y=parseInt' in head: print("→ DSL VM!") else: print("普通 JS IIFE") EOF ``` ### Phase 2: 变量映射表提取(10 分钟) ```python import re with open('target.js', 'r', errors='replace') as f: s = f.read() # 提取开头 2000 字符的 var X=数字 映射 mappings = re.findall(r'var\s+(\w+)\s*=\s*(\d+)', s[:2000]) print('常量映射:') for name, val in mappings: print(f" {name:4s} = {val:3d} (0x{int(val):02x})") ``` ### Phase 3: Opcode 提取与分类(15 分钟) ```python # 1. 提取所有 case all_cases = re.findall(r'case\s+(\d+):', s) unique = sorted(set(int(c) for c in all_cases)) print(f"总 case: {len(all_cases)} 个") print(f"唯一 opcode: {len(unique)} 个: {unique}") # 2. 分类每个 opcode for op in unique: idx = s.find(f'case {op}:') snippet = s[idx:idx+200] if 'd[7]=' in snippet: op_type = 'BRANCH' elif 'return' in snippet: op_type = 'RETURN' elif 'W(C[' in snippet: op_type = 'CALL' elif 'new' in snippet: op_type = 'ALLOC' elif 'try' in snippet or 'catch' in snippet: op_type = 'EXCEPTION' else: op_type = 'ARITH/STORE' print(f" opcode {op:2d}: {op_type}") ``` ### Phase 4: 常量表分析(30 分钟) ```python const_refs = re.findall(r'C\[9\]\[(\d+)\]', s) unique_refs = sorted(set(int(x) for x in const_refs)) print(f"C[9] 引用: {len(unique_refs)} 个索引") print(f"范围: {min(unique_refs)} - {max(unique_refs)}") # 对每个引用分析上下文 for ref in unique_refs[:20]: idx = s.find(f'C[9][{ref}]') ctx = s[max(0,idx-50):idx+80] clean = ''.join(c if c.isprintable() else ' ' for c in ctx) print(f" C[9][{ref}] → {clean}") ``` ### Phase 5: 导出函数追踪(1-2 小时) 导出函数(如 `getToken`)通过以下路径定位: ``` 1. 找 AWSCInner.register() 或类似注册调用 2. 确定注册的模块和工厂函数 3. 找工厂函数返回的对象 → 导出函数定义位置 4. 若函数名不在 JS 中 → 在 C[9] 常量表中作字节码存储 5. 追踪调用链: AWSCInner._modules['fy'].getToken() → W(C[函数索引], null, ...) → DG() 解释器执行编码后的指令序列 ``` ### Phase 6: 运行时注入(若纯静态分析不够) ```javascript // 注入最小 AWSC 兼容环境 const fakeEnv = { AWSCInner: { _modules: {}, register(name, moduleName, factory) { this._modules[moduleName] = factory(); } } }; // 执行 DSL VM 代码 dslVmCode(); // 获取导出 const token = fakeEnv.AWSCInner._modules['fy'].getToken({}); ``` --- ## 4. Opcode 提取与分类 ### 参考 opcode 对照表(基于已有案例) | Opcode | 操作类型 | 特征 | |--------|---------|------| | 0 | **BRANCH** | `d[7]=xxx` 无条件跳转 | | 1 | **CALL** | `W(C[Y],null,function(){...})` 嵌入函数调用 | | 2 | **ARITH** | `d[4]=0`, `d[7]=72` 变量赋值 | | 3 | **ARITH** | `d[0]=d[1][C[x]]`, `d[5]=d[0]<d[3]` 比较运算 | | 4 | **STORE** | `d[8]=d[5]in d[4]` 属性访问/存在检查 | | 5 | **ARITH** | `d[8]=d[4]-d[8]` 算术运算 | | 6 | **RETURN** | `return gV`, `throw` 返回/抛出异常 | | 7 | **ALLOC** | `d[6]=[]`, `d[6][C[8]](...)` push 操作 | | 8 | **BRANCH** | `d[7]=d[k]?512:425` 条件跳转 | | 9 | **STRING** | `d[6][C[t]]=d[m]`, `new fh(...)` 正则 | | 10 | **ALLOC** | 函数参数准备、调用栈创建 | | 11 | **STRING** | `new fh("\\s",d[5])` 正则匹配 | | 12 | **STORE** | `P[d[9]]=d[4][C[H]](d[3])` 数据传递 | | 13 | **CALL** | `C[9][113]=d[9]` 模块初始化 | | 14 | **STRING** | `d[8]=d[9]+d[m]` 字符串拼接 | | 15 | **RETURN** | `return EL;` 函数返回 | | 16 | **ALLOC** | `var r,P,Z,B...` 局部变量声明 | | 17 | **ALLOC** | `(Z=[])[C[8]](69,T,445)` 静态数组初始化 | | 18 | **TABLE** | 函数表/类型表初始化 | | 19 | **EXCEPTION** | `try{for(var RK=x;...` try-catch 循环 | | 20 | **DOM** | `Is[d[o]]` DOM 操作 | | 21 | **STORE** | 安全获取全局/对象属性 | | 22 | **STRING** | `new fh(r,v)` 字符串/正则处理 | | 23 | **BRANCH** | `try...catch` 安全获取 + 条件跳转 | | 24 | **CALL** | `W(C[2],null,8,z,FL)` 多参数函数调用 | | 25 | **EXCEPTION** | `try{...}catch(C){...}` 异常捕获 + 跳转 | --- ## 5. 运行时捕获方案 ### 方案 A: Selenium + CDP 原生事件(推荐,成功率最高) ```python from selenium import webdriver driver = webdriver.Chrome() # 注入反检测 driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": r""" Object.defineProperty(navigator, 'webdriver', {get: () => false}); Object.defineProperty(navigator, 'plugins', {get: () => [1,2,3,4,5]}); Object.defineProperty(navigator, 'languages', {get: () => ['zh-CN','zh','en']}); """ }) # 发送 CDP 原生鼠标事件 driver.execute_cdp_cmd("Input.dispatchMouseEvent", { "type": "mousePressed", "x": 549.5, "y": 441.2, "button": "left", "buttons": 1, "clickCount": 1, "pointerType": "mouse" })
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub