Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/HavocFramework/Havoc/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Command class allows you to define custom commands that operators can execute through your agent in the Havoc client. Each command specifies its parameters, permissions, and generates a task payload for the agent to execute.

Class Definition

from havoc.agent import Command, CommandParam

class CommandShell(Command):
    CommandId = 0x101
    Name = "shell"
    Description = "executes commands using cmd.exe"
    Help = ""
    NeedAdmin = False
    Params = [
        CommandParam(
            name="commands",
            is_file_path=False,
            is_optional=False
        )
    ]
    Mitr = []
    
    def job_generate(self, arguments: dict) -> bytes:
        pass

Required Attributes

CommandId
int
required
Unique identifier for the command. Should match the command ID in your agent implementation.Example: 0x101 or COMMAND_SHELL
Name
string
required
Command name as typed by operators in the Havoc client console.Example: "shell", "upload", "screenshot"
Description
string
required
Brief description of what the command does.
Help
string
Detailed help text displayed when operators run help [command].
NeedAdmin
bool
required
Whether the command requires administrator/elevated privileges.
  • True: Command requires admin rights
  • False: Command works with normal privileges
Params
list[CommandParam]
required
List of parameters the command accepts. Can be an empty list [] for commands with no parameters.
Mitr
list[string]
List of MITRE ATT&CK technique IDs associated with this command.Example: ["T1059.003", "T1106"]

CommandParam

Defines a command parameter with validation rules.
CommandParam(
    name="parameter_name",
    is_file_path=False,
    is_optional=False
)
name
string
required
Parameter name as used in the arguments dictionary.
is_file_path
bool
required
Whether the parameter expects a file path. When True, Havoc validates the file exists.
is_optional
bool
required
Whether the parameter is optional. When False, the command requires this parameter.

Required Methods

job_generate()

Generates the task payload to send to the agent. This method is called when an operator executes the command. Parameters:
arguments
dict
required
Dictionary containing parameter values where keys match the parameter names defined in Params.
Returns: bytes - The packed task payload to send to the agent
def job_generate(self, arguments: dict) -> bytes:
    from havoc.agent import Packer
    
    task = Packer()
    task.add_int(self.CommandId)
    task.add_data(arguments['param_name'])
    
    return task.buffer

Packer Utility

The Packer class builds binary task payloads for your agent.
from havoc.agent import Packer

task = Packer()

Methods

add_int
function
Adds a 4-byte integer to the buffer.
task.add_int(0x101)
task.add_int(1234)
add_data
function
Adds length-prefixed binary data or string to the buffer.
task.add_data("whoami")
task.add_data(b"\x00\x01\x02\x03")
buffer
bytes
The final packed binary buffer to return from job_generate().
return task.buffer

Command Examples

from havoc.agent import Command, CommandParam, Packer

COMMAND_SHELL = 0x101

class CommandShell(Command):
    CommandId = COMMAND_SHELL
    Name = "shell"
    Description = "executes commands using cmd.exe"
    Help = "Usage: shell [command]\nExample: shell whoami"
    NeedAdmin = False
    Params = [
        CommandParam(
            name="commands",
            is_file_path=False,
            is_optional=False
        )
    ]
    Mitr = ["T1059.003"]
    
    def job_generate(self, arguments: dict) -> bytes:
        task = Packer()
        
        task.add_int(self.CommandId)
        task.add_data("c:\\windows\\system32\\cmd.exe /c " + arguments['commands'])
        
        return task.buffer

Registering Commands

Register commands with your agent in the __init__ method:
class CustomAgent(AgentType):
    def __init__(self):
        super().__init__()
        
        # Register all commands
        self.register_command(CommandShell())
        self.register_command(CommandUpload())
        self.register_command(CommandDownload())
        self.register_command(CommandSleep())
        self.register_command(CommandGetuid())

Command Workflow

  1. Operator Input: Operator types command in Havoc client
    shell whoami
    
  2. Parameter Validation: Havoc validates parameters against Params definition
  3. Job Generation: job_generate() is called with parsed arguments
    arguments = {'commands': 'whoami'}
    
  4. Task Packing: Command packs task data using Packer
    task = Packer()
    task.add_int(COMMAND_SHELL)
    task.add_data("cmd.exe /c whoami")
    return task.buffer
    
  5. Transmission: Packed task is sent to agent via Service API
  6. Agent Execution: Agent receives, unpacks, and executes the task
  7. Response: Agent sends results back through the response() handler

Best Practices

Ensure each command has a unique CommandId to avoid conflicts. Consider using a hex range:
COMMAND_SHELL = 0x100
COMMAND_UPLOAD = 0x101
COMMAND_DOWNLOAD = 0x102
Validate arguments in job_generate() before packing:
def job_generate(self, arguments: dict) -> bytes:
    delay = int(arguments['delay'])
    if delay < 0 or delay > 3600:
        raise ValueError("Delay must be between 0 and 3600 seconds")
    # Continue packing...
Set NeedAdmin = True for commands requiring elevated privileges:
class CommandDumpLsass(Command):
    Name = "dump-lsass"
    NeedAdmin = True  # Requires admin
Tag commands with relevant MITRE techniques for threat intelligence:
Mitr = ["T1003.001"]  # LSASS Memory dumping
Provide clear help text with usage examples:
Help = """Usage: upload [local_path] [remote_path]

Uploads a file from the operator's machine to the target.

Examples:
upload /tmp/payload.exe C:\\\\Temp\\\\file.exe
upload ./script.ps1 C:\\\\Users\\\\Public\\\\script.ps1"""

AgentType

Learn about agent implementation and response handling

HavocService

Connect your agent to the Teamserver