# How to Author Custom CAPE Signatures for Malware Detection

> Learn to author custom CAPE signatures in Python for malware detection. Inspect sandbox analysis results and flag malicious behaviors effectively with this guide to kevoreilly/capev2.

- Repository: [Kevin O'Reilly/capev2](https://github.com/kevoreilly/capev2)
- Tags: how-to-guide
- Published: 2026-03-05

---

**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`](https://github.com/kevoreilly/capev2/blob/main/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/main/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/`](https://github.com/kevoreilly/capev2/tree/master/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.

```python
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.

```python
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`](https://github.com/kevoreilly/capev2/blob/main/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:

```python

# 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`:

```python

# 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:

```python

# 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/main/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`](https://github.com/kevoreilly/capev2/blob/main/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.