ransomware defense

Deploying Decoy Files for Ransomware Detection

Deploys canary files (honeytokens) across file systems to detect ransomware encryption activity in real time. Uses strategically placed decoy documents monitored via file integrity monitoring or OS-level watchdogs to trigger alerts when ransomware modifies or encrypts them. Activates for requests involving ransomware canary deployment, honeyfile setup, deception-based ransomware detection, or file integrity monitoring for encryption.

canary-filesdeceptiondetectionfile-integrityhoneytokensransomware
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • Setting up early-warning detection for ransomware on file servers or endpoints
  • Supplementing EDR/AV with a deception-based detection layer that catches unknown ransomware variants
  • Creating high-fidelity ransomware alerts that have very low false-positive rates (legitimate users have no reason to touch decoy files)
  • Testing ransomware response procedures by validating that canary file modifications trigger the expected alerting pipeline
  • Protecting high-value file shares (finance, HR, legal) with tripwire files that indicate unauthorized encryption activity

Do not use decoy files as the sole ransomware defense. They are a detection mechanism, not a prevention mechanism, and should complement backups, EDR, and access controls.

Prerequisites

  • Python 3.8+ with watchdog library for cross-platform file system monitoring
  • Administrative access to target file shares or endpoints for canary placement
  • File integrity monitoring (FIM) tool or SIEM integration for alert routing
  • Understanding of target directory structure to place canaries in high-value locations
  • Windows: NTFS change journal or ReadDirectoryChangesW API access
  • Linux: inotify support in kernel (standard in modern kernels)

Workflow

Step 1: Design Canary File Strategy

Plan file placement for maximum detection coverage:

Canary File Placement Strategy:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Naming Convention:
  - Use names that sort FIRST and LAST alphabetically in each directory
  - Ransomware typically enumerates directories A-Z or Z-A
  - Examples: _AAAA_budget_2024.docx, ~zzzz_report_final.xlsx
 
Placement Locations:
  - Root of every file share (\\server\share\_AAAA_canary.docx)
  - Desktop, Documents, Downloads on each endpoint
  - Department-specific shares (Finance, HR, Legal)
  - Backup staging directories
  - Home directories of high-privilege accounts
 
File Types:
  - .docx, .xlsx, .pdf (most targeted by ransomware)
  - .sql, .bak (database files, high value)
  - Mix of file types to detect ransomware that targets specific extensions

Step 2: Generate Realistic Canary Files

Create decoy files with realistic content and metadata:

import os
import time
 
def create_canary_docx(filepath, content="Q4 Financial Summary - Confidential"):
    """Create a realistic .docx canary file using python-docx."""
    from docx import Document
    doc = Document()
    doc.add_heading("Financial Report - CONFIDENTIAL", level=1)
    doc.add_paragraph(content)
    doc.add_paragraph(f"Generated: {time.strftime('%Y-%m-%d')}")
    doc.save(filepath)
 
def create_canary_txt(filepath):
    """Create a simple text canary with known content for hash verification."""
    content = "CANARY_TOKEN_DO_NOT_MODIFY\n"
    content += f"Created: {time.strftime('%Y-%m-%dT%H:%M:%S')}\n"
    content += "This file is monitored for unauthorized changes.\n"
    with open(filepath, "w") as f:
        f.write(content)

Step 3: Deploy File System Watcher

Monitor canary files for any modification, rename, or deletion:

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
 
class CanaryHandler(FileSystemEventHandler):
    def __init__(self, canary_paths, alert_callback):
        self.canary_paths = set(canary_paths)
        self.alert_callback = alert_callback
 
    def on_modified(self, event):
        if event.src_path in self.canary_paths:
            self.alert_callback("MODIFIED", event.src_path)
 
    def on_deleted(self, event):
        if event.src_path in self.canary_paths:
            self.alert_callback("DELETED", event.src_path)
 
    def on_moved(self, event):
        if event.src_path in self.canary_paths:
            self.alert_callback("RENAMED", event.src_path)

Step 4: Configure Alerting and Response

Define automated responses when canary files are triggered:

Alert Response Matrix:
━━━━━━━━━━━━━━━━━━━━━
Event: Canary MODIFIED
  → Severity: CRITICAL
  → Action: Alert SOC, identify modifying process (PID), isolate endpoint
 
Event: Canary DELETED
  → Severity: HIGH
  → Action: Alert SOC, check for ransomware note in same directory
 
Event: Canary RENAMED (new extension added)
  → Severity: CRITICAL
  → Action: Alert SOC, check extension against known ransomware extensions
  → Automated: Kill modifying process, disable network interface
 
