Summary
Theblockdlls function configures Apollo to prevent non-Microsoft signed DLLs from loading into sacrificial processes created by post-exploitation jobs. This security feature helps evade detection by preventing security products and other third-party DLLs from hooking into processes spawned by Apollo’s post-exploitation commands such as powerpick, execute_assembly, execute_pe, and other commands that require sacrificial processes.
- Needs Admin: False
- Version: 3
- Author: @djhohnstein
Arguments
- block (Boolean) - Enable or disable blocking of non-Microsoft signed DLLs (default: true)
- CLI Name: EnableBlock
- Display Name: Block Non-Microsoft DLLs
Usage
Example 1: Enable DLL Blocking (Default)
Command:Example 2: Disable DLL Blocking
Command:Example 3: Alternative Command Formats
Command:Detailed Summary
Theblockdlls function implements a configuration change that affects how Apollo creates sacrificial processes for post-exploitation commands. Based on the actual source code and verified information from Apollo’s releases:
1. Parameter Processing and Validation
The function handles multiple input formats for operator convenience:- JSON Parameter Structure: Uses
BlockDllsParametersstructure containing a single booleanValuefield mapped from the"block"JSON member - Command Line Parsing: The Python handler (
BlockDllsArguments) processes various text inputs:"true","on"→ Enable DLL blocking (setsblockparameter toTrue)"false","off"→ Disable DLL blocking (setsblockparameter toFalse)- Default value when no parameter specified → Enable DLL blocking (default value is
True)
- Exception Handling: Raises exceptions for invalid command line arguments or missing parameters
2. Core Implementation
The C# implementation is straightforward:- Parameter Deserialization: Uses the agent’s JSON serializer to convert task parameters
- ProcessManager Integration: Calls
BlockDLLs(bool)method on the agent’s ProcessManager instance - Silent Success: Returns empty response body with success status (
CreateTaskResponse("", true)) - No Error Handling: No explicit error handling around the ProcessManager call
3. ProcessManager Implementation
The actual ProcessManager implementation shows how DLL blocking is managed:- Private Field Storage: The
_blockDllsboolean field stores the current DLL blocking state (defaults tofalse) - Simple State Management:
BlockDLLs(bool status)simply updates the_blockDllsfield and returnstrue - Startup Info Integration:
GetStartupInfo()includes theBlockDLLssetting in theApplicationStartupInfostructure - Architecture Awareness: The startup info considers both x64 and x86 process creation
4. Process Creation Integration
The ProcessManager includes additional fields that work together with DLL blocking:- DLL Blocking: Disabled by default (
_blockDlls = false) - Parent Process ID: Set to current Apollo process ID
- x64 Sacrificial Process:
C:\Windows\System32\rundll32.exe(default) - x86 Sacrificial Process:
C:\Windows\SysWOW64\rundll32.exe(default) - Process Arguments:
nullby default for both architectures
5. Sacrificial Process Creation
The ProcessManager creates new processes through theNewProcess method:
- SacrificialProcess Class: Uses a dedicated
SacrificialProcessclass for process creation - Startup Configuration: The
ApplicationStartupInfostructure includes the DLL blocking setting - Agent Context: Passes the agent instance to the new process for integration
- Suspension Support: Can create processes in suspended state for injection scenarios
6. Integration with SpawnTo Configuration
The ProcessManager integrates DLL blocking with sacrificial process configuration:- Architecture-Specific: Maintains separate application paths for x64 and x86 processes
- Command Line Arguments: Supports configurable arguments for each architecture
- Combined Configuration: The
GetStartupInfo()method combines the spawnto configuration with DLL blocking settings - Always Successful: Returns
trueindicating successful configuration update
7. PPID Integration
The ProcessManager also manages parent process ID spoofing alongside DLL blocking:- Session Validation: Ensures target parent process is in the same session as the current Apollo process
- Process Validation: Verifies the target PID exists using
Process.GetProcessById() - Error Handling: Uses try-catch with silent failure for invalid PIDs
- Combined with DLL Blocking: The PPID setting is included in
ApplicationStartupInfoalong with DLL blocking
8. ApplicationStartupInfo Structure
The ProcessManager populates theApplicationStartupInfo structure with all configuration:
- Application Path: Architecture-specific executable path
- Arguments: Architecture-specific command line arguments
- Parent Process ID: Configured PPID for process creation
- DLL Blocking: Current DLL blocking state
- Architecture Selection: Chooses between x64 and x86 configurations based on parameter
9. Command Parsing Implementation Details
The Python argument parser implements flexible input handling:- JSON Support: Accepts JSON-formatted parameters
- Case Insensitive: Converts input to lowercase before processing
- Multiple Formats: Supports “true/false” and “on/off” syntax
- Error Handling: Raises exceptions for invalid inputs or empty commands
- Parameter Addition: Uses
add_arg()to set the boolean parameter
10. Display and Response Handling
The command response handling is implemented in both C# and Python components: C# Response:- Silent Execution: C# component returns empty response body
- Display Parameters: Python component sets display parameters to “true” or “false”
- Success Status: Both components indicate successful task completion
- Guaranteed Success: ProcessManager.BlockDLLs() always returns
true, ensuring successful task completion
11. Configuration Scope and Persistence
Based on the ProcessManager implementation:- Private Field Storage: The
_blockDllsfield is stored as a private instance variable in the ProcessManager - Agent Lifetime: Configuration persists for the current agent session since it’s stored in memory
- Global Impact: Affects all subsequent calls to
GetStartupInfo()which provides configuration for process creation - Override Capability: Can be changed by issuing another
blockdllscommand (callsBlockDLLs()again) - No Persistence: Does not persist across agent restarts since it’s stored in memory
- Default State: Defaults to
false(DLL blocking disabled) when ProcessManager is initialized
12. Integration with Related Commands
The ProcessManager integratesblockdlls with other process management commands:
- spawnto_x86/spawnto_x64: Uses
SetSpawnTo()to configure sacrificial process executables - ppid: Uses
SetPPID()to configure parent process ID spoofing - Combined Configuration: All settings are combined in
ApplicationStartupInfofor process creation - No Conflicts: All settings work together without conflicts since they’re stored in separate fields
13. Operational Considerations
Implementation Details (from actual source code):- Simple State Management: The implementation is straightforward - just setting a boolean flag
- Always Successful: The
BlockDLLs()method always returnstrue, indicating no validation or error checking - Memory-Based: All configuration is stored in memory within the ProcessManager instance
- Architecture Aware: The system maintains separate configurations for x64 and x86 processes
- DLL Blocking: Disabled by default (
_blockDlls = false) - Sacrificial Processes: Uses
rundll32.exefrom System32 (x64) and SysWOW64 (x86) by default - Parent Process: Uses current Apollo process as parent by default
- No Arguments: Process arguments are
nullby default
- The
ApplicationStartupInfostructure is the key integration point where all process creation settings are combined - The
SacrificialProcessclass receives these settings and implements the actual process creation - The ProcessManager acts as a centralized configuration store for all process creation parameters
MITRE ATT&CK Mapping
- T1055 - Process Injection
- T1562 - Impair Defenses
- T1562.001 - Disable or Modify Tools
APIs Used and Their Purposes
| API | Purpose | DLL | Documentation |
|---|---|---|---|
IAgent.GetProcessManager().BlockDLLs(bool) | Configures DLL blocking for sacrificial processes | Apollo Agent | Internal Apollo API |
JsonSerializer.Deserialize<BlockDllsParameters>() | Deserializes JSON task parameters | Apollo Agent | Internal Apollo JSON serialization |
IAgent.GetTaskManager().AddTaskResponseToQueue() | Queues task response for return to Mythic | Apollo Agent | Internal Apollo API |
Security Considerations
Operational Security Benefits
- Detection Evasion: Prevents security products from loading monitoring DLLs into sacrificial processes
- Clean Execution Environment: Sacrificial processes run without third-party modifications
- Stealth Enhancement: Reduces attack surface visible to security monitoring tools
Potential Operational Impacts
- Tool Compatibility: Some tools may fail if they require non-Microsoft DLLs
- Functionality Loss: Advanced features of some tools may be disabled
- Debug Difficulty: Troubleshooting becomes more difficult when expected DLLs are blocked
Configuration Management
- Global Setting: Affects all sacrificial processes created after the command is issued
- Session Scope: Setting persists only for the current agent session
- Override Capability: Can be changed at any time during agent execution
Limitations
- Microsoft-Only Restriction: Only Microsoft-signed DLLs are allowed in sacrificial processes
- Global Application: Cannot selectively apply to specific commands
- Session Persistence: Configuration does not persist across agent restarts
- No Validation: No confirmation that the setting was successfully applied
- Implementation Dependency: Effectiveness depends on the underlying ProcessManager implementation
- Compatibility Issues: Apollo’s releases indicate the feature required multiple hotfixes
Troubleshooting
Common Issues and Solutions
| Issue | Possible Causes | Solutions |
|---|---|---|
| Tool fails after enabling DLL blocking | Tool requires non-Microsoft DLLs | Disable DLL blocking with blockdlls false |
| No visible change in behavior | Setting may be already configured | Check current setting with other process management commands |
| Command execution error | Invalid command line syntax | Use supported formats: true/false or on/off |
Debugging Steps
- Verify Syntax: Ensure command uses supported parameter formats
- Test Impact: Execute a sacrificial process command to test the setting’s effect
- Toggle Setting: Try both enabling and disabling to verify functionality
- Check Compatibility: Test specific tools that may require third-party DLLs