ransomware defense

Detecting Ransomware Encryption Behavior

Detects ransomware encryption activity in real time using entropy analysis, file system I/O monitoring, and behavioral heuristics. Identifies mass file modification patterns, abnormal entropy spikes in written data, and suspicious process behavior characteristic of ransomware encryption routines. Activates for requests involving ransomware behavioral detection, entropy-based file monitoring, I/O anomaly detection, or real-time encryption activity alerting.

behavioral-analysisdetectionentropyfile-monitoringheuristicsransomware
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • Building or tuning a behavioral detection layer for ransomware that catches unknown/zero-day variants
  • Monitoring file servers and endpoints for mass encryption activity that evades signature-based detection
  • Implementing entropy-based detection to identify when files are being replaced with encrypted (high-entropy) content
  • Analyzing suspicious process behavior patterns: rapid sequential file opens, writes, renames, and deletes
  • Validating EDR detection rules against actual ransomware encryption patterns during red team exercises

Do not use entropy analysis alone as the only detection signal. Compressed files (ZIP, JPEG, MP4) naturally have high entropy and will cause false positives. Always combine entropy with behavioral signals like I/O rate and file rename patterns.

Prerequisites

  • Python 3.8+ with watchdog and psutil libraries
  • Administrative access for process monitoring and file system event capture
  • Understanding of Shannon entropy and its application to file content analysis
  • Windows: Sysmon installed for detailed process and file system event logging
  • Linux: auditd configured for file access monitoring, or inotify-based watchers
  • Baseline entropy values for common file types in the monitored environment

Workflow

Step 1: Establish Entropy Baselines

Calculate normal entropy ranges for files in the environment:

Entropy Baselines by File Type:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
File Type       Normal Entropy    Encrypted Entropy
.docx           3.5 - 6.5        7.8 - 8.0
.xlsx           4.0 - 6.8        7.8 - 8.0
.pdf            5.0 - 7.2        7.8 - 8.0
.txt            2.0 - 5.0        7.8 - 8.0
.csv            2.0 - 5.5        7.8 - 8.0
.sql            2.5 - 5.0        7.8 - 8.0
.jpg/.png       7.0 - 7.9        7.9 - 8.0 (hard to distinguish)
.zip/.7z        7.5 - 8.0        7.9 - 8.0 (hard to distinguish)
 
Key insight: Text-based files show the largest entropy jump when encrypted,
making them the best candidates for entropy-based detection.

Step 2: Implement Real-Time Entropy Monitoring

Monitor file writes and calculate entropy of new content:

import math
from collections import Counter
 
def shannon_entropy(data):
    """Calculate Shannon entropy of byte data (0.0 to 8.0 scale)."""
    if not data:
        return 0.0
    freq = Counter(data)
    length = len(data)
    return -sum((c / length) * math.log2(c / length) for c in freq.values())
 
def is_encryption_entropy(data, threshold=7.5):
    """Check if data entropy indicates encryption."""
    entropy = shannon_entropy(data)
    return entropy >= threshold, entropy

Step 3: Monitor File System I/O Patterns

Track process-level file operations for ransomware patterns:

Ransomware I/O Behavior Signatures:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Rapid sequential file modification:
   - >20 files modified per minute by single process
   - Read original → Write encrypted → Rename with new extension
   - Pattern: CreateFile → ReadFile → WriteFile → CloseHandle → MoveFile
 
2. File extension changes:
   - Original: report.docx → Encrypted: report.docx.locked
   - Many extensions changed within short time window
 
3. Ransom note creation:
   - Same text file (README.txt, DECRYPT.html) created in multiple directories
   - Created immediately after file encryption in each directory
 
4. Shadow copy deletion:
   - vssadmin.exe delete shadows /all /quiet
   - wmic.exe shadowcopy delete
   - PowerShell: Get-WmiObject Win32_Shadowcopy | Remove-WmiObject
 
5. Entropy spike pattern:
   - File read: entropy 3.5 (normal document)
   - File write: entropy 7.9 (encrypted content)
   - Delta > 3.0 is strong ransomware indicator

Step 4: Implement Behavioral Scoring

Combine multiple signals into a composite ransomware score:

