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
@@ -0,0 +1,291 @@
1
+ import { z } from 'zod';
2
+ import { createCodeFunctionsSmartRecoverHandler } from '../tools/code-functions-smart-recover.js';
3
+ import { createPESymbolsRecoverHandler } from '../tools/pe-symbols-recover.js';
4
+ import { createCodeFunctionsDefineHandler } from '../tools/code-functions-define.js';
5
+ import { DecompilerWorker } from '../decompiler-worker.js';
6
+ const TOOL_NAME = 'workflow.function_index_recover';
7
+ export const FunctionIndexRecoverWorkflowInputSchema = z.object({
8
+ sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
9
+ define_from: z
10
+ .enum(['auto', 'smart_recover', 'symbols_recover'])
11
+ .default('auto')
12
+ .describe('Which recovered source should be materialized into the function index'),
13
+ max_string_hints: z
14
+ .number()
15
+ .int()
16
+ .min(20)
17
+ .max(400)
18
+ .default(120)
19
+ .describe('Maximum strings inspected when pe.symbols.recover derives recovered names'),
20
+ replace_all: z
21
+ .boolean()
22
+ .default(true)
23
+ .describe('Replace the existing function index before importing recovered boundaries'),
24
+ persist_artifact: z
25
+ .boolean()
26
+ .default(true)
27
+ .describe('Persist the materialized function-definition artifact'),
28
+ register_analysis: z
29
+ .boolean()
30
+ .default(true)
31
+ .describe('Insert a completed function_definition analysis row for the imported index'),
32
+ session_tag: z
33
+ .string()
34
+ .optional()
35
+ .describe('Optional session tag used when persisting recovered function-definition artifacts'),
36
+ include_rank_preview: z
37
+ .boolean()
38
+ .default(true)
39
+ .describe('Return a ranked preview after the recovered function index has been materialized'),
40
+ rank_topk: z
41
+ .number()
42
+ .int()
43
+ .min(1)
44
+ .max(40)
45
+ .default(12)
46
+ .describe('Number of ranked functions returned when include_rank_preview=true'),
47
+ force_refresh: z
48
+ .boolean()
49
+ .default(false)
50
+ .describe('Bypass cache in smart_recover and symbols_recover'),
51
+ });
52
+ const RankPreviewSchema = z.object({
53
+ address: z.string(),
54
+ name: z.string().nullable().optional(),
55
+ score: z.number().nullable().optional(),
56
+ tags: z.array(z.string()).optional(),
57
+ summary: z.string().nullable().optional(),
58
+ });
59
+ export const FunctionIndexRecoverWorkflowOutputSchema = z.object({
60
+ ok: z.boolean(),
61
+ data: z
62
+ .object({
63
+ sample_id: z.string(),
64
+ define_from: z.enum(['smart_recover', 'symbols_recover']),
65
+ recovered_function_count: z.number().int().nonnegative(),
66
+ recovered_symbol_count: z.number().int().nonnegative(),
67
+ imported_count: z.number().int().nonnegative(),
68
+ function_index_status: z.enum(['ready']),
69
+ decompile_status: z.enum(['missing']),
70
+ cfg_status: z.enum(['missing']),
71
+ recovery_strategy: z.array(z.string()),
72
+ imported_artifact: z
73
+ .object({
74
+ id: z.string(),
75
+ type: z.string(),
76
+ path: z.string(),
77
+ sha256: z.string(),
78
+ mime: z.string().optional(),
79
+ })
80
+ .optional(),
81
+ analysis_id: z.string().optional(),
82
+ imported_function_preview: z.array(z.object({
83
+ address: z.string(),
84
+ rva: z.number().nullable(),
85
+ size: z.number().nullable(),
86
+ name: z.string(),
87
+ is_entry_point: z.boolean(),
88
+ is_exported: z.boolean(),
89
+ })),
90
+ recovered_symbol_preview: z.array(z.object({
91
+ address: z.string(),
92
+ recovered_name: z.string(),
93
+ name_strategy: z.string(),
94
+ confidence: z.number(),
95
+ })),
96
+ rank_preview: z.array(RankPreviewSchema).optional(),
97
+ next_steps: z.array(z.string()),
98
+ })
99
+ .optional(),
100
+ warnings: z.array(z.string()).optional(),
101
+ errors: z.array(z.string()).optional(),
102
+ artifacts: z.array(z.any()).optional(),
103
+ metrics: z
104
+ .object({
105
+ elapsed_ms: z.number(),
106
+ tool: z.string(),
107
+ })
108
+ .optional(),
109
+ });
110
+ export const functionIndexRecoverWorkflowToolDefinition = {
111
+ name: TOOL_NAME,
112
+ description: 'Recover a non-Ghidra function index by chaining code.functions.smart_recover, pe.symbols.recover, and code.functions.define, then optionally return a ranked preview.',
113
+ inputSchema: FunctionIndexRecoverWorkflowInputSchema,
114
+ outputSchema: FunctionIndexRecoverWorkflowOutputSchema,
115
+ };
116
+ function normalizeRankPreview(items) {
117
+ return items.map((item) => ({
118
+ address: String(item.address),
119
+ name: item.name ? String(item.name) : null,
120
+ score: typeof item.score === 'number' ? item.score : null,
121
+ tags: Array.isArray(item.tags)
122
+ ? item.tags.map((entry) => String(entry))
123
+ : undefined,
124
+ summary: item.summary ? String(item.summary) : null,
125
+ }));
126
+ }
127
+ export function createFunctionIndexRecoverWorkflowHandler(workspaceManager, database, cacheManager, dependencies = {}) {
128
+ const smartRecoverHandler = dependencies.smartRecoverHandler ||
129
+ createCodeFunctionsSmartRecoverHandler(workspaceManager, database, cacheManager);
130
+ const symbolsRecoverHandler = dependencies.symbolsRecoverHandler ||
131
+ createPESymbolsRecoverHandler(workspaceManager, database, cacheManager);
132
+ const defineHandler = dependencies.defineHandler || createCodeFunctionsDefineHandler(workspaceManager, database);
133
+ return async (args) => {
134
+ const startTime = Date.now();
135
+ try {
136
+ const input = FunctionIndexRecoverWorkflowInputSchema.parse(args);
137
+ const sample = database.findSample(input.sample_id);
138
+ if (!sample) {
139
+ return {
140
+ ok: false,
141
+ errors: [`Sample not found: ${input.sample_id}`],
142
+ metrics: {
143
+ elapsed_ms: Date.now() - startTime,
144
+ tool: TOOL_NAME,
145
+ },
146
+ };
147
+ }
148
+ const warnings = [];
149
+ const [smartRecoverResult, symbolsRecoverResult] = await Promise.all([
150
+ smartRecoverHandler({
151
+ sample_id: input.sample_id,
152
+ force_refresh: input.force_refresh,
153
+ }),
154
+ symbolsRecoverHandler({
155
+ sample_id: input.sample_id,
156
+ max_string_hints: input.max_string_hints,
157
+ force_refresh: input.force_refresh,
158
+ }),
159
+ ]);
160
+ if (!smartRecoverResult.ok || !smartRecoverResult.data) {
161
+ return {
162
+ ok: false,
163
+ errors: [
164
+ `code.functions.smart_recover failed: ${(smartRecoverResult.errors || ['unknown error']).join('; ')}`,
165
+ ],
166
+ warnings: [
167
+ ...(smartRecoverResult.warnings || []),
168
+ ...(symbolsRecoverResult.warnings || []),
169
+ ],
170
+ metrics: {
171
+ elapsed_ms: Date.now() - startTime,
172
+ tool: TOOL_NAME,
173
+ },
174
+ };
175
+ }
176
+ const smartRecoverData = smartRecoverResult.data;
177
+ const symbolsRecoverData = symbolsRecoverResult.ok && symbolsRecoverResult.data
178
+ ? symbolsRecoverResult.data
179
+ : undefined;
180
+ if (!symbolsRecoverResult.ok) {
181
+ warnings.push(`pe.symbols.recover unavailable: ${(symbolsRecoverResult.errors || ['unknown error']).join('; ')}`);
182
+ }
183
+ warnings.push(...(smartRecoverResult.warnings || []));
184
+ warnings.push(...(symbolsRecoverResult.warnings || []));
185
+ const symbolByAddress = new Map((symbolsRecoverData?.symbols || []).map((item) => [item.address.toLowerCase(), item]));
186
+ const symbolByRva = new Map((symbolsRecoverData?.symbols || []).map((item) => [item.rva, item]));
187
+ const defineFrom = input.define_from === 'auto'
188
+ ? symbolsRecoverData && symbolsRecoverData.count > 0
189
+ ? 'symbols_recover'
190
+ : 'smart_recover'
191
+ : input.define_from;
192
+ const definitions = smartRecoverData.functions.map((item) => {
193
+ const symbol = symbolByAddress.get(item.address.toLowerCase()) ||
194
+ symbolByRva.get(item.rva);
195
+ const useRecoveredName = defineFrom === 'symbols_recover' && symbol;
196
+ return {
197
+ address: item.address,
198
+ rva: item.rva,
199
+ size: item.size,
200
+ name: useRecoveredName ? symbol.recovered_name : item.name,
201
+ recovered_name: symbol?.recovered_name,
202
+ is_entry_point: item.is_entry_point,
203
+ is_exported: item.is_exported,
204
+ evidence: Array.from(new Set([...(item.evidence || []), ...(symbol?.evidence || [])])),
205
+ tags: Array.from(new Set([
206
+ `recovery:${item.name}`,
207
+ ...(symbol ? [`symbol_strategy:${symbol.name_strategy}`] : []),
208
+ useRecoveredName ? 'name_source:recovered_symbol' : 'name_source:smart_recover',
209
+ ])),
210
+ };
211
+ });
212
+ const defineResult = await defineHandler({
213
+ sample_id: input.sample_id,
214
+ definitions,
215
+ source: defineFrom,
216
+ replace_all: input.replace_all,
217
+ persist_artifact: input.persist_artifact,
218
+ register_analysis: input.register_analysis,
219
+ session_tag: input.session_tag,
220
+ });
221
+ if (!defineResult.ok || !defineResult.data) {
222
+ return {
223
+ ok: false,
224
+ errors: [
225
+ `code.functions.define failed: ${(defineResult.errors || ['unknown error']).join('; ')}`,
226
+ ],
227
+ warnings: warnings.length > 0 ? warnings : undefined,
228
+ metrics: {
229
+ elapsed_ms: Date.now() - startTime,
230
+ tool: TOOL_NAME,
231
+ },
232
+ };
233
+ }
234
+ const defineData = defineResult.data;
235
+ let rankPreview;
236
+ if (input.include_rank_preview) {
237
+ const decompilerWorker = new DecompilerWorker(database, workspaceManager);
238
+ const ranked = await decompilerWorker.rankFunctions(input.sample_id, input.rank_topk);
239
+ rankPreview = normalizeRankPreview(ranked);
240
+ }
241
+ return {
242
+ ok: true,
243
+ data: {
244
+ sample_id: input.sample_id,
245
+ define_from: defineFrom,
246
+ recovered_function_count: smartRecoverData.count,
247
+ recovered_symbol_count: symbolsRecoverData?.count || 0,
248
+ imported_count: defineData.imported_count,
249
+ function_index_status: defineData.function_index_status,
250
+ decompile_status: defineData.decompile_status,
251
+ cfg_status: defineData.cfg_status,
252
+ recovery_strategy: smartRecoverData.strategy,
253
+ imported_artifact: defineData.artifact,
254
+ analysis_id: defineData.analysis_id,
255
+ imported_function_preview: defineData.imported_functions.slice(0, input.rank_topk),
256
+ recovered_symbol_preview: (symbolsRecoverData?.symbols || [])
257
+ .slice(0, input.rank_topk)
258
+ .map((item) => ({
259
+ address: item.address,
260
+ recovered_name: item.recovered_name,
261
+ name_strategy: item.name_strategy,
262
+ confidence: item.confidence,
263
+ })),
264
+ rank_preview: rankPreview,
265
+ next_steps: Array.from(new Set([
266
+ ...defineData.next_steps,
267
+ 'Use code.functions.list / code.functions.rank to inspect the recovered index.',
268
+ 'Use code.functions.reconstruct or workflow.reconstruct after Ghidra decompile/CFG readiness improves.',
269
+ ])),
270
+ },
271
+ warnings: warnings.length > 0 ? warnings : undefined,
272
+ artifacts: defineResult.artifacts,
273
+ metrics: {
274
+ elapsed_ms: Date.now() - startTime,
275
+ tool: TOOL_NAME,
276
+ },
277
+ };
278
+ }
279
+ catch (error) {
280
+ return {
281
+ ok: false,
282
+ errors: [error instanceof Error ? error.message : String(error)],
283
+ metrics: {
284
+ elapsed_ms: Date.now() - startTime,
285
+ tool: TOOL_NAME,
286
+ },
287
+ };
288
+ }
289
+ };
290
+ }
291
+ //# sourceMappingURL=function-index-recover.js.map