Event: Multiple canaries triggered within 60 seconds
  → Severity: EMERGENCY
  → Action: Network-wide isolation, activate incident response plan

Step 5: Validate Detection Coverage

Test that canary files detect actual ransomware behavior:

# Simulate ransomware encryption (safe test - modifies canary content)
echo "ENCRYPTED_BY_TEST" > /path/to/canary/_AAAA_budget.docx
 
# Simulate ransomware rename (adds extension)
mv /path/to/canary/report.xlsx /path/to/canary/report.xlsx.locked
 
# Verify alerts were generated in SIEM/alerting system

Verification

  • Confirm all canary files are present and unmodified using stored hash baselines
  • Verify that modifying any canary file generates an alert within the expected timeframe (under 30 seconds)
  • Test that alert routing to SOC/SIEM is functional with a controlled modification
  • Validate that automated response actions (process kill, network isolation) execute correctly
  • Check that canary files survive normal backup and restore operations
  • Ensure legitimate users and processes are excluded from false-positive alerts (backup agents, AV scans)

Key Concepts

Term Definition
Canary File A decoy file placed in a directory that is monitored for any access or modification, serving as a tripwire for unauthorized activity
Honeytoken A broader category of deception artifacts (files, credentials, database records) designed to alert when accessed
File Integrity Monitoring Continuous monitoring of file attributes (hash, size, permissions, timestamps) to detect unauthorized changes
ReadDirectoryChangesW Windows API for monitoring file system changes in a directory; used by the watchdog library on Windows
inotify Linux kernel subsystem for monitoring file system events; provides near-instant notification of file changes

Tools & Systems

  • watchdog (Python): Cross-platform file system event monitoring library supporting Windows, Linux, and macOS
  • Canarytokens (Thinkst): Free hosted service for generating various types of canary tokens including files, URLs, and DNS tokens
  • OSSEC/Wazuh: Open-source HIDS with built-in file integrity monitoring and alerting capabilities
  • Elastic Endpoint: Uses canary files internally for ransomware protection and key capture
  • Sysmon: Windows system monitor that logs file creation events (Event ID 11) for canary file monitoring
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md3.1 KB

API Reference: Decoy Files for Ransomware Detection

watchdog Library (Python)

Installation

pip install watchdog

Observer Setup

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
 
observer = Observer()
observer.schedule(handler, path, recursive=True)
observer.start()
observer.join()

Event Types

Event Class Trigger
FileCreatedEvent New file created in watched directory
FileModifiedEvent Existing file content or metadata changed
FileDeletedEvent File removed from watched directory
FileMovedEvent File renamed or moved (src_path, dest_path)
DirCreatedEvent New directory created
DirDeletedEvent Directory removed

Handler Methods

Method Called When
on_created(event) File/directory created
on_modified(event) File/directory modified
on_deleted(event) File/directory deleted
on_moved(event) File/directory renamed/moved
on_any_event(event) Any file system event

Windows ReadDirectoryChangesW API

Monitored Changes

Flag Description
FILE_NOTIFY_CHANGE_FILE_NAME File created, deleted, or renamed
FILE_NOTIFY_CHANGE_DIR_NAME Directory changes
FILE_NOTIFY_CHANGE_SIZE File size changed
FILE_NOTIFY_CHANGE_LAST_WRITE Last write time changed
FILE_NOTIFY_CHANGE_SECURITY Security descriptor changed

Linux inotify Events

Event Masks

Mask Description
IN_MODIFY File was modified
IN_DELETE File was deleted
IN_MOVED_FROM File was renamed (old name)
IN_MOVED_TO File was renamed (new name)
IN_CREATE File was created
IN_ATTRIB Metadata changed

Canarytokens (Thinkst)

Generate Token

URL: https://canarytokens.org/generate
Types: Word document, PDF, DNS, HTTP, AWS key, SQL, SVN

Alert Webhook

POST https://canarytokens.org/webhook
Payload: { "token": "...", "src_ip": "...", "time": "..." }

OSSEC/Wazuh File Integrity Monitoring

Configuration (ossec.conf)

<syscheck>
  <frequency>60</frequency>
  <directories check_all="yes" realtime="yes">/path/to/canaries</directories>
  <alert_new_files>yes</alert_new_files>
</syscheck>

Alert Rule IDs

Rule ID Description
550 File integrity checksum changed
553 File deleted
554 New file added to monitored directory

Sysmon File Monitoring

Event ID 11 - FileCreate

<FileCreate onmatch="include">
  <TargetFilename condition="contains">_AAAA_</TargetFilename>
  <TargetFilename condition="contains">~zzzz_</TargetFilename>
</FileCreate>

Event ID 23 - FileDelete

