@@ -1,302 +1,514 @@
# Cazalla - Basic Mythic Implant in C
# Cazalla - Mythic C2 Agent
Cazalla is a basic Windows implant written in C, designed to interface with the Mythic C2 framework.
<div align="center">
This project was developed based on 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 serves as an initial version of an implant with room for future improvements.

Cazalla is developed by the OFSTeam at Kaseya.
**A Windows implant written in C for the Mythic C2 Framework **
## Supported Commands
[](LICENSE.md)
[](https://github.com/its-a-feature/Mythic)
[]()
Commands are organized by category for better clarity and extensibility.
### 📁 File System Commands
| Command | Description | Status |
|---------|--------------------------|---------|
| `cd` | Change working directory | ✅ |
| `ls` | List directory contents | ✅ |
| `pwd` | Print working directory | ✅ |
| `cp` | Copy an existing file | ✅ |
| `mkdir` | Create a new directory | ✅ |
| `rm` | Delete file/directory | ✅ |
### 🖥️ Console Commands
| Command | Description | Status |
|---------|-------------------------------------|--------|
| `shell` | Execute arbitrary shell command | ✅ |
### 🔄 Execution Control
| Command | Description | Status |
|---------|-------------------|--------|
| `exit` | Exit the implant | ✅ |
| `sleep` | Modify sleep time | ✅ |
### 🧠 System Inspection
| Command | Description | Status |
|---------|-----------------------|--------|
| `ps` | List running processes| ✅ |
> 🔧 To add a new command, see the [Creating New Commands](#creating-new-commands) section below.
</div>
---
## Install Cazalla
## 📋 Table of Contents
Once Mythic is installed and running, use the following command to install Cazalla:
- [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 )
``` sh
./mythic-cli install github <repository-url>
---
## 🎯 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
```
## Communication Protocol
Or install from local directory:
### HEADER - Implant to C2
| Key | Key Len (bytes) | Type |
|---------|-------------------|------------|
| UUID | 36 | Str (char*)|
| Action | 1 | UInt32 |
### HEADER - C2 to Implant
| Key | Key Len (bytes) | Type |
|---------|-------------------|------------|
| Action | 1 | Int32 |
UUID | BODY
#### Checkin - Implant to C2
Expected:
``` json
{
"action" : "checkin" ,
"uuid" : "a21bab2e-462e-49ab-9800-fbedaf53ad15" ,
"ip" : "127.0.0.1" ,
"os" : "win" ,
"arch" : "x64" ,
"hostname" : "PC" ,
"user" : "bob" ,
"domain" : "domain.com" ,
"pid" : 123 ,
"processname" : "malware.exe"
}
``` bash
./mythic-cli install folder /path/to/Cazalla
```
| Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------|
| UUID | 36 | Str (char*) |
| Size IP | 4 | Uint32 |
| IP | Size IP | Str (char*) |
| Size OS | 4 | Uint32 |
| OS | Size OS | Str (char*) |
| Architecture | 1 | Int |
| Size Hostname | 4 | Uint32 |
| HostName | Size Hostname | Str (char*) |
| Size Username | 4 | Uint32 |
| Username | Size Username | Str (char*) |
| Size Domain | 4 | Uint32 |
| Domain | Size Domain | Str (char*) |
| PID | 4 | Uint32 |
| Size Process | 4 | Uint32 |
| Process Name | Size Process Name | Str (char*) |
| Size ExternIP | 4 | Uint32 |
| Extern IP | Size Extern IP | Str (char*) |
### Build the Agent
### Checkin - C2 to Implant
Cazalla can be built directly from the Mythic UI:
| Key | Key Len (bytes) | Type |
|----------|-------------------|-------------|
| New UUID | 36 | Str (char*) |
| Status | 1 | Byte |
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 **
### GetTasking - Implant to C2
The agent will be cross-compiled for Windows using MinGW in a Docker container.
Expected:
---
``` json
{
"action" : "get_tasking" ,
"tasking_size" : 1
}
## 🛠️ 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}
```
| Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------|
| Number tasks | 4 | Uint32 |
### Using the Proxy
### GetTasking - C2 to Implant
After starting SOCKS, configure your tools to use the proxy:
Expected:
#### With proxychains
``` json
{
"action" : "get_tasking" ,
"tasks" : [
{
"command" : "command name" ,
"parameters" : "command param string" ,
"timestamp" : 1578706611.324671 ,
"id" : "task uuid"
}
]
}
``` 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
```
| Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------|
| NumberOfTasks | 4 | Uint32 |
| Size Of Task1 | 4 | Uint32 |
| Task1 CMD | 1 | Int |
| Task1 UUID | 36 | Str (char*) |
| Task1 LenPara1| 4 | Uint32 |
| Task1 Param1 | LenParam1 Task1 | Str(char*) |
#### With curl
### Post Response Header - Implant to C2
| Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------|
| Number Resp | 4 | Uint32 |
### Post Response Header - C2 to Implant
| Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------|
| Number Resp | 4 | Uint32 |
### Post Response Classic Output Return - Implant to C2
Expected:
``` json
{
"action" : "post_response" ,
"responses" : [
{
"task_id" : "uuid of task" ,
. . . r e s p o n s e m e s s a g e
}
]
}
``` bash
curl --socks5 <mythic_server_ip>:7002 https://internal-server.local
```
| Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------|
| UUID Resp 1 | 36 | Str (char*) |
| Size Output R1| 4 | Uint32 |
| Output R1 | Size Output | Bytes |
| Status R1 | 1 | Int |
#### With Firefox/Browser
### Post Response Classic Output Return - C2 to Implant
Configure SOCKS proxy in browser settings:
- **SOCKS Host**: `<mythic_server_ip>`
- **Port**: `7002`
- **SOCKS v5**: Enabled
Expected:
### Mythic Configuration for SOCKS
``` json
{
"action" : "post_response" ,
"responses" : [
{
"task_id" : U U I D ,
"status" : "success" o r "error" ,
"error" : "error message if it exists "
}
]
}
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"
```
| Key | Key Len (bytes) | Type |
|---------------|-------------------|-------------|
| Status Resp1 | 1 | Int |
After editing, restart Mythic:
## Creating New Commands
``` bash
cd ~/Mythic
sudo ./mythic-cli restart
```
### 📦 Mythic Side (Python)
Verify the port is open:
To add a new command in Mythic, create a `.py` file inside the agent's command folder (e.g., `shell.py` ). A basic structure includes:
``` bash
sudo netstat -tlnp | grep 7002
# Should show: tcp 0.0.0.0:7002 0.0.0.0:* LISTEN
```
- TaskArguments clas s
- CommandBase class
### Performance Consideration s
Example: `shell.py`
- **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
class ShellArguments ( TaskArguments ) :
from mythic_container . MythicCommandBase import *
class MyCommandArguments ( TaskArguments ) :
def __init__ ( self , command_line , * * kwargs ) :
. . .
super ( ) . __init__ ( command_line , * * kwargs )
self . args = [
CommandParameter ( name = " command " , type = ParameterType . String , . . . )
CommandParameter ( name = " arg1 " , type = ParameterType . String )
]
class ShellCommand ( CommandBase ) :
cmd = " shell "
. . .
async def create_tasking ( self , task : MythicTask ) :
. . .
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 process_response ( self , task , response ) :
. . .
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
```
### 🧠 C2 Side (Python - `commands_from_c2.py`)
Update the commands dictionary with a unique hex code and input type :
2. **Add to translator ** ( `translator/commands_from_c2.py` ) :
``` python
commands = {
. . .
" newcmd " : { " hex_code " : 0xAB , " input_type " : " string " }
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 ;
}
```
Update `responseTasking` to handle serialization of the new command’ s parameters.
### 💻 Implant Side (C)
4. **Register in command dispatcher ** (`comandos.c` ):
Update the following files:
`comandos.h`
``` c
# define NEWCMD_CMD 0xAB
BOOL ejecutarNuevoCmd ( PAnalizador argumentos ) ;
case 0x99 : // MY_COMMAND
myCommandHandler ( argumentos ) ;
break ;
```
`comandos.c`
Add your command logic in `handleGetTasking()` :
``` c
else if ( tarea = = NEWCMD_CMD ) {
ejecutarNuevoCmd ( analizadorTarea ) ;
}
---
## 🐛 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
```
`nuevo_cmd.c` and `nuevo_cmd.h`
Create your new command implementation.
``` c
BOOL ejecutarNuevoCmd ( PAnalizador argumentos ) {
// handle parsing and execution here
}
**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
```
Don’ t forget to add the source file to the build and include its header where needed.
## Future Development
### Task Stays in "Processing" State
### Planned improvements:
**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)
#### Improvements to perform ASAP:
---
- Proxy
## 📚 References
https://github.com/jeeschr/basic-proxy-server/blob/master/proxy.c
- [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 )
- BOFexecute
- rportfwd
---
https://github.com/fidian/tcp-port-forward/blob/master/portforward.c
https://www.reddit.com/r/C_Programming/s/bWOTxm6phn
## 📄 License
Cazalla is licensed under the **BSD 3-Clause License ** . See [LICENSE.md ](LICENSE.md ) for details.
#### Improvements tier 2:
---
- Persistence and evasion mechanism s
- Full implementation of pwd
- Additional file system and process control commands
- File upload/download
## 👥 Credit s
Made with ☕ and monster by the Kaseya OFSTeam
**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>