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,575 @@
1
+ import path from 'path';
2
+ import { z } from 'zod';
3
+ import { generateCacheKey } from '../cache-manager.js';
4
+ import { lookupCachedResult, formatCacheWarning } from './cache-observability.js';
5
+ import { createPEExportsExtractHandler } from './pe-exports-extract.js';
6
+ import { createPEImportsExtractHandler } from './pe-imports-extract.js';
7
+ import { createStringsExtractHandler } from './strings-extract.js';
8
+ import { createRuntimeDetectHandler } from './runtime-detect.js';
9
+ import { createPackerDetectHandler } from './packer-detect.js';
10
+ import { inspectSampleWorkspace, formatMissingOriginalError, resolvePrimarySamplePath, } from '../sample-workspace.js';
11
+ const TOOL_NAME = 'binary.role.profile';
12
+ const TOOL_VERSION = '0.2.0';
13
+ const CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
14
+ export const BinaryRoleProfileInputSchema = z.object({
15
+ sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
16
+ max_exports: z
17
+ .number()
18
+ .int()
19
+ .min(1)
20
+ .max(32)
21
+ .default(12)
22
+ .describe('Maximum notable exports returned in the summarized export surface'),
23
+ max_strings: z
24
+ .number()
25
+ .int()
26
+ .min(20)
27
+ .max(400)
28
+ .default(120)
29
+ .describe('Maximum strings inspected for COM/service/plugin role heuristics'),
30
+ force_refresh: z
31
+ .boolean()
32
+ .default(false)
33
+ .describe('Bypass cache lookup and recompute from source sample'),
34
+ });
35
+ export const ExportSurfaceSchema = z.object({
36
+ total_exports: z.number().int().nonnegative(),
37
+ total_forwarders: z.number().int().nonnegative(),
38
+ notable_exports: z.array(z.string()),
39
+ com_related_exports: z.array(z.string()),
40
+ service_related_exports: z.array(z.string()),
41
+ plugin_related_exports: z.array(z.string()),
42
+ forwarded_exports: z.array(z.string()),
43
+ });
44
+ export const ImportSurfaceSchema = z.object({
45
+ dll_count: z.number().int().nonnegative(),
46
+ notable_dlls: z.array(z.string()),
47
+ com_related_imports: z.array(z.string()),
48
+ service_related_imports: z.array(z.string()),
49
+ network_related_imports: z.array(z.string()),
50
+ process_related_imports: z.array(z.string()),
51
+ });
52
+ export const RoleIndicatorSchema = z.object({
53
+ likely: z.boolean(),
54
+ confidence: z.number().min(0).max(1),
55
+ evidence: z.array(z.string()),
56
+ });
57
+ export const ExportDispatchProfileSchema = z.object({
58
+ command_like_exports: z.array(z.string()),
59
+ callback_like_exports: z.array(z.string()),
60
+ registration_exports: z.array(z.string()),
61
+ ordinal_only_exports: z.number().int().nonnegative(),
62
+ likely_dispatch_model: z.string(),
63
+ confidence: z.number().min(0).max(1),
64
+ });
65
+ export const ComProfileSchema = z.object({
66
+ clsid_strings: z.array(z.string()),
67
+ progid_strings: z.array(z.string()),
68
+ interface_hints: z.array(z.string()),
69
+ registration_strings: z.array(z.string()),
70
+ class_factory_exports: z.array(z.string()),
71
+ class_factory_surface: z.array(z.string()).default([]),
72
+ confidence: z.number().min(0).max(1),
73
+ });
74
+ export const HostInteractionProfileSchema = z.object({
75
+ likely_hosted: z.boolean(),
76
+ host_hints: z.array(z.string()),
77
+ callback_exports: z.array(z.string()),
78
+ callback_surface: z.array(z.string()).default([]),
79
+ callback_strings: z.array(z.string()),
80
+ service_hooks: z.array(z.string()),
81
+ confidence: z.number().min(0).max(1),
82
+ });
83
+ export const BinaryRoleProfileDataSchema = z.object({
84
+ sample_id: z.string(),
85
+ original_filename: z.string().nullable(),
86
+ binary_role: z.string(),
87
+ role_confidence: z.number().min(0).max(1),
88
+ runtime_hint: z.object({
89
+ is_dotnet: z.boolean().nullable(),
90
+ dotnet_version: z.string().nullable(),
91
+ target_framework: z.string().nullable(),
92
+ primary_runtime: z.string().nullable(),
93
+ }),
94
+ export_surface: ExportSurfaceSchema,
95
+ import_surface: ImportSurfaceSchema,
96
+ packed: z.boolean(),
97
+ packing_confidence: z.number().min(0).max(1),
98
+ indicators: z.object({
99
+ com_server: RoleIndicatorSchema,
100
+ service_binary: RoleIndicatorSchema,
101
+ plugin_binary: RoleIndicatorSchema,
102
+ driver_binary: RoleIndicatorSchema,
103
+ }),
104
+ export_dispatch_profile: ExportDispatchProfileSchema,
105
+ lifecycle_surface: z.array(z.string()).default([]),
106
+ com_profile: ComProfileSchema,
107
+ host_interaction_profile: HostInteractionProfileSchema,
108
+ analysis_priorities: z.array(z.string()),
109
+ strings_considered: z.number().int().nonnegative(),
110
+ });
111
+ export const BinaryRoleProfileOutputSchema = z.object({
112
+ ok: z.boolean(),
113
+ data: BinaryRoleProfileDataSchema.optional(),
114
+ warnings: z.array(z.string()).optional(),
115
+ errors: z.array(z.string()).optional(),
116
+ metrics: z
117
+ .object({
118
+ elapsed_ms: z.number(),
119
+ tool: z.string(),
120
+ cached: z.boolean().optional(),
121
+ cache_key: z.string().optional(),
122
+ cache_tier: z.string().optional(),
123
+ cache_created_at: z.string().optional(),
124
+ cache_expires_at: z.string().optional(),
125
+ cache_hit_at: z.string().optional(),
126
+ })
127
+ .optional(),
128
+ });
129
+ export const binaryRoleProfileToolDefinition = {
130
+ name: TOOL_NAME,
131
+ description: 'Summarize Windows PE role, export surface, DLL/COM/service/plugin indicators, and analysis priorities for EXE/DLL-like samples.',
132
+ inputSchema: BinaryRoleProfileInputSchema,
133
+ outputSchema: BinaryRoleProfileOutputSchema,
134
+ };
135
+ function clamp(value, min = 0, max = 1) {
136
+ if (Number.isNaN(value)) {
137
+ return min;
138
+ }
139
+ return Math.min(max, Math.max(min, value));
140
+ }
141
+ function uniqueStrings(values) {
142
+ const seen = new Set();
143
+ const output = [];
144
+ for (const value of values) {
145
+ const trimmed = (value || '').trim();
146
+ if (!trimmed) {
147
+ continue;
148
+ }
149
+ if (seen.has(trimmed)) {
150
+ continue;
151
+ }
152
+ seen.add(trimmed);
153
+ output.push(trimmed);
154
+ }
155
+ return output;
156
+ }
157
+ async function getOriginalFilename(workspaceManager, sampleId) {
158
+ const { samplePath: primarySamplePath } = await resolvePrimarySamplePath(workspaceManager, sampleId);
159
+ if (!primarySamplePath) {
160
+ return null;
161
+ }
162
+ return path.basename(primarySamplePath);
163
+ }
164
+ function inferBinaryRole(originalFilename, sampleFileType, exportCount, importsData, runtimeData) {
165
+ const loweredName = (originalFilename || '').toLowerCase();
166
+ const loweredType = (sampleFileType || '').toLowerCase();
167
+ const importDlls = Object.keys(importsData?.imports || {}).map((item) => item.toLowerCase());
168
+ const evidence = [];
169
+ if (loweredName.endsWith('.sys') ||
170
+ loweredType.includes('driver') ||
171
+ importDlls.some((item) => item.includes('ntoskrnl') || item.includes('fltmgr'))) {
172
+ evidence.push('driver filename/type/import pattern');
173
+ return { binaryRole: 'driver', roleConfidence: 0.96, roleEvidence: evidence };
174
+ }
175
+ if (runtimeData?.is_dotnet) {
176
+ evidence.push('runtime.detect is_dotnet=true');
177
+ if (loweredName.endsWith('.dll') || loweredType.includes('dll')) {
178
+ evidence.push('dll filename/type');
179
+ return { binaryRole: '.net_library', roleConfidence: 0.95, roleEvidence: evidence };
180
+ }
181
+ return { binaryRole: '.net_executable', roleConfidence: 0.94, roleEvidence: evidence };
182
+ }
183
+ if (loweredName.endsWith('.dll') ||
184
+ loweredName.endsWith('.ocx') ||
185
+ loweredName.endsWith('.cpl') ||
186
+ loweredType.includes('dll')) {
187
+ evidence.push('dll-like filename/type');
188
+ return { binaryRole: 'dll', roleConfidence: exportCount > 0 ? 0.92 : 0.84, roleEvidence: evidence };
189
+ }
190
+ if (loweredName.endsWith('.exe') || loweredType.includes('exe') || loweredType.includes('pe32')) {
191
+ evidence.push('executable filename/type');
192
+ return {
193
+ binaryRole: exportCount > 0 ? 'executable_with_exports' : 'executable',
194
+ roleConfidence: exportCount > 0 ? 0.8 : 0.88,
195
+ roleEvidence: evidence,
196
+ };
197
+ }
198
+ if (exportCount > 0) {
199
+ evidence.push('exports present without clear filename/type');
200
+ return { binaryRole: 'library_like_pe', roleConfidence: 0.73, roleEvidence: evidence };
201
+ }
202
+ return { binaryRole: 'pe_image', roleConfidence: 0.62, roleEvidence: ['generic PE image'] };
203
+ }
204
+ function buildRoleIndicator(confidence, evidence) {
205
+ return {
206
+ likely: confidence >= 0.55,
207
+ confidence: clamp(confidence),
208
+ evidence: uniqueStrings(evidence),
209
+ };
210
+ }
211
+ function flattenImportFunctions(importsData) {
212
+ return uniqueStrings(Object.values(importsData?.imports || {})
213
+ .flatMap((items) => items || [])
214
+ .map((item) => item.trim()));
215
+ }
216
+ export function createBinaryRoleProfileHandler(workspaceManager, database, cacheManager, dependencies) {
217
+ const exportsHandler = dependencies?.exportsHandler ||
218
+ createPEExportsExtractHandler(workspaceManager, database, cacheManager);
219
+ const importsHandler = dependencies?.importsHandler ||
220
+ createPEImportsExtractHandler(workspaceManager, database, cacheManager);
221
+ const stringsHandler = dependencies?.stringsHandler ||
222
+ createStringsExtractHandler(workspaceManager, database, cacheManager);
223
+ const runtimeHandler = dependencies?.runtimeHandler ||
224
+ createRuntimeDetectHandler(workspaceManager, database, cacheManager);
225
+ const packerHandler = dependencies?.packerHandler ||
226
+ createPackerDetectHandler(workspaceManager, database, cacheManager);
227
+ return async (args) => {
228
+ const input = BinaryRoleProfileInputSchema.parse(args);
229
+ const startTime = Date.now();
230
+ try {
231
+ const sample = database.findSample(input.sample_id);
232
+ if (!sample) {
233
+ return {
234
+ ok: false,
235
+ errors: [`Sample not found: ${input.sample_id}`],
236
+ metrics: {
237
+ elapsed_ms: Date.now() - startTime,
238
+ tool: TOOL_NAME,
239
+ },
240
+ };
241
+ }
242
+ const originalFilename = await getOriginalFilename(workspaceManager, input.sample_id);
243
+ if (!originalFilename) {
244
+ const integrity = await inspectSampleWorkspace(workspaceManager, input.sample_id);
245
+ return {
246
+ ok: false,
247
+ errors: [formatMissingOriginalError(input.sample_id, integrity)],
248
+ metrics: {
249
+ elapsed_ms: Date.now() - startTime,
250
+ tool: TOOL_NAME,
251
+ },
252
+ };
253
+ }
254
+ const cacheKey = generateCacheKey({
255
+ sampleSha256: sample.sha256,
256
+ toolName: TOOL_NAME,
257
+ toolVersion: TOOL_VERSION,
258
+ args: {
259
+ max_exports: input.max_exports,
260
+ max_strings: input.max_strings,
261
+ original_filename: originalFilename,
262
+ },
263
+ });
264
+ if (!input.force_refresh) {
265
+ const cachedLookup = await lookupCachedResult(cacheManager, cacheKey);
266
+ if (cachedLookup) {
267
+ return {
268
+ ok: true,
269
+ data: cachedLookup.data,
270
+ warnings: ['Result from cache', formatCacheWarning(cachedLookup.metadata)],
271
+ metrics: {
272
+ elapsed_ms: Date.now() - startTime,
273
+ tool: TOOL_NAME,
274
+ cached: true,
275
+ cache_key: cachedLookup.metadata.key,
276
+ cache_tier: cachedLookup.metadata.tier,
277
+ cache_created_at: cachedLookup.metadata.createdAt,
278
+ cache_expires_at: cachedLookup.metadata.expiresAt,
279
+ cache_hit_at: cachedLookup.metadata.fetchedAt,
280
+ },
281
+ };
282
+ }
283
+ }
284
+ const [exportsResult, importsResult, stringsResult, runtimeResult, packerResult] = await Promise.all([
285
+ exportsHandler({ sample_id: input.sample_id, force_refresh: input.force_refresh }),
286
+ importsHandler({
287
+ sample_id: input.sample_id,
288
+ group_by_dll: true,
289
+ force_refresh: input.force_refresh,
290
+ }),
291
+ stringsHandler({
292
+ sample_id: input.sample_id,
293
+ category_filter: 'all',
294
+ max_strings: input.max_strings,
295
+ force_refresh: input.force_refresh,
296
+ }),
297
+ runtimeHandler({ sample_id: input.sample_id, force_refresh: input.force_refresh }),
298
+ packerHandler({ sample_id: input.sample_id, force_refresh: input.force_refresh }),
299
+ ]);
300
+ const warnings = [
301
+ ...(exportsResult.warnings || []).map((item) => `exports: ${item}`),
302
+ ...(importsResult.warnings || []).map((item) => `imports: ${item}`),
303
+ ...(stringsResult.warnings || []).map((item) => `strings: ${item}`),
304
+ ...(runtimeResult.warnings || []).map((item) => `runtime: ${item}`),
305
+ ...(packerResult.warnings || []).map((item) => `packer: ${item}`),
306
+ ];
307
+ const exportsData = (exportsResult.ok ? exportsResult.data : undefined);
308
+ const importsData = (importsResult.ok ? importsResult.data : undefined);
309
+ const stringsData = (stringsResult.ok ? stringsResult.data : undefined);
310
+ const runtimeData = (runtimeResult.ok ? runtimeResult.data : undefined);
311
+ const packerData = (packerResult.ok ? packerResult.data : undefined);
312
+ const exportEntries = exportsData?.exports || [];
313
+ const forwarders = exportsData?.forwarders || [];
314
+ const importDlls = Object.keys(importsData?.imports || {});
315
+ const importFunctions = flattenImportFunctions(importsData);
316
+ const stringValues = (stringsData?.strings || []).map((item) => item.string);
317
+ const loweredStrings = stringValues.map((item) => item.toLowerCase());
318
+ const exportNames = exportEntries.map((item) => item.name).filter(Boolean);
319
+ const loweredExports = exportNames.map((item) => item.toLowerCase());
320
+ const loweredImportDlls = importDlls.map((item) => item.toLowerCase());
321
+ const loweredImportFunctions = importFunctions.map((item) => item.toLowerCase());
322
+ const { binaryRole, roleConfidence, roleEvidence } = inferBinaryRole(originalFilename, sample.file_type, exportsData?.total_exports ?? exportEntries.length, importsData, runtimeData);
323
+ const clsidStrings = uniqueStrings(stringValues.filter((item) => /\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}/i.test(item))).slice(0, 6);
324
+ const progIdStrings = uniqueStrings(stringValues.filter((item) => /progid|classfactory|iclassfactory|cocreateinstance|dllgetclassobject/i.test(item))).slice(0, 6);
325
+ const comExports = uniqueStrings(exportNames.filter((item) => /dll(getclassobject|canunloadnow|registerserver|unregisterserver)/i.test(item)));
326
+ const serviceExports = uniqueStrings(exportNames.filter((item) => /servicemain|svcmain/i.test(item)));
327
+ const pluginExports = uniqueStrings(exportNames.filter((item) => /plugin|addin|extension|initialize/i.test(item)));
328
+ const commandLikeExports = uniqueStrings(exportNames.filter((item) => /dispatch|command|execute|handle|invoke|run|process|query/i.test(item)));
329
+ const callbackLikeExports = uniqueStrings(exportNames.filter((item) => /callback|hook|notify|event|factory|attach|detach/i.test(item)));
330
+ const registrationExports = uniqueStrings(exportNames.filter((item) => /dll(registerserver|unregisterserver|install)|register/i.test(item)));
331
+ const forwardedExports = uniqueStrings(forwarders.map((item) => `${item.name || `ordinal_${item.ordinal}`} -> ${item.forwarder}`)).slice(0, input.max_exports);
332
+ const comImports = uniqueStrings(importDlls.filter((item) => /ole32|oleaut32|combase|rpcrt4/i.test(item)));
333
+ const serviceImports = uniqueStrings(importDlls.filter((item) => /advapi32/i.test(item)));
334
+ const networkImports = uniqueStrings(importDlls.filter((item) => /winhttp|wininet|ws2_32|dnsapi|urlmon/i.test(item)));
335
+ const processImports = uniqueStrings(importDlls.filter((item) => /kernel32|ntdll|psapi|dbghelp/i.test(item)));
336
+ const comEvidence = [
337
+ ...roleEvidence.filter((item) => item.includes('dll')),
338
+ ...comExports.map((item) => `export:${item}`),
339
+ ...comImports.map((item) => `import:${item}`),
340
+ ...clsidStrings.map((item) => `clsid:${item}`),
341
+ ...progIdStrings.map((item) => `string:${item}`),
342
+ ];
343
+ let comScore = 0;
344
+ if (comExports.length > 0)
345
+ comScore += 0.38;
346
+ if (comImports.length > 0)
347
+ comScore += 0.18;
348
+ if (clsidStrings.length > 0)
349
+ comScore += 0.22;
350
+ if (progIdStrings.length > 0)
351
+ comScore += 0.18;
352
+ if (binaryRole === 'dll' || binaryRole === '.net_library')
353
+ comScore += 0.08;
354
+ const interfaceHints = uniqueStrings(stringValues.filter((item) => /iunknown|idispatch|iclassfactory|ipropertypage|iprovid(e|er)|interface/i.test(item))).slice(0, 8);
355
+ const registrationStrings = uniqueStrings(stringValues.filter((item) => /inprocserver32|localserver32|typelib|appid|clsid|progid|treatas/i.test(item))).slice(0, 8);
356
+ const serviceStrings = uniqueStrings(stringValues.filter((item) => /services\\|registerservicectrlhandler|startservicectrldispatcher|setservicestatus|servicemain/i.test(item))).slice(0, 6);
357
+ const serviceEvidence = [
358
+ ...serviceImports.map((item) => `import:${item}`),
359
+ ...serviceExports.map((item) => `export:${item}`),
360
+ ...serviceStrings.map((item) => `string:${item}`),
361
+ ];
362
+ let serviceScore = 0;
363
+ if (serviceImports.length > 0)
364
+ serviceScore += 0.28;
365
+ if (serviceStrings.length > 0)
366
+ serviceScore += 0.24;
367
+ if (serviceExports.length > 0)
368
+ serviceScore += 0.18;
369
+ if (loweredStrings.some((item) => item.includes('currentcontrolset\\services')))
370
+ serviceScore += 0.16;
371
+ const pluginStrings = uniqueStrings(stringValues.filter((item) => /plugin|extension|addin|host application|register plugin/i.test(item))).slice(0, 6);
372
+ const pluginEvidence = [
373
+ ...pluginExports.map((item) => `export:${item}`),
374
+ ...pluginStrings.map((item) => `string:${item}`),
375
+ ];
376
+ let pluginScore = 0;
377
+ if (pluginExports.length > 0)
378
+ pluginScore += 0.34;
379
+ if (pluginStrings.length > 0)
380
+ pluginScore += 0.22;
381
+ if ((binaryRole === 'dll' || binaryRole === '.net_library') && (pluginExports.length > 0 || pluginStrings.length > 0)) {
382
+ pluginScore += 0.16;
383
+ }
384
+ if (loweredExports.some((item) => item.includes('initialize')))
385
+ pluginScore += 0.1;
386
+ const hostHints = uniqueStrings([
387
+ ...stringValues.filter((item) => /plugin host|host application|shell extension|addin|extension point|loaded by/i.test(item)),
388
+ ...importDlls.filter((item) => /shell32|explorerframe|office|vbscript|jscript/i.test(item)),
389
+ ]).slice(0, 8);
390
+ const callbackStrings = uniqueStrings(stringValues.filter((item) => /callback|event sink|notification|hook chain|observer/i.test(item))).slice(0, 8);
391
+ const serviceHooks = uniqueStrings([
392
+ ...serviceExports,
393
+ ...importFunctions.filter((item) => /startservicectrldispatcher|registerservicectrlhandler|setservicestatus/i.test(item)),
394
+ ]).slice(0, 8);
395
+ let hostInteractionScore = 0;
396
+ if (pluginScore >= 0.4)
397
+ hostInteractionScore += 0.25;
398
+ if (callbackLikeExports.length > 0)
399
+ hostInteractionScore += 0.18;
400
+ if (callbackStrings.length > 0)
401
+ hostInteractionScore += 0.16;
402
+ if (hostHints.length > 0)
403
+ hostInteractionScore += 0.18;
404
+ if (serviceHooks.length > 0)
405
+ hostInteractionScore += 0.12;
406
+ let exportDispatchScore = 0;
407
+ if (commandLikeExports.length > 0)
408
+ exportDispatchScore += 0.34;
409
+ if (callbackLikeExports.length > 0)
410
+ exportDispatchScore += 0.18;
411
+ if (forwardedExports.length > 0)
412
+ exportDispatchScore += 0.08;
413
+ if (registrationExports.length > 0)
414
+ exportDispatchScore += 0.14;
415
+ if ((exportsData?.total_exports ?? exportEntries.length) >= 8)
416
+ exportDispatchScore += 0.12;
417
+ const ordinalOnlyExports = Math.max(0, (exportsData?.total_exports ?? exportEntries.length) - exportNames.length);
418
+ let likelyDispatchModel = 'none';
419
+ if (registrationExports.length > 0 && comScore >= 0.55) {
420
+ likelyDispatchModel = 'com_registration_and_class_factory';
421
+ }
422
+ else if (pluginScore >= 0.55 && hostInteractionScore >= 0.45) {
423
+ likelyDispatchModel = 'plugin_initialization_and_host_callbacks';
424
+ }
425
+ else if (commandLikeExports.length > 0) {
426
+ likelyDispatchModel = 'exported_command_dispatch';
427
+ }
428
+ else if (forwardedExports.length > 0) {
429
+ likelyDispatchModel = 'forwarded_export_surface';
430
+ }
431
+ const driverEvidence = uniqueStrings([
432
+ ...roleEvidence.filter((item) => item.includes('driver')),
433
+ ...loweredImportDlls.filter((item) => item.includes('ntoskrnl') || item.includes('fltmgr')).map((item) => `import:${item}`),
434
+ ]);
435
+ let driverScore = 0;
436
+ if (binaryRole === 'driver')
437
+ driverScore += 0.62;
438
+ if (driverEvidence.length > 1)
439
+ driverScore += 0.2;
440
+ const priorities = [];
441
+ if (binaryRole === 'driver')
442
+ priorities.push('review_driver_entrypoints_and_ioctl_surface');
443
+ if (comScore >= 0.55)
444
+ priorities.push('trace_com_activation_and_class_factory_flow');
445
+ if (registrationExports.length > 0)
446
+ priorities.push('review_registration_exports_and_inprocserver_paths');
447
+ if (serviceScore >= 0.55)
448
+ priorities.push('trace_service_entrypoint_and_scm_lifecycle');
449
+ if (pluginScore >= 0.55)
450
+ priorities.push('trace_host_plugin_exports_and_callback_model');
451
+ if (exportDispatchScore >= 0.5)
452
+ priorities.push('review_exported_command_dispatch_surface');
453
+ if (hostInteractionScore >= 0.5)
454
+ priorities.push('identify_host_callbacks_and_extension_contract');
455
+ if (loweredImportFunctions.some((item) => item.includes('disablethreadlibrarycalls'))) {
456
+ priorities.push('review_dllmain_lifecycle_and_attach_detach_side_effects');
457
+ }
458
+ if ((exportsData?.total_exports ?? exportEntries.length) > 0)
459
+ priorities.push('trace_export_surface_first');
460
+ if ((exportsData?.total_forwarders ?? forwarders.length) > 0)
461
+ priorities.push('inspect_forwarded_exports');
462
+ if (runtimeData?.is_dotnet)
463
+ priorities.push('prefer_managed_metadata_and_il_recovery');
464
+ if (packerData?.packed || (packerData?.confidence || 0) >= 0.45)
465
+ priorities.push('unpack_or_stage_memory_import_before_deep_reconstruct');
466
+ if (networkImports.length > 0)
467
+ priorities.push('review_network_session_setup_and_remote_endpoints');
468
+ if (processImports.length > 0)
469
+ priorities.push('review_process_manipulation_and_dynamic_resolution_paths');
470
+ const lifecycleSurface = uniqueStrings([
471
+ ...exportNames.filter((item) => /dllmain|dllentry|initialize/i.test(item)),
472
+ ...importFunctions.filter((item) => /disablethreadlibrarycalls|getmodulehandle|freelibrary/i.test(item)),
473
+ ...stringValues.filter((item) => /dllmain|dll_process_attach|dll_process_detach|thread_attach|thread_detach/i.test(item)),
474
+ ]).slice(0, input.max_exports);
475
+ const classFactorySurface = uniqueStrings([
476
+ ...comExports,
477
+ ...interfaceHints.filter((item) => /iclassfactory|iunknown|idispatch/i.test(item)),
478
+ ...stringValues.filter((item) => /createinstance|lockserver|dllgetclassobject|cocreateinstance/i.test(item)),
479
+ ]).slice(0, input.max_exports);
480
+ const callbackSurface = uniqueStrings([
481
+ ...callbackLikeExports,
482
+ ...callbackStrings,
483
+ ...hostHints.filter((item) => /plugin|extension|host/i.test(item)),
484
+ ]).slice(0, input.max_exports);
485
+ const payload = {
486
+ sample_id: input.sample_id,
487
+ original_filename: originalFilename,
488
+ binary_role: binaryRole,
489
+ role_confidence: clamp(roleConfidence),
490
+ runtime_hint: {
491
+ is_dotnet: runtimeData?.is_dotnet ?? null,
492
+ dotnet_version: runtimeData?.dotnet_version ?? null,
493
+ target_framework: runtimeData?.target_framework ?? null,
494
+ primary_runtime: [...(runtimeData?.suspected || [])].sort((a, b) => b.confidence - a.confidence)[0]?.runtime ||
495
+ null,
496
+ },
497
+ export_surface: {
498
+ total_exports: exportsData?.total_exports ?? exportEntries.length,
499
+ total_forwarders: exportsData?.total_forwarders ?? forwarders.length,
500
+ notable_exports: uniqueStrings(exportNames).slice(0, input.max_exports),
501
+ com_related_exports: comExports.slice(0, input.max_exports),
502
+ service_related_exports: serviceExports.slice(0, input.max_exports),
503
+ plugin_related_exports: pluginExports.slice(0, input.max_exports),
504
+ forwarded_exports: forwardedExports,
505
+ },
506
+ import_surface: {
507
+ dll_count: importDlls.length,
508
+ notable_dlls: uniqueStrings(importDlls).slice(0, input.max_exports),
509
+ com_related_imports: comImports,
510
+ service_related_imports: serviceImports,
511
+ network_related_imports: networkImports,
512
+ process_related_imports: processImports,
513
+ },
514
+ packed: packerData?.packed === true,
515
+ packing_confidence: clamp(packerData?.confidence || 0),
516
+ indicators: {
517
+ com_server: buildRoleIndicator(comScore, comEvidence),
518
+ service_binary: buildRoleIndicator(serviceScore, serviceEvidence),
519
+ plugin_binary: buildRoleIndicator(pluginScore, pluginEvidence),
520
+ driver_binary: buildRoleIndicator(driverScore, driverEvidence),
521
+ },
522
+ export_dispatch_profile: {
523
+ command_like_exports: commandLikeExports.slice(0, input.max_exports),
524
+ callback_like_exports: callbackLikeExports.slice(0, input.max_exports),
525
+ registration_exports: registrationExports.slice(0, input.max_exports),
526
+ ordinal_only_exports: ordinalOnlyExports,
527
+ likely_dispatch_model: likelyDispatchModel,
528
+ confidence: clamp(exportDispatchScore),
529
+ },
530
+ lifecycle_surface: lifecycleSurface,
531
+ com_profile: {
532
+ clsid_strings: clsidStrings,
533
+ progid_strings: progIdStrings,
534
+ interface_hints: interfaceHints,
535
+ registration_strings: registrationStrings,
536
+ class_factory_exports: comExports.slice(0, input.max_exports),
537
+ class_factory_surface: classFactorySurface,
538
+ confidence: clamp(comScore),
539
+ },
540
+ host_interaction_profile: {
541
+ likely_hosted: hostInteractionScore >= 0.55,
542
+ host_hints: hostHints,
543
+ callback_exports: callbackLikeExports.slice(0, input.max_exports),
544
+ callback_surface: callbackSurface,
545
+ callback_strings: callbackStrings,
546
+ service_hooks: serviceHooks,
547
+ confidence: clamp(hostInteractionScore),
548
+ },
549
+ analysis_priorities: uniqueStrings(priorities).slice(0, 8),
550
+ strings_considered: stringValues.length,
551
+ };
552
+ await cacheManager.setCachedResult(cacheKey, payload, CACHE_TTL_MS, sample.sha256);
553
+ return {
554
+ ok: true,
555
+ data: payload,
556
+ warnings: warnings.length > 0 ? warnings : undefined,
557
+ metrics: {
558
+ elapsed_ms: Date.now() - startTime,
559
+ tool: TOOL_NAME,
560
+ },
561
+ };
562
+ }
563
+ catch (error) {
564
+ return {
565
+ ok: false,
566
+ errors: [error instanceof Error ? error.message : String(error)],
567
+ metrics: {
568
+ elapsed_ms: Date.now() - startTime,
569
+ tool: TOOL_NAME,
570
+ },
571
+ };
572
+ }
573
+ };
574
+ }
575
+ //# sourceMappingURL=binary-role-profile.js.map
@@ -148,9 +148,9 @@ export declare const codeFunctionExplainApplyOutputSchema: z.ZodObject<{
148
148
  sha256: string;
149
149
  mime?: string | undefined;
150
150
  };
