windows-exe-decompiler-mcp-server 0.1.0 → 0.1.3

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.
Files changed (134) hide show
  1. package/CLAUDE_INSTALLATION.md +129 -0
  2. package/CODEX_INSTALLATION.md +25 -1
  3. package/COPILOT_INSTALLATION.md +29 -1
  4. package/LICENSE +21 -21
  5. package/README.md +232 -110
  6. package/dist/analysis-provenance.d.ts +50 -2
  7. package/dist/analysis-provenance.js +1 -0
  8. package/dist/analysis-task-runner.js +92 -0
  9. package/dist/config.d.ts +35 -16
  10. package/dist/config.js +37 -3
  11. package/dist/database.js +115 -115
  12. package/dist/decompiler-worker.d.ts +10 -5
  13. package/dist/decompiler-worker.js +240 -58
  14. package/dist/dynamic-trace.d.ts +6 -0
  15. package/dist/dynamic-trace.js +52 -1
  16. package/dist/ghidra-config.js +17 -1
  17. package/dist/index.js +38 -8
  18. package/dist/pe-runtime-functions.d.ts +90 -0
  19. package/dist/pe-runtime-functions.js +452 -0
  20. package/dist/prompts/module-reconstruction-review.d.ts +5 -0
  21. package/dist/prompts/module-reconstruction-review.js +65 -0
  22. package/dist/runtime-correlation.d.ts +5 -0
  23. package/dist/runtime-correlation.js +179 -2
  24. package/dist/sample-workspace.d.ts +28 -0
  25. package/dist/sample-workspace.js +186 -0
  26. package/dist/semantic-name-suggestion-artifacts.d.ts +56 -0
  27. package/dist/semantic-name-suggestion-artifacts.js +87 -0
  28. package/dist/server.js +1 -1
  29. package/dist/setup-guidance.d.ts +73 -0
  30. package/dist/setup-guidance.js +211 -0
  31. package/dist/tools/artifact-read.d.ts +10 -10
  32. package/dist/tools/artifacts-diff.d.ts +8 -8
  33. package/dist/tools/artifacts-list.d.ts +16 -16
  34. package/dist/tools/attack-map.d.ts +8 -8
  35. package/dist/tools/binary-role-profile.d.ts +1197 -0
  36. package/dist/tools/binary-role-profile.js +575 -0
  37. package/dist/tools/code-function-explain-apply.d.ts +12 -12
  38. package/dist/tools/code-function-explain-prepare.d.ts +12 -12
  39. package/dist/tools/code-function-explain-review.d.ts +58 -58
  40. package/dist/tools/code-function-rename-apply.d.ts +12 -12
  41. package/dist/tools/code-function-rename-prepare.d.ts +14 -14
  42. package/dist/tools/code-function-rename-review.d.ts +66 -66
  43. package/dist/tools/code-functions-define.d.ts +337 -0
  44. package/dist/tools/code-functions-define.js +337 -0
  45. package/dist/tools/code-functions-list.js +1 -1
  46. package/dist/tools/code-functions-rank.js +1 -1
  47. package/dist/tools/code-functions-reconstruct.d.ts +368 -58
  48. package/dist/tools/code-functions-reconstruct.js +130 -10
  49. package/dist/tools/code-functions-smart-recover.d.ts +352 -0
  50. package/dist/tools/code-functions-smart-recover.js +190 -0
  51. package/dist/tools/code-module-review-apply.d.ts +233 -0
  52. package/dist/tools/code-module-review-apply.js +209 -0
  53. package/dist/tools/code-module-review-prepare.d.ts +756 -0
  54. package/dist/tools/code-module-review-prepare.js +343 -0
  55. package/dist/tools/code-module-review.d.ts +474 -0
  56. package/dist/tools/code-module-review.js +566 -0
  57. package/dist/tools/code-reconstruct-export.d.ts +193 -21
  58. package/dist/tools/code-reconstruct-export.js +578 -21
  59. package/dist/tools/code-reconstruct-plan.d.ts +20 -20
  60. package/dist/tools/com-role-profile.d.ts +353 -0
  61. package/dist/tools/com-role-profile.js +186 -0
  62. package/dist/tools/dll-export-profile.d.ts +625 -0
  63. package/dist/tools/dll-export-profile.js +230 -0
  64. package/dist/tools/dotnet-metadata-extract.d.ts +122 -122
  65. package/dist/tools/dotnet-reconstruct-export.d.ts +49 -49
  66. package/dist/tools/dotnet-types-list.d.ts +66 -66
  67. package/dist/tools/dynamic-dependencies.d.ts +144 -8
  68. package/dist/tools/dynamic-dependencies.js +20 -1
  69. package/dist/tools/dynamic-memory-import.js +105 -2
  70. package/dist/tools/ghidra-analyze.d.ts +20 -0
  71. package/dist/tools/ghidra-analyze.js +10 -2
  72. package/dist/tools/ghidra-health.d.ts +177 -0
  73. package/dist/tools/ghidra-health.js +28 -0
  74. package/dist/tools/ioc-export.d.ts +8 -8
  75. package/dist/tools/packer-detect.d.ts +14 -14
  76. package/dist/tools/packer-detect.js +6 -9
  77. package/dist/tools/pe-exports-extract.d.ts +8 -8
  78. package/dist/tools/pe-exports-extract.js +6 -9
  79. package/dist/tools/pe-fingerprint.d.ts +36 -36
  80. package/dist/tools/pe-imports-extract.d.ts +8 -8
  81. package/dist/tools/pe-imports-extract.js +6 -9
  82. package/dist/tools/pe-pdata-extract.d.ts +448 -0
  83. package/dist/tools/pe-pdata-extract.js +219 -0
  84. package/dist/tools/pe-symbols-recover.d.ts +227 -0
  85. package/dist/tools/pe-symbols-recover.js +316 -0
  86. package/dist/tools/report-generate.d.ts +15 -1
  87. package/dist/tools/report-generate.js +139 -16
  88. package/dist/tools/report-summarize.d.ts +2242 -8
  89. package/dist/tools/report-summarize.js +246 -10
  90. package/dist/tools/runtime-detect.d.ts +8 -8
  91. package/dist/tools/runtime-detect.js +2 -12
  92. package/dist/tools/rust-binary-analyze.d.ts +2047 -0
  93. package/dist/tools/rust-binary-analyze.js +443 -0
  94. package/dist/tools/sample-profile-get.d.ts +135 -16
  95. package/dist/tools/sample-profile-get.js +35 -32
  96. package/dist/tools/sandbox-execute.d.ts +10 -10
  97. package/dist/tools/strings-extract.d.ts +8 -8
  98. package/dist/tools/strings-extract.js +2 -12
  99. package/dist/tools/strings-floss-decode.d.ts +8 -8
  100. package/dist/tools/system-health.d.ts +172 -36
  101. package/dist/tools/system-health.js +14 -0
  102. package/dist/tools/system-setup-guide.d.ts +179 -0
  103. package/dist/tools/system-setup-guide.js +62 -0
  104. package/dist/tools/tool-help.d.ts +16 -16
  105. package/dist/tools/tool-help.js +172 -0
  106. package/dist/tools/yara-scan.d.ts +8 -8
  107. package/dist/types.d.ts +2 -0
  108. package/dist/workflows/function-explanation-review.d.ts +3034 -76
  109. package/dist/workflows/function-explanation-review.js +172 -42
  110. package/dist/workflows/function-index-recover.d.ts +333 -0
  111. package/dist/workflows/function-index-recover.js +291 -0
  112. package/dist/workflows/module-reconstruction-review.d.ts +3537 -0
  113. package/dist/workflows/module-reconstruction-review.js +354 -0
  114. package/dist/workflows/reconstruct.d.ts +2182 -223
  115. package/dist/workflows/reconstruct.js +575 -32
  116. package/dist/workflows/semantic-name-review.d.ts +1436 -85
  117. package/dist/workflows/semantic-name-review.js +150 -58
  118. package/dist/workflows/triage.d.ts +8 -8
  119. package/ghidra_scripts/DecompileFunction.java +487 -487
  120. package/ghidra_scripts/ExtractCFG.java +256 -256
  121. package/ghidra_scripts/ExtractFunctions.java +442 -442
  122. package/ghidra_scripts/README.md +112 -112
  123. package/ghidra_scripts/SearchFunctionReferences.java +380 -380
  124. package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -9
  125. package/helpers/DotNetMetadataProbe/Program.cs +566 -566
  126. package/install-to-claude.ps1 +432 -0
  127. package/install-to-codex.ps1 +256 -178
  128. package/install-to-copilot.ps1 +389 -303
  129. package/package.json +4 -2
  130. package/requirements.txt +9 -9
  131. package/workers/requirements-dynamic.txt +11 -11
  132. package/workers/requirements.txt +8 -8
  133. package/workers/speakeasy_compat.py +175 -175
  134. package/workers/static_worker.py +3474 -3474
