515 lines
14 KiB
Markdown
515 lines
14 KiB
Markdown
# Cazalla - Mythic C2 Agent
|
|
|
|
<div align="center">
|
|
|
|

|
|
|
|
**A Windows implant written in C for the Mythic C2 Framework**
|
|
|
|
[](LICENSE.md)
|
|
[](https://github.com/its-a-feature/Mythic)
|
|
[]()
|
|
|
|
</div>
|
|
|
|
---
|
|
|
|
## 📋 Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Features](#features)
|
|
- [Installation](#installation)
|
|
- [Supported Commands](#supported-commands)
|
|
- [SOCKS Proxy Support](#socks-proxy-support)
|
|
- [Communication Protocol](#communication-protocol)
|
|
- [Configuration](#configuration)
|
|
- [Development](#development)
|
|
- [Troubleshooting](#troubleshooting)
|
|
- [Credits](#credits)
|
|
|
|
---
|
|
|
|
## 🎯 Overview
|
|
|
|
**Cazalla** is a lightweight Windows implant written in C, designed to work seamlessly with the [Mythic C2 Framework](https://github.com/its-a-feature/Mythic). It provides essential post-exploitation capabilities including file system manipulation, process enumeration, command execution, and SOCKS proxy functionality.
|
|
|
|
This project was inspired by the article [How to build your own Mythic agent in C](https://red-team-sncf.github.io/how-to-create-your-own-mythic-agent-in-c.html) and has been extended with additional features and improvements.
|
|
|
|
**Developed by:** Kaseya OFSTeam
|
|
|
|
---
|
|
|
|
## ✨ Features
|
|
|
|
- **Lightweight & Portable**: Minimal dependencies, compiled with MinGW for Windows targets
|
|
- **Full Mythic Integration**: Native support for Mythic's translator pattern and RPC system
|
|
- **SOCKS Proxy**: Route traffic through the implant with built-in SOCKS5 support
|
|
- **Dynamic Sleep**: Automatically adjusts beacon interval based on proxy activity
|
|
- **Custom Binary Protocol**: Efficient binary communication with base64 encoding
|
|
- **Modular Commands**: Easy to extend with new capabilities
|
|
|
|
---
|
|
|
|
## 📦 Installation
|
|
|
|
### Prerequisites
|
|
|
|
1. **Mythic Server** (v3.x or later) installed and running
|
|
2. Clone this repository
|
|
|
|
### Install Cazalla on Mythic
|
|
|
|
```bash
|
|
cd ~/Mythic
|
|
./mythic-cli install github https://github.com/<your-org>/Cazalla
|
|
```
|
|
|
|
Or install from local directory:
|
|
|
|
```bash
|
|
./mythic-cli install folder /path/to/Cazalla
|
|
```
|
|
|
|
### Build the Agent
|
|
|
|
Cazalla can be built directly from the Mythic UI:
|
|
|
|
1. Navigate to **Payloads** → **Create Payload**
|
|
2. Select **Cazalla** as the payload type
|
|
3. Configure build parameters (C2 profile, sleep interval, etc.)
|
|
4. Click **Build**
|
|
|
|
The agent will be cross-compiled for Windows using MinGW in a Docker container.
|
|
|
|
---
|
|
|
|
## 🛠️ Supported Commands
|
|
|
|
### File System Operations
|
|
|
|
| Command | Description | Example |
|
|
|---------|-------------|---------|
|
|
| `ls` | List directory contents | `ls C:\Users` |
|
|
| `cd` | Change working directory | `cd C:\Windows\System32` |
|
|
| `pwd` | Print current directory | `pwd` |
|
|
| `cp` | Copy files | `cp source.txt dest.txt` |
|
|
| `mkdir` | Create directory | `mkdir C:\temp\new_folder` |
|
|
| `rm` | Delete file or directory | `rm C:\temp\file.txt` |
|
|
|
|
### Execution & Control
|
|
|
|
| Command | Description | Example |
|
|
|---------|-------------|---------|
|
|
| `shell` | Execute shell command | `shell whoami` |
|
|
| `sleep` | Adjust beacon interval | `sleep {"seconds":30,"jitter":0}` |
|
|
| `exit` | Terminate the implant | `exit` |
|
|
|
|
### System Information
|
|
|
|
| Command | Description | Example |
|
|
|---------|-------------|---------|
|
|
| `ps` | List running processes | `ps` |
|
|
|
|
### Network Operations
|
|
|
|
| Command | Description | Example |
|
|
|---------|-------------|---------|
|
|
| `socks` | Start/stop SOCKS proxy | `socks {"action":"start","port":7002}` |
|
|
|
|
---
|
|
|
|
## 🌐 SOCKS Proxy Support
|
|
|
|
Cazalla includes full SOCKS5 proxy support, allowing you to route traffic through the implant to reach internal network resources.
|
|
|
|
### How It Works
|
|
|
|
1. **Mythic opens a SOCKS port** on the server (default: `7002`)
|
|
2. **Client connects** to Mythic's SOCKS port (e.g., via `proxychains`)
|
|
3. **Mythic forwards** SOCKS traffic to the agent with a unique `server_id` per connection
|
|
4. **Agent establishes** the actual connection to the target host
|
|
5. **Bidirectional relay** between client ↔ Mythic ↔ Agent ↔ Target
|
|
|
|
### Commands
|
|
|
|
```bash
|
|
# Start SOCKS proxy on port 7002
|
|
socks {"action":"start","port":7002}
|
|
|
|
# Stop SOCKS proxy
|
|
socks {"action":"stop","port":7002}
|
|
```
|
|
|
|
### Using the Proxy
|
|
|
|
After starting SOCKS, configure your tools to use the proxy:
|
|
|
|
#### With proxychains
|
|
|
|
```bash
|
|
# Edit /etc/proxychains.conf
|
|
[ProxyList]
|
|
socks5 <mythic_server_ip> 7002
|
|
|
|
# Use with any tool
|
|
proxychains curl https://internal-server.local
|
|
proxychains nmap -sT 192.168.1.0/24
|
|
```
|
|
|
|
#### With curl
|
|
|
|
```bash
|
|
curl --socks5 <mythic_server_ip>:7002 https://internal-server.local
|
|
```
|
|
|
|
#### With Firefox/Browser
|
|
|
|
Configure SOCKS proxy in browser settings:
|
|
- **SOCKS Host**: `<mythic_server_ip>`
|
|
- **Port**: `7002`
|
|
- **SOCKS v5**: Enabled
|
|
|
|
### Mythic Configuration for SOCKS
|
|
|
|
To expose SOCKS ports externally (not just localhost), edit `~/Mythic/.env`:
|
|
|
|
```bash
|
|
# Allow SOCKS ports to bind on 0.0.0.0 (all interfaces)
|
|
MYTHIC_SERVER_DYNAMIC_PORTS_BIND_LOCALHOST_ONLY="false"
|
|
|
|
# Define dynamic port range for SOCKS
|
|
MYTHIC_SERVER_DYNAMIC_PORTS="7000-7010"
|
|
|
|
# Optional: Use host networking for direct port exposure
|
|
MYTHIC_DOCKER_NETWORKING="host"
|
|
```
|
|
|
|
After editing, restart Mythic:
|
|
|
|
```bash
|
|
cd ~/Mythic
|
|
sudo ./mythic-cli restart
|
|
```
|
|
|
|
Verify the port is open:
|
|
|
|
```bash
|
|
sudo netstat -tlnp | grep 7002
|
|
# Should show: tcp 0.0.0.0:7002 0.0.0.0:* LISTEN
|
|
```
|
|
|
|
### Performance Considerations
|
|
|
|
- **Latency**: Proxy speed depends on beacon interval. SOCKS mode automatically reduces sleep to 100ms for responsive connections.
|
|
- **Throughput**: Suitable for interactive sessions and moderate data transfer. Not optimized for large file transfers.
|
|
- **Concurrent Connections**: Supports multiple simultaneous SOCKS connections with independent `server_id` tracking.
|
|
|
|
### Technical Details
|
|
|
|
#### Binary Protocol (0xF5 SOCKS Block)
|
|
|
|
Agent and translator communicate SOCKS data using a custom binary block:
|
|
|
|
```
|
|
[0xF5] [ext_len:4] [server_id:4] [exit:4] [b64_len:4] [base64_data:N]
|
|
```
|
|
|
|
- `0xF5`: SOCKS block marker
|
|
- `ext_len`: Total extension length (remaining bytes)
|
|
- `server_id`: Unique connection ID from Mythic
|
|
- `exit`: `1` if connection should close, `0` otherwise
|
|
- `b64_len`: Length of base64-encoded payload
|
|
- `base64_data`: Base64-encoded raw bytes
|
|
|
|
#### Agent Implementation
|
|
|
|
- **File**: `socks_manager.c` / `socks_manager.h`
|
|
- **Commands**: `0x60` (START_SOCKS), `0x61` (STOP_SOCKS)
|
|
- **Thread Model**: One reader thread per active connection
|
|
- **Socket Timeout**: 60 seconds for idle connections
|
|
|
|
---
|
|
|
|
## 📡 Communication Protocol
|
|
|
|
Cazalla uses a custom binary protocol for efficient communication with Mythic.
|
|
|
|
### Message Structure
|
|
|
|
#### Agent → Mythic
|
|
|
|
```
|
|
[UUID:36] [Action:1] [Body:N]
|
|
```
|
|
|
|
- **UUID**: 36-byte agent identifier (ASCII)
|
|
- **Action**: 1-byte action code (e.g., `0x80` for GET_TASKING, `0x81` for POST_RESPONSE)
|
|
- **Body**: Variable-length payload
|
|
|
|
#### Mythic → Agent
|
|
|
|
```
|
|
[Action:1] [Body:N]
|
|
```
|
|
|
|
- **Action**: 1-byte action code
|
|
- **Body**: Variable-length payload (tasks, SOCKS data, etc.)
|
|
|
|
### Action Codes
|
|
|
|
| Code | Direction | Description |
|
|
|------|-----------|-------------|
|
|
| `0x80` | Agent → Mythic | GET_TASKING (request new tasks) |
|
|
| `0x81` | Agent → Mythic | POST_RESPONSE (send task output) |
|
|
| `0xF5` | Bidirectional | SOCKS data block |
|
|
|
|
### Task Structure
|
|
|
|
Tasks sent to the agent include:
|
|
|
|
```
|
|
[TaskUUID:36] [CommandID:1] [Parameters:N]
|
|
```
|
|
|
|
Example command IDs:
|
|
- `0x01`: Shell command
|
|
- `0x10`: List directory
|
|
- `0x60`: Start SOCKS
|
|
- `0x61`: Stop SOCKS
|
|
|
|
### Encoding
|
|
|
|
All binary data is base64-encoded for transport over HTTP/HTTPS.
|
|
|
|
---
|
|
|
|
## ⚙️ Configuration
|
|
|
|
### Agent Build Parameters
|
|
|
|
When building from Mythic UI:
|
|
|
|
- **Callback Host**: C2 server address
|
|
- **Callback Port**: C2 server port (default: 443)
|
|
- **User Agent**: HTTP User-Agent string
|
|
- **Sleep**: Initial beacon interval in seconds (default: 10)
|
|
- **Jitter**: Random delay percentage (0-100)
|
|
|
|
### Compile-Time Options
|
|
|
|
Edit `Config.h` before building:
|
|
|
|
```c
|
|
#define INITIAL_SLEEP_MS 10000 // Default sleep: 10 seconds
|
|
#define SOCKS_ACTIVE_SLEEP_MS 100 // Sleep when SOCKS active: 100ms
|
|
#define SOCKS_TIMEOUT_SEC 60 // Socket read timeout
|
|
```
|
|
|
|
### Debug Mode
|
|
|
|
Enable verbose logging by defining `DEBUG_SOCKS` during compilation:
|
|
|
|
```bash
|
|
CFLAGS="-DDEBUG_SOCKS" make
|
|
```
|
|
|
|
This enables:
|
|
- `[MAINDBG]`: Main loop and sleep adjustments
|
|
- `[CMDDBG]`: Command parsing
|
|
- `[SOCKSDBG]`: Connection lifecycle
|
|
- `[SLEEPDBG]`: Dynamic sleep changes
|
|
|
|
---
|
|
|
|
## 🔧 Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
Cazalla/
|
|
├── agent_code/cazalla/ # C source code
|
|
│ ├── main.c # Entry point
|
|
│ ├── cazalla.c/h # Main loop
|
|
│ ├── comandos.c/h # Command handlers
|
|
│ ├── paquete.c/h # Packet creation
|
|
│ ├── transporte.c/h # HTTP transport (WinHTTP)
|
|
│ ├── socks_manager.c/h # SOCKS proxy logic
|
|
│ ├── checkin.c/h # Initial check-in
|
|
│ └── Makefile # Build configuration
|
|
├── agent_functions/ # Python command definitions
|
|
│ ├── ls.py, cd.py, pwd.py # File system commands
|
|
│ ├── shell.py, sleep.py # Execution control
|
|
│ ├── socks.py # SOCKS proxy command
|
|
│ └── builder.py # Payload builder
|
|
├── translator/ # Mythic ↔ Agent translation
|
|
│ ├── translator.py # Main translator
|
|
│ ├── commands_from_c2.py # Mythic JSON → Binary
|
|
│ └── commands_from_implant.py # Binary → Mythic JSON
|
|
└── browser_scripts/ # Mythic UI enhancements
|
|
├── ls.js # Directory listing formatter
|
|
└── ps.js # Process list formatter
|
|
```
|
|
|
|
### Adding New Commands
|
|
|
|
1. **Define command in Python** (`agent_functions/my_command.py`):
|
|
|
|
```python
|
|
from mythic_container.MythicCommandBase import *
|
|
|
|
class MyCommandArguments(TaskArguments):
|
|
def __init__(self, command_line, **kwargs):
|
|
super().__init__(command_line, **kwargs)
|
|
self.args = [
|
|
CommandParameter(name="arg1", type=ParameterType.String)
|
|
]
|
|
|
|
class MyCommandCommand(CommandBase):
|
|
cmd = "my_command"
|
|
needs_admin = False
|
|
help_cmd = "my_command <arg1>"
|
|
description = "Does something useful"
|
|
version = 1
|
|
argument_class = MyCommandArguments
|
|
|
|
async def create_go_tasking(self, taskData: PTTaskMessageAllData):
|
|
response = PTTaskCreateTaskingMessageResponse(
|
|
TaskID=taskData.Task.ID,
|
|
Success=True,
|
|
)
|
|
return response
|
|
|
|
async def process_response(self, task: PTTaskMessageAllData, response: any):
|
|
resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True)
|
|
return resp
|
|
```
|
|
|
|
2. **Add to translator** (`translator/commands_from_c2.py`):
|
|
|
|
```python
|
|
elif task_command == "my_command":
|
|
task_data.append(0x99) # Command ID
|
|
arg1 = task.get("parameters", {}).get("arg1", "")
|
|
task_data += len(arg1).to_bytes(4, 'big')
|
|
task_data += arg1.encode('utf-8')
|
|
```
|
|
|
|
3. **Implement handler in C** (`comandos.c`):
|
|
|
|
```c
|
|
BOOL myCommandHandler(PAnalizador argumentos) {
|
|
SIZE_T tamanoUuid = 36;
|
|
PCHAR taskUuid = getString(argumentos, &tamanoUuid);
|
|
|
|
SIZE_T arg1Size = 0;
|
|
PCHAR arg1 = getString(argumentos, &arg1Size);
|
|
|
|
// Do something with arg1
|
|
|
|
// Send response
|
|
PPaquete respuesta = nuevoPaquete(POST_RESPONSE, TRUE);
|
|
addString(respuesta, taskUuid, FALSE);
|
|
PackageAddFormatPrintf(respuesta, "Command executed: %s\n", arg1);
|
|
|
|
Analizador* resp = mandarPaquete(respuesta);
|
|
liberarPaquete(respuesta);
|
|
if (resp) liberarAnalizador(resp);
|
|
|
|
return TRUE;
|
|
}
|
|
```
|
|
|
|
4. **Register in command dispatcher** (`comandos.c`):
|
|
|
|
```c
|
|
case 0x99: // MY_COMMAND
|
|
myCommandHandler(argumentos);
|
|
break;
|
|
```
|
|
|
|
---
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### Agent Won't Check In
|
|
|
|
- Verify C2 profile settings (host, port, endpoint)
|
|
- Check network connectivity from target to C2 server
|
|
- Review Mythic logs: `sudo docker logs mythic_server`
|
|
- Enable debug logging in agent and rebuild
|
|
|
|
### SOCKS Proxy Not Working
|
|
|
|
**Port not accessible:**
|
|
```bash
|
|
# Check if port is open
|
|
sudo netstat -tlnp | grep 7002
|
|
|
|
# Ensure Mythic config allows external binding
|
|
grep DYNAMIC_PORTS_BIND_LOCALHOST_ONLY ~/Mythic/.env
|
|
# Should be "false" for external access
|
|
```
|
|
|
|
**Proxy times out:**
|
|
- Verify agent is active and not sleeping
|
|
- Check translator logs: `sudo docker logs cazalla_translator`
|
|
- Ensure `server_id` validation in `socks_manager.c` allows Mythic's IDs
|
|
|
|
**Data not flowing:**
|
|
- Enable `DEBUG_SOCKS` and rebuild agent
|
|
- Check for `0xF5` block in agent logs
|
|
- Verify translator is encoding/decoding SOCKS blocks correctly
|
|
|
|
### Compilation Errors
|
|
|
|
**`inet_pton` not found (MinGW):**
|
|
- Use `inet_addr` instead (Windows-native)
|
|
- Already fixed in current version
|
|
|
|
**Missing headers:**
|
|
```bash
|
|
# Install MinGW dependencies in Docker
|
|
apt-get update && apt-get install -y mingw-w64
|
|
```
|
|
|
|
### Task Stays in "Processing" State
|
|
|
|
**Commands like `exit`, `socks start/stop`:**
|
|
- Ensure handler sends `POST_RESPONSE` with task UUID
|
|
- Mark task as completed in `create_go_tasking` or `process_response`
|
|
- For `exit`, mark completed immediately (agent terminates)
|
|
|
|
---
|
|
|
|
## 📚 References
|
|
|
|
- [Mythic Documentation](https://docs.mythic-c2.net/)
|
|
- [Building a Mythic Agent in C](https://red-team-sncf.github.io/how-to-create-your-own-mythic-agent-in-c.html)
|
|
- [SOCKS5 Protocol (RFC 1928)](https://www.rfc-editor.org/rfc/rfc1928)
|
|
- [Mythic Translator Pattern](https://docs.mythic-c2.net/customizing/payload-type-development/translation-containers)
|
|
|
|
---
|
|
|
|
## 📄 License
|
|
|
|
Cazalla is licensed under the **BSD 3-Clause License**. See [LICENSE.md](LICENSE.md) for details.
|
|
|
|
---
|
|
|
|
## 👥 Credits
|
|
|
|
**Developed by:** Kaseya OFSTeam
|
|
|
|
Special thanks to:
|
|
- The Mythic C2 team for the excellent framework
|
|
- The SNCF Red Team for the foundational C agent tutorial
|
|
- The open-source security community
|
|
|
|
---
|
|
|
|
<div align="center">
|
|
|
|
**Made with ☕ and 💻 by the Kaseya OFSTeam**
|
|
|
|
</div>
|