mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-10 13:14:55 +03:00
c47eed6a64
- 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
165 lines
6.1 KiB
Python
165 lines
6.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Windows Amcache.hve forensic analysis agent.
|
|
|
|
Parses Amcache.hve registry hive to extract program execution history,
|
|
file metadata, and device information using the regipy library.
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import datetime
|
|
|
|
try:
|
|
from regipy.registry import RegistryHive
|
|
HAS_REGIPY = True
|
|
except ImportError:
|
|
HAS_REGIPY = False
|
|
|
|
|
|
AMCACHE_FILE_KEY = "Root\InventoryApplicationFile"
|
|
AMCACHE_APP_KEY = "Root\InventoryApplication"
|
|
AMCACHE_DEVICE_KEY = "Root\InventoryDevicePnp"
|
|
AMCACHE_DRIVER_KEY = "Root\InventoryDriverBinary"
|
|
|
|
SUSPICIOUS_PATHS = [
|
|
"\\temp\\", "\\tmp\\", "\\appdata\\local\\temp",
|
|
"\\downloads\\", "\\public\\", "\\programdata\\",
|
|
"\\recycle", "\\users\\public",
|
|
]
|
|
|
|
SUSPICIOUS_NAMES = [
|
|
"mimikatz", "psexec", "lazagne", "procdump", "rubeus",
|
|
"sharphound", "bloodhound", "cobalt", "beacon",
|
|
"powershell_ise", "certutil", "mshta",
|
|
]
|
|
|
|
|
|
def parse_amcache_files(hive_path):
|
|
"""Parse InventoryApplicationFile entries from Amcache.hve."""
|
|
if not HAS_REGIPY:
|
|
return {"error": "regipy not installed. pip install regipy"}
|
|
try:
|
|
reg = RegistryHive(hive_path)
|
|
entries = []
|
|
for subkey in reg.get_key(AMCACHE_FILE_KEY).iter_subkeys():
|
|
values = {v.name: v.value for v in subkey.iter_values()}
|
|
entries.append({
|
|
"name": values.get("Name", ""),
|
|
"lower_case_path": values.get("LowerCaseLongPath", ""),
|
|
"publisher": values.get("Publisher", ""),
|
|
"version": values.get("Version", ""),
|
|
"sha1": values.get("FileId", "").lstrip("0000").lower() if values.get("FileId") else "",
|
|
"size": values.get("Size", 0),
|
|
"link_date": values.get("LinkDate", ""),
|
|
"program_id": values.get("ProgramId", ""),
|
|
"last_modified": subkey.header.last_modified.isoformat() if subkey.header.last_modified else "",
|
|
})
|
|
return entries
|
|
except Exception as e:
|
|
return {"error": str(e)}
|
|
|
|
|
|
def parse_amcache_apps(hive_path):
|
|
"""Parse InventoryApplication entries."""
|
|
if not HAS_REGIPY:
|
|
return {"error": "regipy not installed"}
|
|
try:
|
|
reg = RegistryHive(hive_path)
|
|
apps = []
|
|
for subkey in reg.get_key(AMCACHE_APP_KEY).iter_subkeys():
|
|
values = {v.name: v.value for v in subkey.iter_values()}
|
|
apps.append({
|
|
"name": values.get("Name", ""),
|
|
"version": values.get("Version", ""),
|
|
"publisher": values.get("Publisher", ""),
|
|
"install_date": values.get("InstallDate", ""),
|
|
"source": values.get("Source", ""),
|
|
"uninstall_string": values.get("UninstallString", ""),
|
|
"registry_key_path": values.get("RegistryKeyPath", ""),
|
|
})
|
|
return apps
|
|
except Exception as e:
|
|
return {"error": str(e)}
|
|
|
|
|
|
def detect_suspicious(entries):
|
|
"""Flag suspicious entries based on path and name patterns."""
|
|
findings = []
|
|
for entry in entries:
|
|
if isinstance(entry, dict) and "error" not in entry:
|
|
path = entry.get("lower_case_path", "").lower()
|
|
name = entry.get("name", "").lower()
|
|
reasons = []
|
|
for sp in SUSPICIOUS_PATHS:
|
|
if sp in path:
|
|
reasons.append(f"Suspicious path: {sp}")
|
|
for sn in SUSPICIOUS_NAMES:
|
|
if sn in name:
|
|
reasons.append(f"Suspicious name: {sn}")
|
|
if not entry.get("publisher"):
|
|
reasons.append("Missing publisher metadata")
|
|
if reasons:
|
|
findings.append({
|
|
"name": entry.get("name", ""),
|
|
"path": entry.get("lower_case_path", ""),
|
|
"sha1": entry.get("sha1", ""),
|
|
"reasons": reasons,
|
|
})
|
|
return findings
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Amcache.hve forensic analysis agent")
|
|
parser.add_argument("hive", nargs="?", help="Path to Amcache.hve file")
|
|
parser.add_argument("--apps", action="store_true", help="Parse InventoryApplication entries")
|
|
parser.add_argument("--suspicious-only", action="store_true", help="Show only suspicious entries")
|
|
parser.add_argument("--output", "-o", help="Output JSON report path")
|
|
args = parser.parse_args()
|
|
|
|
print("[*] Amcache.hve Forensic Analysis Agent")
|
|
print(f" regipy available: {HAS_REGIPY}")
|
|
|
|
if not args.hive:
|
|
print("\n[DEMO] Amcache.hve location: C:\\Windows\\AppCompat\\Programs\\Amcache.hve")
|
|
print(" Usage: python agent.py Amcache.hve [--apps] [--suspicious-only]")
|
|
print(" Extracts: file paths, SHA-1 hashes, publisher, timestamps, install info")
|
|
print(json.dumps({"demo": True, "regipy_available": HAS_REGIPY}, indent=2))
|
|
sys.exit(0)
|
|
|
|
report = {"timestamp": datetime.datetime.utcnow().isoformat() + "Z", "hive": args.hive}
|
|
|
|
files = parse_amcache_files(args.hive)
|
|
if isinstance(files, list):
|
|
report["file_entries"] = len(files)
|
|
suspicious = detect_suspicious(files)
|
|
report["suspicious_count"] = len(suspicious)
|
|
if args.suspicious_only:
|
|
report["findings"] = suspicious
|
|
else:
|
|
report["entries"] = files[:100]
|
|
report["suspicious"] = suspicious
|
|
print(f"[*] File entries: {len(files)}")
|
|
print(f"[*] Suspicious: {len(suspicious)}")
|
|
for s in suspicious[:10]:
|
|
print(f" [!] {s['name']}: {', '.join(s['reasons'])}")
|
|
else:
|
|
report["error"] = files
|
|
|
|
if args.apps:
|
|
apps = parse_amcache_apps(args.hive)
|
|
if isinstance(apps, list):
|
|
report["app_entries"] = len(apps)
|
|
print(f"[*] Application entries: {len(apps)}")
|
|
|
|
if args.output:
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
|
|
print(json.dumps({"file_entries": report.get("file_entries", 0),
|
|
"suspicious": report.get("suspicious_count", 0)}, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|