package/README.md CHANGED
@@ -1,44 +1,43 @@
1
1
  # Windows EXE Decompiler MCP Server
2
2
 
3
- 中文说明见 [`README_zh.md`](./README_zh.md).
3
+ Chinese version: [`README_zh.md`](./README_zh.md)
4
4
 
5
- An MCP server for Windows binary reverse engineering.
5
+ An MCP server for Windows reverse engineering. It exposes PE triage, Ghidra-backed inspection, DLL/COM profiling, runtime evidence ingestion, Rust/.NET recovery, source-like reconstruction, and LLM-assisted review as reusable MCP tools for any tool-calling LLM.
6
6
 
7
- It exposes PE triage, native and .NET analysis, Ghidra-backed function
8
- inspection, runtime evidence import, reconstruction workflows, and report
9
- generation as MCP tools that any tool-calling LLM can consume.
7
+ ## What this server is for
10
8
 
11
- ## What this project is for
9
+ This project is meant to be a reusable reverse-engineering tool surface, not a pile of one-off local scripts.
12
10
 
13
- This server is designed to provide a reusable reverse-engineering tool surface
14
- over MCP instead of one-off local scripts.
11
+ It is designed to help MCP clients:
15
12
 
16
- Primary use cases:
13
+ - triage Windows PE samples quickly
14
+ - inspect imports, exports, strings, packers, runtime hints, and binary role
15
+ - use Ghidra when available for decompile, CFG, search, and reconstruction
16
+ - recover usable function indexes when Ghidra function extraction fails
17
+ - correlate static evidence, runtime traces, memory snapshots, and semantic review artifacts
18
+ - export source-like reconstruction output with optional build and harness validation
17
19
 
