mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-29 23:46:53 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,66 @@
|
||||
# API Reference: Steganography Detection Agent
|
||||
|
||||
## Overview
|
||||
|
||||
Detects hidden data in images and media using LSB analysis with Pillow/numpy, trailing data detection, and subprocess wrappers for binwalk, zsteg, and steghide.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| Pillow | >= 9.0 | Image loading and pixel manipulation |
|
||||
| numpy | >= 1.23 | Array-based LSB bit extraction and statistics |
|
||||
|
||||
## External Tools (Optional)
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| binwalk | Embedded file and data detection |
|
||||
| zsteg | PNG/BMP LSB steganography detection |
|
||||
| steghide | JPEG/BMP/WAV/AU data extraction with passwords |
|
||||
|
||||
## Core Functions
|
||||
|
||||
### `check_trailing_data(filepath)`
|
||||
Detects data appended after JPEG (FF D9) or PNG (IEND) end markers, and embedded ZIP/RAR archives.
|
||||
- **Returns**: `dict` with `trailing_bytes`, `embedded_zip`, `embedded_rar`
|
||||
|
||||
### `lsb_analysis(filepath)`
|
||||
Analyzes LSB bit distribution across RGB channels. Flags `NEAR_RANDOM` (possible stego) or `SIGNIFICANT_DEVIATION`.
|
||||
- **Returns**: `dict[str, dict]` - per-channel zeros, ones, ratio, anomaly
|
||||
|
||||
### `extract_lsb_data(filepath, output_path)`
|
||||
Extracts red channel LSB data and checks for known file signatures (ZIP, PNG, JPEG, PDF, GIF).
|
||||
- **Returns**: `dict` with `output`, `header_hex`, `detected_format`
|
||||
|
||||
### `run_binwalk(filepath)`
|
||||
Subprocess wrapper for binwalk embedded file detection.
|
||||
- **Returns**: `dict` with `tool` and `output`
|
||||
|
||||
### `run_zsteg(filepath)`
|
||||
Subprocess wrapper for zsteg PNG/BMP LSB analysis.
|
||||
- **Returns**: `dict` with `tool` and `output`
|
||||
|
||||
### `run_steghide_extract(filepath, passwords=None)`
|
||||
Attempts steghide extraction with a password list.
|
||||
- **Default passwords**: empty, password, secret, hidden, stego, test, 123456
|
||||
- **Returns**: `list[dict]` - successful extractions with password and output path
|
||||
|
||||
### `analyze_file(filepath, output_dir=None)`
|
||||
Full analysis pipeline combining all detection methods.
|
||||
- **Returns**: `dict` - complete report with findings list
|
||||
|
||||
## Finding Types
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `trailing_data` | Data after image end marker |
|
||||
| `embedded_archive` | ZIP/RAR found within file |
|
||||
| `lsb_hidden_file` | Known file format in LSB data |
|
||||
| `steghide_extraction` | Successfully extracted hidden data |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
python agent.py suspect_image.png
|
||||
```
|
||||
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Steganography detection agent using Pillow, numpy, and subprocess tools."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import struct
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
except ImportError:
|
||||
print("Install: pip install Pillow numpy")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def check_trailing_data(filepath):
|
||||
"""Check for data appended after JPEG/PNG end markers."""
|
||||
with open(filepath, "rb") as f:
|
||||
data = f.read()
|
||||
filesize = len(data)
|
||||
findings = {"filepath": filepath, "filesize": filesize, "trailing_bytes": 0}
|
||||
if data[:2] == b"\xff\xd8":
|
||||
jpeg_end = data.rfind(b"\xff\xd9")
|
||||
if jpeg_end > 0:
|
||||
trailing = filesize - jpeg_end - 2
|
||||
if trailing > 0:
|
||||
findings["trailing_bytes"] = trailing
|
||||
findings["format"] = "JPEG"
|
||||
elif data[:4] == b"\x89PNG":
|
||||
iend = data.rfind(b"IEND")
|
||||
if iend > 0:
|
||||
end_pos = iend + 8
|
||||
trailing = filesize - end_pos
|
||||
if trailing > 0:
|
||||
findings["trailing_bytes"] = trailing
|
||||
findings["format"] = "PNG"
|
||||
zip_offset = data.find(b"PK\x03\x04")
|
||||
rar_offset = data.find(b"Rar!\x1a\x07")
|
||||
if zip_offset > 0:
|
||||
findings["embedded_zip"] = zip_offset
|
||||
if rar_offset > 0:
|
||||
findings["embedded_rar"] = rar_offset
|
||||
return findings
|
||||
|
||||
|
||||
def lsb_analysis(filepath):
|
||||
"""Perform LSB analysis on image channels."""
|
||||
img = Image.open(filepath).convert("RGB")
|
||||
pixels = np.array(img)
|
||||
results = {}
|
||||
for channel, name in enumerate(["Red", "Green", "Blue"]):
|
||||
lsb_data = pixels[:, :, channel] & 1
|
||||
zeros = int(np.sum(lsb_data == 0))
|
||||
ones = int(np.sum(lsb_data == 1))
|
||||
total = zeros + ones
|
||||
ratio = ones / total if total > 0 else 0
|
||||
anomaly = "NORMAL"
|
||||
if abs(ratio - 0.5) < 0.01:
|
||||
anomaly = "NEAR_RANDOM"
|
||||
elif ratio > 0.55 or ratio < 0.45:
|
||||
anomaly = "SIGNIFICANT_DEVIATION"
|
||||
results[name] = {
|
||||
"zeros": zeros, "ones": ones, "ratio": round(ratio, 4),
|
||||
"anomaly": anomaly,
|
||||
}
|
||||
return results
|
||||
|
||||
|
||||
def extract_lsb_data(filepath, output_path):
|
||||
"""Extract LSB data from red channel and check for file signatures."""
|
||||
img = Image.open(filepath).convert("RGB")
|
||||
pixels = np.array(img)
|
||||
lsb_bits = (pixels[:, :, 0] & 1).flatten()
|
||||
lsb_bytes = np.packbits(lsb_bits)
|
||||
with open(output_path, "wb") as f:
|
||||
f.write(lsb_bytes.tobytes())
|
||||
header = bytes(lsb_bytes[:16])
|
||||
detected = None
|
||||
if header[:4] == b"PK\x03\x04":
|
||||
detected = "ZIP archive"
|
||||
elif header[:3] == b"GIF":
|
||||
detected = "GIF image"
|
||||
elif header[:4] == b"\x89PNG":
|
||||
detected = "PNG image"
|
||||
elif header[:2] == b"\xff\xd8":
|
||||
detected = "JPEG image"
|
||||
elif header[:4] == b"%PDF":
|
||||
detected = "PDF document"
|
||||
return {"output": output_path, "header_hex": header.hex(), "detected_format": detected}
|
||||
|
||||
|
||||
def run_binwalk(filepath):
|
||||
"""Run binwalk to detect embedded files."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["binwalk", filepath], capture_output=True, text=True, timeout=30
|
||||
)
|
||||
return {"tool": "binwalk", "output": result.stdout.strip()}
|
||||
except FileNotFoundError:
|
||||
return {"tool": "binwalk", "output": "binwalk not installed"}
|
||||
except subprocess.TimeoutExpired:
|
||||
return {"tool": "binwalk", "output": "timeout"}
|
||||
|
||||
|
||||
def run_zsteg(filepath):
|
||||
"""Run zsteg on PNG/BMP files for LSB detection."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["zsteg", filepath], capture_output=True, text=True, timeout=30
|
||||
)
|
||||
return {"tool": "zsteg", "output": result.stdout.strip()}
|
||||
except FileNotFoundError:
|
||||
return {"tool": "zsteg", "output": "zsteg not installed"}
|
||||
except subprocess.TimeoutExpired:
|
||||
return {"tool": "zsteg", "output": "timeout"}
|
||||
|
||||
|
||||
def run_steghide_extract(filepath, passwords=None):
|
||||
"""Attempt steghide extraction with multiple passwords."""
|
||||
if passwords is None:
|
||||
passwords = ["", "password", "secret", "hidden", "stego", "test", "123456"]
|
||||
results = []
|
||||
for pwd in passwords:
|
||||
try:
|
||||
out_file = f"/tmp/steghide_{pwd or 'empty'}.bin"
|
||||
result = subprocess.run(
|
||||
["steghide", "extract", "-sf", filepath, "-p", pwd,
|
||||
"-xf", out_file, "-f"],
|
||||
capture_output=True, text=True, timeout=10
|
||||
)
|
||||
if "extracted" in result.stdout.lower() or result.returncode == 0:
|
||||
results.append({"password": pwd or "(empty)", "success": True, "output": out_file})
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired):
|
||||
break
|
||||
return results
|
||||
|
||||
|
||||
def analyze_file(filepath, output_dir=None):
|
||||
"""Full steganalysis pipeline for a single file."""
|
||||
if output_dir is None:
|
||||
output_dir = os.path.dirname(filepath)
|
||||
report = {"file": filepath, "findings": []}
|
||||
trailing = check_trailing_data(filepath)
|
||||
if trailing["trailing_bytes"] > 0:
|
||||
report["findings"].append({
|
||||
"type": "trailing_data",
|
||||
"detail": f"{trailing['trailing_bytes']} bytes after {trailing.get('format', 'unknown')} end marker",
|
||||
})
|
||||
if "embedded_zip" in trailing:
|
||||
report["findings"].append({"type": "embedded_archive", "detail": f"ZIP at offset {trailing['embedded_zip']}"})
|
||||
ext = Path(filepath).suffix.lower()
|
||||
if ext in (".png", ".bmp", ".jpg", ".jpeg", ".gif"):
|
||||
report["lsb_analysis"] = lsb_analysis(filepath)
|
||||
lsb_out = os.path.join(output_dir, "lsb_extracted.bin")
|
||||
report["lsb_extract"] = extract_lsb_data(filepath, lsb_out)
|
||||
if report["lsb_extract"]["detected_format"]:
|
||||
report["findings"].append({
|
||||
"type": "lsb_hidden_file",
|
||||
"detail": f"Detected {report['lsb_extract']['detected_format']} in LSB data",
|
||||
})
|
||||
report["binwalk"] = run_binwalk(filepath)
|
||||
if ext in (".png", ".bmp"):
|
||||
report["zsteg"] = run_zsteg(filepath)
|
||||
if ext in (".jpg", ".jpeg", ".bmp", ".wav", ".au"):
|
||||
report["steghide"] = run_steghide_extract(filepath)
|
||||
if report["steghide"]:
|
||||
report["findings"].append({
|
||||
"type": "steghide_extraction",
|
||||
"detail": f"Data extracted with {len(report['steghide'])} password(s)",
|
||||
})
|
||||
return report
|
||||
|
||||
|
||||
def print_report(report):
|
||||
print("Steganalysis Report")
|
||||
print("=" * 40)
|
||||
print(f"File: {report['file']}")
|
||||
if "lsb_analysis" in report:
|
||||
print("\nLSB Analysis:")
|
||||
for channel, data in report["lsb_analysis"].items():
|
||||
print(f" {channel}: ratio={data['ratio']} ({data['anomaly']})")
|
||||
print(f"\nFindings: {len(report['findings'])}")
|
||||
for f in report["findings"]:
|
||||
print(f" [{f['type']}] {f['detail']}")
|
||||
if "binwalk" in report and report["binwalk"]["output"] != "binwalk not installed":
|
||||
print(f"\nBinwalk:\n{report['binwalk']['output']}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python agent.py <image_file>")
|
||||
sys.exit(1)
|
||||
result = analyze_file(sys.argv[1])
|
||||
print_report(result)
|
||||
Reference in New Issue
Block a user