windows-exe-decompiler-mcp-server 0.1.0

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 (190) hide show
  1. package/CODEX_INSTALLATION.md +69 -0
  2. package/COPILOT_INSTALLATION.md +77 -0
  3. package/LICENSE +21 -0
  4. package/README.md +314 -0
  5. package/bin/windows-exe-decompiler-mcp-server.js +3 -0
  6. package/dist/analysis-provenance.d.ts +184 -0
  7. package/dist/analysis-provenance.js +74 -0
  8. package/dist/analysis-task-runner.d.ts +31 -0
  9. package/dist/analysis-task-runner.js +160 -0
  10. package/dist/artifact-inventory.d.ts +23 -0
  11. package/dist/artifact-inventory.js +175 -0
  12. package/dist/cache-manager.d.ts +128 -0
  13. package/dist/cache-manager.js +454 -0
  14. package/dist/confidence-semantics.d.ts +66 -0
  15. package/dist/confidence-semantics.js +122 -0
  16. package/dist/config.d.ts +335 -0
  17. package/dist/config.js +193 -0
  18. package/dist/database.d.ts +227 -0
  19. package/dist/database.js +601 -0
  20. package/dist/decompiler-worker.d.ts +441 -0
  21. package/dist/decompiler-worker.js +1962 -0
  22. package/dist/dynamic-trace.d.ts +95 -0
  23. package/dist/dynamic-trace.js +629 -0
  24. package/dist/env-validator.d.ts +15 -0
  25. package/dist/env-validator.js +249 -0
  26. package/dist/error-handler.d.ts +28 -0
  27. package/dist/error-handler.example.d.ts +22 -0
  28. package/dist/error-handler.example.js +141 -0
  29. package/dist/error-handler.js +139 -0
  30. package/dist/ghidra-analysis-status.d.ts +49 -0
  31. package/dist/ghidra-analysis-status.js +178 -0
  32. package/dist/ghidra-config.d.ts +134 -0
  33. package/dist/ghidra-config.js +464 -0
  34. package/dist/index.d.ts +9 -0
  35. package/dist/index.js +200 -0
  36. package/dist/job-queue.d.ts +169 -0
  37. package/dist/job-queue.js +407 -0
  38. package/dist/logger.d.ts +106 -0
  39. package/dist/logger.js +176 -0
  40. package/dist/policy-guard.d.ts +115 -0
  41. package/dist/policy-guard.js +243 -0
  42. package/dist/process-output.d.ts +15 -0
  43. package/dist/process-output.js +90 -0
  44. package/dist/prompts/function-explanation-review.d.ts +5 -0
  45. package/dist/prompts/function-explanation-review.js +64 -0
  46. package/dist/prompts/semantic-name-review.d.ts +5 -0
  47. package/dist/prompts/semantic-name-review.js +63 -0
  48. package/dist/runtime-correlation.d.ts +34 -0
  49. package/dist/runtime-correlation.js +279 -0
  50. package/dist/runtime-paths.d.ts +3 -0
  51. package/dist/runtime-paths.js +11 -0
  52. package/dist/selection-diff.d.ts +667 -0
  53. package/dist/selection-diff.js +53 -0
  54. package/dist/semantic-name-suggestion-artifacts.d.ts +116 -0
  55. package/dist/semantic-name-suggestion-artifacts.js +314 -0
  56. package/dist/server.d.ts +129 -0
  57. package/dist/server.js +578 -0
  58. package/dist/tools/artifact-read.d.ts +235 -0
  59. package/dist/tools/artifact-read.js +317 -0
  60. package/dist/tools/artifacts-diff.d.ts +728 -0
  61. package/dist/tools/artifacts-diff.js +304 -0
  62. package/dist/tools/artifacts-list.d.ts +515 -0
  63. package/dist/tools/artifacts-list.js +389 -0
  64. package/dist/tools/attack-map.d.ts +290 -0
  65. package/dist/tools/attack-map.js +519 -0
  66. package/dist/tools/cache-observability.d.ts +4 -0
  67. package/dist/tools/cache-observability.js +36 -0
  68. package/dist/tools/code-function-cfg.d.ts +50 -0
  69. package/dist/tools/code-function-cfg.js +102 -0
  70. package/dist/tools/code-function-decompile.d.ts +55 -0
  71. package/dist/tools/code-function-decompile.js +103 -0
  72. package/dist/tools/code-function-disassemble.d.ts +43 -0
  73. package/dist/tools/code-function-disassemble.js +185 -0
  74. package/dist/tools/code-function-explain-apply.d.ts +255 -0
  75. package/dist/tools/code-function-explain-apply.js +225 -0
  76. package/dist/tools/code-function-explain-prepare.d.ts +535 -0
  77. package/dist/tools/code-function-explain-prepare.js +276 -0
  78. package/dist/tools/code-function-explain-review.d.ts +397 -0
  79. package/dist/tools/code-function-explain-review.js +589 -0
  80. package/dist/tools/code-function-rename-apply.d.ts +248 -0
  81. package/dist/tools/code-function-rename-apply.js +220 -0
  82. package/dist/tools/code-function-rename-prepare.d.ts +506 -0
  83. package/dist/tools/code-function-rename-prepare.js +279 -0
  84. package/dist/tools/code-function-rename-review.d.ts +574 -0
  85. package/dist/tools/code-function-rename-review.js +761 -0
  86. package/dist/tools/code-functions-list.d.ts +37 -0
  87. package/dist/tools/code-functions-list.js +91 -0
  88. package/dist/tools/code-functions-rank.d.ts +34 -0
  89. package/dist/tools/code-functions-rank.js +90 -0
  90. package/dist/tools/code-functions-reconstruct.d.ts +2725 -0
  91. package/dist/tools/code-functions-reconstruct.js +2807 -0
  92. package/dist/tools/code-functions-search.d.ts +39 -0
  93. package/dist/tools/code-functions-search.js +90 -0
  94. package/dist/tools/code-reconstruct-export.d.ts +1212 -0
  95. package/dist/tools/code-reconstruct-export.js +4002 -0
  96. package/dist/tools/code-reconstruct-plan.d.ts +274 -0
  97. package/dist/tools/code-reconstruct-plan.js +342 -0
  98. package/dist/tools/dotnet-metadata-extract.d.ts +541 -0
  99. package/dist/tools/dotnet-metadata-extract.js +355 -0
  100. package/dist/tools/dotnet-reconstruct-export.d.ts +567 -0
  101. package/dist/tools/dotnet-reconstruct-export.js +1151 -0
  102. package/dist/tools/dotnet-types-list.d.ts +325 -0
  103. package/dist/tools/dotnet-types-list.js +201 -0
  104. package/dist/tools/dynamic-dependencies.d.ts +115 -0
  105. package/dist/tools/dynamic-dependencies.js +213 -0
  106. package/dist/tools/dynamic-memory-import.d.ts +10 -0
  107. package/dist/tools/dynamic-memory-import.js +567 -0
  108. package/dist/tools/dynamic-trace-import.d.ts +10 -0
  109. package/dist/tools/dynamic-trace-import.js +235 -0
  110. package/dist/tools/entrypoint-fallback-disasm.d.ts +30 -0
  111. package/dist/tools/entrypoint-fallback-disasm.js +89 -0
  112. package/dist/tools/ghidra-analyze.d.ts +88 -0
  113. package/dist/tools/ghidra-analyze.js +208 -0
  114. package/dist/tools/ghidra-health.d.ts +37 -0
  115. package/dist/tools/ghidra-health.js +212 -0
  116. package/dist/tools/ioc-export.d.ts +209 -0
  117. package/dist/tools/ioc-export.js +542 -0
  118. package/dist/tools/packer-detect.d.ts +165 -0
  119. package/dist/tools/packer-detect.js +284 -0
  120. package/dist/tools/pe-exports-extract.d.ts +175 -0
  121. package/dist/tools/pe-exports-extract.js +253 -0
  122. package/dist/tools/pe-fingerprint.d.ts +234 -0
  123. package/dist/tools/pe-fingerprint.js +269 -0
  124. package/dist/tools/pe-imports-extract.d.ts +105 -0
  125. package/dist/tools/pe-imports-extract.js +245 -0
  126. package/dist/tools/report-generate.d.ts +157 -0
  127. package/dist/tools/report-generate.js +457 -0
  128. package/dist/tools/report-summarize.d.ts +2131 -0
  129. package/dist/tools/report-summarize.js +596 -0
  130. package/dist/tools/runtime-detect.d.ts +135 -0
  131. package/dist/tools/runtime-detect.js +247 -0
  132. package/dist/tools/sample-ingest.d.ts +94 -0
  133. package/dist/tools/sample-ingest.js +327 -0
  134. package/dist/tools/sample-profile-get.d.ts +183 -0
  135. package/dist/tools/sample-profile-get.js +121 -0
  136. package/dist/tools/sandbox-execute.d.ts +441 -0
  137. package/dist/tools/sandbox-execute.js +392 -0
  138. package/dist/tools/strings-extract.d.ts +375 -0
  139. package/dist/tools/strings-extract.js +314 -0
  140. package/dist/tools/strings-floss-decode.d.ts +143 -0
  141. package/dist/tools/strings-floss-decode.js +259 -0
  142. package/dist/tools/system-health.d.ts +434 -0
  143. package/dist/tools/system-health.js +446 -0
  144. package/dist/tools/task-cancel.d.ts +21 -0
  145. package/dist/tools/task-cancel.js +70 -0
  146. package/dist/tools/task-status.d.ts +27 -0
  147. package/dist/tools/task-status.js +106 -0
  148. package/dist/tools/task-sweep.d.ts +22 -0
  149. package/dist/tools/task-sweep.js +77 -0
  150. package/dist/tools/tool-help.d.ts +340 -0
  151. package/dist/tools/tool-help.js +261 -0
  152. package/dist/tools/yara-scan.d.ts +554 -0
  153. package/dist/tools/yara-scan.js +313 -0
  154. package/dist/types.d.ts +266 -0
  155. package/dist/types.js +41 -0
  156. package/dist/worker-pool.d.ts +204 -0
  157. package/dist/worker-pool.js +650 -0
  158. package/dist/workflows/deep-static.d.ts +104 -0
  159. package/dist/workflows/deep-static.js +276 -0
  160. package/dist/workflows/function-explanation-review.d.ts +655 -0
  161. package/dist/workflows/function-explanation-review.js +440 -0
  162. package/dist/workflows/reconstruct.d.ts +2053 -0
  163. package/dist/workflows/reconstruct.js +666 -0
  164. package/dist/workflows/semantic-name-review.d.ts +2418 -0
  165. package/dist/workflows/semantic-name-review.js +521 -0
  166. package/dist/workflows/triage.d.ts +659 -0
  167. package/dist/workflows/triage.js +1374 -0
  168. package/dist/workspace-manager.d.ts +150 -0
  169. package/dist/workspace-manager.js +411 -0
  170. package/ghidra_scripts/DecompileFunction.java +487 -0
  171. package/ghidra_scripts/DecompileFunction.py +150 -0
  172. package/ghidra_scripts/ExtractCFG.java +256 -0
  173. package/ghidra_scripts/ExtractCFG.py +233 -0
  174. package/ghidra_scripts/ExtractFunctions.java +442 -0
  175. package/ghidra_scripts/ExtractFunctions.py +101 -0
  176. package/ghidra_scripts/README.md +125 -0
  177. package/ghidra_scripts/SearchFunctionReferences.java +380 -0
  178. package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -0
  179. package/helpers/DotNetMetadataProbe/Program.cs +566 -0
  180. package/install-to-codex.ps1 +178 -0
  181. package/install-to-copilot.ps1 +303 -0
  182. package/package.json +101 -0
  183. package/requirements.txt +9 -0
  184. package/workers/requirements-dynamic.txt +11 -0
  185. package/workers/requirements.txt +8 -0
  186. package/workers/speakeasy_compat.py +175 -0
  187. package/workers/static_worker.py +5183 -0
  188. package/workers/yara_rules/default.yar +33 -0
  189. package/workers/yara_rules/malware_families.yar +93 -0
  190. package/workers/yara_rules/packers.yar +80 -0