18
- - Windows PE triage
19
- - import / export / string / YARA analysis
20
- - Ghidra-assisted decompile, CFG, and function search
21
- - .NET metadata inspection
22
- - runtime trace and memory snapshot import
23
- - function naming and explanation review workflows
24
- - source-like reconstruction export with validation harnesses
20
+ ## Core capability areas
25
21
 
26
- ## Current capability areas
27
-
28
- ### Static analysis
22
+ ### Sample and static analysis
29
23
 
30
24
  - `sample.ingest`
31
25
  - `sample.profile.get`
32
26
  - `pe.fingerprint`
33
27
  - `pe.imports.extract`
34
28
  - `pe.exports.extract`
29
+ - `pe.pdata.extract`
30
+ - `dll.export.profile`
31
+ - `com.role.profile`
35
32
  - `strings.extract`
36
33
  - `strings.floss.decode`
37
34
  - `yara.scan`
38
35
  - `runtime.detect`
39
36
  - `packer.detect`
37
+ - `binary.role.profile`
38
+ - `system.setup.guide`
40
39
 
41
- ### Ghidra and code analysis
40
+ ### Ghidra and function analysis
42
41
 
43
42
  - `ghidra.health`
44
43
  - `ghidra.analyze`
@@ -50,18 +49,19 @@ Primary use cases:
50
49
  - `code.function.cfg`
51
50
  - `code.functions.reconstruct`
52
51
 
53
- ### Reconstruction and review workflows
52
+ ### Recovery for Rust and hard native samples
53
+
54
+ - `code.functions.smart_recover`
55
+ - `pe.symbols.recover`
56
+ - `code.functions.define`
57
+ - `rust_binary.analyze`
58
+ - `workflow.function_index_recover`
59
+
60
+ ### .NET and managed inspection
54
61
 
55
- - `code.reconstruct.plan`
56
- - `code.reconstruct.export`
57
62
  - `dotnet.metadata.extract`
58
63
  - `dotnet.types.list`
59
64
  - `dotnet.reconstruct.export`
60
- - `workflow.triage`
61
- - `workflow.deep_static`
62
- - `workflow.reconstruct`
63
- - `workflow.semantic_name_review`
64
- - `workflow.function_explanation_review`
65
65
 
66
66
  ### Runtime evidence and reporting
67
67
 
@@ -78,6 +78,155 @@ Primary use cases:
78
78
  - `artifacts.diff`
79
79
  - `tool.help`
80
80
 