151
+ next_steps: string[];
151
152
  accepted_count: number;
152
153
  rejected_count: number;
153
- next_steps: string[];
154
154
  accepted_explanations: {
155
155
  function: string | null;
156
156
  address: string | null;
@@ -167,9 +167,9 @@ export declare const codeFunctionExplainApplyOutputSchema: z.ZodObject<{
167
167
  sha256: string;
168
168
  mime?: string | undefined;
169
169
  };
170
+ next_steps: string[];
170
171
  accepted_count: number;
171
172
  rejected_count: number;
172
- next_steps: string[];
173
173
  accepted_explanations: {
174
174
  function: string | null;
175
175
  address: string | null;
@@ -193,10 +193,6 @@ export declare const codeFunctionExplainApplyOutputSchema: z.ZodObject<{
193
193
  }>>;
194
194
  }, "strip", z.ZodTypeAny, {
195
195
  ok: boolean;
196
- metrics?: {
197
- elapsed_ms: number;
198
- tool: string;
199
- } | undefined;
200
196
  data?: {
201
197
  sample_id: string;
202
198
  artifact: {
@@ -206,9 +202,9 @@ export declare const codeFunctionExplainApplyOutputSchema: z.ZodObject<{
206
202
  sha256: string;
207
203
  mime?: string | undefined;
208
204
  };
205
+ next_steps: string[];
209
206
  accepted_count: number;
210
207
  rejected_count: number;
211
- next_steps: string[];
212
208
  accepted_explanations: {
213
209
  function: string | null;
214
210
  address: string | null;
@@ -217,15 +213,15 @@ export declare const codeFunctionExplainApplyOutputSchema: z.ZodObject<{
217
213
  rewrite_guidance_count: number;
218
214
  }[];
219
215
  } | undefined;
216
+ metrics?: {
217
+ elapsed_ms: number;
218
+ tool: string;
219
+ } | undefined;
220
220
  warnings?: string[] | undefined;
221
221
  errors?: string[] | undefined;
222
222
  artifacts?: any[] | undefined;
223
223
  }, {
224
224
  ok: boolean;
225
- metrics?: {
226
- elapsed_ms: number;
227
- tool: string;
228
- } | undefined;
229
225
  data?: {
230
226
  sample_id: string;
231
227
  artifact: {
@@ -235,9 +231,9 @@ export declare const codeFunctionExplainApplyOutputSchema: z.ZodObject<{
235
231
  sha256: string;
236
232
  mime?: string | undefined;
237
233
  };
234
+ next_steps: string[];
238
235
  accepted_count: number;
239
236
  rejected_count: number;
240
- next_steps: string[];
241
237
  accepted_explanations: {
242
238
  function: string | null;
243
239
  address: string | null;
@@ -246,6 +242,10 @@ export declare const codeFunctionExplainApplyOutputSchema: z.ZodObject<{
246
242
  rewrite_guidance_count: number;
247
243
  }[];
248
244
  } | undefined;
245
+ metrics?: {
246
+ elapsed_ms: number;
247
+ tool: string;
248
+ } | undefined;
249
249
  warnings?: string[] | undefined;
250
250
  errors?: string[] | undefined;
251
251
  artifacts?: any[] | undefined;