def calculate_ransomware_score(process_metrics):
    """Score process behavior for ransomware likelihood (0-100)."""
    score = 0
 
    # High file modification rate
    files_per_min = process_metrics.get("files_modified_per_minute", 0)
    if files_per_min > 50:
        score += 30
    elif files_per_min > 20:
        score += 15
 
    # Entropy increase in written files
    avg_entropy_delta = process_metrics.get("avg_entropy_delta", 0)
    if avg_entropy_delta > 3.0:
        score += 30
    elif avg_entropy_delta > 2.0:
        score += 15
 
    # File extension changes
    extension_changes = process_metrics.get("extension_changes", 0)
    if extension_changes > 10:
        score += 20
    elif extension_changes > 3:
        score += 10
 
    # Ransom note creation
    if process_metrics.get("ransom_note_created", False):
        score += 20
 
    return min(score, 100)

Step 5: Configure Automated Response Thresholds

Set detection thresholds and automated containment actions:

Detection Thresholds:
━━━━━━━━━━━━━━━━━━━━
Score 0-25:   INFORMATIONAL - Log only, no action
Score 25-50:  LOW - Alert SOC for investigation
Score 50-75:  HIGH - Alert SOC, suspend process, snapshot VM
Score 75-100: CRITICAL - Kill process, isolate endpoint, alert IR team
 
Automated Response Actions:
  - Suspend/kill the encrypting process
  - Disable network adapter to prevent lateral movement
  - Create volume shadow copy snapshot before further damage
  - Capture process memory dump for forensic analysis
  - Send SIEM alert with process details, affected files, and timeline

Verification

  • Test detection against known ransomware samples in an isolated sandbox environment
  • Verify that entropy monitoring correctly identifies encrypted vs. compressed files
  • Confirm that behavioral scoring produces low false-positive rates on normal workloads
  • Validate automated response actions execute within acceptable time (under 5 seconds)
  • Test with multiple ransomware families (LockBit, BlackCat, Conti) to verify coverage
  • Benchmark monitoring overhead to ensure it does not degrade endpoint performance

Key Concepts

Term Definition
Shannon Entropy Mathematical measure of randomness in data (0-8 for bytes); encrypted data approaches 8.0, while text files are typically 2-5
Differential Entropy The change in entropy between a file's original and modified content; a spike indicates encryption
I/O Rate Anomaly Abnormally high rate of file read/write operations by a single process, characteristic of bulk encryption
Behavioral Scoring Combining multiple weak signals (entropy, I/O rate, file renames) into a composite confidence score
Entropy Evasion Techniques used by advanced ransomware to defeat entropy detection, such as Base64 encoding output or partial encryption

Tools & Systems

  • Sysmon: Windows system monitor providing detailed file system and process events for behavioral analysis
  • watchdog (Python): Cross-platform file system monitoring library for real-time file change detection
  • psutil (Python): Process and system monitoring library for tracking per-process I/O statistics
  • Elastic Endpoint: Commercial endpoint protection with built-in ransomware behavioral detection using canary files
  • Wazuh: Open-source security platform with file integrity monitoring and active response capabilities
Source materials

References and resources

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

References 1

api-reference.md2.6 KB

API Reference: Detecting Ransomware Encryption Behavior

Shannon Entropy

Formula: H(X) = -Sum p(x) log2(p(x)). For byte data range is 0.0 to 8.0.

Python Implementation

import math
from collections import Counter
 
def shannon_entropy(data):
    freq = Counter(data)
    length = len(data)
    return -sum((c / length) * math.log2(c / length) for c in freq.values())

Entropy Thresholds

Range Interpretation Example
0.0-1.0 Nearly uniform Null files
1.0-4.0 Low entropy Plain text
4.0-6.0 Mixed content Office docs
6.0-7.0 Compressed PDF
7.0-7.5 Highly compressed ZIP JPEG
7.5-7.9 Block cipher encrypted AES-CBC
7.9-8.0 Stream cipher encrypted AES-CTR ChaCha20

psutil Process IO Monitoring

import psutil
proc = psutil.Process(pid)
io = proc.io_counters()
# Fields: read_bytes write_bytes read_count write_count