81
+ ### Semantic review and reconstruction
82
+
83
+ - `code.function.rename.prepare`
84
+ - `code.function.rename.review`
85
+ - `code.function.rename.apply`
86
+ - `code.function.explain.prepare`
87
+ - `code.function.explain.review`
88
+ - `code.function.explain.apply`
89
+ - `code.module.review.prepare`
90
+ - `code.module.review`
91
+ - `code.module.review.apply`
92
+ - `code.reconstruct.plan`
93
+ - `code.reconstruct.export`
94
+
95
+ ## High-level workflows
96
+
97
+ These are the main orchestration entrypoints for MCP clients.
98
+
99
+ ### `workflow.triage`
100
+
101
+ Fast first-pass triage for PE samples. Use this when you want a quick answer before deeper recovery.
102
+
103
+ ### `workflow.deep_static`
104
+
105
+ Long-running static pipeline for deeper analysis and ranking. Supports async job mode.
106
+
107
+ ### `workflow.reconstruct`
108
+
109
+ The main high-level reconstruction workflow.
110
+
111
+ It can:
112
+
113
+ - run binary preflight
114
+ - detect Rust-oriented samples
115
+ - profile DLL lifecycle, export dispatch, callback surface, and COM activation hints
116
+ - auto-recover a function index when Ghidra function extraction is missing or degraded
117
+ - export native or .NET reconstruction output
118
+ - optionally validate build and run the generated harness
119
+ - tune export strategy based on role-aware preflight for native Rust, DLL, and COM-oriented samples
120
+ - carry runtime and semantic provenance through the result
121
+
122
+ ### `workflow.function_index_recover`
123
+
124
+ High-level recovery chain for hard native binaries:
125
+
126
+ - `code.functions.smart_recover`
127
+ - `pe.symbols.recover`
128
+ - `code.functions.define`
129
+
130
+ Use this when Ghidra analysis exists but function extraction is empty or degraded.
131
+
132
+ ### `workflow.semantic_name_review`
133
+
134
+ High-level semantic naming review workflow for external LLM clients. It can prepare evidence, request model review through MCP sampling when available, apply accepted names, and optionally refresh reconstruct/export output.
135
+
136
+ ### `workflow.function_explanation_review`
137
+
138
+ High-level explanation workflow for external LLM clients. It can prepare evidence, request structured explanations, apply them, and optionally rerun reconstruct/export.
139
+
140
+ ### `workflow.module_reconstruction_review`
141
+
142
+ High-level module review workflow for external LLM clients. It can prepare reconstructed modules for review, request structured module refinements through MCP sampling when available, apply accepted module summaries and guidance, and optionally refresh reconstruct/export output.
143
+
144
+ ## Universal recovery model
145
+
146
+ This server does not assume Ghidra is always able to recover functions correctly.
147
+
148
+ For difficult native samples, especially Rust, Go, or heavily optimized binaries, the recovery path is:
149
+
150
+ 1. `ghidra.analyze`
151
+ 2. if Ghidra post-script extraction fails, use `pe.pdata.extract`
152
+ 3. recover candidate function boundaries with `code.functions.smart_recover`
153
+ 4. recover names with `pe.symbols.recover`
154
+ 5. import the recovered boundaries with `code.functions.define`
155
+ 6. continue with `code.functions.list`, `code.functions.rank`, `code.functions.reconstruct`, or `workflow.reconstruct`
156
+
157
+ This means `function_index` readiness is tracked separately from `decompile` and `cfg` readiness.
158
+
159
+ ## Evidence scope, semantic scope, and replayability
160
+
161
+ Most high-level tools support explicit scope control so clients can choose between all history and the current session.
162
+
163
+ Runtime evidence selection:
164
+
165
+ - `evidence_scope=all`
166
+ - `evidence_scope=latest`
167
+ - `evidence_scope=session` with `evidence_session_tag`
168
+
169
+ Semantic naming / explanation / module-review selection:
170
+
171
+ - `semantic_scope=all`
172
+ - `semantic_scope=latest`
173
+ - `semantic_scope=session` with `semantic_session_tag`
174
+
175
+ Comparison-aware outputs are also supported through:
176
+
177
+ - `compare_evidence_scope`
178
+ - `compare_evidence_session_tag`
179
+ - `compare_semantic_scope`
180
+ - `compare_semantic_session_tag`
181
+
182
+ This allows MCP clients to ask not only "what is the current result?" but also "what changed compared with the previous evidence or semantic review session?"
183
+
184
+ ## LLM review layers
185
+
186
+ This server supports multiple structured review layers for MCP clients with tool calling and optional sampling:
187
+
188
+ - function naming review
189
+ - function explanation review
190
+ - module reconstruction review
191
+
192
+ Each layer follows the same pattern:
193
+
194
+ 1. prepare a structured evidence bundle
195
+ 2. optionally ask the connected MCP client to perform a constrained review through sampling
196
+ 3. apply accepted results as stable semantic artifacts
197
+ 4. rerun reconstruct/export/report workflows against explicit semantic scope
198
+
199
+ ## Async job model
200
+
201
+ Long-running workflows support queued execution and background completion:
202
+
203
+ - `workflow.deep_static`
204
+ - `workflow.reconstruct`
205
+ - `workflow.semantic_name_review`
206
+ - `workflow.function_explanation_review`
207
+ - `workflow.module_reconstruction_review`
208
+
209
+ Use these with:
210
+
211
+ - `task.status`
212
+ - `task.cancel`
213
+ - `task.sweep`
214
+
215
+ ## Environment bootstrap and setup guidance
216
+
217
+ If a client starts using the server before Python, dynamic-analysis extras, or Ghidra are configured, use:
218
+
219
+ - `system.health`
220
+ - `dynamic.dependencies`
221
+ - `ghidra.health`
222
+ - `system.setup.guide`
223
+
224
+ These return structured setup actions and required user inputs so an MCP client can explicitly ask for:
225
+
226
+ - `python -m pip install ...`
227
+ - `GHIDRA_PATH` / `GHIDRA_INSTALL_DIR`
228
+ - optional dynamic-analysis extras such as Speakeasy/Frida dependencies
229
+
81
230
  ## Project layout
82
231
 
83
232
  ```text
@@ -90,6 +239,8 @@ tests/ unit and integration tests
90
239
  workers/ Python worker, YARA rules, dynamic helpers
91
240
  install-to-codex.ps1 local Codex MCP install helper
92
241
  install-to-copilot.ps1 local GitHub Copilot MCP install helper
242
+ install-to-claude.ps1 local Claude Code MCP install helper
243
+ docs/QUALITY_EVALUATION.md evaluation checklist for regression and release readiness
93
244
  ```
94
245
 
95
246
  ## Prerequisites
