mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-30 07:56:52 +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,62 @@
|
||||
# API Reference: Performing Disk Forensics Investigation
|
||||
|
||||
## pytsk3 Library (The Sleuth Kit Python Bindings)
|
||||
|
||||
| Class/Method | Description |
|
||||
|--------------|-------------|
|
||||
| `pytsk3.Img_Info(path)` | Open disk image (raw, E01, AFF) |
|
||||
| `pytsk3.FS_Info(img_info)` | Parse file system from image |
|
||||
| `fs.open_dir(path)` | Open directory for listing |
|
||||
| `fs.open_file(path)` | Open file for reading content |
|
||||
| `entry.info.meta` | Access file metadata (timestamps, size, flags) |
|
||||
| `TSK_FS_META_FLAG_UNALLOC` | Flag indicating deleted/unallocated file |
|
||||
|
||||
## File Metadata Fields
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `meta.crtime` | File creation time (NTFS) |
|
||||
| `meta.mtime` | Last modification time |
|
||||
| `meta.atime` | Last access time |
|
||||
| `meta.ctime` | Metadata change time |
|
||||
| `meta.size` | File size in bytes |
|
||||
| `meta.addr` | Inode/MFT entry number |
|
||||
| `meta.flags` | Allocation flags |
|
||||
|
||||
## NTFS MFT Structure
|
||||
|
||||
| Offset | Size | Description |
|
||||
|--------|------|-------------|
|
||||
| 0x00 | 4 bytes | Signature ("FILE") |
|
||||
| 0x16 | 2 bytes | Flags (in-use, directory) |
|
||||
| 0x1C | 4 bytes | Real size of MFT entry |
|
||||
|
||||
## Key Libraries
|
||||
|
||||
- **pytsk3** (`pip install pytsk3`): Python bindings for The Sleuth Kit
|
||||
- **dfvfs** (`pip install dfvfs`): Digital Forensics Virtual File System
|
||||
- **hashlib** (stdlib): Image integrity verification (MD5, SHA-256)
|
||||
- **struct** (stdlib): Parse binary MFT entry headers
|
||||
|
||||
## CLI Tools (Reference)
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `fls -r image.dd` | Recursively list files (TSK) |
|
||||
| `icat image.dd inode` | Extract file by inode number |
|
||||
| `mmls image.dd` | List disk partitions |
|
||||
| `fsstat image.dd` | File system statistics |
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| Image path | Path to forensic disk image (dd, E01, AFF) |
|
||||
| MFT export | Exported $MFT file for NTFS-specific analysis |
|
||||
|
||||
## References
|
||||
|
||||
- [The Sleuth Kit](https://www.sleuthkit.org/)
|
||||
- [pytsk3 Documentation](https://github.com/py4n6/pytsk)
|
||||
- [Autopsy Digital Forensics](https://www.autopsy.com/)
|
||||
- [SANS Forensics Poster](https://www.sans.org/posters/windows-forensic-analysis/)
|
||||
@@ -0,0 +1,272 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Disk Forensics Investigation Agent
|
||||
Performs disk forensics analysis including image verification, file system
|
||||
parsing, deleted file recovery, and timeline generation using pytsk3 and
|
||||
hashlib for evidence integrity.
|
||||
"""
|
||||
|
||||
import csv
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import pytsk3
|
||||
HAS_PYTSK3 = True
|
||||
except ImportError:
|
||||
HAS_PYTSK3 = False
|
||||
|
||||
|
||||
def verify_image_integrity(image_path: str) -> dict:
|
||||
"""Calculate and verify hash of forensic disk image."""
|
||||
if not os.path.exists(image_path):
|
||||
return {"error": f"Image not found: {image_path}"}
|
||||
|
||||
md5 = hashlib.md5()
|
||||
sha256 = hashlib.sha256()
|
||||
size = 0
|
||||
|
||||
with open(image_path, "rb") as f:
|
||||
while True:
|
||||
chunk = f.read(65536)
|
||||
if not chunk:
|
||||
break
|
||||
md5.update(chunk)
|
||||
sha256.update(chunk)
|
||||
size += len(chunk)
|
||||
|
||||
return {
|
||||
"image_path": image_path,
|
||||
"size_bytes": size,
|
||||
"size_gb": round(size / (1024**3), 2),
|
||||
"md5": md5.hexdigest(),
|
||||
"sha256": sha256.hexdigest(),
|
||||
"verified_at": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
|
||||
|
||||
def parse_filesystem_pytsk3(image_path: str) -> dict:
|
||||
"""Parse file system from disk image using pytsk3."""
|
||||
if not HAS_PYTSK3:
|
||||
return {"error": "pytsk3 not installed. Install with: pip install pytsk3"}
|
||||
|
||||
try:
|
||||
img = pytsk3.Img_Info(image_path)
|
||||
fs = pytsk3.FS_Info(img)
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to open image: {e}"}
|
||||
|
||||
fs_info = {
|
||||
"fs_type": str(fs.info.ftype),
|
||||
"block_size": fs.info.block_size,
|
||||
"block_count": fs.info.block_count,
|
||||
"total_size_gb": round(fs.info.block_size * fs.info.block_count / (1024**3), 2),
|
||||
}
|
||||
|
||||
return fs_info
|
||||
|
||||
|
||||
def list_files_pytsk3(image_path: str, directory: str = "/") -> list[dict]:
|
||||
"""List files in a directory within the disk image."""
|
||||
if not HAS_PYTSK3:
|
||||
return [{"error": "pytsk3 not installed"}]
|
||||
|
||||
try:
|
||||
img = pytsk3.Img_Info(image_path)
|
||||
fs = pytsk3.FS_Info(img)
|
||||
dir_obj = fs.open_dir(directory)
|
||||
except Exception as e:
|
||||
return [{"error": str(e)}]
|
||||
|
||||
files = []
|
||||
for entry in dir_obj:
|
||||
name = entry.info.name.name.decode("utf-8", errors="ignore")
|
||||
if name in (".", ".."):
|
||||
continue
|
||||
|
||||
meta = entry.info.meta
|
||||
if meta:
|
||||
files.append({
|
||||
"name": name,
|
||||
"type": "directory" if meta.type == pytsk3.TSK_FS_META_TYPE_DIR else "file",
|
||||
"size": meta.size,
|
||||
"created": datetime.fromtimestamp(meta.crtime, tz=timezone.utc).isoformat() if meta.crtime else "",
|
||||
"modified": datetime.fromtimestamp(meta.mtime, tz=timezone.utc).isoformat() if meta.mtime else "",
|
||||
"accessed": datetime.fromtimestamp(meta.atime, tz=timezone.utc).isoformat() if meta.atime else "",
|
||||
"inode": meta.addr,
|
||||
"flags": str(meta.flags),
|
||||
})
|
||||
|
||||
return files
|
||||
|
||||
|
||||
def find_deleted_files(image_path: str) -> list[dict]:
|
||||
"""Search for deleted files in the disk image."""
|
||||
if not HAS_PYTSK3:
|
||||
return [{"error": "pytsk3 not installed"}]
|
||||
|
||||
try:
|
||||
img = pytsk3.Img_Info(image_path)
|
||||
fs = pytsk3.FS_Info(img)
|
||||
except Exception as e:
|
||||
return [{"error": str(e)}]
|
||||
|
||||
deleted = []
|
||||
|
||||
def walk_directory(dir_obj, path="/"):
|
||||
for entry in dir_obj:
|
||||
name = entry.info.name.name.decode("utf-8", errors="ignore")
|
||||
if name in (".", ".."):
|
||||
continue
|
||||
|
||||
meta = entry.info.meta
|
||||
if meta and meta.flags & pytsk3.TSK_FS_META_FLAG_UNALLOC:
|
||||
deleted.append({
|
||||
"name": name,
|
||||
"path": f"{path}{name}",
|
||||
"size": meta.size,
|
||||
"deleted_approx": datetime.fromtimestamp(
|
||||
meta.mtime, tz=timezone.utc
|
||||
).isoformat() if meta.mtime else "",
|
||||
"inode": meta.addr,
|
||||
"recoverable": meta.size > 0,
|
||||
})
|
||||
|
||||
if meta and meta.type == pytsk3.TSK_FS_META_TYPE_DIR:
|
||||
try:
|
||||
sub_dir = fs.open_dir(inode=meta.addr)
|
||||
walk_directory(sub_dir, f"{path}{name}/")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
root = fs.open_dir("/")
|
||||
walk_directory(root)
|
||||
except Exception as e:
|
||||
deleted.append({"error": str(e)})
|
||||
|
||||
return deleted
|
||||
|
||||
|
||||
def parse_mft_entries(mft_path: str) -> list[dict]:
|
||||
"""Parse MFT entries from an exported $MFT file for NTFS analysis."""
|
||||
entries = []
|
||||
if not os.path.exists(mft_path):
|
||||
return [{"error": f"MFT file not found: {mft_path}"}]
|
||||
|
||||
with open(mft_path, "rb") as f:
|
||||
entry_size = 1024
|
||||
entry_num = 0
|
||||
while True:
|
||||
data = f.read(entry_size)
|
||||
if len(data) < entry_size:
|
||||
break
|
||||
|
||||
if data[:4] == b"FILE":
|
||||
flags = struct.unpack_from("<H", data, 22)[0]
|
||||
is_deleted = not (flags & 0x01)
|
||||
is_directory = bool(flags & 0x02)
|
||||
|
||||
entries.append({
|
||||
"entry_number": entry_num,
|
||||
"is_deleted": is_deleted,
|
||||
"is_directory": is_directory,
|
||||
"flags": flags,
|
||||
})
|
||||
|
||||
entry_num += 1
|
||||
if entry_num >= 10000:
|
||||
break
|
||||
|
||||
total = len(entries)
|
||||
deleted = sum(1 for e in entries if e["is_deleted"])
|
||||
|
||||
return entries[:100] if len(entries) > 100 else entries
|
||||
|
||||
|
||||
def build_timeline(files: list[dict]) -> list[dict]:
|
||||
"""Build a timeline of file system activity from file metadata."""
|
||||
events = []
|
||||
|
||||
for f in files:
|
||||
if isinstance(f, dict) and "error" not in f:
|
||||
if f.get("created"):
|
||||
events.append({"timestamp": f["created"], "event": "created", "path": f.get("name", "")})
|
||||
if f.get("modified"):
|
||||
events.append({"timestamp": f["modified"], "event": "modified", "path": f.get("name", "")})
|
||||
if f.get("accessed"):
|
||||
events.append({"timestamp": f["accessed"], "event": "accessed", "path": f.get("name", "")})
|
||||
|
||||
events.sort(key=lambda x: x.get("timestamp", ""))
|
||||
return events
|
||||
|
||||
|
||||
def generate_report(
|
||||
integrity: dict, fs_info: dict, files: list, deleted: list, timeline: list
|
||||
) -> str:
|
||||
"""Generate disk forensics investigation report."""
|
||||
lines = [
|
||||
"DISK FORENSICS INVESTIGATION REPORT",
|
||||
"=" * 50,
|
||||
f"Date: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}",
|
||||
"",
|
||||
"IMAGE INTEGRITY:",
|
||||
f" Image: {integrity.get('image_path', 'N/A')}",
|
||||
f" Size: {integrity.get('size_gb', 'N/A')} GB",
|
||||
f" MD5: {integrity.get('md5', 'N/A')}",
|
||||
f" SHA-256: {integrity.get('sha256', 'N/A')}",
|
||||
"",
|
||||
"FILE SYSTEM:",
|
||||
f" Type: {fs_info.get('fs_type', 'N/A')}",
|
||||
f" Total Size: {fs_info.get('total_size_gb', 'N/A')} GB",
|
||||
"",
|
||||
f"FILES FOUND: {len(files)}",
|
||||
f"DELETED FILES: {len([d for d in deleted if d.get('recoverable')])} recoverable",
|
||||
f"TIMELINE EVENTS: {len(timeline)}",
|
||||
]
|
||||
|
||||
if deleted:
|
||||
lines.extend(["", "DELETED FILES (SAMPLE):"])
|
||||
for d in deleted[:10]:
|
||||
if "error" not in d:
|
||||
lines.append(f" {d.get('path', 'N/A')} ({d.get('size', 0)} bytes)")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: {sys.argv[0]} <disk_image_path> [mft_path]")
|
||||
sys.exit(1)
|
||||
|
||||
image_path = sys.argv[1]
|
||||
mft_path = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
|
||||
print(f"[*] Verifying image integrity: {image_path}")
|
||||
integrity = verify_image_integrity(image_path)
|
||||
print(f"[*] SHA-256: {integrity.get('sha256', 'error')}")
|
||||
|
||||
print("[*] Parsing file system...")
|
||||
fs_info = parse_filesystem_pytsk3(image_path)
|
||||
|
||||
print("[*] Listing files...")
|
||||
files = list_files_pytsk3(image_path)
|
||||
|
||||
print("[*] Searching for deleted files...")
|
||||
deleted = find_deleted_files(image_path)
|
||||
|
||||
timeline = build_timeline(files)
|
||||
|
||||
report = generate_report(integrity, fs_info, files, deleted, timeline)
|
||||
print(report)
|
||||
|
||||
output = f"disk_forensics_{datetime.now(timezone.utc).strftime('%Y%m%d')}.json"
|
||||
with open(output, "w") as f:
|
||||
json.dump({"integrity": integrity, "fs_info": fs_info, "deleted_files": deleted,
|
||||
"timeline": timeline[:100]}, f, indent=2)
|
||||
print(f"\n[*] Results saved to {output}")
|
||||
Reference in New Issue
Block a user