security
PROCESS INJECTION DETECTION LLD
Tamper resistance, sandboxing, remote scan policy, and security deep dives.
Context Rail
Tags and Themes
On This Page
- 1. Purpose
- 2. Scope
- 3. Current Implementation Summary
- 3.1 Where the logic lives
- 3.2 Process-protection probe set in runner
- 4. Current Detection Internals (Windows)
- 4.1 Probe: process_injection
- 4.2 Probe: trampoline
- 4.3 Probe: iat_got
- 4.4 Probe: module_integrity
- 4.5 Probe: memory_page_anomaly
- 5. Current End-to-End Flow
- 6. Why this design is useful
- 7. Current Gaps and Limitations
- 8. Future Expansion: Other Processes (Assume Required Privileges)
- 8.1 Design principles
- 8.2 Proposed architecture components
- 8.3 Remote inspection heuristics for other processes
- 8.4 Suggested confidence model for multi-process expansion
- 8.5 Data model proposal
- 8.6 Scan loop pseudocode
- 8.7 State machine for one process
- 9. Integration Plan for Mutant Codebase
- Phase 1: Refactor and abstraction
- Phase 2: Multi-process read-only detector
- Phase 3: Controlled enforcement
- Phase 4: Performance and quality hardening
- 10. Testing Strategy
- 10.1 Unit tests
- 10.2 Integration tests
- 10.3 Performance tests
- 11. Security and Safety Notes
- 12. Practical Student Takeaway
- 13. Companion Implementation Blueprint (Code-Level)
- 13.1 Proposed file map (new and existing)
- 13.2 Proposed domain model (security/processscan_types.go)
- 13.3 Config and env gates (security/processscan_config.go)
- 13.4 Correlator contract (security/processscan_correlator.go)
- 13.5 Windows scanner contract (security/processscan_windows.go)
- 13.6 Cross-platform stub (security/processscan_windows_stub.go)
- 13.7 Manager/orchestration (security/processscan_manager.go)
- 13.8 Runner integration plan (runner/runner.go)
- 13.9 Telemetry schema extension (security/telemetry.go)
- 13.10 Test blueprint
- 13.11 Incremental delivery checklist
- 13.13 Deep-dive reference
- 13.12 Mermaid implementation dependency graph
- 13.13 Practical coding tip for this repo
Process Injection Detection LLD
1. Purpose
This Low Level Design (LLD) explains how Mutant currently detects process injection-related tampering and how to expand this into a richer, multi-process detector in the future.
Primary goals:
- Explain what is implemented today.
- Explain why it works and where it is weak.
- Propose a robust future design for scanning other processes when the agent has enough privileges.
2. Scope
In scope:
- Windows process-injection related anti-tamper probes.
- Runner-side enforcement and confidence thresholding.
- Future architecture for cross-process detection.
- Data model, scoring, and rollout plan.
Out of scope:
- Offensive code or exploit implementation.
- Kernel driver implementation.
- Full EDR product design.
3. Current Implementation Summary
3.1 Where the logic lives
- Probe router: security/antitamper_routing.go
- Probe engine: security/antitamper_probe.go
- Windows probe implementations: security/antitamper_windows.go
- Probe names and confidences: security/antitamper_constants.go
- Runner enforcement: runner/runner.go
- Process protection env gate: security/const.go
3.2 Process-protection probe set in runner
Runner currently checks this set before decode and before execution:
- process_injection
- trampoline
- iat_got
- module_integrity
- memory_page_anomaly
Diagnostic note:
- This 5-probe set is used for runner enforcement only.
- Builtin diagnostics (for example
security_statusbuiltins) invoke broader probe lists for observability and troubleshooting.
Enforcement condition:
- If any signal has detected=true and confidence >= 80, runner treats it as process protection event and applies tamper policy.
Gates:
- runtime setting=1 must be enabled.
- runtime setting controls runner-side enforcement.
4. Current Detection Internals (Windows)
4.1 Probe: process_injection
Function: detectProcessInjection()
Signal sources:
- Environment markers
- COR_ENABLE_PROFILING
- COR_PROFILER
- COR_PROFILER_PATH
- JAVA_TOOL_OPTIONS
- _NT_SYMBOL_PATH
- Process list markers via tasklist output
- processhacker
- x64dbg
- ollydbg
- cheat engine
- frida
- dnspy
Confidence strategy:
- Base marker hit: 70
- Environment-only hit: 90
- Env + process hit: 95
4.2 Probe: trampoline
Function: detectTrampoline()
Target APIs include selected ntdll and kernel32 exports such as NtOpenProcess, NtWriteVirtualMemory, NtCreateThreadEx, CreateRemoteThread.
Method:
- Resolve function address.
- Read first bytes of function prologue.
- Match common hook trampoline signatures:
- Relative JMP/CALL
- Indirect JMP pattern
- movabs+jmp register pattern
Confidence:
- One hit: 75
- Multi-hit (>=2): 90
4.3 Probe: iat_got
Function: detectIATGOT()
Method:
- Resolve sensitive exports from ntdll.
- Query memory info for each resolved address.
- Compare allocation base with expected module handle.
- If base differs, export may be redirected/hooked.
Confidence:
- Redirected export hit: 90
4.4 Probe: module_integrity
Function: detectModuleIntegrity()
Method:
- Check whether suspicious instrumentation DLL markers are loaded.
- Example markers include frida and detour-style module names.
Confidence:
- Suspicious module marker hit: 85
4.5 Probe: memory_page_anomaly
Function: detectMemoryPageAnomaly()
Method:
- Resolve addresses of selected sensitive APIs.
- Query memory protection for those addresses.
- Flag when code pages are RWX (PAGE_EXECUTE_READWRITE).
Confidence:
- RWX anomaly hit: 92
5. Current End-to-End Flow
6. Why this design is useful
- Fast and low-overhead.
- Cross-checks different evidence types (env/process/hooks/pages/modules).
- Confidence model avoids hard fail on weak single marker.
- Runner enforces policy at two useful stages.
7. Current Gaps and Limitations
- Mostly self-process visibility, not full ecosystem visibility.
- Marker-based checks can have false positives.
- tasklist string matching is coarse.
- No deep remote-process memory/thread correlation yet.
- No baseline learning per process image hash.
8. Future Expansion: Other Processes (Assume Required Privileges)
If we have sufficient privileges (for example, SeDebugPrivilege where needed), we can extend from self-protection to host-level process injection detection.
8.1 Design principles
- Least privilege first, escalate only when necessary.
- Multi-signal correlation, not single-signature verdicts.
- Safe-by-default: detection mode first, enforcement later.
- Explainability: every verdict must contain evidence.
8.2 Proposed architecture components
- ProcessEnumerator
- Enumerate process IDs and metadata.
- AccessController
- Acquire handles with minimal rights.
- Escalate rights only for deeper checks.
- RemoteInspector
- Module map checks.
- Memory region checks via VirtualQueryEx.
- Thread start address checks.
- SignalCorrelator
- Aggregate evidence and compute confidence.
- ActionEngine
- Emit telemetry.
- Apply policy (warn, isolate, terminate) per mode.
8.3 Remote inspection heuristics for other processes
When allowed by rights and policy:
- Process metadata signals
- Parent-child anomalies.
- Unexpected image path or signer mismatch.
- Module signals
- Unsigned or untrusted modules in sensitive processes.
- User-writable path DLLs loaded into high-trust processes.
- Memory signals
- RWX private regions.
- RX private regions without mapped image backing.
- Thread signals
- Thread start address inside suspicious private pages.
- Start address not inside known module boundaries.
- API-hook signals
- Prologue patch patterns in key exports.
- IAT/GOT redirection anomalies.
8.4 Suggested confidence model for multi-process expansion
Use weighted additive scoring and cap at 100.
Example weights:
- Suspicious env or tool markers: +20
- Hook prologue hit on critical API: +25
- IAT/GOT redirection hit: +30
- RWX private executable region: +30
- Thread start in private executable memory: +35
- Unsigned injected module in trusted process: +35
Then convert score to action bands:
- 0-39: informational
- 40-69: suspicious, monitor only
- 70-84: high risk, block sensitive actions
- 85-100: critical, hard response as per policy
8.5 Data model proposal
type RemoteProcessSignal struct {
ProcessID uint32
ProcessName string
SignalName string
Detected bool
Confidence int
Evidence map[string]string
Timestamp int64
}
type ProcessRiskVerdict struct {
ProcessID uint32
FinalScore int
RiskBand string
Signals []RemoteProcessSignal
}
8.6 Scan loop pseudocode
for process in enumerateProcesses():
h = openProcessWithLeastPrivilege(process)
if h unavailable:
continue
signals = []
signals += checkModuleAnomalies(h)
signals += checkMemoryRegions(h)
signals += checkThreadStartAddresses(h)
signals += checkHookPatterns(h)
verdict = correlate(signals)
emitTelemetry(verdict)
applyPolicyIfNeeded(verdict)
8.7 State machine for one process
9. Integration Plan for Mutant Codebase
Recommended phased rollout:
Phase 1: Refactor and abstraction
- Extract existing process-protection probes behind a detector interface.
- Keep current behavior unchanged.
- Add structured evidence fields to signal detail.
Phase 2: Multi-process read-only detector
- Add process enumerator and remote inspectors in observe-only mode.
- Emit telemetry only, no enforcement.
- Tune confidence weights with test datasets.
Phase 3: Controlled enforcement
- Add policy bands for remote-process verdicts.
- Enable enforcement only in secure mode or explicit opt-in.
- Keep allowlist support for enterprise compatibility tools.
Phase 4: Performance and quality hardening
- Sampling and rate limiting.
- Baseline cache by process image hash.
- Differential scanning to avoid repeated full scans.
10. Testing Strategy
10.1 Unit tests
- Signature parsers and prologue matchers.
- Confidence scoring math.
- Correlator risk-band boundaries.
10.2 Integration tests
- Mock process table and module maps.
- Validate scanner behavior on access denied.
- Validate action decisions for synthetic signal combinations.
10.3 Performance tests
- Scan latency per N processes.
- CPU and memory overhead budget.
- Telemetry volume under burst conditions.
11. Security and Safety Notes
- Keep strict audit logs for every high-risk verdict.
- Never auto-kill critical system processes without policy safeguards.
- Use signed allowlists for known-good enterprise agents.
- Prefer deterministic evidence over opaque black-box scoring.
12. Practical Student Takeaway
If you remember one thing: strong process injection detection is not one magic API call. It is a pipeline:
- gather multiple low-level signals,
- correlate them into confidence,
- apply a clear policy based on operating mode,
- keep observability for debugging and tuning.
That is exactly the direction this design follows.
13. Companion Implementation Blueprint (Code-Level)
This section maps the future architecture to concrete files, interfaces, function signatures, and rollout tasks inside this repository.
13.1 Proposed file map (new and existing)
Reuse existing files:
- security/antitamper_probe.go
- security/antitamper_routing.go
- security/antitamper_constants.go
- security/telemetry.go
- runner/runner.go
Add new files (recommended):
- security/processscan_types.go
- security/processscan_config.go
- security/processscan_correlator.go
- security/processscan_manager.go
- security/processscan_windows.go
- security/processscan_windows_stub.go
- security/processscan_windows_test.go
- security/processscan_correlator_test.go
Why this split:
- Keep Windows syscall/API interactions isolated.
- Keep scoring logic platform-agnostic and testable.
- Keep manager/orchestration independent from detection primitives.
13.2 Proposed domain model (security/processscan_types.go)
Status: implemented (with current fields in code).
package security
type SignalSource string
const (
SignalSourceEnv SignalSource = "env"
SignalSourceProcess SignalSource = "process"
SignalSourceModule SignalSource = "module"
SignalSourceMemory SignalSource = "memory"
SignalSourceThread SignalSource = "thread"
SignalSourceHook SignalSource = "hook"
)
type RemoteProcessTarget struct {
PID uint32
Name string
ImagePath string
ParentPID uint32
SessionID uint32
IsProtected bool
}
type RemoteProcessSignal struct {
PID uint32
Name string
Source SignalSource
SignalName string
Detected bool
Weight int
Evidence map[string]string
}
type ProcessRiskVerdict struct {
PID uint32
Name string
FinalScore int
RiskBand string
Signals []RemoteProcessSignal
}
13.3 Config and env gates (security/processscan_config.go)
Current runtime settings:
- runtime setting
- runtime setting (off, observe, enforce)
- runtime setting
- runtime setting
- runtime setting
Suggested struct:
type RemoteScanConfig struct {
Enabled bool
Mode string // off|observe|enforce
MaxProcesses int
IntervalMs int
Allowlist map[string]struct{}
HighRiskScore int
CriticalScore int
}
13.4 Correlator contract (security/processscan_correlator.go)
Status: implemented and covered by unit tests.
func CorrelateProcessSignals(target RemoteProcessTarget, signals []RemoteProcessSignal) ProcessRiskVerdict
Rules:
- Sum weights only for detected=true signals.
- Cap final score at 100.
- Assign risk bands:
- score < 40 => low
- 40 <= score < 70 => medium
- 70 <= score < 85 => high
- score >= 85 => critical
- Keep all evidence in verdict for explainability.
13.5 Windows scanner contract (security/processscan_windows.go)
type ProcessEnumerator interface {
ListTargets(cfg RemoteScanConfig) ([]RemoteProcessTarget, error)
}
type RemoteInspector interface {
InspectTarget(target RemoteProcessTarget, cfg RemoteScanConfig) ([]RemoteProcessSignal, error)
}
func ScanRemoteProcessesWindows(cfg RemoteScanConfig) ([]ProcessRiskVerdict, error)
Current implementation notes:
- Scanner hook and contract are implemented.
- Current windows scanner returns empty verdicts (
nil, nil) as safe no-op. - Enumerator/inspector depth remains planned work.
13.6 Cross-platform stub (security/processscan_windows_stub.go)
Build tag: !windows
Behavior:
- Return empty verdict list.
- Return nil error.
- Keep caller flow simple and safe.
13.7 Manager/orchestration (security/processscan_manager.go)
Current API:
func RunRemoteProcessScan(stage string) ([]ProcessRiskVerdict, bool, error)
Behavior:
- Parse config and check gates.
- If disabled, return enabled=false.
- Run platform scanner.
- Emit telemetry per verdict.
- Return results for runner policy integration.
13.8 Runner integration plan (runner/runner.go)
Status: implemented.
Add one function call in enforcement pipeline after existing enforceProcessProtection:
func enforceRemoteProcessProtection(secureMode bool, stage string) error
Decision model:
- observe mode:
- record telemetry only
- never block execution
- enforce mode:
- if any verdict score >= critical threshold, apply tamper response
- if high threshold only, optionally warn or delay by policy
13.9 Telemetry schema extension (security/telemetry.go)
Current event names:
- remote_process_scan_invoked
- remote_process_scan_error
- remote_process_suspicious
- remote_process_critical
Recommended fields:
- stage
- pid
- process_name
- score
- risk_band
- top_signals
13.10 Test blueprint
Unit tests:
- processscan_correlator_test.go
- score caps
- risk band boundaries
- empty signal set behavior
- processscan_config parsing tests
- invalid mode fallback
- max process defaults
Windows tests:
- processscan_windows_test.go
- mocked enumerator/inspector behavior
- access denied path
- no targets path
Runner tests:
- new tests in runner/runner_test.go
- observe mode does not block
- enforce mode blocks on critical verdict
13.11 Incremental delivery checklist
Sprint A (scaffolding):
- Add types/config/correlator with tests. [done]
- Add manager with no-op windows scanner. [done]
- Add telemetry wiring. [done]
Sprint B (read-only scanner):
- Implement enumeration + one inspector (modules).
- Enable observe mode only.
- Collect metrics in CI and staging.
Sprint C (full signal set):
- Add memory/thread/hook inspectors.
- Tune scoring against false-positive datasets.
- Publish calibration notes in docs.
Sprint D (enforcement):
- Enable enforce mode behind env gate. [done]
- Roll out to secure profile first. [in progress]
- Keep emergency kill-switch runtime setting. [done via mode/off gate]
13.13 Deep-dive reference
For a code-accurate deep dive on current remote-scan architecture and behavior, see:
13.12 Mermaid implementation dependency graph
13.13 Practical coding tip for this repo
Follow the same OS pattern already used in security package:
- Keep Windows implementation in *_windows.go.
- Keep !windows stubs returning safe defaults.
- Keep routing and policy logic in OS-agnostic files.
This will preserve build stability and avoid cross-platform regressions.