@@ -108,7 +259,7 @@ Optional but strongly recommended:
108
259
  - Python packages from [`requirements.txt`](./requirements.txt)
109
260
  - Python worker packages from [`workers/requirements.txt`](./workers/requirements.txt)
110
261
 
111
- ## Local development setup
262
+ ## Local development
112
263
 
113
264
  Install JavaScript dependencies:
114
265
 
@@ -124,7 +275,7 @@ python -m pip install -r workers/requirements.txt
124
275
  python -m pip install -r workers/requirements-dynamic.txt
125
276
  ```
126
277
 
127
- Build the server:
278
+ Build:
128
279
 
129
280
  ```bash
130
281
  npm run build
@@ -136,7 +287,7 @@ Run tests:
136
287
  npm test
137
288
  ```
138
289
 
139
- Start the server locally:
290
+ Start locally:
140
291
 
141
292
  ```bash
142
293
  npm start
@@ -146,8 +297,6 @@ npm start
146
297
 
147
298
  ### Generic stdio config
148
299
 
149
- Most MCP clients can start this server with:
150
-
151
300
  ```json
152
301
  {
153
302
  "mcpServers": {
@@ -166,19 +315,32 @@ Most MCP clients can start this server with:
166
315
 
167
316
  ### Local install helpers
168
317
 
169
- This repository already includes local install scripts:
170
-
171
318
  - Codex: [`install-to-codex.ps1`](./install-to-codex.ps1)
319
+ - Claude Code: [`install-to-claude.ps1`](./install-to-claude.ps1)
172
320
  - GitHub Copilot: [`install-to-copilot.ps1`](./install-to-copilot.ps1)
173
321
 
174
322
  Related docs:
175
323
 
176
324
  - [`CODEX_INSTALLATION.md`](./CODEX_INSTALLATION.md)
177
325
  - [`COPILOT_INSTALLATION.md`](./COPILOT_INSTALLATION.md)
326
+ - [`CLAUDE_INSTALLATION.md`](./CLAUDE_INSTALLATION.md)
327
+
328
+ ## Persistent storage
329
+
330
+ By default, runtime state is stored under the user profile instead of the current working directory:
331
+
332
+ - Windows workspace root: `%USERPROFILE%/.windows-exe-decompiler-mcp-server/workspaces`
333
+ - SQLite database: `%USERPROFILE%/.windows-exe-decompiler-mcp-server/data/database.db`
334
+ - File cache: `%USERPROFILE%/.windows-exe-decompiler-mcp-server/cache`
335
+ - Audit log: `%USERPROFILE%/.windows-exe-decompiler-mcp-server/audit.log`
336
+
337
+ You can override these with environment variables or the user config file:
338
+
339
+ - `%USERPROFILE%/.windows-exe-decompiler-mcp-server/config.json`
178
340
 
179
341
  ## Sample ingest note
180
342
 
181
- For local IDE clients such as VS Code or Copilot, prefer:
343
+ For local IDE clients such as VS Code or Copilot, prefer local file paths:
182
344
 
183
345
  ```json
184
346
  {
@@ -189,23 +351,20 @@ For local IDE clients such as VS Code or Copilot, prefer:
189
351
  }