Sysmon Event IDs

Event ID Event Relevance
1 Process Create Identify encrypting process
2 File time changed Timestomping
11 FileCreate Ransom notes
15 FileCreateStreamHash ADS usage
23 FileDelete Shadow copy deletion
26 FileDeleteDetected File deletion

Windows ETW Providers

Microsoft-Windows-Kernel-File GUID: EDD08927-9CC4-4E65-B970-C2560FB5C289

Event ID Description
10 Create (open)
11 Close
12 Read
14 Write
15 SetInformation

Behavioral Scoring

Signal Weight Threshold
Files modified per min 30 pts Over 50
Entropy delta 30 pts Over 3.0
Extension changes 20 pts Over 10
Ransom note creation 20 pts Any

Score Interpretation

Score Severity Action
0-25 INFO Log
25-50 LOW Alert SOC
50-75 HIGH Suspend process
75-100 CRITICAL Kill and isolate

Shadow Copy Deletion

Command Method
vssadmin delete shadows /all /quiet VSS Admin
wmic shadowcopy delete WMI
bcdedit /set recoveryenabled no Disable recovery
wbadmin delete catalog -quiet Delete backup

watchdog Library

Method Trigger
on_created File created
on_modified File modified
on_deleted File deleted
on_moved File renamed

Double Extension Detection

parts = filename.rsplit(".", 2)
if len(parts) >= 3:
    original_ext = "." + parts[-2]
    appended_ext = "." + parts[-1]

Scripts 1

agent.py11.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Ransomware encryption behavior detection agent.