Logs file deletions including archived file content.

Common Ransomware File Extensions

Extension Family
.locked LockBit, Generic
.encrypted Generic
.wncry WannaCry
.dharma Dharma/CrySiS
.basta Black Basta
.lockbit LockBit 3.0
.conti Conti
.ryuk Ryuk
.revil REvil/Sodinokibi
.akira Akira

Scripts 1

agent.py9.2 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Decoy file (canary) deployment agent for ransomware detection.

Deploys canary files across file systems and monitors them for modifications
that indicate ransomware encryption activity. Provides real-time alerting
when decoy files are modified, renamed, or deleted.
"""

import hashlib
import json
import logging
import os
import sys
import time
from datetime import datetime

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
)
logger = logging.getLogger("canary_agent")

CANARY_EXTENSIONS = [".docx", ".xlsx", ".pdf", ".csv", ".sql", ".txt", ".pptx"]

CANARY_NAMES_FIRST = [
    "_AAAA_budget_2024", "_AAAA_financial_report", "_AAAA_payroll_data",
    "_AAA_employee_records", "_AAA_client_contracts",
]

CANARY_NAMES_LAST = [
    "~zzzz_annual_review", "~zzzz_backup_config", "~zzzz_tax_returns",
    "~zzz_insurance_claims", "~zzz_merger_docs",
]

RANSOMWARE_EXTENSIONS = {
    ".locked", ".encrypted", ".crypt", ".locky", ".cerber", ".wncry",
    ".dharma", ".basta", ".blackcat", ".hive", ".royal", ".akira",
    ".lockbit", ".conti", ".ryuk", ".maze", ".revil", ".phobos",
    ".makop", ".stop", ".djvu", ".rhysida",
}

RANSOM_NOTE_NAMES = {
    "readme.txt", "readme.html", "decrypt.txt", "decrypt.html",
    "how_to_decrypt.txt", "restore_files.txt", "read_me.txt",
    "how_to_recover.txt", "ransom_note.txt",
}


def compute_file_hash(filepath):
    """Compute SHA-256 hash of a file."""
    sha256 = hashlib.sha256()
    with open(filepath, "rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):
            sha256.update(chunk)
    return sha256.hexdigest()


def generate_canary_content(canary_type, name):
    """Generate realistic content for canary files."""
    timestamp = datetime.now().isoformat()
    content = f"CANARY_TOKEN:{name}\n"
    content += f"Generated: {timestamp}\n"
    content += f"Classification: CONFIDENTIAL\n\n"

    if "budget" in name or "financial" in name:
        content += "Q4 Financial Summary\n"
        content += "Total Revenue: $12,450,000\n"
        content += "Operating Expenses: $8,230,000\n"
        content += "Net Income: $4,220,000\n"
    elif "payroll" in name or "employee" in name:
        content += "Employee Records - Human Resources\n"
        content += "Total Headcount: 342\n"
        content += "Departments: Engineering, Sales, Marketing, Operations\n"
    elif "client" in name or "contract" in name:
        content += "Client Contract Summary\n"
        content += "Active Contracts: 156\n"
        content += "Pending Renewal: 23\n"
    else:
        content += "Internal Document - Do Not Distribute\n"
        content += "This document contains sensitive business information.\n"

    return content


def deploy_canaries(target_dirs, canaries_per_dir=4):
    """Deploy canary files to target directories."""
    deployed = []
    names = CANARY_NAMES_FIRST[:canaries_per_dir // 2] + CANARY_NAMES_LAST[:canaries_per_dir // 2]

    for target_dir in target_dirs:
        if not os.path.isdir(target_dir):
            logger.warning("Directory does not exist: %s", target_dir)
            continue

        for i, name in enumerate(names):
            ext = CANARY_EXTENSIONS[i % len(CANARY_EXTENSIONS)]
            filename = f"{name}{ext}"
            filepath = os.path.join(target_dir, filename)

            content = generate_canary_content(ext, name)
            with open(filepath, "w") as f:
                f.write(content)

            file_hash = compute_file_hash(filepath)
            record = {
                "path": filepath,
                "hash": file_hash,
                "size": os.path.getsize(filepath),
                "deployed_at": datetime.now().isoformat(),
                "name": filename,
            }
            deployed.append(record)
            logger.info("Deployed canary: %s (hash: %s)", filepath, file_hash[:16])

    return deployed


def check_canary_integrity(canary_records):
    """Check all canary files for modifications, deletions, or renames."""
    alerts = []

    for record in canary_records:
        filepath = record["path"]

        if not os.path.exists(filepath):
            # Check if file was renamed with ransomware extension
            parent_dir = os.path.dirname(filepath)
            basename = os.path.basename(filepath)
            renamed = False
            if os.path.isdir(parent_dir):
                for f in os.listdir(parent_dir):
                    if f.startswith(basename) and any(f.endswith(ext) for ext in RANSOMWARE_EXTENSIONS):
                        alerts.append({
                            "type": "RANSOMWARE_RENAME",
                            "severity": "CRITICAL",
                            "original": filepath,
                            "renamed_to": os.path.join(parent_dir, f),
                            "timestamp": datetime.now().isoformat(),
                        })
                        renamed = True
                        break

            if not renamed:
                alerts.append({
                    "type": "CANARY_DELETED",
                    "severity": "HIGH",
                    "path": filepath,
                    "timestamp": datetime.now().isoformat(),
                })
            continue

        current_hash = compute_file_hash(filepath)
        if current_hash != record["hash"]:
            alerts.append({
                "type": "CANARY_MODIFIED",
                "severity": "CRITICAL",
                "path": filepath,
                "original_hash": record["hash"],
                "current_hash": current_hash,
                "timestamp": datetime.now().isoformat(),
            })

        current_size = os.path.getsize(filepath)
        if abs(current_size - record["size"]) > record["size"] * 0.5:
            alerts.append({
                "type": "SIGNIFICANT_SIZE_CHANGE",
                "severity": "HIGH",
                "path": filepath,
                "original_size": record["size"],
                "current_size": current_size,
                "timestamp": datetime.now().isoformat(),
            })

    # Check for ransom notes in canary directories
    checked_dirs = set()
    for record in canary_records:
        parent_dir = os.path.dirname(record["path"])
        if parent_dir in checked_dirs or not os.path.isdir(parent_dir):
            continue
        checked_dirs.add(parent_dir)
        for f in os.listdir(parent_dir):
            if f.lower() in RANSOM_NOTE_NAMES:
                alerts.append({
                    "type": "RANSOM_NOTE_DETECTED",
                    "severity": "CRITICAL",
                    "path": os.path.join(parent_dir, f),
                    "timestamp": datetime.now().isoformat(),
                })

    return alerts


def monitor_loop(canary_records, interval=10):
    """Continuously monitor canary files at specified interval."""
    logger.info("Starting canary monitoring loop (interval: %ds)", interval)
    logger.info("Monitoring %d canary files", len(canary_records))

    while True:
        alerts = check_canary_integrity(canary_records)
        if alerts:
            for alert in alerts:
                logger.critical(
                    "ALERT [%s] %s: %s",
                    alert["severity"],
                    alert["type"],
                    alert.get("path", alert.get("original", "unknown")),
                )
            print(json.dumps({"alerts": alerts}, indent=2))
        time.sleep(interval)


if __name__ == "__main__":
    print("=" * 60)
    print("Ransomware Canary File Deployment Agent")
    print("Deploy and monitor decoy files for encryption detection")
    print("=" * 60)

    if len(sys.argv) < 2:
        print("\nUsage:")
        print("  python agent.py deploy <dir1> [dir2] ...   Deploy canaries")
        print("  python agent.py check <registry.json>      Check canary integrity")
        print("  python agent.py monitor <registry.json>     Continuous monitoring")
        sys.exit(0)

    command = sys.argv[1]

    if command == "deploy":
        dirs = sys.argv[2:] if len(sys.argv) > 2 else [os.getcwd()]
        records = deploy_canaries(dirs)
        registry_file = "canary_registry.json"
        with open(registry_file, "w") as f:
            json.dump(records, f, indent=2)
        print(f"\n[+] Deployed {len(records)} canary files across {len(dirs)} directories")
        print(f"[+] Registry saved to: {registry_file}")

    elif command == "check":
        if len(sys.argv) < 3:
            print("[!] Provide canary registry JSON file")
            sys.exit(1)
        with open(sys.argv[2]) as f:
            records = json.load(f)
        alerts = check_canary_integrity(records)
        if alerts:
            print(f"\n[!] {len(alerts)} ALERTS DETECTED:")
            for a in alerts:
                print(f"  [{a['severity']}] {a['type']}: {a.get('path', a.get('original'))}")
        else:
            print(f"\n[+] All {len(records)} canary files intact. No alerts.")

    elif command == "monitor":
        if len(sys.argv) < 3:
            print("[!] Provide canary registry JSON file")
            sys.exit(1)
        with open(sys.argv[2]) as f:
            records = json.load(f)
        interval = int(sys.argv[3]) if len(sys.argv) > 3 else 10
        monitor_loop(records, interval)

    else:
        print(f"[!] Unknown command: {command}")
Keep exploring