190
352
  ```
191
353
 
192
- Use `bytes_b64` only when the MCP client cannot access the same filesystem as
193
- the MCP server.
354
+ Use `bytes_b64` only when the client cannot access the same filesystem as the server.
194
355
 
195
356
  ## Publishing to npm
196
357
 
197
- ### What is included in the npm package
198
-
199
358
  The published package includes:
200
359
 
201
360
  - compiled `dist/`
202
- - a CLI entrypoint in `bin/`
361
+ - the CLI entrypoint in `bin/`
203
362
  - Python workers and YARA rules
204
363
  - Ghidra helper scripts
205
364
  - the .NET metadata helper source
206
365
  - MCP client install scripts
207
366
 
208
- It intentionally excludes:
367
+ It excludes:
209
368
 
210
369
  - tests
211
370
  - local workspaces
@@ -213,68 +372,49 @@ It intentionally excludes:
213
372
  - generated reports
214
373
  - scratch documents and internal progress notes
215
374
 
216
- ### Pre-publish checklist
217
-
218
- 1. Pick a package name that is available on npm.
219
- 2. Update the version in [`package.json`](./package.json).
220
- 3. Run:
221
-
222
- ```bash
223
- npm run release:check
224
- ```
225
-
226
- 4. Inspect the dry-run pack list:
227
-
228
- ```bash
229
- npm run pack:dry-run
230
- ```
231
-
232
- 5. Log in to npm:
233
-
234
- ```bash
235
- npm login
236
- ```
237
-
238
- 6. Publish:
375
+ Pre-publish checklist:
239
376
 
240
- ```bash
241
- npm publish
242
- ```
243
-
244
- ### GitHub Actions
245
-
246
- This repository now includes:
377
+ 1. Update the version in [`package.json`](./package.json).
378
+ 2. Run `npm run release:check`.
379
+ 3. Inspect `npm run pack:dry-run`.
380
+ 4. Log in with `npm login`.
381
+ 5. Publish with `npm publish --access public`.
247
382
 
248
- - [`ci.yml`](./.github/workflows/ci.yml): build, Python syntax check, key unit tests, and `npm pack --dry-run`
249
- - [`publish-npm.yml`](./.github/workflows/publish-npm.yml): publish on `v*` tags or manual dispatch, then create a GitHub Release with the npm tarball attached
250
- - [`dependabot.yml`](./.github/dependabot.yml): weekly npm and GitHub Actions dependency updates
383
+ GitHub automation included in this repository:
251
384
 
252
- Before npm publishing from GitHub Actions, add this repository secret:
385
+ - [`ci.yml`](./.github/workflows/ci.yml)
386
+ - [`publish-npm.yml`](./.github/workflows/publish-npm.yml)
387
+ - [`dependabot.yml`](./.github/dependabot.yml)
253
388
 
254
- - `NPM_TOKEN`
389
+ For GitHub Actions publishing, configure the `NPM_TOKEN` repository secret.
255
390
 
256
- Recommended release flow:
391
+ ## Security boundaries
257
392
 
258
- ```bash
259
- npm version patch
260
- git push origin main --follow-tags
261
- ```
393
+ This project is for analysis workflows, not live malware operations.
262
394
 
263
- That tag push will trigger the publish workflow.
395
+ Current strengths:
264
396
 
265
- ## Contributing
397
+ - PE triage and classification support
398
+ - reverse-engineering evidence extraction
399
+ - IOC and ATT&CK export
400
+ - runtime evidence import and correlation
401
+ - source-like reconstruction and review
266
402
 
267
- See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for local
268
- setup, validation, and release steps.
403
+ Current non-goals:
269
404
 
270
- ## Security
405
+ - original source recovery for complex native binaries
406
+ - guaranteed malware family attribution from static evidence alone
407
+ - fully automatic unpacking for every packer
408
+ - high-confidence semantic recovery of every function in heavily optimized code
271
409
 
272
- See [`SECURITY.md`](./SECURITY.md) for disclosure guidance
273
- and operational boundaries.
410
+ ## Contributing and release process
274
411
 
275
- ### Using the published package
412
+ - Contributor guide: [`CONTRIBUTING.md`](./CONTRIBUTING.md)
413
+ - Quality evaluation notes: [`docs/QUALITY_EVALUATION.md`](./docs/QUALITY_EVALUATION.md)
414
+ - Example benchmark corpus: [`examples/benchmark-corpus.example.json`](./examples/benchmark-corpus.example.json)
415
+ - Security policy: [`SECURITY.md`](./SECURITY.md)
276
416
 
277
- Once published, an MCP client can use `npx`:
417
+ ## Using the published package
278
418
 
279
419
  ```json
280
420
  {
@@ -291,24 +431,6 @@ Once published, an MCP client can use `npx`:
291
431
  }
