2025-04-08 18:30:08 +02:00
2025-04-02 16:45:10 +02:00
2025-04-02 16:45:10 +02:00
2025-04-07 10:49:56 +00:00
2025-04-07 10:49:56 +00:00

Cazalla - Basic Mythic Implant in C

Cazalla is a basic Windows implant written in C, designed to interface with the Mythic C2 framework.

This project was developed based on the article How to build your own Mythic agent in C and serves as an initial version of an implant with room for future improvements.

Cazalla is developed by the OFSTeam at Kaseya.

Supported Commands

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 section below.


Install Cazalla

Once Mythic is installed and running, use the following command to install Cazalla:

./mythic-cli install github <repository-url>

Communication Protocol

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:

{
    "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"
}
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*)

Checkin - C2 to Implant

Key Key Len (bytes) Type
New UUID 36 Str (char*)
Status 1 Byte

GetTasking - Implant to C2

Expected:

{
    "action": "get_tasking",
    "tasking_size": 1
}
Key Key Len (bytes) Type
Number tasks 4 Uint32

GetTasking - C2 to Implant

Expected:

{
    "action": "get_tasking",
    "tasks": [
        {
            "command": "command name",
            "parameters": "command param string",
            "timestamp": 1578706611.324671,
            "id": "task uuid"
        }
    ]
}
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*)

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:

{
    "action": "post_response",
    "responses": [
        {
            "task_id": "uuid of task",
            ... response message
        }
    ]
}
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

Post Response Classic Output Return - C2 to Implant

Expected:

{
    "action": "post_response",
    "responses": [
        {
            "task_id": UUID,
            "status": "success" or "error",
            "error": "error message if it exists"
        }
    ]
}
Key Key Len (bytes) Type
Status Resp1 1 Int

Creating New Commands

📦 Mythic Side (Python)

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:

  • TaskArguments class
  • CommandBase class

Example: shell.py

class ShellArguments(TaskArguments):
    def __init__(self, command_line, **kwargs):
        ...
        self.args = [
            CommandParameter(name="command", type=ParameterType.String, ...)
        ]

class ShellCommand(CommandBase):
    cmd = "shell"
    ...
    async def create_tasking(self, task: MythicTask):
        ...

    async def process_response(self, task, response):
        ...

🧠 C2 Side (Python - commands_from_c2.py)

Update the commands dictionary with a unique hex code and input type:

commands = {
    ...
    "newcmd": {"hex_code": 0xAB, "input_type": "string"}
}

Update responseTasking to handle serialization of the new commands parameters.

💻 Implant Side (C)

Update the following files:

comandos.h

#define NEWCMD_CMD 0xAB
BOOL ejecutarNuevoCmd(PAnalizador argumentos);

comandos.c Add your command logic in handleGetTasking():

else if (tarea == NEWCMD_CMD) {
    ejecutarNuevoCmd(analizadorTarea);
}

nuevo_cmd.c and nuevo_cmd.h Create your new command implementation.

BOOL ejecutarNuevoCmd(PAnalizador argumentos) {
    // handle parsing and execution here
}

Dont forget to add the source file to the build and include its header where needed.

Future Development

Planned improvements:

  • Full implementation of pwd
  • Additional file system and process control commands
  • File upload/download
  • Persistence and evasion mechanisms

Made with by the Kaseya OFSTeam

S
Description
No description provided
Readme 3.5 MiB
Languages
C 96.4%
Python 3.5%