@@ -0,0 +1,304 @@
1
+ import { z } from 'zod';
2
+ import { listArtifactInventory, normalizeRelativeArtifactPath } from '../artifact-inventory.js';
3
+ const TOOL_NAME = 'artifacts.diff';
4
+ const TOOL_VERSION = '0.1.0';
5
+ export const artifactsDiffInputSchema = z.object({
6
+ sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
7
+ left_session_tag: z
8
+ .string()
9
+ .min(1)
10
+ .describe('Base session tag such as reports/reconstruct/<session>'),
11
+ right_session_tag: z
12
+ .string()
13
+ .min(1)
14
+ .describe('Comparison session tag such as reports/reconstruct/<session>'),
15
+ artifact_type: z.string().optional().describe('Optional artifact type filter'),
16
+ artifact_types: z
17
+ .array(z.string())
18
+ .optional()
19
+ .describe('Optional artifact type filter list (union with artifact_type)'),
20
+ path_prefix: z
21
+ .string()
22
+ .optional()
23
+ .describe('Optional relative path prefix filter applied to both sessions before diffing'),
24
+ include_untracked_files: z
25
+ .boolean()
26
+ .optional()
27
+ .default(true)
28
+ .describe('Include untracked export files while diffing session contents'),
29
+ recursive: z
30
+ .boolean()
31
+ .optional()
32
+ .default(true)
33
+ .describe('Recursively scan export roots for untracked files'),
34
+ scan_roots: z
35
+ .array(z.string())
36
+ .optional()
37
+ .default(['reports', 'ghidra', 'dotnet'])
38
+ .describe('Workspace subdirectories to scan for untracked export files'),
39
+ match_by: z
40
+ .enum(['type_path', 'path', 'type'])
41
+ .default('type_path')
42
+ .describe('Keying strategy used to align artifacts across sessions'),
43
+ latest_per_key: z
44
+ .boolean()
45
+ .optional()
46
+ .default(true)
47
+ .describe('Keep only the newest artifact per comparison key inside each session before diffing'),
48
+ });
49
+ const ArtifactSnapshotSchema = z.object({
50
+ id: z.string(),
51
+ type: z.string(),
52
+ path: z.string(),
53
+ sha256: z.string(),
54
+ created_at: z.string(),
55
+ exists: z.boolean(),
56
+ tracked: z.boolean(),
57
+ size_bytes: z.number().nullable(),
58
+ modified_at: z.string().nullable(),
59
+ retention_bucket: z.enum(['active', 'recent', 'archive']),
60
+ age_days: z.number().int().nonnegative(),
61
+ });
62
+ const ArtifactChangeSchema = z.object({
63
+ key: z.string(),
64
+ differences: z.array(z.string()),
65
+ left: ArtifactSnapshotSchema,
66
+ right: ArtifactSnapshotSchema,
67
+ });
68
+ export const artifactsDiffOutputSchema = z.object({
69
+ ok: z.boolean(),
70
+ data: z
71
+ .object({
72
+ sample_id: z.string(),
73
+ left_session_tag: z.string(),
74
+ right_session_tag: z.string(),
75
+ artifact_type: z.string().nullable(),
76
+ artifact_types: z.array(z.string()).nullable(),
77
+ path_prefix: z.string().nullable(),
78
+ match_by: z.enum(['type_path', 'path', 'type']),
79
+ latest_per_key: z.boolean(),
80
+ tool_version: z.string(),
81
+ left_count: z.number().int().nonnegative(),
82
+ right_count: z.number().int().nonnegative(),
83
+ added: z.array(z.object({ key: z.string(), artifact: ArtifactSnapshotSchema })),
84
+ removed: z.array(z.object({ key: z.string(), artifact: ArtifactSnapshotSchema })),
85
+ changed: z.array(ArtifactChangeSchema),
86
+ unchanged_count: z.number().int().nonnegative(),
87
+ summary: z.object({
88
+ added_count: z.number().int().nonnegative(),
89
+ removed_count: z.number().int().nonnegative(),
90
+ changed_count: z.number().int().nonnegative(),
91
+ unchanged_count: z.number().int().nonnegative(),
92
+ changed_fields: z.record(z.number().int().nonnegative()),
93
+ left_types: z.array(z.string()),
94
+ right_types: z.array(z.string()),
95
+ }),
96
+ })
97
+ .optional(),
98
+ warnings: z.array(z.string()).optional(),
99
+ errors: z.array(z.string()).optional(),
100
+ metrics: z
101
+ .object({
102
+ elapsed_ms: z.number(),
103
+ tool: z.string(),
104
+ })
105
+ .optional(),
106
+ });
107
+ export const artifactsDiffToolDefinition = {
108
+ name: TOOL_NAME,
109
+ description: 'Compare artifact inventory between two sessions for one sample, including tracked and optional untracked files.',
110
+ inputSchema: artifactsDiffInputSchema,
111
+ outputSchema: artifactsDiffOutputSchema,
112
+ };
113
+ function toTimestamp(value) {
114
+ if (!value) {
115
+ return 0;
116
+ }
117
+ const parsed = new Date(value).getTime();
118
+ return Number.isFinite(parsed) ? parsed : 0;
119
+ }
120
+ function makeKey(item, matchBy) {
121
+ const normalizedPath = normalizeRelativeArtifactPath(item.path).toLowerCase();
122
+ if (matchBy === 'path') {
123
+ return normalizedPath;
124
+ }
125
+ if (matchBy === 'type') {
126
+ return item.type;
127
+ }
128
+ return `${item.type}::${normalizedPath}`;
129
+ }
130
+ function simplifyArtifact(item) {
131
+ return {
132
+ id: item.id,
133
+ type: item.type,
134
+ path: item.path,
135
+ sha256: item.sha256,
136
+ created_at: item.created_at,
137
+ exists: item.exists,
138
+ tracked: item.tracked,
139
+ size_bytes: item.size_bytes,
140
+ modified_at: item.modified_at,
141
+ retention_bucket: item.retention_bucket,
142
+ age_days: item.age_days,
143
+ };
144
+ }
145
+ function selectArtifactsForSession(artifacts, sessionTag, pathPrefix, matchBy = 'type_path', latestPerKey = true) {
146
+ let filtered = artifacts.filter((item) => item.session_tag === sessionTag);
147
+ if (pathPrefix) {
148
+ const normalizedPrefix = normalizeRelativeArtifactPath(pathPrefix).toLowerCase();
149
+ filtered = filtered.filter((item) => normalizeRelativeArtifactPath(item.path).toLowerCase().startsWith(normalizedPrefix));
150
+ }
151
+ const selected = new Map();
152
+ for (const item of filtered) {
153
+ const simplified = simplifyArtifact(item);
154
+ const key = makeKey(simplified, matchBy);
155
+ if (!latestPerKey) {
156
+ if (!selected.has(key)) {
157
+ selected.set(key, simplified);
158
+ }
159
+ continue;
160
+ }
161
+ const existing = selected.get(key);
162
+ if (!existing || toTimestamp(simplified.created_at) > toTimestamp(existing.created_at)) {
163
+ selected.set(key, simplified);
164
+ }
165
+ }
166
+ return selected;
167
+ }
168
+ function collectDifferences(left, right) {
169
+ const differences = [];
170
+ const fields = [
171
+ 'type',
172
+ 'path',
173
+ 'sha256',
174
+ 'exists',
175
+ 'tracked',
176
+ 'size_bytes',
177
+ 'modified_at',
178
+ 'retention_bucket',
179
+ 'created_at',
180
+ ];
181
+ for (const field of fields) {
182
+ if (left[field] !== right[field]) {
183
+ differences.push(field);
184
+ }
185
+ }
186
+ return differences;
187
+ }
188
+ export function createArtifactsDiffHandler(workspaceManager, database) {
189
+ return async (args) => {
190
+ const startTime = Date.now();
191
+ try {
192
+ const input = artifactsDiffInputSchema.parse(args);
193
+ const sample = database.findSample(input.sample_id);
194
+ if (!sample) {
195
+ return {
196
+ ok: false,
197
+ errors: [`Sample not found: ${input.sample_id}`],
198
+ metrics: {
199
+ elapsed_ms: Date.now() - startTime,
200
+ tool: TOOL_NAME,
201
+ },
202
+ };
203
+ }
204
+ const typeFilter = new Set();
205
+ if (input.artifact_type) {
206
+ typeFilter.add(input.artifact_type);
207
+ }
208
+ for (const item of input.artifact_types || []) {
209
+ typeFilter.add(item);
210
+ }
211
+ const inventory = await listArtifactInventory(workspaceManager, database, input.sample_id, {
212
+ artifactTypes: typeFilter,
213
+ includeMissing: true,
214
+ includeUntrackedFiles: input.include_untracked_files,
215
+ recursive: input.recursive,
216
+ scanRoots: input.scan_roots,
217
+ });
218
+ const leftItems = selectArtifactsForSession(inventory, input.left_session_tag, input.path_prefix, input.match_by, input.latest_per_key);
219
+ const rightItems = selectArtifactsForSession(inventory, input.right_session_tag, input.path_prefix, input.match_by, input.latest_per_key);
220
+ const allKeys = new Set([...leftItems.keys(), ...rightItems.keys()]);
221
+ const added = [];
222
+ const removed = [];
223
+ const changed = [];
224
+ let unchangedCount = 0;
225
+ const changedFields = {};
226
+ for (const key of Array.from(allKeys).sort()) {
227
+ const left = leftItems.get(key);
228
+ const right = rightItems.get(key);
229
+ if (!left && right) {
230
+ added.push({ key, artifact: right });
231
+ continue;
232
+ }
233
+ if (left && !right) {
234
+ removed.push({ key, artifact: left });
235
+ continue;
236
+ }
237
+ if (!left || !right) {
238
+ continue;
239
+ }
240
+ const differences = collectDifferences(left, right);
241
+ if (differences.length === 0) {
242
+ unchangedCount += 1;
243
+ continue;
244
+ }
245
+ for (const field of differences) {
246
+ changedFields[field] = (changedFields[field] || 0) + 1;
247
+ }
248
+ changed.push({ key, differences, left, right });
249
+ }
250
+ const warnings = [];
251
+ if (leftItems.size === 0) {
252
+ warnings.push(`No artifacts matched left_session_tag=${input.left_session_tag}.`);
253
+ }
254
+ if (rightItems.size === 0) {
255
+ warnings.push(`No artifacts matched right_session_tag=${input.right_session_tag}.`);
256
+ }
257
+ return {
258
+ ok: true,
259
+ data: {
260
+ sample_id: input.sample_id,
261
+ left_session_tag: input.left_session_tag,
262
+ right_session_tag: input.right_session_tag,
263
+ artifact_type: input.artifact_type || null,
264
+ artifact_types: typeFilter.size > 0 ? Array.from(typeFilter) : null,
265
+ path_prefix: input.path_prefix || null,
266
+ match_by: input.match_by,
267
+ latest_per_key: input.latest_per_key,
268
+ tool_version: TOOL_VERSION,
269
+ left_count: leftItems.size,
270
+ right_count: rightItems.size,
271
+ added,
272
+ removed,
273
+ changed,
274
+ unchanged_count: unchangedCount,
275
+ summary: {
276
+ added_count: added.length,
277
+ removed_count: removed.length,
278
+ changed_count: changed.length,
279
+ unchanged_count: unchangedCount,
280
+ changed_fields: changedFields,
281
+ left_types: Array.from(new Set(Array.from(leftItems.values()).map((item) => item.type))).sort(),
282
+ right_types: Array.from(new Set(Array.from(rightItems.values()).map((item) => item.type))).sort(),
283
+ },
284
+ },
285
+ warnings: warnings.length > 0 ? warnings : undefined,
286
+ metrics: {
287
+ elapsed_ms: Date.now() - startTime,
288
+ tool: TOOL_NAME,
289
+ },
290
+ };
291
+ }
292
+ catch (error) {
293
+ return {
294
+ ok: false,
295
+ errors: [error instanceof Error ? error.message : String(error)],
296
+ metrics: {
297
+ elapsed_ms: Date.now() - startTime,
298
+ tool: TOOL_NAME,
299
+ },
300
+ };
301
+ }
302
+ };
303
+ }
304
+ //# sourceMappingURL=artifacts-diff.js.map