292
432
  ```
293
433
 
294
- ## Security boundaries
295
-
296
- This project is designed for analysis workflows, not for live malware
297
- operations. Current practical strengths are:
298
-
299
- - triage and classification support
300
- - reverse-engineering evidence extraction
301
- - IOC and ATT&CK export
302
- - runtime evidence import and correlation
303
- - source-like reconstruction and review
304
-
305
- Current non-goals:
306
-
307
- - original source recovery for complex native binaries
308
- - guaranteed malware family attribution from static evidence alone
309
- - full automatic unpacking for all packers
310
- - high-confidence semantic recovery of every function in heavily optimized code
311
-
312
434
  ## License
313
435
 
314
- This project is released under the MIT license. See [`LICENSE`](./LICENSE).
436
+ Released under the MIT license. See [`LICENSE`](./LICENSE).
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import type { DynamicEvidenceScope, DynamicTraceSummary } from './dynamic-trace.js';
3
- import type { SemanticArtifactScope, SemanticFunctionExplanationIndex, SemanticNameSuggestionIndex } from './semantic-name-suggestion-artifacts.js';
3
+ import type { SemanticArtifactScope, SemanticFunctionExplanationIndex, SemanticModuleReviewIndex, SemanticNameSuggestionIndex } from './semantic-name-suggestion-artifacts.js';
4
4
  export declare const ArtifactSelectionProvenanceSchema: z.ZodObject<{
5
5
  scope: z.ZodEnum<["all", "latest", "session"]>;
6
6
  session_selector: z.ZodNullable<z.ZodString>;
@@ -114,6 +114,34 @@ export declare const AnalysisProvenanceSchema: z.ZodObject<{
114
114
  earliest_artifact_at: string | null;
115
115
  latest_artifact_at: string | null;
116
116
  }>>;
117
+ semantic_module_reviews: z.ZodOptional<z.ZodObject<{
118
+ scope: z.ZodEnum<["all", "latest", "session"]>;
119
+ session_selector: z.ZodNullable<z.ZodString>;
120
+ artifact_count: z.ZodNumber;
121
+ artifact_ids: z.ZodArray<z.ZodString, "many">;
122
+ session_tags: z.ZodArray<z.ZodString, "many">;
123
+ earliest_artifact_at: z.ZodNullable<z.ZodString>;
124
+ latest_artifact_at: z.ZodNullable<z.ZodString>;
125
+ scope_note: z.ZodString;
126
+ }, "strip", z.ZodTypeAny, {
127
+ artifact_count: number;
128
+ scope_note: string;
129
+ artifact_ids: string[];
130
+ session_selector: string | null;
131
+ session_tags: string[];
132
+ scope: "all" | "latest" | "session";
133
+ earliest_artifact_at: string | null;
134
+ latest_artifact_at: string | null;
135
+ }, {
136
+ artifact_count: number;
137
+ scope_note: string;
138
+ artifact_ids: string[];
139
+ session_selector: string | null;
140
+ session_tags: string[];
141
+ scope: "all" | "latest" | "session";
142
+ earliest_artifact_at: string | null;
143
+ latest_artifact_at: string | null;
144
+ }>>;
117
145
  }, "strip", z.ZodTypeAny, {
118
146
  runtime: {
119
147
  artifact_count: number;
@@ -125,6 +153,16 @@ export declare const AnalysisProvenanceSchema: z.ZodObject<{
125
153
  earliest_artifact_at: string | null;
126
154
  latest_artifact_at: string | null;
127
155
  };
156
+ semantic_module_reviews?: {
157
+ artifact_count: number;
158
+ scope_note: string;
159
+ artifact_ids: string[];
160
+ session_selector: string | null;
161
+ session_tags: string[];
162
+ scope: "all" | "latest" | "session";
163
+ earliest_artifact_at: string | null;
164
+ latest_artifact_at: string | null;
165
+ } | undefined;
128
166
  semantic_names?: {
129
167
  artifact_count: number;
130
168
  scope_note: string;
@@ -156,6 +194,16 @@ export declare const AnalysisProvenanceSchema: z.ZodObject<{
156
194
  earliest_artifact_at: string | null;
157
195
  latest_artifact_at: string | null;
158
196
  };
197
+ semantic_module_reviews?: {
198
+ artifact_count: number;
199
+ scope_note: string;
200
+ artifact_ids: string[];
201
+ session_selector: string | null;
202
+ session_tags: string[];
203
+ scope: "all" | "latest" | "session";
204
+ earliest_artifact_at: string | null;
205
+ latest_artifact_at: string | null;
206
+ } | undefined;
159
207
  semantic_names?: {
160
208
  artifact_count: number;
161
209
  scope_note: string;
@@ -179,6 +227,6 @@ export declare const AnalysisProvenanceSchema: z.ZodObject<{
179
227
  }>;
180
228
  type ArtifactSelectionProvenance = z.infer<typeof ArtifactSelectionProvenanceSchema>;
181
229
  export declare function buildRuntimeArtifactProvenance(dynamicEvidence: DynamicTraceSummary | null | undefined, scope: DynamicEvidenceScope, sessionTag?: string | null): ArtifactSelectionProvenance;
182
- export declare function buildSemanticArtifactProvenance(label: 'semantic naming artifacts' | 'semantic explanation artifacts', index: SemanticNameSuggestionIndex | SemanticFunctionExplanationIndex | null | undefined, scope: SemanticArtifactScope, sessionTag?: string | null): ArtifactSelectionProvenance;
230
+ export declare function buildSemanticArtifactProvenance(label: 'semantic naming artifacts' | 'semantic explanation artifacts' | 'semantic module review artifacts', index: SemanticNameSuggestionIndex | SemanticFunctionExplanationIndex | SemanticModuleReviewIndex | null | undefined, scope: SemanticArtifactScope, sessionTag?: string | null): ArtifactSelectionProvenance;
183
231
  export {};
184
232
  //# sourceMappingURL=analysis-provenance.d.ts.map
@@ -13,6 +13,7 @@ export const AnalysisProvenanceSchema = z.object({
13
13
  runtime: ArtifactSelectionProvenanceSchema,
14
14
  semantic_names: ArtifactSelectionProvenanceSchema.optional(),
15
15
  semantic_explanations: ArtifactSelectionProvenanceSchema.optional(),
16
+ semantic_module_reviews: ArtifactSelectionProvenanceSchema.optional(),
16
17
  });
17
18
  function emptyScopeNote(label, scope, sessionTag) {
18
19
  if (scope === 'session' && sessionTag?.trim()) {
@@ -5,6 +5,10 @@
5
5
  import { DecompilerWorker, GhidraProcessError } from './decompiler-worker.js';
6
6
  import { logger } from './logger.js';
7
7
  import { deepStaticWorkflow } from './workflows/deep-static.js';
8
+ import { createReconstructWorkflowHandler } from './workflows/reconstruct.js';
9
+ import { createSemanticNameReviewWorkflowHandler } from './workflows/semantic-name-review.js';
10
+ import { createFunctionExplanationReviewWorkflowHandler } from './workflows/function-explanation-review.js';
11
+ import { createModuleReconstructionReviewWorkflowHandler } from './workflows/module-reconstruction-review.js';
8
12
  export class AnalysisTaskRunner {
9
13
  jobQueue;
10
14
  decompilerWorker;
@@ -120,6 +124,10 @@ export class AnalysisTaskRunner {
120
124
  timeout: job.timeout,
121
125
  maxCpu: options.max_cpu || '4',
122
126
  projectKey: options.project_key,
127
+ processor: options.processor,
128
+ languageId: options.language_id,
129
+ cspec: options.cspec,
130
+ scriptPaths: options.script_paths,
123
131
  abortSignal,
124
132
  });
125
133
  return this.decompilerWorker.createJobResult(analysisResult, 0);
@@ -154,6 +162,90 @@ export class AnalysisTaskRunner {
154
162
  },
155
163
  };
156
164
  }
165
+ if (job.tool === 'workflow.reconstruct') {
166
+ if (!this.cacheManager) {
167
+ throw new Error('workflow.reconstruct requires cache manager for queued execution');
168
+ }
169
+ this.jobQueue.updateProgress(job.id, 5);
170
+ const handler = createReconstructWorkflowHandler(this.workspaceManager, this.database, this.cacheManager);
171
+ const result = await handler(job.args || {});
172
+ this.jobQueue.updateProgress(job.id, 100);
173
+ return {
174
+ jobId: job.id,
175
+ ok: result.ok,
176
+ data: result.data,
177
+ errors: result.errors || [],
178
+ warnings: result.warnings || [],
179
+ artifacts: result.artifacts || [],
180
+ metrics: {
181
+ elapsedMs: typeof result.metrics?.elapsed_ms === 'number' ? result.metrics.elapsed_ms : 0,
182
+ peakRssMb: 0,
183
+ },
184
+ };
185
+ }
186
+ if (job.tool === 'workflow.semantic_name_review') {
187
+ if (!this.cacheManager) {
188
+ throw new Error('workflow.semantic_name_review requires cache manager for queued execution');
189
+ }
190
+ this.jobQueue.updateProgress(job.id, 5);
191
+ const handler = createSemanticNameReviewWorkflowHandler(this.workspaceManager, this.database, this.cacheManager);
192
+ const result = await handler(job.args || {});
193
+ this.jobQueue.updateProgress(job.id, 100);
194
+ return {
195
+ jobId: job.id,
196
+ ok: result.ok,
197
+ data: result.data,
198
+ errors: result.errors || [],
199
+ warnings: result.warnings || [],
200
+ artifacts: result.artifacts || [],
201
+ metrics: {
202
+ elapsedMs: typeof result.metrics?.elapsed_ms === 'number' ? result.metrics.elapsed_ms : 0,
203
+ peakRssMb: 0,
204
+ },
205
+ };
206
+ }
207
+ if (job.tool === 'workflow.function_explanation_review') {
208
+ if (!this.cacheManager) {
209
+ throw new Error('workflow.function_explanation_review requires cache manager for queued execution');
210
+ }
211
+ this.jobQueue.updateProgress(job.id, 5);
212
+ const handler = createFunctionExplanationReviewWorkflowHandler(this.workspaceManager, this.database, this.cacheManager);
213
+ const result = await handler(job.args || {});
214
+ this.jobQueue.updateProgress(job.id, 100);
215
+ return {
216
+ jobId: job.id,
217
+ ok: result.ok,
218
+ data: result.data,
219
+ errors: result.errors || [],
220
+ warnings: result.warnings || [],
221
+ artifacts: result.artifacts || [],
222
+ metrics: {
223
+ elapsedMs: typeof result.metrics?.elapsed_ms === 'number' ? result.metrics.elapsed_ms : 0,
224
+ peakRssMb: 0,
225
+ },
226
+ };
227
+ }
228
+ if (job.tool === 'workflow.module_reconstruction_review') {
229
+ if (!this.cacheManager) {
230
+ throw new Error('workflow.module_reconstruction_review requires cache manager for queued execution');
231
+ }
232
+ this.jobQueue.updateProgress(job.id, 5);
233
+ const handler = createModuleReconstructionReviewWorkflowHandler(this.workspaceManager, this.database, this.cacheManager);
234
+ const result = await handler(job.args || {});
235
+ this.jobQueue.updateProgress(job.id, 100);
236
+ return {
237
+ jobId: job.id,
238
+ ok: result.ok,
239
+ data: result.data,
240
+ errors: result.errors || [],
241
+ warnings: result.warnings || [],
242
+ artifacts: result.artifacts || [],
243
+ metrics: {
244
+ elapsedMs: typeof result.metrics?.elapsed_ms === 'number' ? result.metrics.elapsed_ms : 0,
245
+ peakRssMb: 0,
246
+ },
247
+ };
248
+ }
157
249
  throw new Error(`Unsupported queued tool: ${job.tool}`);
158
250
  }
159
251
  }