#!/usr/bin/env python3 """Malware-report helpers: generate a structured skeleton and check a draft for completeness. Text-only tooling. ``scaffold`` prints a Markdown report template; ``check`` verifies a draft contains the required sections and at least one ATT&CK technique reference. """ from __future__ import annotations import argparse import datetime as _dt import re import sys from pathlib import Path REQUIRED_SECTIONS = [ "Executive Summary", "Sample Identity", "Capabilities", "Indicators of Compromise", "ATT&CK Mapping", "Detection and Response", ] _ATTACK_RE = re.compile(r"\bT\d{4}(\.\d{3})?\b") def scaffold(sha256: str, name: str) -> str: today = _dt.date.today().isoformat() return f"""# Malware Analysis Report: {name} _Date: {today} · Analyst: · Confidence: _ ## Executive Summary <3-5 sentences: what it is, what it does, risk, recommended action.> ## Sample Identity | Field | Value | |---|---| | Filename (as received) | | | SHA-256 | {sha256} | | SHA-1 / MD5 | <...> | | File type / size | <...> | | First seen / source | {today} / | | Signing | | ## Capabilities | Capability | Evidence | ATT&CK | |---|---|---| | Persistence | | T1547.001 | | Command and Control | | T1071.001 | | Defense Evasion | | T1027 | ## Indicators of Compromise **Host** - **Network (defanged)** - hxxps://evil[.]com/api ```csv type,value,context domain,evil.com,c2 sha256,{sha256},sample ``` ## ATT&CK Mapping - T1547.001 — Registry Run Keys - T1071.001 — Web Protocols ## Detection and Response - Detection: - Hunt: - Containment / remediation: """ def check(text: str) -> list[str]: problems = [] for section in REQUIRED_SECTIONS: if section.lower() not in text.lower(): problems.append(f"missing section: {section}") if not _ATTACK_RE.search(text): problems.append("no ATT&CK technique IDs found") if "http://" in text or "https://" in text: problems.append("clickable URL present; defang before sharing") return problems def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description="Malware report helpers") sub = parser.add_subparsers(dest="cmd", required=True) p_s = sub.add_parser("scaffold", help="print a report skeleton") p_s.add_argument("--sha256", required=True) p_s.add_argument("--name", required=True) p_c = sub.add_parser("check", help="check a draft for completeness") p_c.add_argument("file") args = parser.parse_args(argv) if args.cmd == "scaffold": print(scaffold(args.sha256, args.name)) return 0 problems = check(Path(args.file).read_text(encoding="utf-8", errors="replace")) if problems: for p in problems: print(f"- {p}") return 1 print("OK: report contains all required sections and ATT&CK references.") return 0 if __name__ == "__main__": sys.exit(main())