Detects ransomware activity using entropy analysis, file system I/O monitoring,
and behavioral heuristics. Monitors file modifications for entropy spikes and
mass rename patterns characteristic of ransomware encryption.
"""

import hashlib
import json
import logging
import math
import os
import sys
import time
from collections import Counter

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

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

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

HIGH_VALUE_EXTENSIONS = {
    ".docx", ".xlsx", ".pptx", ".pdf", ".doc", ".xls", ".ppt",
    ".csv", ".sql", ".mdb", ".accdb", ".bak", ".zip", ".7z",
    ".pst", ".ost", ".eml", ".jpg", ".png", ".dwg", ".vmdk",
}


def shannon_entropy(data):
    """Calculate Shannon entropy of byte data (0.0 to 8.0)."""
    if not data:
        return 0.0
    freq = Counter(data)
    length = len(data)
    return -sum((c / length) * math.log2(c / length) for c in freq.values())


def analyze_file_entropy(filepath):
    """Analyze entropy of a file and its segments."""
    with open(filepath, "rb") as f:
        data = f.read()

    if not data:
        return {"overall": 0.0, "is_encrypted": False}

    overall = shannon_entropy(data)
    file_size = len(data)

    chunk_size = min(4096, file_size // 4) if file_size > 16 else file_size
    first_entropy = shannon_entropy(data[:chunk_size])
    mid_entropy = shannon_entropy(data[file_size // 2: file_size // 2 + chunk_size])
    last_entropy = shannon_entropy(data[-chunk_size:])

    return {
        "overall": round(overall, 4),
        "first_chunk": round(first_entropy, 4),
        "mid_chunk": round(mid_entropy, 4),
        "last_chunk": round(last_entropy, 4),
        "file_size": file_size,
        "is_encrypted": overall > 7.5,
        "is_partial_encryption": abs(first_entropy - mid_entropy) > 2.0,
    }


def scan_directory_entropy(directory, extensions=None):
    """Scan directory for files with high entropy indicating encryption."""
    results = {"total_files": 0, "encrypted_files": 0, "files": []}

    for root, dirs, files in os.walk(directory):
        for filename in files:
            filepath = os.path.join(root, filename)
            ext = os.path.splitext(filename)[1].lower()

            if extensions and ext not in extensions:
                continue

            try:
                analysis = analyze_file_entropy(filepath)
                results["total_files"] += 1

                if analysis["is_encrypted"]:
                    results["encrypted_files"] += 1
                    analysis["path"] = filepath
                    analysis["filename"] = filename
                    results["files"].append(analysis)
            except (OSError, PermissionError):
                continue

    results["encryption_ratio"] = (
        round(results["encrypted_files"] / results["total_files"], 4)
        if results["total_files"] > 0 else 0
    )
    return results


def detect_ransomware_indicators(directory):
    """Detect multiple ransomware indicators in a directory tree."""
    indicators = {
        "ransomware_extensions": [],
        "ransom_notes": [],
        "high_entropy_files": [],
        "renamed_files": [],
        "score": 0,
    }

    for root, dirs, files in os.walk(directory):
        for filename in files:
            filepath = os.path.join(root, filename)
            lower_name = filename.lower()

            # Check for ransomware file extensions
            ext = os.path.splitext(filename)[1].lower()
            if ext in RANSOMWARE_EXTENSIONS:
                indicators["ransomware_extensions"].append(filepath)

            # Check for double extensions (report.docx.locked)
            parts = filename.rsplit(".", 2)
            if len(parts) >= 3:
                original_ext = "." + parts[-2].lower()
                appended_ext = "." + parts[-1].lower()
                if original_ext in HIGH_VALUE_EXTENSIONS and appended_ext in RANSOMWARE_EXTENSIONS:
                    indicators["renamed_files"].append({
                        "path": filepath,
                        "original_ext": original_ext,
                        "ransomware_ext": appended_ext,
                    })

            # Check for ransom notes
            if lower_name in RANSOM_NOTE_NAMES:
                indicators["ransom_notes"].append(filepath)

            # Check entropy of high-value file types
            if ext in HIGH_VALUE_EXTENSIONS:
                try:
                    analysis = analyze_file_entropy(filepath)
                    if analysis["is_encrypted"]:
                        indicators["high_entropy_files"].append({
                            "path": filepath,
                            "entropy": analysis["overall"],
                        })
                except (OSError, PermissionError):
                    continue

    # Calculate ransomware score
    score = 0
    score += min(len(indicators["ransomware_extensions"]) * 5, 30)
    score += min(len(indicators["ransom_notes"]) * 15, 30)
    score += min(len(indicators["high_entropy_files"]) * 3, 20)
    score += min(len(indicators["renamed_files"]) * 5, 20)
    indicators["score"] = min(score, 100)

    if indicators["score"] >= 75:
        indicators["verdict"] = "CRITICAL - Active ransomware encryption detected"
    elif indicators["score"] >= 50:
        indicators["verdict"] = "HIGH - Strong ransomware indicators present"
    elif indicators["score"] >= 25:
        indicators["verdict"] = "MEDIUM - Suspicious activity, investigate further"
    else:
        indicators["verdict"] = "LOW - No significant ransomware indicators"

    return indicators


def snapshot_directory_state(directory):
    """Take a baseline snapshot of directory for differential analysis."""
    snapshot = {}
    for root, dirs, files in os.walk(directory):
        for filename in files:
            filepath = os.path.join(root, filename)
            try:
                stat = os.stat(filepath)
                sha256 = hashlib.sha256()
                with open(filepath, "rb") as f:
                    for chunk in iter(lambda: f.read(65536), b""):
                        sha256.update(chunk)
                snapshot[filepath] = {
                    "hash": sha256.hexdigest(),
                    "size": stat.st_size,
                    "mtime": stat.st_mtime,
                }
            except (OSError, PermissionError):
                continue
    return snapshot


def compare_snapshots(before, after):
    """Compare two directory snapshots to detect bulk encryption."""
    changes = {"modified": [], "deleted": [], "created": [], "total_changes": 0}

    for path, info in before.items():
        if path not in after:
            changes["deleted"].append(path)
        elif after[path]["hash"] != info["hash"]:
            changes["modified"].append({
                "path": path,
                "size_before": info["size"],
                "size_after": after[path]["size"],
            })

    for path in after:
        if path not in before:
            changes["created"].append(path)

    changes["total_changes"] = (
        len(changes["modified"]) + len(changes["deleted"]) + len(changes["created"])
    )

    if changes["total_changes"] > 0:
        mod_ratio = len(changes["modified"]) / max(len(before), 1)
        changes["bulk_modification_ratio"] = round(mod_ratio, 4)
        changes["ransomware_likely"] = mod_ratio > 0.3 and len(changes["modified"]) > 10
    else:
        changes["bulk_modification_ratio"] = 0
        changes["ransomware_likely"] = False

    return changes


if __name__ == "__main__":
    print("=" * 60)
    print("Ransomware Encryption Behavior Detection Agent")
    print("Entropy analysis, I/O monitoring, behavioral heuristics")
    print("=" * 60)

    if len(sys.argv) < 2:
        print("\nUsage:")
        print("  python agent.py scan <directory>          Scan for ransomware indicators")
        print("  python agent.py entropy <directory>       Entropy scan of files")
        print("  python agent.py entropy-file <file>       Analyze single file entropy")
        print("  python agent.py snapshot <directory>      Take baseline snapshot")
        print("  python agent.py compare <snap1> <snap2>   Compare two snapshots")
        sys.exit(0)

    command = sys.argv[1]

    if command == "scan":
        target = sys.argv[2] if len(sys.argv) > 2 else os.getcwd()
        print(f"\n[*] Scanning {target} for ransomware indicators...")
        results = detect_ransomware_indicators(target)
        print(f"\n--- Ransomware Detection Results ---")
        print(f"  Score: {results['score']}/100")
        print(f"  Verdict: {results['verdict']}")
        print(f"  Ransomware extensions found: {len(results['ransomware_extensions'])}")
        print(f"  Ransom notes found: {len(results['ransom_notes'])}")
        print(f"  High-entropy files: {len(results['high_entropy_files'])}")
        print(f"  Renamed files: {len(results['renamed_files'])}")
        print(f"\n{json.dumps(results, indent=2, default=str)}")

    elif command == "entropy":
        target = sys.argv[2] if len(sys.argv) > 2 else os.getcwd()
        print(f"\n[*] Entropy scanning {target}...")
        results = scan_directory_entropy(target, HIGH_VALUE_EXTENSIONS)
        print(f"\n--- Entropy Scan Results ---")
        print(f"  Total files scanned: {results['total_files']}")
        print(f"  Files with encrypted entropy: {results['encrypted_files']}")
        print(f"  Encryption ratio: {results['encryption_ratio']}")
        for f in results["files"][:10]:
            print(f"  [!] {f['filename']}: entropy={f['overall']}")

    elif command == "entropy-file":
        if len(sys.argv) < 3:
            print("[!] Provide a file path")
            sys.exit(1)
        filepath = sys.argv[2]
        analysis = analyze_file_entropy(filepath)
        print(f"\n--- File Entropy Analysis ---")
        print(f"  File: {filepath}")
        print(f"  Overall entropy: {analysis['overall']}")
        print(f"  First chunk: {analysis['first_chunk']}")
        print(f"  Mid chunk: {analysis['mid_chunk']}")
        print(f"  Last chunk: {analysis['last_chunk']}")
        print(f"  Encrypted: {analysis['is_encrypted']}")
        print(f"  Partial encryption: {analysis['is_partial_encryption']}")

    elif command == "snapshot":
        target = sys.argv[2] if len(sys.argv) > 2 else os.getcwd()
        print(f"\n[*] Taking snapshot of {target}...")
        snap = snapshot_directory_state(target)
        output = f"snapshot_{int(time.time())}.json"
        with open(output, "w") as f:
            json.dump(snap, f, indent=2)
        print(f"[+] Snapshot saved: {output} ({len(snap)} files)")

    elif command == "compare":
        if len(sys.argv) < 4:
            print("[!] Provide two snapshot JSON files")
            sys.exit(1)
        with open(sys.argv[2]) as f:
            snap1 = json.load(f)
        with open(sys.argv[3]) as f:
            snap2 = json.load(f)
        changes = compare_snapshots(snap1, snap2)
        print(f"\n--- Snapshot Comparison ---")
        print(f"  Modified: {len(changes['modified'])}")
        print(f"  Deleted: {len(changes['deleted'])}")
        print(f"  Created: {len(changes['created'])}")
        print(f"  Ransomware likely: {changes['ransomware_likely']}")
        print(f"\n{json.dumps(changes, indent=2, default=str)}")

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