Files
Anthropic-Cybersecurity-Skills/skills/extracting-memory-artifacts-with-rekall/scripts/agent.py
T
mukul975 c47eed6a64 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
2026-03-19 13:26:49 +01:00

170 lines
5.7 KiB
Python

#!/usr/bin/env python3
"""Agent for extracting memory forensic artifacts using Rekall."""
import json
import argparse
from datetime import datetime
from rekall import session
from rekall import plugins
def create_session(image_path, profile_path=None):
"""Create a Rekall session for a memory image."""
kwargs = {
"filename": image_path,
"autodetect": ["rsds"],
}
if profile_path:
kwargs["profile_path"] = [profile_path]
else:
kwargs["profile_path"] = [
"https://github.com/google/rekall-profiles/raw/master"
]
return session.Session(**kwargs)
def list_processes(s):
"""List all processes using pslist plugin."""
processes = []
for proc in s.plugins.pslist():
processes.append({
"pid": int(proc.pid),
"ppid": int(proc.ppid),
"name": str(proc.name),
"create_time": str(getattr(proc, "create_time", "")),
})
return processes
def find_hidden_processes(s):
"""Detect hidden processes by comparing pslist vs psscan."""
pslist_pids = {}
for proc in s.plugins.pslist():
pslist_pids[int(proc.pid)] = str(proc.name)
psscan_pids = {}
for proc in s.plugins.psscan():
psscan_pids[int(proc.pid)] = str(proc.name)
hidden = []
for pid, name in psscan_pids.items():
if pid not in pslist_pids and pid > 0:
hidden.append({"pid": pid, "name": name, "detection": "psscan only"})
return hidden
def detect_code_injection(s):
"""Detect injected code using malfind plugin (VAD analysis)."""
injections = []
for result in s.plugins.malfind():
injections.append({
"pid": int(getattr(result, "pid", 0)),
"process": str(getattr(result, "name", "")),
"address": hex(getattr(result, "address", 0)),
"protection": str(getattr(result, "protection", "")),
"tag": str(getattr(result, "tag", "")),
})
return injections
def list_network_connections(s):
"""List network connections using netscan plugin."""
connections = []
for conn in s.plugins.netscan():
connections.append({
"pid": int(getattr(conn, "pid", 0)),
"local_addr": str(getattr(conn, "local_addr", "")),
"remote_addr": str(getattr(conn, "remote_addr", "")),
"state": str(getattr(conn, "state", "")),
"protocol": str(getattr(conn, "protocol", "")),
})
return connections
def list_dlls(s, target_pid=None):
"""List loaded DLLs for processes using dlllist plugin."""
dlls = []
for entry in s.plugins.dlllist(pids=[target_pid] if target_pid else None):
dlls.append({
"pid": int(getattr(entry, "pid", 0)),
"process": str(getattr(entry, "name", "")),
"dll_path": str(getattr(entry, "path", "")),
"base": hex(getattr(entry, "base", 0)),
"size": int(getattr(entry, "size", 0)),
})
return dlls
def check_drivers(s):
"""List loaded kernel drivers using modules plugin."""
drivers = []
for mod in s.plugins.modules():
drivers.append({
"name": str(getattr(mod, "name", "")),
"base": hex(getattr(mod, "base", 0)),
"size": int(getattr(mod, "size", 0)),
})
return drivers
def analyze_vad(s, target_pid):
"""Analyze Virtual Address Descriptor tree for a process."""
vad_entries = []
for entry in s.plugins.vadinfo(pids=[target_pid]):
vad_entries.append({
"start": hex(getattr(entry, "start", 0)),
"end": hex(getattr(entry, "end", 0)),
"protection": str(getattr(entry, "protection", "")),
"tag": str(getattr(entry, "tag", "")),
"filename": str(getattr(entry, "filename", "")),
})
return vad_entries
def main():
parser = argparse.ArgumentParser(description="Rekall Memory Forensics Agent")
parser.add_argument("--image", required=True, help="Path to memory image")
parser.add_argument("--profile-path", help="Path to Rekall profiles")
parser.add_argument("--pid", type=int, help="Target PID for focused analysis")
parser.add_argument("--output", default="rekall_report.json")
parser.add_argument("--action", choices=[
"pslist", "hidden", "malfind", "netscan", "dlls", "full_analysis"
], default="full_analysis")
args = parser.parse_args()
s = create_session(args.image, args.profile_path)
report = {"image": args.image, "generated_at": datetime.utcnow().isoformat(),
"findings": {}}
if args.action in ("pslist", "full_analysis"):
procs = list_processes(s)
report["findings"]["processes"] = procs
print(f"[+] Processes found: {len(procs)}")
if args.action in ("hidden", "full_analysis"):
hidden = find_hidden_processes(s)
report["findings"]["hidden_processes"] = hidden
print(f"[+] Hidden processes: {len(hidden)}")
if args.action in ("malfind", "full_analysis"):
injections = detect_code_injection(s)
report["findings"]["code_injection"] = injections
print(f"[+] Code injections detected: {len(injections)}")
if args.action in ("netscan", "full_analysis"):
conns = list_network_connections(s)
report["findings"]["network_connections"] = conns
print(f"[+] Network connections: {len(conns)}")
if args.action in ("dlls", "full_analysis"):
drivers = check_drivers(s)
report["findings"]["kernel_drivers"] = drivers
print(f"[+] Kernel drivers: {len(drivers)}")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()