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.
- package/CLAUDE_INSTALLATION.md +129 -0
- package/CODEX_INSTALLATION.md +25 -1
- package/COPILOT_INSTALLATION.md +29 -1
- package/LICENSE +21 -21
- package/README.md +232 -110
- package/dist/analysis-provenance.d.ts +50 -2
- package/dist/analysis-provenance.js +1 -0
- package/dist/analysis-task-runner.js +92 -0
- package/dist/config.d.ts +35 -16
- package/dist/config.js +37 -3
- package/dist/database.js +115 -115
- package/dist/decompiler-worker.d.ts +10 -5
- package/dist/decompiler-worker.js +240 -58
- package/dist/dynamic-trace.d.ts +6 -0
- package/dist/dynamic-trace.js +52 -1
- package/dist/ghidra-config.js +17 -1
- package/dist/index.js +38 -8
- package/dist/pe-runtime-functions.d.ts +90 -0
- package/dist/pe-runtime-functions.js +452 -0
- package/dist/prompts/module-reconstruction-review.d.ts +5 -0
- package/dist/prompts/module-reconstruction-review.js +65 -0
- package/dist/runtime-correlation.d.ts +5 -0
- package/dist/runtime-correlation.js +179 -2
- package/dist/sample-workspace.d.ts +28 -0
- package/dist/sample-workspace.js +186 -0
- package/dist/semantic-name-suggestion-artifacts.d.ts +56 -0
- package/dist/semantic-name-suggestion-artifacts.js +87 -0
- package/dist/server.js +1 -1
- package/dist/setup-guidance.d.ts +73 -0
- package/dist/setup-guidance.js +211 -0
- package/dist/tools/artifact-read.d.ts +10 -10
- package/dist/tools/artifacts-diff.d.ts +8 -8
- package/dist/tools/artifacts-list.d.ts +16 -16
- package/dist/tools/attack-map.d.ts +8 -8
- package/dist/tools/binary-role-profile.d.ts +1197 -0
- package/dist/tools/binary-role-profile.js +575 -0
- package/dist/tools/code-function-explain-apply.d.ts +12 -12
- package/dist/tools/code-function-explain-prepare.d.ts +12 -12
- package/dist/tools/code-function-explain-review.d.ts +58 -58
- package/dist/tools/code-function-rename-apply.d.ts +12 -12
- package/dist/tools/code-function-rename-prepare.d.ts +14 -14
- package/dist/tools/code-function-rename-review.d.ts +66 -66
- package/dist/tools/code-functions-define.d.ts +337 -0
- package/dist/tools/code-functions-define.js +337 -0
- package/dist/tools/code-functions-list.js +1 -1
- package/dist/tools/code-functions-rank.js +1 -1
- package/dist/tools/code-functions-reconstruct.d.ts +368 -58
- package/dist/tools/code-functions-reconstruct.js +130 -10
- package/dist/tools/code-functions-smart-recover.d.ts +352 -0
- package/dist/tools/code-functions-smart-recover.js +190 -0
- package/dist/tools/code-module-review-apply.d.ts +233 -0
- package/dist/tools/code-module-review-apply.js +209 -0
- package/dist/tools/code-module-review-prepare.d.ts +756 -0
- package/dist/tools/code-module-review-prepare.js +343 -0
- package/dist/tools/code-module-review.d.ts +474 -0
- package/dist/tools/code-module-review.js +566 -0
- package/dist/tools/code-reconstruct-export.d.ts +193 -21
- package/dist/tools/code-reconstruct-export.js +578 -21
- package/dist/tools/code-reconstruct-plan.d.ts +20 -20
- package/dist/tools/com-role-profile.d.ts +353 -0
- package/dist/tools/com-role-profile.js +186 -0
- package/dist/tools/dll-export-profile.d.ts +625 -0
- package/dist/tools/dll-export-profile.js +230 -0
- package/dist/tools/dotnet-metadata-extract.d.ts +122 -122
- package/dist/tools/dotnet-reconstruct-export.d.ts +49 -49
- package/dist/tools/dotnet-types-list.d.ts +66 -66
- package/dist/tools/dynamic-dependencies.d.ts +144 -8
- package/dist/tools/dynamic-dependencies.js +20 -1
- package/dist/tools/dynamic-memory-import.js +105 -2
- package/dist/tools/ghidra-analyze.d.ts +20 -0
- package/dist/tools/ghidra-analyze.js +10 -2
- package/dist/tools/ghidra-health.d.ts +177 -0
- package/dist/tools/ghidra-health.js +28 -0
- package/dist/tools/ioc-export.d.ts +8 -8
- package/dist/tools/packer-detect.d.ts +14 -14
- package/dist/tools/packer-detect.js +6 -9
- package/dist/tools/pe-exports-extract.d.ts +8 -8
- package/dist/tools/pe-exports-extract.js +6 -9
- package/dist/tools/pe-fingerprint.d.ts +36 -36
- package/dist/tools/pe-imports-extract.d.ts +8 -8
- package/dist/tools/pe-imports-extract.js +6 -9
- package/dist/tools/pe-pdata-extract.d.ts +448 -0
- package/dist/tools/pe-pdata-extract.js +219 -0
- package/dist/tools/pe-symbols-recover.d.ts +227 -0
- package/dist/tools/pe-symbols-recover.js +316 -0
- package/dist/tools/report-generate.d.ts +15 -1
- package/dist/tools/report-generate.js +139 -16
- package/dist/tools/report-summarize.d.ts +2242 -8
- package/dist/tools/report-summarize.js +246 -10
- package/dist/tools/runtime-detect.d.ts +8 -8
- package/dist/tools/runtime-detect.js +2 -12
- package/dist/tools/rust-binary-analyze.d.ts +2047 -0
- package/dist/tools/rust-binary-analyze.js +443 -0
- package/dist/tools/sample-profile-get.d.ts +135 -16
- package/dist/tools/sample-profile-get.js +35 -32
- package/dist/tools/sandbox-execute.d.ts +10 -10
- package/dist/tools/strings-extract.d.ts +8 -8
- package/dist/tools/strings-extract.js +2 -12
- package/dist/tools/strings-floss-decode.d.ts +8 -8
- package/dist/tools/system-health.d.ts +172 -36
- package/dist/tools/system-health.js +14 -0
- package/dist/tools/system-setup-guide.d.ts +179 -0
- package/dist/tools/system-setup-guide.js +62 -0
- package/dist/tools/tool-help.d.ts +16 -16
- package/dist/tools/tool-help.js +172 -0
- package/dist/tools/yara-scan.d.ts +8 -8
- package/dist/types.d.ts +2 -0
- package/dist/workflows/function-explanation-review.d.ts +3034 -76
- package/dist/workflows/function-explanation-review.js +172 -42
- package/dist/workflows/function-index-recover.d.ts +333 -0
- package/dist/workflows/function-index-recover.js +291 -0
- package/dist/workflows/module-reconstruction-review.d.ts +3537 -0
- package/dist/workflows/module-reconstruction-review.js +354 -0
- package/dist/workflows/reconstruct.d.ts +2182 -223
- package/dist/workflows/reconstruct.js +575 -32
- package/dist/workflows/semantic-name-review.d.ts +1436 -85
- package/dist/workflows/semantic-name-review.js +150 -58
- package/dist/workflows/triage.d.ts +8 -8
- package/ghidra_scripts/DecompileFunction.java +487 -487
- package/ghidra_scripts/ExtractCFG.java +256 -256
- package/ghidra_scripts/ExtractFunctions.java +442 -442
- package/ghidra_scripts/README.md +112 -112
- package/ghidra_scripts/SearchFunctionReferences.java +380 -380
- package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -9
- package/helpers/DotNetMetadataProbe/Program.cs +566 -566
- package/install-to-claude.ps1 +432 -0
- package/install-to-codex.ps1 +256 -178
- package/install-to-copilot.ps1 +389 -303
- package/package.json +4 -2
- package/requirements.txt +9 -9
- package/workers/requirements-dynamic.txt +11 -11
- package/workers/requirements.txt +8 -8
- package/workers/speakeasy_compat.py +175 -175
- package/workers/static_worker.py +3474 -3474
|
@@ -9,13 +9,19 @@ import { createRuntimeDetectHandler } from '../tools/runtime-detect.js';
|
|
|
9
9
|
import { createCodeReconstructPlanHandler } from '../tools/code-reconstruct-plan.js';
|
|
10
10
|
import { createCodeReconstructExportHandler } from '../tools/code-reconstruct-export.js';
|
|
11
11
|
import { createDotNetReconstructExportHandler } from '../tools/dotnet-reconstruct-export.js';
|
|
12
|
-
import { findBestGhidraAnalysis } from '../ghidra-analysis-status.js';
|
|
12
|
+
import { findBestGhidraAnalysis, isGhidraCapabilityReady, } from '../ghidra-analysis-status.js';
|
|
13
13
|
import { loadDynamicTraceEvidence } from '../dynamic-trace.js';
|
|
14
14
|
import { loadSemanticFunctionExplanationIndex, loadSemanticNameSuggestionIndex, } from '../semantic-name-suggestion-artifacts.js';
|
|
15
|
+
import { BinaryRoleProfileDataSchema, createBinaryRoleProfileHandler, } from '../tools/binary-role-profile.js';
|
|
16
|
+
import { ComRoleProfileDataSchema, createComRoleProfileHandler, } from '../tools/com-role-profile.js';
|
|
17
|
+
import { DllExportProfileDataSchema, createDllExportProfileHandler, } from '../tools/dll-export-profile.js';
|
|
18
|
+
import { createRustBinaryAnalyzeHandler, } from '../tools/rust-binary-analyze.js';
|
|
19
|
+
import { createFunctionIndexRecoverWorkflowHandler } from './function-index-recover.js';
|
|
15
20
|
import { AnalysisProvenanceSchema, buildRuntimeArtifactProvenance, buildSemanticArtifactProvenance, } from '../analysis-provenance.js';
|
|
16
21
|
import { AnalysisSelectionDiffSchema, buildArtifactSelectionDiff, } from '../selection-diff.js';
|
|
22
|
+
import { RequiredUserInputSchema, SetupActionSchema, collectSetupGuidanceFromWorkerResult, mergeRequiredUserInputs, mergeSetupActions, } from '../setup-guidance.js';
|
|
17
23
|
const TOOL_NAME = 'workflow.reconstruct';
|
|
18
|
-
const TOOL_VERSION = '0.1.
|
|
24
|
+
const TOOL_VERSION = '0.1.5';
|
|
19
25
|
const CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
20
26
|
export const ReconstructWorkflowInputSchema = z.object({
|
|
21
27
|
sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
|
|
@@ -96,6 +102,14 @@ export const ReconstructWorkflowInputSchema = z.object({
|
|
|
96
102
|
.string()
|
|
97
103
|
.optional()
|
|
98
104
|
.describe('Optional baseline semantic artifact session selector used when compare_semantic_scope=session'),
|
|
105
|
+
include_preflight: z
|
|
106
|
+
.boolean()
|
|
107
|
+
.default(true)
|
|
108
|
+
.describe('Run binary role and language-specific preflight profiling before planning and export'),
|
|
109
|
+
auto_recover_function_index: z
|
|
110
|
+
.boolean()
|
|
111
|
+
.default(true)
|
|
112
|
+
.describe('When native function-index coverage is missing, automatically run workflow.function_index_recover before export'),
|
|
99
113
|
include_plan: z
|
|
100
114
|
.boolean()
|
|
101
115
|
.default(true)
|
|
@@ -196,29 +210,115 @@ const ExportSummarySchema = z.object({
|
|
|
196
210
|
binary_profile: BinaryProfileSchema.nullable(),
|
|
197
211
|
managed_profile: ManagedProfileSchema.nullable(),
|
|
198
212
|
});
|
|
213
|
+
const PreflightRustProfileSchema = z.object({
|
|
214
|
+
suspected_rust: z.boolean(),
|
|
215
|
+
confidence: z.number().min(0).max(1),
|
|
216
|
+
primary_runtime: z.string().nullable(),
|
|
217
|
+
runtime_hints: z.array(z.string()),
|
|
218
|
+
crate_hints: z.array(z.string()),
|
|
219
|
+
cargo_paths: z.array(z.string()),
|
|
220
|
+
recovered_function_count: z.number().int().nonnegative(),
|
|
221
|
+
recovered_symbol_count: z.number().int().nonnegative(),
|
|
222
|
+
importable_with_code_functions_define: z.boolean(),
|
|
223
|
+
analysis_priorities: z.array(z.string()),
|
|
224
|
+
});
|
|
225
|
+
const PreflightDllProfileSchema = z.object({
|
|
226
|
+
library_like: z.boolean(),
|
|
227
|
+
role_confidence: z.number().min(0).max(1),
|
|
228
|
+
likely_entry_model: z.string(),
|
|
229
|
+
dll_entry_hints: z.array(z.string()),
|
|
230
|
+
dispatch_model: z.string(),
|
|
231
|
+
host_hints: z.array(z.string()),
|
|
232
|
+
lifecycle_surface: DllExportProfileDataSchema.shape.lifecycle_surface,
|
|
233
|
+
class_factory_surface: DllExportProfileDataSchema.shape.class_factory_surface,
|
|
234
|
+
callback_surface: DllExportProfileDataSchema.shape.callback_surface,
|
|
235
|
+
analysis_priorities: z.array(z.string()),
|
|
236
|
+
});
|
|
237
|
+
const PreflightComProfileSchema = z.object({
|
|
238
|
+
likely_com_server: z.boolean(),
|
|
239
|
+
com_confidence: z.number().min(0).max(1),
|
|
240
|
+
activation_model: z.string(),
|
|
241
|
+
class_factory_exports: z.array(z.string()),
|
|
242
|
+
registration_exports: z.array(z.string()),
|
|
243
|
+
clsid_strings: z.array(z.string()),
|
|
244
|
+
progid_strings: z.array(z.string()),
|
|
245
|
+
interface_hints: z.array(z.string()),
|
|
246
|
+
class_factory_surface: ComRoleProfileDataSchema.shape.class_factory_surface,
|
|
247
|
+
activation_steps: z.array(z.string()),
|
|
248
|
+
analysis_priorities: z.array(z.string()),
|
|
249
|
+
});
|
|
250
|
+
const RoleAwareExportTuningSchema = z.object({
|
|
251
|
+
topk: z.number().int().positive(),
|
|
252
|
+
module_limit: z.number().int().positive(),
|
|
253
|
+
min_module_size: z.number().int().positive(),
|
|
254
|
+
include_imports: z.boolean(),
|
|
255
|
+
include_strings: z.boolean(),
|
|
256
|
+
});
|
|
257
|
+
const RoleAwareStrategySchema = z.object({
|
|
258
|
+
target_role: z.string(),
|
|
259
|
+
priority_order: z.array(z.string()),
|
|
260
|
+
focus_areas: z.array(z.string()),
|
|
261
|
+
rationale: z.array(z.string()),
|
|
262
|
+
export_tuning: RoleAwareExportTuningSchema,
|
|
263
|
+
});
|
|
264
|
+
const FunctionIndexRecoverySummarySchema = z.object({
|
|
265
|
+
applied: z.boolean(),
|
|
266
|
+
define_from: z.enum(['smart_recover', 'symbols_recover']).nullable(),
|
|
267
|
+
recovered_function_count: z.number().int().nonnegative(),
|
|
268
|
+
recovered_symbol_count: z.number().int().nonnegative(),
|
|
269
|
+
imported_count: z.number().int().nonnegative(),
|
|
270
|
+
function_index_status: z.enum(['ready']).nullable(),
|
|
271
|
+
decompile_status: z.enum(['missing']).nullable(),
|
|
272
|
+
cfg_status: z.enum(['missing']).nullable(),
|
|
273
|
+
recovery_strategy: z.array(z.string()),
|
|
274
|
+
next_steps: z.array(z.string()),
|
|
275
|
+
});
|
|
276
|
+
const PreflightSummarySchema = z.object({
|
|
277
|
+
binary_profile: BinaryRoleProfileDataSchema.nullable(),
|
|
278
|
+
dll_profile: PreflightDllProfileSchema.nullable(),
|
|
279
|
+
com_profile: PreflightComProfileSchema.nullable(),
|
|
280
|
+
rust_profile: PreflightRustProfileSchema.nullable(),
|
|
281
|
+
function_index_recovery: FunctionIndexRecoverySummarySchema.nullable(),
|
|
282
|
+
role_strategy: RoleAwareStrategySchema.nullable(),
|
|
283
|
+
});
|
|
284
|
+
const ReconstructQueuedDataSchema = z.object({
|
|
285
|
+
job_id: z.string(),
|
|
286
|
+
status: z.literal('queued'),
|
|
287
|
+
tool: z.literal(TOOL_NAME),
|
|
288
|
+
sample_id: z.string(),
|
|
289
|
+
requested_path: z.enum(['auto', 'native', 'dotnet']),
|
|
290
|
+
progress: z.number().int().min(0).max(100),
|
|
291
|
+
});
|
|
292
|
+
const ReconstructCompletedDataSchema = z.object({
|
|
293
|
+
sample_id: z.string(),
|
|
294
|
+
selected_path: z.enum(['native', 'dotnet']),
|
|
295
|
+
degraded: z.boolean(),
|
|
296
|
+
stage_status: z.object({
|
|
297
|
+
runtime: z.enum(['ok', 'failed']),
|
|
298
|
+
preflight_binary_profile: z.enum(['ok', 'failed', 'skipped']),
|
|
299
|
+
preflight_dll_profile: z.enum(['ok', 'failed', 'skipped']),
|
|
300
|
+
preflight_com_profile: z.enum(['ok', 'failed', 'skipped']),
|
|
301
|
+
preflight_rust_profile: z.enum(['ok', 'failed', 'skipped']),
|
|
302
|
+
function_index_recovery: z.enum(['ok', 'failed', 'skipped']),
|
|
303
|
+
plan: z.enum(['ok', 'failed', 'skipped']),
|
|
304
|
+
export_primary: z.enum(['ok', 'failed', 'skipped']),
|
|
305
|
+
export_fallback: z.enum(['ok', 'failed', 'skipped']),
|
|
306
|
+
}),
|
|
307
|
+
provenance: AnalysisProvenanceSchema,
|
|
308
|
+
selection_diffs: AnalysisSelectionDiffSchema.optional(),
|
|
309
|
+
runtime: RuntimeSummarySchema,
|
|
310
|
+
preflight: PreflightSummarySchema.optional(),
|
|
311
|
+
plan: PlanSummarySchema.nullable(),
|
|
312
|
+
export: ExportSummarySchema.nullable(),
|
|
313
|
+
notes: z.array(z.string()),
|
|
314
|
+
});
|
|
199
315
|
export const ReconstructWorkflowOutputSchema = z.object({
|
|
200
316
|
ok: z.boolean(),
|
|
201
|
-
data: z
|
|
202
|
-
.object({
|
|
203
|
-
sample_id: z.string(),
|
|
204
|
-
selected_path: z.enum(['native', 'dotnet']),
|
|
205
|
-
degraded: z.boolean(),
|
|
206
|
-
stage_status: z.object({
|
|
207
|
-
runtime: z.enum(['ok', 'failed']),
|
|
208
|
-
plan: z.enum(['ok', 'failed', 'skipped']),
|
|
209
|
-
export_primary: z.enum(['ok', 'failed', 'skipped']),
|
|
210
|
-
export_fallback: z.enum(['ok', 'failed', 'skipped']),
|
|
211
|
-
}),
|
|
212
|
-
provenance: AnalysisProvenanceSchema,
|
|
213
|
-
selection_diffs: AnalysisSelectionDiffSchema.optional(),
|
|
214
|
-
runtime: RuntimeSummarySchema,
|
|
215
|
-
plan: PlanSummarySchema.nullable(),
|
|
216
|
-
export: ExportSummarySchema.nullable(),
|
|
217
|
-
notes: z.array(z.string()),
|
|
218
|
-
})
|
|
219
|
-
.optional(),
|
|
317
|
+
data: z.union([ReconstructCompletedDataSchema, ReconstructQueuedDataSchema]).optional(),
|
|
220
318
|
warnings: z.array(z.string()).optional(),
|
|
221
319
|
errors: z.array(z.string()).optional(),
|
|
320
|
+
setup_actions: z.array(SetupActionSchema).optional(),
|
|
321
|
+
required_user_inputs: z.array(RequiredUserInputSchema).optional(),
|
|
222
322
|
artifacts: z.array(z.any()).optional(),
|
|
223
323
|
metrics: z
|
|
224
324
|
.object({
|
|
@@ -235,7 +335,7 @@ export const ReconstructWorkflowOutputSchema = z.object({
|
|
|
235
335
|
});
|
|
236
336
|
export const reconstructWorkflowToolDefinition = {
|
|
237
337
|
name: TOOL_NAME,
|
|
238
|
-
description: 'Run a complete source-reconstruction workflow with auto routing (native/.NET), planning, export, and cache observability.',
|
|
338
|
+
description: 'Run a complete source-reconstruction workflow with auto routing (native/.NET), binary/language preflight profiling, optional function-index recovery, planning, export, and cache observability.',
|
|
239
339
|
inputSchema: ReconstructWorkflowInputSchema,
|
|
240
340
|
outputSchema: ReconstructWorkflowOutputSchema,
|
|
241
341
|
};
|
|
@@ -261,7 +361,174 @@ function summarizeRuntime(runtimeData) {
|
|
|
261
361
|
primary_runtime: pickPrimaryRuntime(runtimeData),
|
|
262
362
|
};
|
|
263
363
|
}
|
|
264
|
-
|
|
364
|
+
function pickLatestAnalysisMarker(analyses, predicate) {
|
|
365
|
+
const sorted = [...analyses]
|
|
366
|
+
.filter(predicate)
|
|
367
|
+
.sort((left, right) => {
|
|
368
|
+
const leftTs = new Date(left.finished_at || left.started_at || 0).getTime();
|
|
369
|
+
const rightTs = new Date(right.finished_at || right.started_at || 0).getTime();
|
|
370
|
+
return rightTs - leftTs;
|
|
371
|
+
});
|
|
372
|
+
const selected = sorted[0];
|
|
373
|
+
if (!selected) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
stage: selected.stage,
|
|
378
|
+
backend: selected.backend,
|
|
379
|
+
status: selected.status,
|
|
380
|
+
finished_at: selected.finished_at || selected.started_at || null,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function summarizeRustPreflight(data) {
|
|
384
|
+
return {
|
|
385
|
+
suspected_rust: data.suspected_rust,
|
|
386
|
+
confidence: data.confidence,
|
|
387
|
+
primary_runtime: data.primary_runtime,
|
|
388
|
+
runtime_hints: data.runtime_hints,
|
|
389
|
+
crate_hints: data.crate_hints,
|
|
390
|
+
cargo_paths: data.cargo_paths,
|
|
391
|
+
recovered_function_count: data.recovered_function_count,
|
|
392
|
+
recovered_symbol_count: data.recovered_symbol_count,
|
|
393
|
+
importable_with_code_functions_define: data.importable_with_code_functions_define,
|
|
394
|
+
analysis_priorities: data.analysis_priorities,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function summarizeDllPreflight(data) {
|
|
398
|
+
return {
|
|
399
|
+
library_like: data.library_like,
|
|
400
|
+
role_confidence: data.role_confidence,
|
|
401
|
+
likely_entry_model: data.likely_entry_model,
|
|
402
|
+
dll_entry_hints: data.dll_entry_hints,
|
|
403
|
+
dispatch_model: data.export_dispatch_profile.likely_dispatch_model,
|
|
404
|
+
host_hints: data.host_interaction_profile.host_hints,
|
|
405
|
+
lifecycle_surface: data.lifecycle_surface,
|
|
406
|
+
class_factory_surface: data.class_factory_surface,
|
|
407
|
+
callback_surface: data.callback_surface,
|
|
408
|
+
analysis_priorities: data.analysis_priorities,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function summarizeComPreflight(data) {
|
|
412
|
+
return {
|
|
413
|
+
likely_com_server: data.likely_com_server,
|
|
414
|
+
com_confidence: data.com_confidence,
|
|
415
|
+
activation_model: data.activation_model,
|
|
416
|
+
class_factory_exports: data.class_factory_exports,
|
|
417
|
+
registration_exports: data.registration_exports,
|
|
418
|
+
clsid_strings: data.clsid_strings,
|
|
419
|
+
progid_strings: data.progid_strings,
|
|
420
|
+
interface_hints: data.interface_hints,
|
|
421
|
+
class_factory_surface: data.class_factory_surface,
|
|
422
|
+
activation_steps: data.activation_steps,
|
|
423
|
+
analysis_priorities: data.analysis_priorities,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
function buildRoleAwareStrategy(args) {
|
|
427
|
+
const rationale = [];
|
|
428
|
+
const focusAreas = new Set();
|
|
429
|
+
const priorityOrder = new Set();
|
|
430
|
+
let targetRole = 'native_executable';
|
|
431
|
+
const exportTuning = {
|
|
432
|
+
topk: 16,
|
|
433
|
+
module_limit: 8,
|
|
434
|
+
min_module_size: 1,
|
|
435
|
+
include_imports: true,
|
|
436
|
+
include_strings: true,
|
|
437
|
+
};
|
|
438
|
+
if (args.runtimeData?.is_dotnet) {
|
|
439
|
+
targetRole = 'managed_assembly';
|
|
440
|
+
rationale.push('runtime.detect reported CLR/.NET metadata');
|
|
441
|
+
focusAreas.add('managed_metadata_and_il');
|
|
442
|
+
}
|
|
443
|
+
else if (args.comProfile?.likely_com_server) {
|
|
444
|
+
targetRole = 'com_server';
|
|
445
|
+
rationale.push(`COM preflight suggests activation model ${args.comProfile.activation_model}`);
|
|
446
|
+
focusAreas.add('class_factory_and_registration');
|
|
447
|
+
exportTuning.topk = 20;
|
|
448
|
+
exportTuning.module_limit = 10;
|
|
449
|
+
}
|
|
450
|
+
else if (args.dllProfile?.library_like && args.dllProfile.dispatch_model !== 'none') {
|
|
451
|
+
targetRole = 'export_dispatch_dll';
|
|
452
|
+
rationale.push(`DLL preflight suggests dispatch model ${args.dllProfile.dispatch_model}`);
|
|
453
|
+
focusAreas.add('export_dispatch_surface');
|
|
454
|
+
exportTuning.topk = 18;
|
|
455
|
+
exportTuning.module_limit = 10;
|
|
456
|
+
}
|
|
457
|
+
else if (args.dllProfile?.library_like && args.dllProfile.host_hints.length > 0) {
|
|
458
|
+
targetRole = 'hosted_plugin_or_service_dll';
|
|
459
|
+
rationale.push('DLL preflight suggests hosted/plugin lifecycle');
|
|
460
|
+
focusAreas.add('host_callbacks_and_attach_detach');
|
|
461
|
+
exportTuning.topk = 18;
|
|
462
|
+
exportTuning.module_limit = 9;
|
|
463
|
+
}
|
|
464
|
+
else if (args.dllProfile?.library_like) {
|
|
465
|
+
targetRole = 'dll_library';
|
|
466
|
+
rationale.push(`DLL preflight suggests entry model ${args.dllProfile.likely_entry_model}`);
|
|
467
|
+
focusAreas.add('dllmain_and_export_surface');
|
|
468
|
+
exportTuning.topk = 18;
|
|
469
|
+
exportTuning.module_limit = 9;
|
|
470
|
+
}
|
|
471
|
+
else if (args.rustProfile?.suspected_rust) {
|
|
472
|
+
targetRole = 'native_rust_executable';
|
|
473
|
+
rationale.push(`Rust preflight confidence ${args.rustProfile.confidence.toFixed(2)}`);
|
|
474
|
+
focusAreas.add('pdata_recovery_and_runtime_wrappers');
|
|
475
|
+
exportTuning.topk = 20;
|
|
476
|
+
exportTuning.module_limit = 9;
|
|
477
|
+
}
|
|
478
|
+
else if (args.binaryProfile?.indicators.service_binary.likely) {
|
|
479
|
+
targetRole = 'service_binary';
|
|
480
|
+
rationale.push('binary.role.profile found service-oriented indicators');
|
|
481
|
+
focusAreas.add('service_entrypoints_and_hooks');
|
|
482
|
+
exportTuning.topk = 18;
|
|
483
|
+
exportTuning.module_limit = 9;
|
|
484
|
+
}
|
|
485
|
+
for (const item of args.binaryProfile?.analysis_priorities || []) {
|
|
486
|
+
priorityOrder.add(item);
|
|
487
|
+
}
|
|
488
|
+
for (const item of args.dllProfile?.analysis_priorities || []) {
|
|
489
|
+
priorityOrder.add(item);
|
|
490
|
+
}
|
|
491
|
+
for (const item of args.comProfile?.analysis_priorities || []) {
|
|
492
|
+
priorityOrder.add(item);
|
|
493
|
+
}
|
|
494
|
+
for (const item of args.rustProfile?.analysis_priorities || []) {
|
|
495
|
+
priorityOrder.add(item);
|
|
496
|
+
}
|
|
497
|
+
if (args.comProfile?.class_factory_exports.length) {
|
|
498
|
+
focusAreas.add('class_factory_exports');
|
|
499
|
+
}
|
|
500
|
+
if (args.dllProfile?.dll_entry_hints.length) {
|
|
501
|
+
focusAreas.add('dll_entry_lifecycle');
|
|
502
|
+
}
|
|
503
|
+
if (args.binaryProfile?.export_dispatch_profile.likely_dispatch_model !== 'none') {
|
|
504
|
+
focusAreas.add('dispatch_model_reconstruction');
|
|
505
|
+
}
|
|
506
|
+
if (args.binaryProfile?.host_interaction_profile.likely_hosted) {
|
|
507
|
+
focusAreas.add('host_interaction_model');
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
target_role: targetRole,
|
|
511
|
+
priority_order: Array.from(priorityOrder),
|
|
512
|
+
focus_areas: Array.from(focusAreas),
|
|
513
|
+
rationale,
|
|
514
|
+
export_tuning: exportTuning,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
function summarizeFunctionIndexRecovery(data) {
|
|
518
|
+
return {
|
|
519
|
+
applied: true,
|
|
520
|
+
define_from: data.define_from,
|
|
521
|
+
recovered_function_count: data.recovered_function_count,
|
|
522
|
+
recovered_symbol_count: data.recovered_symbol_count,
|
|
523
|
+
imported_count: data.imported_count,
|
|
524
|
+
function_index_status: data.function_index_status,
|
|
525
|
+
decompile_status: data.decompile_status,
|
|
526
|
+
cfg_status: data.cfg_status,
|
|
527
|
+
recovery_strategy: data.recovery_strategy,
|
|
528
|
+
next_steps: data.next_steps,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
export function createReconstructWorkflowHandler(workspaceManager, database, cacheManager, dependencies, jobQueue) {
|
|
265
532
|
const runtimeDetectHandler = dependencies?.runtimeDetectHandler ||
|
|
266
533
|
createRuntimeDetectHandler(workspaceManager, database, cacheManager);
|
|
267
534
|
const planHandler = dependencies?.planHandler ||
|
|
@@ -270,6 +537,20 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
270
537
|
createCodeReconstructExportHandler(workspaceManager, database, cacheManager);
|
|
271
538
|
const dotnetExportHandler = dependencies?.dotnetExportHandler ||
|
|
272
539
|
createDotNetReconstructExportHandler(workspaceManager, database, cacheManager);
|
|
540
|
+
const binaryRoleProfileHandler = dependencies?.binaryRoleProfileHandler ||
|
|
541
|
+
createBinaryRoleProfileHandler(workspaceManager, database, cacheManager);
|
|
542
|
+
const dllExportProfileHandler = dependencies?.dllExportProfileHandler ||
|
|
543
|
+
createDllExportProfileHandler(workspaceManager, database, cacheManager, {
|
|
544
|
+
binaryRoleProfileHandler,
|
|
545
|
+
});
|
|
546
|
+
const comRoleProfileHandler = dependencies?.comRoleProfileHandler ||
|
|
547
|
+
createComRoleProfileHandler(workspaceManager, database, cacheManager, {
|
|
548
|
+
binaryRoleProfileHandler,
|
|
549
|
+
});
|
|
550
|
+
const rustBinaryAnalyzeHandler = dependencies?.rustBinaryAnalyzeHandler ||
|
|
551
|
+
createRustBinaryAnalyzeHandler(workspaceManager, database, cacheManager);
|
|
552
|
+
const functionIndexRecoverHandler = dependencies?.functionIndexRecoverHandler ||
|
|
553
|
+
createFunctionIndexRecoverWorkflowHandler(workspaceManager, database, cacheManager);
|
|
273
554
|
return async (args) => {
|
|
274
555
|
const input = ReconstructWorkflowInputSchema.parse(args);
|
|
275
556
|
const startTime = Date.now();
|
|
@@ -281,10 +562,48 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
281
562
|
errors: [`Sample not found: ${input.sample_id}`],
|
|
282
563
|
};
|
|
283
564
|
}
|
|
565
|
+
if (jobQueue) {
|
|
566
|
+
const jobTimeoutMs = Math.max(input.build_timeout_ms + input.run_timeout_ms + 45 * 60 * 1000, 60 * 60 * 1000);
|
|
567
|
+
const jobId = jobQueue.enqueue({
|
|
568
|
+
type: 'static',
|
|
569
|
+
tool: TOOL_NAME,
|
|
570
|
+
sampleId: input.sample_id,
|
|
571
|
+
args: input,
|
|
572
|
+
priority: 5,
|
|
573
|
+
timeout: jobTimeoutMs,
|
|
574
|
+
retryPolicy: {
|
|
575
|
+
maxRetries: 1,
|
|
576
|
+
backoffMs: 5000,
|
|
577
|
+
retryableErrors: ['E_TIMEOUT', 'E_RESOURCE_EXHAUSTED'],
|
|
578
|
+
},
|
|
579
|
+
});
|
|
580
|
+
return {
|
|
581
|
+
ok: true,
|
|
582
|
+
data: {
|
|
583
|
+
job_id: jobId,
|
|
584
|
+
status: 'queued',
|
|
585
|
+
tool: TOOL_NAME,
|
|
586
|
+
sample_id: input.sample_id,
|
|
587
|
+
requested_path: input.path,
|
|
588
|
+
progress: 0,
|
|
589
|
+
},
|
|
590
|
+
metrics: {
|
|
591
|
+
elapsed_ms: Date.now() - startTime,
|
|
592
|
+
tool: TOOL_NAME,
|
|
593
|
+
},
|
|
594
|
+
};
|
|
595
|
+
}
|
|
284
596
|
const warnings = [];
|
|
285
597
|
const notes = [];
|
|
598
|
+
let setupActions = [];
|
|
599
|
+
let requiredUserInputs = [];
|
|
286
600
|
const stageStatus = {
|
|
287
601
|
runtime: 'failed',
|
|
602
|
+
preflight_binary_profile: 'skipped',
|
|
603
|
+
preflight_dll_profile: 'skipped',
|
|
604
|
+
preflight_com_profile: 'skipped',
|
|
605
|
+
preflight_rust_profile: 'skipped',
|
|
606
|
+
function_index_recovery: 'skipped',
|
|
288
607
|
plan: 'skipped',
|
|
289
608
|
export_primary: 'skipped',
|
|
290
609
|
export_fallback: 'skipped',
|
|
@@ -303,6 +622,11 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
303
622
|
else {
|
|
304
623
|
stageStatus.runtime = 'ok';
|
|
305
624
|
}
|
|
625
|
+
{
|
|
626
|
+
const setupGuidance = collectSetupGuidanceFromWorkerResult(runtimeResult);
|
|
627
|
+
setupActions = mergeSetupActions(setupActions, setupGuidance.setupActions);
|
|
628
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, setupGuidance.requiredUserInputs);
|
|
629
|
+
}
|
|
306
630
|
let selectedPath;
|
|
307
631
|
if (input.path === 'auto') {
|
|
308
632
|
selectedPath = runtimeData?.is_dotnet ? 'dotnet' : 'native';
|
|
@@ -330,7 +654,145 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
330
654
|
if (selectedPath === 'native' && runtimeData?.is_dotnet) {
|
|
331
655
|
warnings.push('Selected native path while runtime indicates .NET; forcing native as requested.');
|
|
332
656
|
}
|
|
333
|
-
|
|
657
|
+
let analyses = database.findAnalysesBySample(input.sample_id);
|
|
658
|
+
let completedGhidraAnalysis = findBestGhidraAnalysis(analyses, 'function_index');
|
|
659
|
+
const hasReadyGhidraFunctionIndex = Boolean(completedGhidraAnalysis && isGhidraCapabilityReady(completedGhidraAnalysis, 'function_index'));
|
|
660
|
+
const hasFunctionDefinitionIndex = analyses.some((analysis) => analysis.stage === 'function_definition' && analysis.status === 'done');
|
|
661
|
+
let binaryProfileData = null;
|
|
662
|
+
let dllProfileData = null;
|
|
663
|
+
let comProfileData = null;
|
|
664
|
+
let rustProfileData = null;
|
|
665
|
+
let functionIndexRecoveryData = null;
|
|
666
|
+
let functionIndexRecoveryApplied = false;
|
|
667
|
+
let roleStrategy = null;
|
|
668
|
+
if (input.include_preflight) {
|
|
669
|
+
const binaryProfileResult = await binaryRoleProfileHandler({
|
|
670
|
+
sample_id: input.sample_id,
|
|
671
|
+
force_refresh: !input.reuse_cached,
|
|
672
|
+
});
|
|
673
|
+
if (binaryProfileResult.ok && binaryProfileResult.data) {
|
|
674
|
+
binaryProfileData = binaryProfileResult.data;
|
|
675
|
+
stageStatus.preflight_binary_profile = 'ok';
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
stageStatus.preflight_binary_profile = 'failed';
|
|
679
|
+
warnings.push(`binary.role.profile unavailable: ${(binaryProfileResult.errors || ['unknown error']).join('; ')}`);
|
|
680
|
+
}
|
|
681
|
+
if (binaryProfileResult.warnings?.length) {
|
|
682
|
+
warnings.push(...binaryProfileResult.warnings.map((item) => `binary.role.profile: ${item}`));
|
|
683
|
+
}
|
|
684
|
+
{
|
|
685
|
+
const setupGuidance = collectSetupGuidanceFromWorkerResult(binaryProfileResult);
|
|
686
|
+
setupActions = mergeSetupActions(setupActions, setupGuidance.setupActions);
|
|
687
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, setupGuidance.requiredUserInputs);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (selectedPath === 'native' && !runtimeData?.is_dotnet && input.include_preflight) {
|
|
691
|
+
const dllProfileResult = await dllExportProfileHandler({
|
|
692
|
+
sample_id: input.sample_id,
|
|
693
|
+
force_refresh: !input.reuse_cached,
|
|
694
|
+
});
|
|
695
|
+
if (dllProfileResult.ok && dllProfileResult.data) {
|
|
696
|
+
dllProfileData = summarizeDllPreflight(dllProfileResult.data);
|
|
697
|
+
stageStatus.preflight_dll_profile = 'ok';
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
stageStatus.preflight_dll_profile = 'failed';
|
|
701
|
+
warnings.push(`dll.export.profile unavailable: ${(dllProfileResult.errors || ['unknown error']).join('; ')}`);
|
|
702
|
+
}
|
|
703
|
+
if (dllProfileResult.warnings?.length) {
|
|
704
|
+
warnings.push(...dllProfileResult.warnings.map((item) => `dll.export.profile: ${item}`));
|
|
705
|
+
}
|
|
706
|
+
{
|
|
707
|
+
const setupGuidance = collectSetupGuidanceFromWorkerResult(dllProfileResult);
|
|
708
|
+
setupActions = mergeSetupActions(setupActions, setupGuidance.setupActions);
|
|
709
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, setupGuidance.requiredUserInputs);
|
|
710
|
+
}
|
|
711
|
+
const comProfileResult = await comRoleProfileHandler({
|
|
712
|
+
sample_id: input.sample_id,
|
|
713
|
+
force_refresh: !input.reuse_cached,
|
|
714
|
+
});
|
|
715
|
+
if (comProfileResult.ok && comProfileResult.data) {
|
|
716
|
+
comProfileData = summarizeComPreflight(comProfileResult.data);
|
|
717
|
+
stageStatus.preflight_com_profile = 'ok';
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
stageStatus.preflight_com_profile = 'failed';
|
|
721
|
+
warnings.push(`com.role.profile unavailable: ${(comProfileResult.errors || ['unknown error']).join('; ')}`);
|
|
722
|
+
}
|
|
723
|
+
if (comProfileResult.warnings?.length) {
|
|
724
|
+
warnings.push(...comProfileResult.warnings.map((item) => `com.role.profile: ${item}`));
|
|
725
|
+
}
|
|
726
|
+
{
|
|
727
|
+
const setupGuidance = collectSetupGuidanceFromWorkerResult(comProfileResult);
|
|
728
|
+
setupActions = mergeSetupActions(setupActions, setupGuidance.setupActions);
|
|
729
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, setupGuidance.requiredUserInputs);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
if (selectedPath === 'native' && !runtimeData?.is_dotnet && input.include_preflight) {
|
|
733
|
+
const rustProfileResult = await rustBinaryAnalyzeHandler({
|
|
734
|
+
sample_id: input.sample_id,
|
|
735
|
+
force_refresh: !input.reuse_cached,
|
|
736
|
+
});
|
|
737
|
+
if (rustProfileResult.ok && rustProfileResult.data) {
|
|
738
|
+
rustProfileData = rustProfileResult.data;
|
|
739
|
+
stageStatus.preflight_rust_profile = 'ok';
|
|
740
|
+
}
|
|
741
|
+
else {
|
|
742
|
+
stageStatus.preflight_rust_profile = 'failed';
|
|
743
|
+
warnings.push(`rust_binary.analyze unavailable: ${(rustProfileResult.errors || ['unknown error']).join('; ')}`);
|
|
744
|
+
}
|
|
745
|
+
if (rustProfileResult.warnings?.length) {
|
|
746
|
+
warnings.push(...rustProfileResult.warnings.map((item) => `rust_binary.analyze: ${item}`));
|
|
747
|
+
}
|
|
748
|
+
{
|
|
749
|
+
const setupGuidance = collectSetupGuidanceFromWorkerResult(rustProfileResult);
|
|
750
|
+
setupActions = mergeSetupActions(setupActions, setupGuidance.setupActions);
|
|
751
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, setupGuidance.requiredUserInputs);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
if (input.include_preflight) {
|
|
755
|
+
roleStrategy = buildRoleAwareStrategy({
|
|
756
|
+
runtimeData,
|
|
757
|
+
binaryProfile: binaryProfileData,
|
|
758
|
+
dllProfile: dllProfileData,
|
|
759
|
+
comProfile: comProfileData,
|
|
760
|
+
rustProfile: rustProfileData ? summarizeRustPreflight(rustProfileData) : null,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
if (selectedPath === 'native' &&
|
|
764
|
+
input.auto_recover_function_index &&
|
|
765
|
+
!hasReadyGhidraFunctionIndex &&
|
|
766
|
+
!hasFunctionDefinitionIndex) {
|
|
767
|
+
const functionIndexRecoverResult = await functionIndexRecoverHandler({
|
|
768
|
+
sample_id: input.sample_id,
|
|
769
|
+
define_from: 'auto',
|
|
770
|
+
include_rank_preview: false,
|
|
771
|
+
persist_artifact: true,
|
|
772
|
+
register_analysis: true,
|
|
773
|
+
replace_all: true,
|
|
774
|
+
force_refresh: !input.reuse_cached,
|
|
775
|
+
});
|
|
776
|
+
if (functionIndexRecoverResult.ok && functionIndexRecoverResult.data) {
|
|
777
|
+
functionIndexRecoveryData = summarizeFunctionIndexRecovery(functionIndexRecoverResult.data);
|
|
778
|
+
functionIndexRecoveryApplied = true;
|
|
779
|
+
stageStatus.function_index_recovery = 'ok';
|
|
780
|
+
analyses = database.findAnalysesBySample(input.sample_id);
|
|
781
|
+
completedGhidraAnalysis = findBestGhidraAnalysis(analyses, 'function_index');
|
|
782
|
+
}
|
|
783
|
+
else {
|
|
784
|
+
stageStatus.function_index_recovery = 'failed';
|
|
785
|
+
warnings.push(`workflow.function_index_recover unavailable: ${(functionIndexRecoverResult.errors || ['unknown error']).join('; ')}`);
|
|
786
|
+
}
|
|
787
|
+
if (functionIndexRecoverResult.warnings?.length) {
|
|
788
|
+
warnings.push(...functionIndexRecoverResult.warnings.map((item) => `workflow.function_index_recover: ${item}`));
|
|
789
|
+
}
|
|
790
|
+
{
|
|
791
|
+
const setupGuidance = collectSetupGuidanceFromWorkerResult(functionIndexRecoverResult);
|
|
792
|
+
setupActions = mergeSetupActions(setupActions, setupGuidance.setupActions);
|
|
793
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, setupGuidance.requiredUserInputs);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
334
796
|
const dynamicEvidence = await loadDynamicTraceEvidence(workspaceManager, database, input.sample_id, {
|
|
335
797
|
evidenceScope: input.evidence_scope,
|
|
336
798
|
sessionTag: input.evidence_session_tag,
|
|
@@ -368,7 +830,17 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
368
830
|
selectionDiffs.semantic_names = buildArtifactSelectionDiff('semantic_names', provenance.semantic_names, buildSemanticArtifactProvenance('semantic naming artifacts', baselineSemanticNameIndex, input.compare_semantic_scope, input.compare_semantic_session_tag));
|
|
369
831
|
selectionDiffs.semantic_explanations = buildArtifactSelectionDiff('semantic_explanations', provenance.semantic_explanations, buildSemanticArtifactProvenance('semantic explanation artifacts', baselineSemanticExplanationIndex, input.compare_semantic_scope, input.compare_semantic_session_tag));
|
|
370
832
|
}
|
|
371
|
-
const
|
|
833
|
+
const functionDefinitionMarker = pickLatestAnalysisMarker(analyses, (analysis) => analysis.stage === 'function_definition');
|
|
834
|
+
const analysisMarker = JSON.stringify({
|
|
835
|
+
ghidra_function_index: completedGhidraAnalysis
|
|
836
|
+
? {
|
|
837
|
+
id: completedGhidraAnalysis.id,
|
|
838
|
+
status: completedGhidraAnalysis.status,
|
|
839
|
+
finished_at: completedGhidraAnalysis.finished_at || completedGhidraAnalysis.started_at || null,
|
|
840
|
+
}
|
|
841
|
+
: null,
|
|
842
|
+
function_definition: functionDefinitionMarker,
|
|
843
|
+
});
|
|
372
844
|
const cacheKey = generateCacheKey({
|
|
373
845
|
sampleSha256: sample.sha256,
|
|
374
846
|
toolName: TOOL_NAME,
|
|
@@ -391,6 +863,8 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
391
863
|
compare_evidence_session_tag: input.compare_evidence_session_tag || null,
|
|
392
864
|
compare_semantic_scope: input.compare_semantic_scope || null,
|
|
393
865
|
compare_semantic_session_tag: input.compare_semantic_session_tag || null,
|
|
866
|
+
include_preflight: input.include_preflight,
|
|
867
|
+
auto_recover_function_index: input.auto_recover_function_index,
|
|
394
868
|
include_plan: input.include_plan,
|
|
395
869
|
include_obfuscation_fallback: input.include_obfuscation_fallback,
|
|
396
870
|
fallback_on_error: input.fallback_on_error,
|
|
@@ -449,11 +923,23 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
449
923
|
if (planResult.warnings && planResult.warnings.length > 0) {
|
|
450
924
|
warnings.push(...planResult.warnings.map((item) => `plan: ${item}`));
|
|
451
925
|
}
|
|
926
|
+
{
|
|
927
|
+
const setupGuidance = collectSetupGuidanceFromWorkerResult(planResult);
|
|
928
|
+
setupActions = mergeSetupActions(setupActions, setupGuidance.setupActions);
|
|
929
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, setupGuidance.requiredUserInputs);
|
|
930
|
+
}
|
|
452
931
|
}
|
|
453
932
|
let exportSummary = null;
|
|
454
933
|
let artifacts = [];
|
|
455
934
|
const primaryPath = selectedPath;
|
|
456
935
|
const fallbackPath = primaryPath === 'dotnet' ? 'native' : 'dotnet';
|
|
936
|
+
const nativeExportTuning = roleStrategy?.export_tuning || {
|
|
937
|
+
topk: Math.max(input.topk, 16),
|
|
938
|
+
module_limit: 8,
|
|
939
|
+
min_module_size: 1,
|
|
940
|
+
include_imports: true,
|
|
941
|
+
include_strings: true,
|
|
942
|
+
};
|
|
457
943
|
const runExport = async (pathToRun) => {
|
|
458
944
|
if (pathToRun === 'dotnet') {
|
|
459
945
|
const dotnetResult = await dotnetExportHandler({
|
|
@@ -463,13 +949,14 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
463
949
|
include_obfuscation_fallback: input.include_obfuscation_fallback,
|
|
464
950
|
evidence_scope: input.evidence_scope,
|
|
465
951
|
evidence_session_tag: input.evidence_session_tag,
|
|
466
|
-
reuse_cached: input.reuse_cached,
|
|
952
|
+
reuse_cached: input.reuse_cached && !functionIndexRecoveryApplied,
|
|
467
953
|
});
|
|
468
954
|
if (!dotnetResult.ok || !dotnetResult.data) {
|
|
469
955
|
return {
|
|
470
956
|
ok: false,
|
|
471
957
|
errors: dotnetResult.errors || ['dotnet.reconstruct.export failed'],
|
|
472
958
|
warnings: dotnetResult.warnings || [],
|
|
959
|
+
setupGuidance: collectSetupGuidanceFromWorkerResult(dotnetResult),
|
|
473
960
|
};
|
|
474
961
|
}
|
|
475
962
|
const data = dotnetResult.data;
|
|
@@ -477,6 +964,7 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
477
964
|
ok: true,
|
|
478
965
|
warnings: dotnetResult.warnings || [],
|
|
479
966
|
artifacts: dotnetResult.artifacts || [],
|
|
967
|
+
setupGuidance: collectSetupGuidanceFromWorkerResult(dotnetResult),
|
|
480
968
|
summary: {
|
|
481
969
|
tool: 'dotnet.reconstruct.export',
|
|
482
970
|
export_root: data.export_root,
|
|
@@ -503,11 +991,11 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
503
991
|
}
|
|
504
992
|
const nativeResult = await nativeExportHandler({
|
|
505
993
|
sample_id: input.sample_id,
|
|
506
|
-
topk: input.topk,
|
|
507
|
-
module_limit:
|
|
508
|
-
min_module_size:
|
|
509
|
-
include_imports:
|
|
510
|
-
include_strings:
|
|
994
|
+
topk: Math.max(input.topk, nativeExportTuning.topk),
|
|
995
|
+
module_limit: nativeExportTuning.module_limit,
|
|
996
|
+
min_module_size: nativeExportTuning.min_module_size,
|
|
997
|
+
include_imports: nativeExportTuning.include_imports,
|
|
998
|
+
include_strings: nativeExportTuning.include_strings,
|
|
511
999
|
export_name: input.export_name,
|
|
512
1000
|
validate_build: input.validate_build,
|
|
513
1001
|
run_harness: input.run_harness,
|
|
@@ -518,13 +1006,17 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
518
1006
|
evidence_session_tag: input.evidence_session_tag,
|
|
519
1007
|
semantic_scope: input.semantic_scope,
|
|
520
1008
|
semantic_session_tag: input.semantic_session_tag,
|
|
521
|
-
|
|
1009
|
+
role_target: roleStrategy?.target_role,
|
|
1010
|
+
role_focus_areas: roleStrategy?.focus_areas || [],
|
|
1011
|
+
role_priority_order: roleStrategy?.priority_order || [],
|
|
1012
|
+
reuse_cached: input.reuse_cached && !functionIndexRecoveryApplied,
|
|
522
1013
|
});
|
|
523
1014
|
if (!nativeResult.ok || !nativeResult.data) {
|
|
524
1015
|
return {
|
|
525
1016
|
ok: false,
|
|
526
1017
|
errors: nativeResult.errors || ['code.reconstruct.export failed'],
|
|
527
1018
|
warnings: nativeResult.warnings || [],
|
|
1019
|
+
setupGuidance: collectSetupGuidanceFromWorkerResult(nativeResult),
|
|
528
1020
|
};
|
|
529
1021
|
}
|
|
530
1022
|
const data = nativeResult.data;
|
|
@@ -532,6 +1024,7 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
532
1024
|
ok: true,
|
|
533
1025
|
warnings: nativeResult.warnings || [],
|
|
534
1026
|
artifacts: nativeResult.artifacts || [],
|
|
1027
|
+
setupGuidance: collectSetupGuidanceFromWorkerResult(nativeResult),
|
|
535
1028
|
summary: {
|
|
536
1029
|
tool: 'code.reconstruct.export',
|
|
537
1030
|
export_root: data.export_root,
|
|
@@ -561,12 +1054,16 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
561
1054
|
stageStatus.export_primary = 'ok';
|
|
562
1055
|
exportSummary = primaryExportResult.summary;
|
|
563
1056
|
artifacts = primaryExportResult.artifacts || [];
|
|
1057
|
+
setupActions = mergeSetupActions(setupActions, primaryExportResult.setupGuidance.setupActions);
|
|
1058
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, primaryExportResult.setupGuidance.requiredUserInputs);
|
|
564
1059
|
if (primaryExportResult.warnings.length > 0) {
|
|
565
1060
|
warnings.push(...primaryExportResult.warnings.map((item) => `${primaryPath === 'dotnet' ? 'dotnet_export' : 'native_export'}: ${item}`));
|
|
566
1061
|
}
|
|
567
1062
|
}
|
|
568
1063
|
else {
|
|
569
1064
|
stageStatus.export_primary = 'failed';
|
|
1065
|
+
setupActions = mergeSetupActions(setupActions, primaryExportResult.setupGuidance.setupActions);
|
|
1066
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, primaryExportResult.setupGuidance.requiredUserInputs);
|
|
570
1067
|
warnings.push(`primary export(${primaryPath}) failed: ${(primaryExportResult.errors || ['unknown error']).join('; ')}`);
|
|
571
1068
|
if (primaryExportResult.warnings.length > 0) {
|
|
572
1069
|
warnings.push(...primaryExportResult.warnings.map((item) => `${primaryPath === 'dotnet' ? 'dotnet_export' : 'native_export'}: ${item}`));
|
|
@@ -578,6 +1075,8 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
578
1075
|
stageStatus.export_fallback = 'ok';
|
|
579
1076
|
exportSummary = fallbackExportResult.summary;
|
|
580
1077
|
artifacts = fallbackExportResult.artifacts || [];
|
|
1078
|
+
setupActions = mergeSetupActions(setupActions, fallbackExportResult.setupGuidance.setupActions);
|
|
1079
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, fallbackExportResult.setupGuidance.requiredUserInputs);
|
|
581
1080
|
selectedPath = fallbackPath;
|
|
582
1081
|
notes.push(`Primary export path failed; switched to fallback path: ${fallbackPath}.`);
|
|
583
1082
|
if (fallbackExportResult.warnings.length > 0) {
|
|
@@ -586,6 +1085,8 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
586
1085
|
}
|
|
587
1086
|
else {
|
|
588
1087
|
stageStatus.export_fallback = 'failed';
|
|
1088
|
+
setupActions = mergeSetupActions(setupActions, fallbackExportResult.setupGuidance.setupActions);
|
|
1089
|
+
requiredUserInputs = mergeRequiredUserInputs(requiredUserInputs, fallbackExportResult.setupGuidance.requiredUserInputs);
|
|
589
1090
|
warnings.push(`fallback export(${fallbackPath}) failed: ${(fallbackExportResult.errors || ['unknown error']).join('; ')}`);
|
|
590
1091
|
if (fallbackExportResult.warnings.length > 0) {
|
|
591
1092
|
warnings.push(...fallbackExportResult.warnings.map((item) => `${fallbackPath === 'dotnet' ? 'dotnet_export' : 'native_export'}: ${item}`));
|
|
@@ -600,6 +1101,8 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
600
1101
|
ok: false,
|
|
601
1102
|
errors: ['All export paths failed and allow_partial=false.'],
|
|
602
1103
|
warnings,
|
|
1104
|
+
setup_actions: setupActions.length > 0 ? setupActions : undefined,
|
|
1105
|
+
required_user_inputs: requiredUserInputs.length > 0 ? requiredUserInputs : undefined,
|
|
603
1106
|
metrics: {
|
|
604
1107
|
elapsed_ms: Date.now() - startTime,
|
|
605
1108
|
tool: TOOL_NAME,
|
|
@@ -615,6 +1118,32 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
615
1118
|
else {
|
|
616
1119
|
notes.push('Runtime signal indicates native path; exact original source text is not recoverable.');
|
|
617
1120
|
}
|
|
1121
|
+
if (binaryProfileData?.export_dispatch_profile?.likely_dispatch_model &&
|
|
1122
|
+
binaryProfileData.export_dispatch_profile.likely_dispatch_model !== 'none') {
|
|
1123
|
+
notes.push(`Binary role preflight suggests dispatch model: ${binaryProfileData.export_dispatch_profile.likely_dispatch_model}.`);
|
|
1124
|
+
}
|
|
1125
|
+
if (dllProfileData?.dll_entry_hints.length) {
|
|
1126
|
+
notes.push(`DLL/export preflight hints: ${dllProfileData.dll_entry_hints.slice(0, 3).join(' ')}`);
|
|
1127
|
+
}
|
|
1128
|
+
if (comProfileData?.likely_com_server) {
|
|
1129
|
+
notes.push(`COM preflight suggests activation model: ${comProfileData.activation_model}.`);
|
|
1130
|
+
}
|
|
1131
|
+
if (binaryProfileData?.host_interaction_profile?.likely_hosted) {
|
|
1132
|
+
notes.push('Binary role preflight suggests the sample is likely hosted as a DLL/plugin/service component.');
|
|
1133
|
+
}
|
|
1134
|
+
if (rustProfileData?.suspected_rust) {
|
|
1135
|
+
notes.push(`Rust preflight recovered ${rustProfileData.recovered_function_count} function candidates and ${rustProfileData.recovered_symbol_count} symbol hints.`);
|
|
1136
|
+
if (rustProfileData.crate_hints.length > 0) {
|
|
1137
|
+
notes.push(`Rust crate hints: ${rustProfileData.crate_hints.slice(0, 4).join(', ')}.`);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
if (functionIndexRecoveryData?.applied) {
|
|
1141
|
+
notes.push(`Function index recovery imported ${functionIndexRecoveryData.imported_count} recovered functions before export.`);
|
|
1142
|
+
}
|
|
1143
|
+
if (roleStrategy) {
|
|
1144
|
+
notes.push(`Role-aware strategy selected target role ${roleStrategy.target_role}${roleStrategy.focus_areas.length ? ` with focus on ${roleStrategy.focus_areas.join(', ')}` : ''}.`);
|
|
1145
|
+
notes.push(`Role-aware export tuning: topk=${roleStrategy.export_tuning.topk}, module_limit=${roleStrategy.export_tuning.module_limit}, min_module_size=${roleStrategy.export_tuning.min_module_size}, imports=${roleStrategy.export_tuning.include_imports ? 'on' : 'off'}, strings=${roleStrategy.export_tuning.include_strings ? 'on' : 'off'}.`);
|
|
1146
|
+
}
|
|
618
1147
|
if (exportSummary?.binary_profile?.analysis_priorities?.length) {
|
|
619
1148
|
notes.push(`Binary profile priorities: ${exportSummary.binary_profile.analysis_priorities.join(', ')}.`);
|
|
620
1149
|
}
|
|
@@ -635,6 +1164,16 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
635
1164
|
provenance,
|
|
636
1165
|
selection_diffs: Object.keys(selectionDiffs).length > 0 ? selectionDiffs : undefined,
|
|
637
1166
|
runtime: summarizeRuntime(runtimeData),
|
|
1167
|
+
preflight: input.include_preflight || stageStatus.function_index_recovery !== 'skipped'
|
|
1168
|
+
? {
|
|
1169
|
+
binary_profile: binaryProfileData,
|
|
1170
|
+
dll_profile: dllProfileData,
|
|
1171
|
+
com_profile: comProfileData,
|
|
1172
|
+
rust_profile: rustProfileData ? summarizeRustPreflight(rustProfileData) : null,
|
|
1173
|
+
function_index_recovery: functionIndexRecoveryData,
|
|
1174
|
+
role_strategy: roleStrategy,
|
|
1175
|
+
}
|
|
1176
|
+
: undefined,
|
|
638
1177
|
plan: planSummary,
|
|
639
1178
|
export: exportSummary,
|
|
640
1179
|
notes,
|
|
@@ -644,6 +1183,8 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
644
1183
|
ok: true,
|
|
645
1184
|
data: outputData,
|
|
646
1185
|
warnings: warnings.length > 0 ? warnings : undefined,
|
|
1186
|
+
setup_actions: setupActions.length > 0 ? setupActions : undefined,
|
|
1187
|
+
required_user_inputs: requiredUserInputs.length > 0 ? requiredUserInputs : undefined,
|
|
647
1188
|
artifacts: artifacts,
|
|
648
1189
|
metrics: {
|
|
649
1190
|
elapsed_ms: Date.now() - startTime,
|
|
@@ -655,6 +1196,8 @@ export function createReconstructWorkflowHandler(workspaceManager, database, cac
|
|
|
655
1196
|
return {
|
|
656
1197
|
ok: false,
|
|
657
1198
|
errors: [normalizeError(error)],
|
|
1199
|
+
setup_actions: undefined,
|
|
1200
|
+
required_user_inputs: undefined,
|
|
658
1201
|
metrics: {
|
|
659
1202
|
elapsed_ms: Date.now() - startTime,
|
|
660
1203
|
tool: TOOL_NAME,
|