@reverse-craft/ai-tools 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,4 +4,4 @@
4
4
  * Tests the MCP tool's input validation and response format properties.
5
5
  */
6
6
  export {};
7
- //# sourceMappingURL=findJsvmpDispatcherTool.test.d.ts.map
7
+ //# sourceMappingURL=findJsvmpDispatcherTool.property.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findJsvmpDispatcherTool.property.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/findJsvmpDispatcherTool.property.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -15,13 +15,37 @@ export interface FormattedCode {
15
15
  /**
16
16
  * Detection type for JSVMP patterns
17
17
  */
18
- export type DetectionType = "If-Else Dispatcher" | "Switch Dispatcher" | "Instruction Array" | "Stack Operation";
18
+ export type DetectionType = "If-Else Dispatcher" | "Switch Dispatcher" | "Instruction Array";
19
19
  /**
20
20
  * Confidence level for detection results
21
21
  */
22
22
  export type ConfidenceLevel = "ultra_high" | "high" | "medium" | "low";
23
23
  /**
24
- * A detected region in the code
24
+ * VM Component variable identification
25
+ */
26
+ export interface VMComponentVariable {
27
+ variable_name: string | null;
28
+ confidence: ConfidenceLevel;
29
+ reasoning: string;
30
+ }
31
+ /**
32
+ * VM Components for a JSVMP instance
33
+ */
34
+ export interface VMComponents {
35
+ instruction_pointer: VMComponentVariable;
36
+ stack_pointer: VMComponentVariable;
37
+ virtual_stack: VMComponentVariable;
38
+ bytecode_array: VMComponentVariable;
39
+ }
40
+ /**
41
+ * Debugging entry point information
42
+ */
43
+ export interface DebuggingEntryPoint {
44
+ line_number: number;
45
+ description: string;
46
+ }
47
+ /**
48
+ * A detected region in the code (enhanced with VM components)
25
49
  */
