|
| 1 | +"""Malware investigation dispatch-hub graph (opt-in) over the shared substrate. |
| 2 | +
|
| 3 | +RFC-13 (#68). Where ``malware.investigate.v2`` wires the phases by static |
| 4 | +edges and a kind router, this graph runs them as a discovery-driven |
| 5 | +dispatch: setup, then the hub, then a phase, then back to the hub, until |
| 6 | +emit. The hub activates a phase only when its ``condition`` holds, so the |
| 7 | +deep phases fire on real discoveries posted to the shared ledger rather |
| 8 | +than on a fixed edge. |
| 9 | +
|
| 10 | +Phase activation: |
| 11 | +
|
| 12 | +* ``triage`` -- gated on target readiness (the same static-analysis gate |
| 13 | + V2 uses). It runs first and posts its structural findings to the ledger. |
| 14 | +* ``unpack`` -- ``capability="re"``, ``trust="confirmed"``: activates once |
| 15 | + a discovery is confirmed by a quorum decision (the reverse-engineering |
| 16 | + specialist's phase). |
| 17 | +* ``config_extract`` -- ``capability="crypto"``, ``trust="confirmed"``: |
| 18 | + activates on a confirmed discovery (the config/crypto specialist). |
| 19 | +* ``full_analysis`` -- unconditional, ``trust="advisory"``, declared last: |
| 20 | + the fallback deep phase that always remains available so the hub never |
| 21 | + dead-ends when no discovery routed to a specialist phase. |
| 22 | +
|
| 23 | +Malware runs a single agent server (ida_headless), so ``_branch_capability`` |
| 24 | +is not threaded and the capability fields document intent rather than |
| 25 | +enforce per-branch routing (that matters for the multi-persona vr hub). |
| 26 | +The definition ships alongside V1 and V2; a seed binds it per investigation |
| 27 | +only after an operator smoke. |
| 28 | +""" |
| 29 | +from __future__ import annotations |
| 30 | + |
| 31 | +from typing import cast |
| 32 | + |
| 33 | +from aila.modules.malware.workflow.definitions import _build_services |
| 34 | +from aila.modules.malware.workflow.definitions_v2 import ( |
| 35 | + _CONFIG_EXTRACT_DIRECTIVE, |
| 36 | + _FULL_ANALYSIS_DIRECTIVE, |
| 37 | + _TRIAGE_DIRECTIVE, |
| 38 | + _loop_builder, |
| 39 | + _setup_builder, |
| 40 | + _target_ready, |
| 41 | +) |
| 42 | +from aila.modules.malware.workflow.states.investigation_emit import ( |
| 43 | + state_investigation_emit, |
| 44 | +) |
| 45 | +from aila.platform.services.ledger import make_discovery_condition |
| 46 | +from aila.platform.workflows.phase_graph import ( |
| 47 | + PhaseSpec, |
| 48 | + build_dispatch_workflow, |
| 49 | +) |
| 50 | +from aila.platform.workflows.types import HandlerFn |
| 51 | + |
| 52 | +__all__ = ["MALWARE_HUB_PHASES", "MALWARE_INVESTIGATE_HUB"] |
| 53 | + |
| 54 | +_UNPACK_DIRECTIVE = ( |
| 55 | + "UNPACKING PHASE. Objective: defeat the packer or obfuscation blocking " |
| 56 | + "static analysis -- identify the packer, dump the unpacked image, and " |
| 57 | + "reconstruct imports so the deeper phases read real code. Submit once " |
| 58 | + "the sample is statically analyzable." |
| 59 | +) |
| 60 | + |
| 61 | +MALWARE_HUB_PHASES: tuple[PhaseSpec, ...] = ( |
| 62 | + PhaseSpec( |
| 63 | + name="triage", |
| 64 | + directive=_TRIAGE_DIRECTIVE, |
| 65 | + max_turns=20, |
| 66 | + condition=_target_ready, |
| 67 | + trust="confirmed", |
| 68 | + ), |
| 69 | + PhaseSpec( |
| 70 | + name="unpack", |
| 71 | + directive=_UNPACK_DIRECTIVE, |
| 72 | + condition=make_discovery_condition("discovery", confirmed_only=True), |
| 73 | + capability="re", |
| 74 | + trust="confirmed", |
| 75 | + ), |
| 76 | + PhaseSpec( |
| 77 | + name="config_extract", |
| 78 | + directive=_CONFIG_EXTRACT_DIRECTIVE, |
| 79 | + condition=make_discovery_condition("discovery", confirmed_only=True), |
| 80 | + capability="crypto", |
| 81 | + trust="confirmed", |
| 82 | + ), |
| 83 | + PhaseSpec( |
| 84 | + name="full_analysis", |
| 85 | + directive=_FULL_ANALYSIS_DIRECTIVE, |
| 86 | + trust="advisory", |
| 87 | + ), |
| 88 | +) |
| 89 | + |
| 90 | + |
| 91 | +MALWARE_INVESTIGATE_HUB = build_dispatch_workflow( |
| 92 | + "malware.investigate.hub", |
| 93 | + MALWARE_HUB_PHASES, |
| 94 | + services_factory=_build_services, |
| 95 | + setup_builder=_setup_builder, |
| 96 | + loop_builder=_loop_builder, |
| 97 | + emit_handler=cast("HandlerFn", state_investigation_emit), |
| 98 | +) |
0 commit comments