How to Author Custom CAPE Signatures for Malware Detection

Custom CAPE signatures are Python classes that inherit from Signature and automatically flag malicious behaviors by inspecting sandbox analysis results.

To author custom CAPE signatures for malware detection, you write small Python modules that analyze the JSON output generated by CAPEv2 (the successor to Cuckoo Sandbox). Each signature lives in the modules/signatures/ directory and derives from the base Signature class defined in lib/cuckoo/common/abstracts.py.

Understanding the Signature Architecture

All detection logic in CAPEv2 stems from the Signature base class located in [lib/cuckoo/common/abstracts.py](https://github.com/kevoreilly/capev2/blob/master/lib/cuckoo/common/abstracts.py#L27‑L45). This abstract class provides the framework for metadata declaration, result querying, and match reporting.

CAPE discovers signatures automatically by importing every .py file found in modules/signatures/ during startup. No manual registration is required; placing a valid signature file in this directory makes it available immediately upon restart.

Signature Metadata and Structure

Every signature must define class-level attributes that describe the detection rule. These metadata fields control how CAPE categorizes and displays matches in the final report.

Key attributes include:

  • name – Unique identifier for the signature
  • description – Human-readable explanation of the detected behavior
  • severity – Integer indicating threat level (typically 1-5)
  • categories – List of classification strings (e.g., ["trojan"], ["generic"])
  • authors – List of contributor names
  • minimum – Minimum CAPE version required to run the signature

Detection Logic Implementation

CAPE supports two execution models for signatures: non-evented (batch analysis) and evented (streaming analysis).

Non-Evented Signatures

Non-evented signatures implement the run(self) method. CAPE executes this method once after the entire analysis report is constructed, making it suitable for inspecting aggregated data like file lists or registry changes.

def run(self):
    # Inspect summary data and return True if matched

    return self.check_file(pattern=r".*\.exe$", regex=True)

Evented Signatures

Evented signatures set evented = True and implement on_call(self, call, process). This approach provides superior performance because CAPE invokes the callback for each API call during analysis rather than after.

evented = True
filter_apinames = set(["GetSystemMetrics"])

def on_call(self, call, process):
    if call["api"] == "GetSystemMetrics":
        return True  # Record match

    return None    # Continue scanning

Helper Methods for Pattern Matching

The Signature base class provides convenience methods to avoid manual JSON traversal. These helpers search the summary section of the report and return True when matches are found:

  • check_file(pattern, regex=False) – Searches created/dropped files
  • check_mutex(pattern) – Detects mutex creation
  • check_api(pattern, process=None) – Matches API call names
  • check_key(pattern) – Looks for registry key modifications

Internally, these methods call _check_value against the analysis summary data.

Step-by-Step Guide to Creating a Custom Signature

Follow this workflow to deploy a new detection rule in CAPEv2:

  1. Create the file – Add a new Python file to modules/signatures/ (e.g., my_detector.py)
  2. Import the base class – Use from lib.cuckoo.common.abstracts import Signature
  3. Define metadata – Set name, description, severity, and other class attributes
  4. Implement detection – Write either run() for non-evented or on_call() for evented logic using helper methods
  5. Restart CAPE – Reload the application or use the web API to refresh signatures

Practical Code Examples

Detecting Executable File Creation (Non-Evented)

This signature flags any analysis that creates a .exe file on the filesystem:


# modules/signatures/creates_exe.py

from lib.cuckoo.common.abstracts import Signature

class CreatesExe(Signature):
    name = "creates_exe"
    description = "Detects creation of a Windows executable"
    severity = 2
    categories = ["generic"]
    authors = ["Your Name"]
    minimum = "0.5"

    def run(self):
        return self.check_file(pattern=r".*\.exe$", regex=True)

The check_file helper searches the files list in the analysis summary. Returning True causes CAPE to record this signature in the final JSON report.

Monitoring System Metrics API Calls (Evented)

This evented signature detects sandbox-aware malware that queries screen resolution via GetSystemMetrics:


# modules/signatures/get_system_metrics.py

from lib.cuckoo.common.abstracts import Signature

class SystemMetrics(Signature):
    name = "system_metrics"
    description = "Detects use of GetSystemMetrics API"
    severity = 2
    categories = ["generic"]
    authors = ["Your Name"]
    minimum = "1.0"
    evented = True
    filter_apinames = set(["GetSystemMetrics"])

    def on_call(self, call, process):
        if call["api"] == "GetSystemMetrics":
            return True
        return None

Setting evented = True enables streaming analysis. The filter_apinames attribute limits callbacks to only the specified API, reducing overhead.

Identifying Malicious Mutexes

This signature detects a specific known-bad mutex pattern:


# modules/signatures/bad_mutex.py

from lib.cuckoo.common.abstracts import Signature

class BadMutex(Signature):
    name = "bad_mutex"
    description = "Detects mutex i_am_a_malware"
    severity = 3
    categories = ["trojan"]
    families = ["badmalware"]
    authors = ["Your Name"]
    minimum = "0.5"

    def run(self):
        return self.check_mutex("i_am_a_malware")

The check_mutex helper performs an exact match against the mutexes list in the summary report.

Loading and Testing Your Signature

CAPE automatically loads signatures from modules/signatures/ via the initialization logic in [modules/signatures/__init__.py](https://github.com/kevoreilly/capev2/blob/master/modules/signatures/__init__.py). When a signature returns True (or a list of matches when all=True), the framework automatically appends the signature data to the signatures array in the analysis JSON.

To test changes, restart the CAPE processor or trigger a signature reload through the web API. The signature will appear in the "Signatures" section of any analysis report where the detection conditions are met.

Summary

  • Custom CAPE signatures are Python classes inheriting from Signature in lib/cuckoo/common/abstracts.py
  • Storage location for new signatures is the modules/signatures/ directory
  • Two execution models: Non-evented (run() method) for post-analysis inspection and evented (on_call() method) for real-time API monitoring
  • Helper methods like check_file(), check_mutex(), and check_api() simplify pattern matching against sandbox results
  • Auto-discovery eliminates registration steps; files placed in the signatures folder are imported automatically at startup

Frequently Asked Questions

Where are custom signatures stored in CAPEv2?

Custom signatures must reside in the modules/signatures/ directory within your CAPEv2 installation. CAPE imports every .py file in this location during startup, so no additional configuration is required to register new detection rules.

What is the difference between evented and non-evented signatures?

Non-evented signatures implement the run() method and execute once after the analysis report is fully generated, making them ideal for inspecting aggregated data like file lists or registry keys. Evented signatures set evented = True and use on_call() to process each API call in real-time, offering significantly better performance for behavior-based detection.

How do I test a new signature without restarting CAPE?

While CAPE loads signatures at startup, you can trigger a reload via the web API or restart the processing daemon to pick up changes. For rapid iteration, run a single analysis task and inspect the JSON output to verify your signature logic matches the expected data structures.

Can signatures reference data outside the summary report?

The built-in helper methods (check_file, check_mutex, etc.) specifically query the summary section of the report. For advanced use cases requiring raw API call inspection or cross-referencing non-summary data, you can manually traverse the full JSON structure within the run() method, though this requires deeper knowledge of the CAPE output schema.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →