# Cazalla - Mythic C2 Agent
**A Windows implant written in C for the Mythic C2 Framework**
[](LICENSE.md)
[](https://github.com/its-a-feature/Mythic)
[]()
---
## 📋 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//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.
---
## 🔨 Customizing Cazalla
If you've forked Cazalla or made local changes and want to use your customized version, you need to configure Mythic to use local builds instead of remote images.
### Making Changes Work
By default, Mythic may use pre-built remote images for faster deployment. However, if you've made local changes to the agent code, translator, or any Python files, you need to configure Mythic to use your local build context.
#### Configure Build Variables
After installing Cazalla, Mythic will add these variables to your `~/Mythic/.env` file:
```bash
# Use local build context instead of remote image
CAZALLA_USE_BUILD_CONTEXT="true"
# Use direct mount instead of Docker volume (recommended for development)
CAZALLA_USE_VOLUME="false"
# Optional: Remote image URL (only used if USE_BUILD_CONTEXT is false)
CAZALLA_REMOTE_IMAGE="ghcr.io/your-org/cazalla:v1.0.0"
```
#### Variables Explanation
- **`CAZALLA_USE_BUILD_CONTEXT`**:
- Set to `"true"` to build from your local `Dockerfile` and include your local changes
- Set to `"false"` (default) to use the pre-built remote image
- **Important**: You must set this to `"true"` if you've modified any files!
- **`CAZALLA_USE_VOLUME`**:
- Set to `"false"` (default) to mount the local folder directly into the container
- Set to `"true"` to use a Docker volume instead
- Direct mount is better for development as changes are immediately visible
- **`CAZALLA_REMOTE_IMAGE`** (optional):
- Specifies a pre-built remote image URL
- Only used when `CAZALLA_USE_BUILD_CONTEXT="false"`
#### Apply Changes
After modifying these variables, rebuild the container:
```bash
cd ~/Mythic
sudo ./mythic-cli build cazalla
```
#### Verifying Your Changes
1. Make your code changes
2. Set `CAZALLA_USE_BUILD_CONTEXT="true"` in `~/Mythic/.env`
3. Run `sudo ./mythic-cli build cazalla`
4. Check logs: `sudo docker logs cazalla_translator`
If changes still don't appear:
- Verify the `Dockerfile` copies your modified files (see line 39: `COPY ./ /Mythic/cazalla/`)
- Check that file paths in the Dockerfile match your directory structure
- Ensure you're editing files in the correct location (inside `Payload_Type/cazalla/`)
#### Example: Customizing Agent Code
```bash
# 1. Edit agent C code
vim Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c
# 2. Ensure build context is enabled
echo 'CAZALLA_USE_BUILD_CONTEXT="true"' >> ~/Mythic/.env
# 3. Rebuild the container
cd ~/Mythic
sudo ./mythic-cli build cazalla
# 4. Rebuild a payload from the UI
# Your changes will now be included in the compiled agent
```
For more information, see the [Mythic documentation on customizing public agents](https://docs.mythic-c2.net/customizing/customizing-public-agent).
---
## 🛠️ 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 7002
# Use with any tool
proxychains curl https://internal-server.local
proxychains nmap -sT 192.168.1.0/24
```
#### With curl
```bash
curl --socks5 :7002 https://internal-server.local
```
#### With Firefox/Browser
Configure SOCKS proxy in browser settings:
- **SOCKS Host**: ``
- **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 "
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
---
**Made with ☕ and 💻 by the Kaseya OFSTeam**