26
50
  export interface DetectionRegion {
27
51
  start: number;
@@ -29,12 +53,21 @@ export interface DetectionRegion {
29
53
  type: DetectionType;
30
54
  confidence: ConfidenceLevel;
31
55
  description: string;
56
+ vm_components?: VMComponents;
57
+ debugging_entry_point?: DebuggingEntryPoint;
58
+ }
59
+ /**
60
+ * Summary information for detection result
61
+ */
62
+ export interface DetectionSummary {
63
+ overall_description: string;
64
+ debugging_recommendation: string;
32
65
  }
33
66
  /**
34
- * Complete detection result from LLM analysis
67
+ * Complete detection result from LLM analysis (enhanced)
35
68
  */
36
69
  export interface DetectionResult {
37
- summary: string;
70
+ summary: string | DetectionSummary;
38
71
  regions: DetectionRegion[];
39
72
  }
40
73
  /**
@@ -120,8 +153,9 @@ export declare function createBatches(formattedLines: string[], maxTokensPerBatc
120
153
  * Validates:
121
154
  * - JSON is parseable
122
155
  * - Required fields exist: summary, regions
123
- * - Each region has required fields: start, end, type, confidence, description
156
+ * - Each region has required fields: start/start_line, end/end_line, type, confidence, description
124
157
  * - Enum values are valid
158
+ * - Supports both old and new JSON formats
125
159
  *
126
160
  * @param jsonString - JSON string from LLM response
127
161
  * @returns Parsed and validated DetectionResult
@@ -1 +1 @@
1
- {"version":3,"file":"jsvmpDetector.d.ts","sourceRoot":"","sources":["../src/jsvmpDetector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jsvmpDetector.d.ts","sourceRoot":"","sources":["../src/jsvmpDetector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAiC,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG1E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,oBAAoB,GACpB,mBAAmB,GACnB,mBAAmB,CAAC;AAExB;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,eAAe,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,mBAAmB,CAAC;IACnC,cAAc,EAAE,mBAAmB,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,eAAe,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACnC,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAsBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAY,GACtB,OAAO,CAAC,aAAa,CAAC,CAuDxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAY,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAiD9B;AAcD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,MAAM,EAAE,EACxB,iBAAiB,EAAE,MAAM,GACxB,SAAS,EAAE,CAgCb;AA4GD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CA2GxE;AA0ED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,eAAe,CA8EjF;AAiBD;;;;;;;;GAQG;AACH,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,SAAS,EAAE,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAkB3D;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CA+E/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"llmConfig.d.ts","sourceRoot":"","sources":["../src/llmConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAIpE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAgBA,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,IAAI,CAM9E;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAoC/C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AA6DD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,aAAa,CAwBpE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAyB5D"}
1
+ {"version":3,"file":"llmConfig.d.ts","sourceRoot":"","sources":["../src/llmConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAIpE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAgBA,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,IAAI,CAM9E;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAoC/C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAgGD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,aAAa,CAwBpE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAyB5D"}
package/dist/server.js CHANGED
@@ -78,53 +78,83 @@ function buildJSVMPSystemPrompt() {
78
78
  return `You are a Senior JavaScript Reverse Engineer and De-obfuscation Expert. Your specialty is analyzing **JSVMP (JavaScript Virtual Machine Protection)**.
79
79
 
80
80
  **Context: What is JSVMP?**
81
- JSVMP is a protection technique where original JavaScript code is compiled into custom **bytecode** and executed by a custom **interpreter** (virtual machine) written in JavaScript.
81
+ JSVMP is a protection technique where original JavaScript code is compiled into custom **bytecode** and executed by a custom **interpreter** (virtual machine) written in JavaScript. A single JavaScript file may contain **multiple, independent JSVMP instances**.
82
82
 
83
- Key components of JSVMP code include:
84
- 1. **The Virtual Stack:** A central array used to store operands and results (e.g., \`stack[pointer++]\` or \`v[p--]\`).
85
- 2. **The Dispatcher:** A control flow structure inside a loop that decides which instruction to execute next based on the current bytecode (opcode).
86
- * *Common variants:* A massive \`switch\` statement, a deeply nested \`if-else\` chain (binary search style), or a function array mapping (\`handlers[opcode]()\`).
87
- 3. **The Bytecode:** A large string or array of integers representing the program logic.
83
+ Key components of each JSVMP instance include:
84
+ 1. **The Bytecode Array:** A large array of integers representing the program logic for that specific VM.
85
+ 2. **The Virtual Stack:** A central array used to store operands and results for that VM.
86
+ 3. **The Dispatcher:** A control flow structure (e.g., a \`while\` loop with a \`switch\` or \`if-else\` chain) that reads an opcode and executes the corresponding logic for that VM.
87
+ 4. **Key State Variables:** The "registers" of a specific VM, such as its **Instruction Pointer (IP/PC)** and **Stack Pointer (SP)**.
88
+ 5. **Debugging Entry Point:** The single most critical line number within a specific dispatcher loop to set a breakpoint for observing that VM's state.
88
89
 
89
90
  **Task:**
90
- Analyze the provided JavaScript code snippet to identify regions that match JSVMP structural patterns.
91
+ Your primary task is to analyze the provided JavaScript code snippet to identify **all independent JSVMP instances** and produce a comprehensive report for each one. You are NOT creating or analyzing any Intermediate Representation (IR). Your goal is to provide the necessary information for a subsequent tool to analyze each VM instance separately and create its IR and mappings.
92
+
93
+ Specifically, for **EACH** JSVMP instance you identify, you must:
94
+ 1. Define its location (**region**) and dispatcher type.
95
+ 2. Identify the specific **variables** that function as its core **Key State Variables** (Instruction Pointer, Stack Pointer, Virtual Stack, and Bytecode Array).
96
+ 3. Pinpoint the exact source code **line number** that serves as its optimal **Debugging Entry Point**.
97
+ 4. Summarize all findings in a single, structured JSON output.
91
98
 
92
99
  **Input Data Format:**
93
100
  The code is provided in a simplified format: \`LineNo SourceLoc Code\`.
94
101
  * **Example:** \`10 L234:56 var x = stack[p++];\`
95
- * **Instruction:** Focus on the **LineNo** (1st column) and **Code** (3rd column onwards). Ignore the \`SourceLoc\` (middle column).
96
-
97
- **Detection Rules & Confidence Levels:**
98
- Please assign confidence based on the following criteria:
99
-
100
- * **Ultra High:**
101
- * A combination of a **Main Loop** + **Dispatcher** + **Stack Operations** appears in the same block.
102
- * *Example:* A \`while(true)\` loop containing a huge \`if-else\` chain where branches perform \`stack[p++]\` operations.
102
+ * **Instruction:** Focus on the **LineNo** (1st column) and **Code** (3rd column onwards).
103
103
 
104
- * **High:**
105
- * Distinct **Dispatcher** structures found (e.g., a \`switch\` with >20 cases, or an \`if-else\` chain nested >10 levels deep checking integer values).
106
- * Large arrays containing only function definitions (Instruction Handlers).
107
-
108
- * **Medium:**
109
- * Isolated **Stack Operations** (e.g., \`v2[p2] = v2[p2 - 1]\`) without visible dispatchers nearby.
110
- * Suspicious \`while\` loops iterating over a string/array.
111
-
112
- * **Low:**
113
- * Generic obfuscation patterns (short variable names, comma operators) that *might* be part of a VM but lack specific structural proof.
104
+ **Detection Rules:**
105
+ * **Region Identification:** An individual JSVMP instance is often characterized by a self-contained block containing a **Main Loop** + **Dispatcher** + **Stack Operations**.
106
+ * **Instruction Pointer (IP) Identification:**
107
+ * It is used as the **index for the Bytecode Array of its VM instance**.
108
+ * It is **predictably incremented** in almost every loop iteration.
109
+ * In some branches (jumps), it is **overwritten** with a new value.
110
+ * **Stack Pointer (SP) Identification:**
111
+ * It is used as the **index for the Virtual Stack array of its VM instance**.
112
+ * Its value consistently **increments after a write** (push) and **decrements before a read** (pop).
113
+ * **Debugging Entry Point Identification:**
114
+ * This is the line **inside a specific dispatcher loop** but **before its \`switch\` or \`if-else\` chain begins**. It is typically located right after the \`opcode\` is read from the bytecode array.
114
115
 
115
116
  **Output Format:**
116
117
  Return **ONLY valid JSON**. No markdown wrapper, no conversational text.
117
118
 
118
119
  **JSON Schema:**
119
120
  {
120
- "summary": "Brief analysis of the code structure in chinese, shortly",
121
+ "summary": {
122
+ "overall_description": "\u5BF9\u5728\u6587\u4EF6\u4E2D\u53D1\u73B0\u7684JSVMP\u5B9E\u4F8B\u6570\u91CF\u548C\u7C7B\u578B\u7684\u7B80\u8981\u4E2D\u6587\u603B\u7ED3\u3002",
123
+ "debugging_recommendation": "\u4E3A\u4E0B\u4E00\u6B65\u5206\u6790\u63D0\u4F9B\u7684\u603B\u4F53\u4E2D\u6587\u5EFA\u8BAE\u3002\u4F8B\u5982\uFF1A'\u5DF2\u8BC6\u522B\u51FA N \u4E2A\u72EC\u7ACB\u7684JSVMP\u5B9E\u4F8B\u3002\u5EFA\u8BAE\u5BF9\u6BCF\u4E2A\u5B9E\u4F8B\u5206\u522B\u5728\u6307\u5B9A\u7684"\u8C03\u8BD5\u5165\u53E3\u70B9"\u8BBE\u7F6E\u6761\u4EF6\u65AD\u70B9\uFF0C\u5E76\u76D1\u63A7\u5176\u5404\u81EA\u7684\u7EC4\u4EF6\u53D8\u91CF\u3002'"
124
+ },
121
125
  "regions": [
122
126
  {
123
- "start": <start_line>,
124
- "end": <end_line>,
125
- "type": "<If-Else Dispatcher | Switch Dispatcher | Instruction Array | Stack Operation>",
127
+ "start_line": "<start_line_integer>",
128
+ "end_line": "<end_line_integer>",
129
+ "type": "<If-Else Dispatcher | Switch Dispatcher | Instruction Array>",
126
130
  "confidence": "<ultra_high | high | medium | low>",
127
- "description": "<Why you flagged this. Mention specific variables like 'v2', 'p2' or structures. in chinese, shortly>"
131
+ "description": "\u5BF9\u8FD9\u4E2A\u7279\u5B9AJSVMP\u5B9E\u4F8B\u7684\u7B80\u8981\u4E2D\u6587\u63CF\u8FF0\u3002",
132
+ "vm_components": {
133
+ "instruction_pointer": {
134
+ "variable_name": "<identified_variable_name | null>",
135
+ "confidence": "<high | medium | low>",
136
+ "reasoning": "Why this variable is the IP for THIS VM instance. E.g., 'Used as index for bytecode array _0x123 within this region.'"
137
+ },
138
+ "stack_pointer": {
139
+ "variable_name": "<identified_variable_name | null>",
140
+ "confidence": "<high | medium | low>",
141
+ "reasoning": "Why this variable is the SP for THIS VM instance. E.g., 'Used as index for stack array _0x456.'"
142
+ },
143
+ "virtual_stack": {
144
+ "variable_name": "<identified_array_name | null>",
145
+ "confidence": "<high | medium | low>",
146
+ "reasoning": "Why this array is the stack for THIS VM instance. E.g., 'Frequently accessed using its stack_pointer _0x789.'"
147
+ },
148
+ "bytecode_array": {
149
+ "variable_name": "<identified_array_name | null>",
150
+ "confidence": "<high | medium | low>",
151
+ "reasoning": "Why this array is the bytecode for THIS VM instance. E.g., 'A large, static array indexed by its instruction_pointer _0x123.'"
152
+ }
153
+ },
154
+ "debugging_entry_point": {
155
+ "line_number": "<line_number_integer>",
156
+ "description": "The optimal breakpoint line for THIS VM instance. E.g., 'This line is after the opcode is fetched and before this region's switch statement.'"
157
+ }
128
158
  }
129
159
  ]
130
160
  }`;
@@ -309,8 +339,7 @@ function createBatches(formattedLines, maxTokensPerBatch) {
309
339
  var VALID_DETECTION_TYPES = [
310
340
  "If-Else Dispatcher",
311
341
  "Switch Dispatcher",
312
- "Instruction Array",
313
- "Stack Operation"
342
+ "Instruction Array"
314
343
  ];
315
344
  var VALID_CONFIDENCE_LEVELS = [
316
345
  "ultra_high",
@@ -324,6 +353,57 @@ function isValidDetectionType(value) {
324
353
  function isValidConfidenceLevel(value) {
325
354
  return VALID_CONFIDENCE_LEVELS.includes(value);
326
355
  }
356
+ function parseVMComponentVariable(obj, fieldName) {
357
+ const component = obj[fieldName];
358
+ if (!component || typeof component !== "object") {
359
+ return null;
360
+ }
361
+ const variableName = component.variable_name;
362
+ const confidence = component.confidence;
363
+ const reasoning = component.reasoning;
364
+ if (typeof confidence !== "string" || !isValidConfidenceLevel(confidence)) {
365
+ return null;
366
+ }
367
+ return {
368
+ variable_name: typeof variableName === "string" ? variableName : null,
369
+ confidence,
370
+ reasoning: typeof reasoning === "string" ? reasoning : ""
371
+ };
372
+ }
373
+ function parseVMComponents(obj) {
374
+ const vmComponents = obj.vm_components;
375
+ if (!vmComponents || typeof vmComponents !== "object") {
376
+ return void 0;
377
+ }
378
+ const ip = parseVMComponentVariable(vmComponents, "instruction_pointer");
379
+ const sp = parseVMComponentVariable(vmComponents, "stack_pointer");
380
+ const stack = parseVMComponentVariable(vmComponents, "virtual_stack");
381
+ const bytecode = parseVMComponentVariable(vmComponents, "bytecode_array");
382
+ if (!ip && !sp && !stack && !bytecode) {
383
+ return void 0;
384
+ }
385
+ return {
386
+ instruction_pointer: ip ?? { variable_name: null, confidence: "low", reasoning: "" },
387
+ stack_pointer: sp ?? { variable_name: null, confidence: "low", reasoning: "" },
388
+ virtual_stack: stack ?? { variable_name: null, confidence: "low", reasoning: "" },
389
+ bytecode_array: bytecode ?? { variable_name: null, confidence: "low", reasoning: "" }
390
+ };
391
+ }
392
+ function parseDebuggingEntryPoint(obj) {
393
+ const entryPoint = obj.debugging_entry_point;
394
+ if (!entryPoint || typeof entryPoint !== "object") {
395
+ return void 0;
396
+ }
397
+ const lineNumber = entryPoint.line_number;
398
+ const description = entryPoint.description;
399
+ if (typeof lineNumber !== "number") {
400
+ return void 0;
401
+ }
402
+ return {
403
+ line_number: lineNumber,
404
+ description: typeof description === "string" ? description : ""
405
+ };
406
+ }
327
407
  function parseDetectionResult(jsonString) {
328
408
  let parsed;
329
409
  try {
@@ -335,7 +415,19 @@ function parseDetectionResult(jsonString) {
335
415
  throw new Error("LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u671F\u671B\u5BF9\u8C61\u7C7B\u578B");
336
416
  }
337
417
  const obj = parsed;
338
- if (typeof obj.summary !== "string") {
418
+ let summary;
419
+ if (typeof obj.summary === "string") {
420
+ summary = obj.summary;
421
+ } else if (typeof obj.summary === "object" && obj.summary !== null) {
422
+ const summaryObj = obj.summary;
423
+ if (typeof summaryObj.overall_description !== "string" || typeof summaryObj.debugging_recommendation !== "string") {
424
+ throw new Error("LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Csummary \u5BF9\u8C61\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5");
425
+ }
426
+ summary = {
427
+ overall_description: summaryObj.overall_description,
428
+ debugging_recommendation: summaryObj.debugging_recommendation
429
+ };
430
+ } else {
339
431
  throw new Error("LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: summary");
340
432
  }
341
433
  if (!Array.isArray(obj.regions)) {
@@ -347,11 +439,13 @@ function parseDetectionResult(jsonString) {
347
439
  if (typeof region !== "object" || region === null) {
348
440
  throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u4E0D\u662F\u5BF9\u8C61`);
349
441
  }
350
- if (typeof region.start !== "number") {
351
- throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: start`);
442
+ const startLine = region.start_line ?? region.start;
443
+ const endLine = region.end_line ?? region.end;
444
+ if (typeof startLine !== "number") {
445
+ throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: start_line \u6216 start`);
352
446
  }
353
- if (typeof region.end !== "number") {
354
- throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: end`);
447
+ if (typeof endLine !== "number") {
448
+ throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: end_line \u6216 end`);
355
449
  }
356
450
  if (typeof region.type !== "string") {
357
451
  throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: type`);
@@ -372,16 +466,20 @@ function parseDetectionResult(jsonString) {
372
466
  `LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}].confidence \u503C\u65E0\u6548: "${region.confidence}". \u6709\u6548\u503C: ${VALID_CONFIDENCE_LEVELS.join(", ")}`
373
467
  );
374
468
  }
469
+ const vmComponents = parseVMComponents(region);
470
+ const debuggingEntryPoint = parseDebuggingEntryPoint(region);
375
471
  validatedRegions.push({
376
- start: region.start,
377
- end: region.end,
472
+ start: startLine,
473
+ end: endLine,
378
474
  type: region.type,
379
475
  confidence: region.confidence,
380
- description: region.description
476
+ description: region.description,
477
+ ...vmComponents && { vm_components: vmComponents },
478
+ ...debuggingEntryPoint && { debugging_entry_point: debuggingEntryPoint }
381
479
  });
382
480
  }
383
481
  return {
384
- summary: obj.summary,
482
+ summary,
385
483
  regions: validatedRegions
386
484
  };
387
485
  }
@@ -390,13 +488,45 @@ function formatDetectionResultOutput(result, filePath, totalLines, batchCount) {
390
488
  lines.push("=== JSVMP Dispatcher Detection Result ===");
391
489
  lines.push(`File: ${filePath} (${totalLines} lines, ${batchCount} batch${batchCount > 1 ? "es" : ""})`);
392
490
  lines.push("");
393
- lines.push(`Summary: ${result.summary}`);
491
+ if (typeof result.summary === "string") {
492
+ lines.push(`Summary: ${result.summary}`);
493
+ } else {
494
+ lines.push(`Summary: ${result.summary.overall_description}`);
495
+ lines.push(`Recommendation: ${result.summary.debugging_recommendation}`);
496
+ }
394
497
  lines.push("");
395
498
  if (result.regions.length > 0) {
396
- lines.push("Detected Regions:");
397
- for (const region of result.regions) {
499
+ lines.push(`Detected Regions (${result.regions.length} JSVMP instance${result.regions.length > 1 ? "s" : ""}):`);
500
+ lines.push("");
501
+ for (let i = 0; i < result.regions.length; i++) {
502
+ const region = result.regions[i];
503
+ lines.push(`--- Instance ${i + 1} ---`);
398
504
  lines.push(`[${region.confidence}] Lines ${region.start}-${region.end}: ${region.type}`);
399
505
  lines.push(` ${region.description}`);
506
+ if (region.vm_components) {
507
+ lines.push(" VM Components:");
508
+ const { instruction_pointer, stack_pointer, virtual_stack, bytecode_array } = region.vm_components;
509
+ if (instruction_pointer.variable_name) {
510
+ lines.push(` - Instruction Pointer: ${instruction_pointer.variable_name} [${instruction_pointer.confidence}]`);
511
+ lines.push(` ${instruction_pointer.reasoning}`);
512
+ }
513
+ if (stack_pointer.variable_name) {
514
+ lines.push(` - Stack Pointer: ${stack_pointer.variable_name} [${stack_pointer.confidence}]`);
515
+ lines.push(` ${stack_pointer.reasoning}`);
516
+ }
517
+ if (virtual_stack.variable_name) {
518
+ lines.push(` - Virtual Stack: ${virtual_stack.variable_name} [${virtual_stack.confidence}]`);
519
+ lines.push(` ${virtual_stack.reasoning}`);
520
+ }
521
+ if (bytecode_array.variable_name) {
522
+ lines.push(` - Bytecode Array: ${bytecode_array.variable_name} [${bytecode_array.confidence}]`);
523
+ lines.push(` ${bytecode_array.reasoning}`);
524
+ }
525
+ }
526
+ if (region.debugging_entry_point) {
527
+ lines.push(` Debugging Entry Point: Line ${region.debugging_entry_point.line_number}`);
528
+ lines.push(` ${region.debugging_entry_point.description}`);
529
+ }
400
530
  lines.push("");
401
531
  }
402
532
  } else {
@@ -412,8 +542,20 @@ function mergeDetectionResults(results) {
412
542
  const sortedRegions = [...results[0].regions].sort((a, b) => a.start - b.start);
413
543
  return { summary: results[0].summary, regions: sortedRegions };
414
544
  }
415
- const summaries = results.map((r, i) => `[Batch ${i + 1}] ${r.summary}`);
416
- const combinedSummary = summaries.join("\n");
545
+ const summaryParts = [];
546
+ for (let i = 0; i < results.length; i++) {
547
+ const summary = results[i].summary;
548
+ if (typeof summary === "string") {
549
+ summaryParts.push(`[Batch ${i + 1}] ${summary}`);
550
+ } else {
551
+ summaryParts.push(`[Batch ${i + 1}] ${summary.overall_description}`);
552
+ }
553
+ }
554
+ const lastSummary = results[results.length - 1].summary;
555
+ const combinedSummary = {
556
+ overall_description: summaryParts.join("\n"),
557
+ debugging_recommendation: typeof lastSummary === "string" ? "\u8BF7\u53C2\u8003\u5404\u6279\u6B21\u7684\u5206\u6790\u7ED3\u679C\u8FDB\u884C\u8C03\u8BD5\u3002" : lastSummary.debugging_recommendation
558
+ };
417
559
  const allRegions = [];
418
560
  for (const result of results) {
419
561
  allRegions.push(...result.regions);
@@ -539,15 +681,16 @@ var findJsvmpDispatcherTool = defineTool({
539
681
  name: "find_jsvmp_dispatcher",
540
682
  description: `Detect JSVMP (JavaScript Virtual Machine Protection) patterns in code using LLM analysis.
541
683
 
542
- JSVMP is a code protection technique that converts JavaScript to bytecode executed by a virtual machine. This tool identifies:
543
- - If-Else Dispatchers: Nested if-else chains for instruction dispatch
544
- - Switch Dispatchers: Large switch statements (>20 cases) for opcode handling
545
- - Instruction Arrays: Arrays storing bytecode instructions
546
- - Stack Operations: Virtual stack push/pop patterns
684
+ JSVMP is a code protection technique that converts JavaScript to bytecode executed by a virtual machine. A single file may contain multiple independent JSVMP instances.
547
685
 
548
- Automatically splits large files into batches based on token limits and merges results.
686
+ This tool identifies for each JSVMP instance:
687
+ - Region location and dispatcher type (If-Else Dispatcher, Switch Dispatcher, Instruction Array)
688
+ - VM Components: Instruction Pointer (IP), Stack Pointer (SP), Virtual Stack, Bytecode Array
689
+ - Debugging Entry Point: The optimal line number to set breakpoints
549
690
 
550
- Returns detection results with confidence levels (ultra_high, high, medium, low) and detailed descriptions.
691
+ Detection confidence levels: ultra_high, high, medium, low
692
+
693
+ Automatically splits large files into batches based on token limits and merges results.
551
694
 
552
695
  Requires OPENAI_API_KEY environment variable. Optional: OPENAI_BASE_URL, OPENAI_MODEL.`,
553
696
  schema: FindJsvmpDispatcherInputSchema,