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:
mukul975
2026-03-10 21:02:12 +01:00
parent c74d52fa30
commit 27c6414ca5
1390 changed files with 106806 additions and 0 deletions
@@ -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,92 @@
# API Reference: Browser Forensics with Hindsight
## Hindsight CLI
### Syntax
```bash
hindsight.py -i <profile_path> # Analyze Chrome profile
hindsight.py -i <path> -o <output_dir> # Save results
hindsight.py -i <path> -f xlsx # Export as Excel
hindsight.py -i <path> -f sqlite # Export as SQLite
hindsight.py -i <path> -b <browser_type> # Specify browser type
```
### Browser Types
| Flag | Browser |
|------|---------|
| `Chrome` | Google Chrome |
| `Edge` | Microsoft Edge (Chromium) |
| `Brave` | Brave Browser |
| `Opera` | Opera (Chromium) |
### Output Artifacts
| Table | Description |
|-------|-------------|
| `urls` | Browsing history with visit counts |
| `downloads` | File downloads with source URLs |
| `cookies` | Cookie values, domains, expiry |
| `autofill` | Form autofill entries |
| `bookmarks` | Saved bookmarks |
| `preferences` | Browser configuration |
| `local_storage` | Site local storage data |
| `login_data` | Saved credential metadata |
| `extensions` | Installed extensions with permissions |
## Chrome SQLite Databases
### History Database
```sql
-- Browsing history
SELECT u.url, u.title, v.visit_time, v.transition
FROM visits v JOIN urls u ON v.url = u.id
ORDER BY v.visit_time DESC;
-- Downloads
SELECT target_path, tab_url, total_bytes, start_time, danger_type, mime_type
FROM downloads ORDER BY start_time DESC;
```
### Cookies Database
```sql
SELECT host_key, name, value, creation_utc, expires_utc, is_secure, is_httponly
FROM cookies ORDER BY creation_utc DESC;
```
### Web Data Database (Autofill)
```sql
SELECT name, value, count, date_created, date_last_used
FROM autofill ORDER BY date_last_used DESC;
```
## Chrome Timestamp Conversion
### Format
Microseconds since January 1, 1601 (Windows FILETIME base)
### Python Conversion
```python
import datetime
def chrome_to_datetime(chrome_time):
epoch = datetime.datetime(1601, 1, 1)
return epoch + datetime.timedelta(microseconds=chrome_time)
```
## Browser Profile Paths
| OS | Browser | Default Path |
|----|---------|-------------|
| Windows | Chrome | `%LOCALAPPDATA%\Google\Chrome\User Data\Default` |
| Windows | Edge | `%LOCALAPPDATA%\Microsoft\Edge\User Data\Default` |
| Linux | Chrome | `~/.config/google-chrome/Default` |
| macOS | Chrome | `~/Library/Application Support/Google/Chrome/Default` |
## Transition Types (visit_transition & 0xFF)
| Value | Type | Description |
|-------|------|-------------|
| 0 | LINK | Clicked a link |
| 1 | TYPED | Typed URL in address bar |
| 2 | AUTO_BOOKMARK | Via bookmark |
| 3 | AUTO_SUBFRAME | Subframe navigation |
| 5 | GENERATED | Generated (e.g., search) |
| 7 | FORM_SUBMIT | Form submission |
| 8 | RELOAD | Page reload |
@@ -0,0 +1,256 @@
#!/usr/bin/env python3
"""Browser forensics analysis agent using Hindsight concepts.
Parses Chromium-based browser artifacts (Chrome, Edge, Brave) including
history, downloads, cookies, autofill, and extensions from SQLite databases.
"""
import os
import sys
import json
import sqlite3
import datetime
import hashlib
from collections import defaultdict
def chrome_time_to_datetime(chrome_time):
"""Convert Chrome timestamp (microseconds since 1601-01-01) to datetime."""
if not chrome_time or chrome_time == 0:
return None
try:
epoch = datetime.datetime(1601, 1, 1)
delta = datetime.timedelta(microseconds=chrome_time)
return (epoch + delta).isoformat() + "Z"
except (OverflowError, OSError):
return None
def find_browser_profiles(base_path=None):
"""Locate Chromium-based browser profile directories."""
if base_path and os.path.isdir(base_path):
return [base_path]
profiles = []
home = os.path.expanduser("~")
candidates = [
os.path.join(home, "AppData", "Local", "Google", "Chrome", "User Data", "Default"),
os.path.join(home, "AppData", "Local", "Microsoft", "Edge", "User Data", "Default"),
os.path.join(home, "AppData", "Local", "BraveSoftware", "Brave-Browser", "User Data", "Default"),
os.path.join(home, ".config", "google-chrome", "Default"),
os.path.join(home, ".config", "chromium", "Default"),
os.path.join(home, ".config", "microsoft-edge", "Default"),
]
for path in candidates:
if os.path.isdir(path):
profiles.append(path)
return profiles
def parse_history(profile_path):
"""Parse browsing history from History SQLite database."""
db_path = os.path.join(profile_path, "History")
if not os.path.exists(db_path):
return []
entries = []
try:
conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
cursor = conn.cursor()
cursor.execute("""
SELECT u.url, u.title, v.visit_time, v.transition, u.visit_count
FROM visits v JOIN urls u ON v.url = u.id
ORDER BY v.visit_time DESC LIMIT 5000
""")
for url, title, visit_time, transition, count in cursor.fetchall():
entries.append({
"url": url, "title": title or "",
"visit_time": chrome_time_to_datetime(visit_time),
"transition": transition & 0xFF,
"visit_count": count,
})
conn.close()
except sqlite3.Error as e:
entries.append({"error": str(e)})
return entries
def parse_downloads(profile_path):
"""Parse download history from History database."""
db_path = os.path.join(profile_path, "History")
if not os.path.exists(db_path):
return []
downloads = []
try:
conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
cursor = conn.cursor()
cursor.execute("""
SELECT target_path, tab_url, total_bytes, start_time, end_time,
danger_type, interrupt_reason, mime_type
FROM downloads ORDER BY start_time DESC LIMIT 1000
""")
for row in cursor.fetchall():
downloads.append({
"target_path": row[0], "source_url": row[1],
"total_bytes": row[2],
"start_time": chrome_time_to_datetime(row[3]),
"end_time": chrome_time_to_datetime(row[4]),
"danger_type": row[5], "interrupt_reason": row[6],
"mime_type": row[7],
})
conn.close()
except sqlite3.Error as e:
downloads.append({"error": str(e)})
return downloads
def parse_cookies(profile_path):
"""Parse cookies from Cookies database."""
db_path = os.path.join(profile_path, "Cookies")
if not os.path.exists(db_path):
db_path = os.path.join(profile_path, "Network", "Cookies")
if not os.path.exists(db_path):
return []
cookies = []
try:
conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
cursor = conn.cursor()
cursor.execute("""
SELECT host_key, name, path, creation_utc, expires_utc,
is_secure, is_httponly, samesite
FROM cookies ORDER BY creation_utc DESC LIMIT 2000
""")
for row in cursor.fetchall():
cookies.append({
"host": row[0], "name": row[1], "path": row[2],
"created": chrome_time_to_datetime(row[3]),
"expires": chrome_time_to_datetime(row[4]),
"secure": bool(row[5]), "httponly": bool(row[6]),
"samesite": row[7],
})
conn.close()
except sqlite3.Error as e:
cookies.append({"error": str(e)})
return cookies
def parse_autofill(profile_path):
"""Parse autofill data from Web Data database."""
db_path = os.path.join(profile_path, "Web Data")
if not os.path.exists(db_path):
return []
entries = []
try:
conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
cursor = conn.cursor()
cursor.execute("""
SELECT name, value, count, date_created, date_last_used
FROM autofill ORDER BY date_last_used DESC LIMIT 500
""")
for row in cursor.fetchall():
entries.append({
"field_name": row[0], "value": row[1][:50] + "..." if len(row[1]) > 50 else row[1],
"usage_count": row[2],
"created": chrome_time_to_datetime(row[3] * 1000000 if row[3] else 0),
"last_used": chrome_time_to_datetime(row[4] * 1000000 if row[4] else 0),
})
conn.close()
except sqlite3.Error as e:
entries.append({"error": str(e)})
return entries
def parse_extensions(profile_path):
"""Parse installed browser extensions."""
ext_dir = os.path.join(profile_path, "Extensions")
extensions = []
if not os.path.isdir(ext_dir):
return extensions
for ext_id in os.listdir(ext_dir):
ext_path = os.path.join(ext_dir, ext_id)
if os.path.isdir(ext_path):
versions = sorted(os.listdir(ext_path))
manifest_path = os.path.join(ext_path, versions[-1], "manifest.json") if versions else None
name = ext_id
if manifest_path and os.path.exists(manifest_path):
try:
with open(manifest_path, "r", encoding="utf-8") as f:
manifest = json.load(f)
name = manifest.get("name", ext_id)
extensions.append({
"id": ext_id, "name": name,
"version": manifest.get("version", "?"),
"permissions": manifest.get("permissions", [])[:10],
})
except (json.JSONDecodeError, IOError):
extensions.append({"id": ext_id, "name": name, "version": "unknown"})
return extensions
def detect_suspicious_activity(history, downloads):
"""Flag suspicious browsing and download patterns."""
findings = []
suspicious_domains = ["pastebin.com", "ngrok.io", "raw.githubusercontent.com",
"transfer.sh", "file.io", "temp.sh", "anonfiles.com"]
for entry in history:
url = entry.get("url", "").lower()
for domain in suspicious_domains:
if domain in url:
findings.append({
"type": "suspicious_url", "url": entry["url"],
"domain": domain, "time": entry.get("visit_time"),
})
dangerous_mimes = ["application/x-msdownload", "application/x-msdos-program",
"application/x-executable", "application/vnd.ms-excel.sheet.macroEnabled"]
for dl in downloads:
if dl.get("danger_type", 0) > 0:
findings.append({
"type": "dangerous_download", "path": dl.get("target_path"),
"source": dl.get("source_url"), "danger_type": dl.get("danger_type"),
})
if dl.get("mime_type", "") in dangerous_mimes:
findings.append({
"type": "suspicious_mime", "mime": dl.get("mime_type"),
"path": dl.get("target_path"),
})
return findings
if __name__ == "__main__":
print("=" * 60)
print("Browser Forensics Analysis Agent")
print("Chromium history, downloads, cookies, extensions")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
profiles = find_browser_profiles(target)
if not profiles:
print("\n[!] No browser profiles found.")
print("[DEMO] Usage: python agent.py <profile_path>")
print(" e.g. python agent.py ~/AppData/Local/Google/Chrome/User\\ Data/Default")
sys.exit(0)
for profile in profiles:
print(f"\n[*] Profile: {profile}")
history = parse_history(profile)
print(f" History entries: {len(history)}")
for h in history[:5]:
print(f" {h.get('visit_time', '?')} | {h.get('title', '')[:50]} | {h.get('url', '')[:60]}")
downloads = parse_downloads(profile)
print(f" Downloads: {len(downloads)}")
for d in downloads[:5]:
print(f" {d.get('start_time', '?')} | {d.get('mime_type', '?')} | {os.path.basename(d.get('target_path', ''))}")
cookies = parse_cookies(profile)
print(f" Cookies: {len(cookies)}")
extensions = parse_extensions(profile)
print(f" Extensions: {len(extensions)}")
for ext in extensions[:5]:
print(f" {ext.get('name', '?')} v{ext.get('version', '?')} [{ext.get('id', '')[:20]}]")
findings = detect_suspicious_activity(history, downloads)
print(f"\n --- Suspicious Activity: {len(findings)} findings ---")
for f in findings[:10]:
print(f" [{f['type']}] {f.get('url', f.get('path', ''))}")