Dsl Vm Reverse

zhaoxuya520/reverse-skill/skills/reverse-engineering/dsl-vm-reverse

作者 zhaoxuya520cab634bd855f无许可证40K 个星标收录于 2026年10月9日更新于 2026年10月9日仓库2周前更新

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.

AI 生成的概览

指导逆向基于 JavaScript 的自定义 DSL/VM 解释器、操作码分发器与风控引擎。

功能
提供分阶段工作流,用于识别自定义 JavaScript 操作码虚拟机、提取变量映射与操作码表、分析常量表并追踪导出函数。内容包含操作码分类参考、使用 Selenium CDP 或 Playwright 的运行时捕获方案,以及常见状态码列表。产出为分析指导与提取流程,而非生成文件。
适用场景
适用于分析 IIFE 或基于 switch 的操作码分发器、非标准类 WASM 的 JavaScript 运行时或风控引擎。面向提取指令表、还原字节码语义、在运行时捕获虚拟机状态或重建执行流程等任务。
运行要求
仅为说明文档,不附带脚本。按流程操作可能需要 Python 3、Selenium CDP 或 Playwright 等浏览器自动化环境,以及访问目标页面的网络连接。

🔄 DSL 自定义虚拟机逆向(DSL VM Reverse Engineering)

ACTION REQUIRED(读完后立刻执行)

  1. NOW: 确认当前任务是自定义 JS opcode VM / 风控引擎,不是标准 WASM 或普通 webpack
  2. NOW: case-init 直到 scope.md 就绪;离线样本用 offline / lab
  3. ACT: 从「3. 通用逆向工作流」Phase 1 做文件分类,不要停在目录

用于逆向基于 JavaScript 实现的自定义 WASM 虚拟机/风控引擎


目录


1. 适用范围

当目标文件符合以下 任意特征 时使用本 skill:

#特征说明
1IIFE 开头 + 大量单字母变量名!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){...})普通 JSjs-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 VMpython3 << '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) * 100print(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. 提取所有 caseall_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. 分类每个 opcodefor 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操作类型特征
0BRANCHd[7]=xxx 无条件跳转
1CALLW(C[Y],null,function(){...}) 嵌入函数调用
2ARITHd[4]=0, d[7]=72 变量赋值
3ARITHd[0]=d[1][C[x]], d[5]=d[0]<d[3] 比较运算
4STOREd[8]=d[5]in d[4] 属性访问/存在检查
5ARITHd[8]=d[4]-d[8] 算术运算
6RETURNreturn gV, throw 返回/抛出异常
7ALLOCd[6]=[], d[6][C[8]](...) push 操作
8BRANCHd[7]=d[k]?512:425 条件跳转
9STRINGd[6][C[t]]=d[m], new fh(...) 正则
10ALLOC函数参数准备、调用栈创建
11STRINGnew fh("\\s",d[5]) 正则匹配
12STOREP[d[9]]=d[4][C[H]](d[3]) 数据传递
13CALLC[9][113]=d[9] 模块初始化
14STRINGd[8]=d[9]+d[m] 字符串拼接
15RETURNreturn EL; 函数返回
16ALLOCvar r,P,Z,B... 局部变量声明
17ALLOC(Z=[])[C[8]](69,T,445) 静态数组初始化
18TABLE函数表/类型表初始化
19EXCEPTIONtry{for(var RK=x;... try-catch 循环
20DOMIs[d[o]] DOM 操作
21STORE安全获取全局/对象属性
22STRINGnew fh(r,v) 字符串/正则处理
23BRANCHtry...catch 安全获取 + 条件跳转
24CALLW(C[2],null,8,z,FL) 多参数函数调用
25EXCEPTIONtry{...}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"})

方案 B: Playwright 无头浏览器

javascript
const { chromium } = require('playwright');
async function run() {    const browser = await chromium.launch();    const page = await browser.newPage();
    // 拦截网络请求    await page.route('**/api/**', async route => {        await route.continue_();    });
    await page.goto('https://target-page.com');
    // 等待 DSL VM 初始化    await page.waitForFunction(() => {        return window.AWSCInner &&               window.AWSCInner._modules &&               window.AWSCInner._modules['fy'];    });
    // 执行操作    await page.mouse.move(500, 400);    await page.mouse.down();    // ... 操作序列    await page.mouse.up();}

方案 C: 纯协议验证(成功率极低)

DSL VM 生成的 token 通常与浏览器上下文强绑定(TLS JA3 指纹、IP、Cookie、请求头等),脱离浏览器后服务端可检测到上下文不匹配。不建议使用纯协议方案。


6. 常见状态码

Code含义处理
0验证通过 ✅取出 sessionId + sig
300风控拦截被拦截,无法通过
8778验证失败,需重试重试操作
8776操作太快,需重试增加延迟后重试
69634通用失败检查参数是否正确

7. Skill 自检清单

  • 我是否完成了 DSL VM 识别(IIFE + 单字母变量 + DG() 解释器)?
  • 我是否提取了变量映射表(var X=数字)?
  • 我是否提取了 opcode 列表并分类?
  • 我是否分析了常量表 C[9] 的引用范围?
  • 我是否定位了导出函数注册点?
  • 纯静态分析不够时,我是否尝试了运行时注入方案?
  • 任务完成后是否回写了 field-journal?
  • 是否发现新工具/新场景 → 更新 routing.md?

路由注册

类型路由
目标类型: WASM / DSL VM / 自定义指令集reverse-engineering/dsl-vm-reverse/SKILL.md
用户意图: "DSL VM / 风控引擎逆向"本 skill
工具链: Playwright / Selenium CDP浏览器注入方案

路径交叉

DSL VM 逆向路径:  reverse-engineering/dsl-vm-reverse/ → Phase 1-6 工作流  ↓ 若需要捕获运行时数据  browser-automation/ → Playwright/Selenium CDP  ↓ 若需要分析 API 协议层  js-reverse/ → Observe→Capture→Rebuild

来源与署名

来源:zhaoxuya520/reverse-skill位于skills/reverse-engineering/dsl-vm-reverse提交cab634b

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架