mirror of
https://github.com/Aryma-f4/Ares-mythic.git
synced 2026-06-18 03:04:12 +00:00
279 lines
10 KiB
Markdown
279 lines
10 KiB
Markdown
# Apollo agent refactor analysis
|
|
|
|
## Scope
|
|
|
|
This review focuses on making the Apollo agent easier to maintain, safer to evolve, and easier to test. It does not include adding persistence, automatic privilege retention, exploit delivery, or integration with offensive exploit frameworks. If you need legitimate startup automation, the safer direction is a controlled startup pipeline for configuration validation, capability initialization, and operator-approved workflows.
|
|
|
|
## Current architecture summary
|
|
|
|
### Startup flow
|
|
|
|
- `Apollo/Program.cs` performs COM security initialization, runs environmental keying checks, constructs `Agent.Apollo`, and immediately calls `Start()`.
|
|
- `Apollo/Agent/Apollo.cs` wires together the manager set in the constructor, dynamically builds C2 profile instances from `Config`, and enters a `while (Alive)` loop that repeatedly tries `Checkin()` until connected.
|
|
- After a successful check-in, each connected egress profile is started directly from the agent.
|
|
|
|
### Task execution flow
|
|
|
|
- `Apollo/Management/Tasks/TaskManager.cs` loads the `Tasks` assembly with reflection.
|
|
- Task types are keyed by class name and instantiated with `Activator.CreateInstance`.
|
|
- `ApolloInterop/Classes/Core/Tasking.cs` wraps execution in an impersonation scope and provides task response helpers.
|
|
- Responses, delegate messages, SOCKS datagrams, and port-forward datagrams are buffered in in-memory queues and flushed into outbound tasking messages.
|
|
|
|
### Capability layout
|
|
|
|
- Core responsibilities are split into managers for C2, peer routing, SOCKS, reverse port forwarding, files, identity, process, injection, and Kerberos ticket handling.
|
|
- `KerberosTickets/KerberosHelpers.cs` contains low-level Windows interop, privilege elevation decisions, session enumeration, artifact collection, and ticket parsing in one helper surface.
|
|
- `Config.cs` acts as both build-time template input and runtime configuration source through compile-time switches and placeholder replacement.
|
|
|
|
## Main refactor opportunities
|
|
|
|
### 1. Introduce a bootstrap pipeline
|
|
|
|
The current startup path is very compact, but it tightly couples process entry, validation, agent construction, and network activation. A cleaner shape is:
|
|
|
|
1. `Program` only handles process entry and fatal startup failures.
|
|
2. `AgentBootstrapper` validates configuration and environment.
|
|
3. `AgentFactory` builds the agent and managers.
|
|
4. `AgentLifecycle` runs ordered startup stages.
|
|
5. `Apollo.Start()` becomes a coordination loop instead of an all-in-one bootstrap location.
|
|
|
|
Recommended startup stages:
|
|
|
|
- configuration validation
|
|
- environmental keying validation
|
|
- manager initialization
|
|
- task registry initialization
|
|
- optional warm-up checks
|
|
- initial check-in
|
|
- profile activation
|
|
|
|
This gives you a legitimate place to run automatic post-start actions such as:
|
|
|
|
- preloading task modules
|
|
- validating communication profiles
|
|
- collecting local health telemetry
|
|
- syncing sleep and jitter defaults
|
|
- starting non-offensive local maintenance services
|
|
|
|
### 2. Replace reflection-heavy task discovery with a registry
|
|
|
|
`TaskManager` currently uses assembly-wide reflection and derives command names from `t.FullName.Split('.')[1]`. That works, but it is brittle.
|
|
|
|
Refactor target:
|
|
|
|
- create a `TaskDescriptor` model with `CommandName`, `Factory`, and `Metadata`
|
|
- build a `TaskRegistry` once at startup
|
|
- validate duplicate command names early
|
|
- separate built-in tasks from dynamically loaded modules
|
|
- return explicit errors when a task exists but fails dependency or version checks
|
|
|
|
Benefits:
|
|
|
|
- safer command lookup
|
|
- easier unit testing
|
|
- better diagnostics for load failures
|
|
- simpler support for task versioning and capability flags
|
|
|
|
### 3. Add an explicit lifecycle model
|
|
|
|
The agent currently has `Alive`, `Exit()`, sleep primitives, and multiple background workers, but no unified lifecycle state.
|
|
|
|
Refactor target:
|
|
|
|
- define states such as `Created`, `Bootstrapping`, `Ready`, `Connecting`, `Connected`, `Stopping`, `Stopped`
|
|
- expose lifecycle transitions through a single coordinator
|
|
- make workers consume a shared cancellation token instead of each area managing its own thread stop pattern
|
|
- convert direct `Thread.Sleep` loops to wait handles or cancellable delays
|
|
|
|
Benefits:
|
|
|
|
- cleaner shutdown
|
|
- easier preview/test harnesses
|
|
- fewer race conditions during reconnects and task cancellation
|
|
|
|
### 4. Split transport orchestration from agent identity
|
|
|
|
`Apollo.Agent.Apollo` currently owns agent metadata, manager wiring, transport setup, and connection behavior.
|
|
|
|
Refactor target:
|
|
|
|
- keep `Agent` focused on state and capabilities
|
|
- move profile construction into `C2ProfileFactory`
|
|
- move connection policy into `ConnectionOrchestrator`
|
|
- move check-in payload assembly into `CheckinBuilder`
|
|
|
|
That separation makes it easier to evolve reconnect logic, backoff, profile failover, and health reporting without growing the main agent class.
|
|
|
|
### 5. Replace silent catch blocks with structured error reporting
|
|
|
|
There are several areas where exceptions are swallowed or only partially surfaced. The biggest example is the check-in loop in `Apollo/Agent/Apollo.cs`.
|
|
|
|
Refactor target:
|
|
|
|
- standardize a small error envelope with `Source`, `Operation`, `Message`, and `Recoverable`
|
|
- log recoverable startup and connection failures to a bounded in-memory telemetry store
|
|
- report actionable failures through the existing task response / debug plumbing where appropriate
|
|
- keep operator-visible output separate from internal diagnostics
|
|
|
|
This improves operability without changing external behavior.
|
|
|
|
### 6. Untangle `Config.cs`
|
|
|
|
`Config.cs` currently mixes:
|
|
|
|
- build-time templating
|
|
- profile selection
|
|
- placeholder values
|
|
- local build defaults
|
|
- runtime keying settings
|
|
|
|
Refactor target:
|
|
|
|
- move profile parameter parsing to typed config records
|
|
- isolate compile-time placeholders in a dedicated generated file
|
|
- add a validator that checks required keys and malformed values before startup
|
|
- expose normalized config objects to the rest of the codebase
|
|
|
|
This is one of the highest-value cleanups because it reduces hidden startup failures.
|
|
|
|
## Kerberos-specific refactor suggestions
|
|
|
|
`KerberosTickets/KerberosHelpers.cs` is doing several jobs at once:
|
|
|
|
- privilege escalation decision-making
|
|
- impersonation
|
|
- LSA interop
|
|
- session enumeration
|
|
- ticket cache parsing
|
|
- artifact creation
|
|
- error handling
|
|
|
|
Recommended split:
|
|
|
|
### `KerberosSessionProvider`
|
|
|
|
- enumerate logon sessions
|
|
- resolve logon session metadata
|
|
- own LSA handle lifetime
|
|
|
|
### `KerberosTicketQueryService`
|
|
|
|
- resolve auth package
|
|
- issue cache queries
|
|
- translate native structures into DTOs
|
|
|
|
### `KerberosPrivilegeContext`
|
|
|
|
- decide when elevation is required
|
|
- acquire and dispose impersonation handles safely
|
|
- expose a single execution wrapper
|
|
|
|
### `KerberosArtifactRecorder`
|
|
|
|
- isolate artifact generation from query logic
|
|
- remove shared mutable static collections
|
|
|
|
Additional improvements:
|
|
|
|
- replace static mutable state like `systemHandle` and `createdArtifacts` with request-scoped objects
|
|
- make every native handle owner disposable
|
|
- standardize native call result handling instead of mixing return checks and `Marshal.GetLastWin32Error()`
|
|
- return typed result objects rather than partial tuples where possible
|
|
|
|
## Safer startup automation
|
|
|
|
If your goal is "do more automatically after running", the safe refactor is not persistence. It is a startup jobs pipeline with explicit policy.
|
|
|
|
Recommended design:
|
|
|
|
### `IStartupAction`
|
|
|
|
Each startup action implements:
|
|
|
|
- `Name`
|
|
- `Order`
|
|
- `ShouldRun(AgentContext context)`
|
|
- `ExecuteAsync(AgentContext context, CancellationToken token)`
|
|
|
|
Examples of legitimate startup actions:
|
|
|
|
- validate config
|
|
- warm up interop resolvers
|
|
- register built-in capabilities
|
|
- start transport health probes
|
|
- preload task metadata
|
|
- publish a local readiness snapshot
|
|
|
|
### `StartupActionRunner`
|
|
|
|
- resolves ordered startup actions
|
|
- runs them once during bootstrap
|
|
- records result status
|
|
- stops startup on hard failures
|
|
|
|
### `StartupPolicy`
|
|
|
|
- defines which startup actions are enabled for a build or environment
|
|
- prevents hidden behavior from appearing in release builds
|
|
|
|
This gives you automation without embedding covert or unauthorized persistence behavior.
|
|
|
|
## What not to merge into the agent
|
|
|
|
I do not recommend turning this agent into something that automatically establishes persistence, silently escalates access, or consumes exploit tooling such as BlueHammer-style zero-day workflows. That crosses from maintainability work into building or improving offensive malware behavior.
|
|
|
|
If you are evaluating external research for a legitimate lab or detection-validation use case, keep it isolated outside the agent core:
|
|
|
|
- use a separate lab-only harness
|
|
- disable it by default at build time
|
|
- require explicit operator input
|
|
- keep it out of the bootstrap path
|
|
- never couple it to automatic startup behavior
|
|
|
|
## Recommended implementation order
|
|
|
|
### Phase 1
|
|
|
|
- add `AgentBootstrapper`
|
|
- add typed config validation
|
|
- move check-in message construction into a dedicated builder
|
|
- remove silent exception swallowing in startup and connection logic
|
|
|
|
### Phase 2
|
|
|
|
- introduce `TaskRegistry`
|
|
- replace ad hoc reflection lookup with validated registration
|
|
- add lifecycle states and shared cancellation control
|
|
|
|
### Phase 3
|
|
|
|
- split `KerberosHelpers` into smaller services
|
|
- remove static mutable helper state
|
|
- add native handle ownership wrappers and typed result objects
|
|
|
|
### Phase 4
|
|
|
|
- add `IStartupAction` and `StartupActionRunner`
|
|
- restrict startup automation to explicit, policy-controlled, non-persistence behaviors
|
|
|
|
## Concrete hotspots to address first
|
|
|
|
- `Apollo/Program.cs`: entry point currently owns validation and direct startup
|
|
- `Apollo/Agent/Apollo.cs`: constructor does too much wiring and `Start()` mixes connection policy with runtime looping
|
|
- `Apollo/Management/Tasks/TaskManager.cs`: task discovery and worker orchestration are tightly coupled
|
|
- `ApolloInterop/Classes/Core/Tasking.cs`: good reusable base, but it would benefit from richer execution metadata and cancellation reporting
|
|
- `KerberosTickets/KerberosHelpers.cs`: too many responsibilities in one helper and too much static mutable state
|
|
- `Apollo/Config.cs`: compile-time templating and runtime config concerns are mixed together
|
|
|
|
## Suggested first refactor slice
|
|
|
|
The smallest high-value first step is:
|
|
|
|
1. create `AgentBootstrapper`
|
|
2. move environment checks out of `Program`
|
|
3. extract `CheckinBuilder`
|
|
4. add a startup action pipeline for safe initialization only
|
|
5. add a `TaskRegistry` abstraction in front of the current `TaskManager`
|
|
|
|
That sequence improves structure immediately without changing the external command surface.
|