mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-13 19:05:17 +03:00
Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to the Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by the Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding any notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. Please do not remove or change
|
||||
the license header comment from a contributed file except when
|
||||
necessary.
|
||||
|
||||
Copyright 2026 mukul975
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,197 @@
|
||||
---
|
||||
name: detecting-ransomware-encryption-behavior
|
||||
description: >
|
||||
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.
|
||||
domain: cybersecurity
|
||||
subdomain: ransomware-defense
|
||||
tags: [ransomware, detection, entropy, behavioral-analysis, file-monitoring, heuristics]
|
||||
version: 1.0.0
|
||||
author: mahipal
|
||||
license: Apache-2.0
|
||||
---
|
||||
|
||||
# Detecting Ransomware Encryption Behavior
|
||||
|
||||
## 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:
|
||||
|
||||
```python
|
||||
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:
|
||||
|
||||
```python
|
||||
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
|
||||
@@ -0,0 +1,106 @@
|
||||
# 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
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
parts = filename.rsplit(".", 2)
|
||||
if len(parts) >= 3:
|
||||
original_ext = "." + parts[-2]
|
||||
appended_ext = "." + parts[-1]
|
||||
```
|
||||
@@ -0,0 +1,314 @@
|
||||
#!/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}")
|
||||
Reference in New Issue
Block a user