#!/usr/bin/env python3 """Generate x64dbg command scripts of strategic API breakpoints. Emits a ``.txt`` script of ``bp`` commands (loadable in x64dbg) for a chosen analysis goal, so a debugging session starts with the right breakpoints. This produces a text script only; it does not attach to or run any process. """ from __future__ import annotations import argparse import sys PRESETS: dict[str, list[str]] = { "unpacking": [ "VirtualAlloc", "VirtualAllocEx", "VirtualProtect", "VirtualProtectEx", "LoadLibraryA", "LoadLibraryW", "GetProcAddress", ], "injection": [ "VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread", "NtCreateThreadEx", "QueueUserAPC", "SetThreadContext", "ResumeThread", "NtUnmapViewOfSection", "CreateProcessInternalW", ], "crypto": [ "CryptDecrypt", "CryptEncrypt", "CryptAcquireContextA", "CryptImportKey", "BCryptDecrypt", "BCryptEncrypt", ], "network": [ "InternetOpenA", "InternetOpenW", "InternetConnectA", "HttpOpenRequestA", "HttpSendRequestA", "WinHttpConnect", "WinHttpSendRequest", "connect", "send", ], "persistence": [ "RegSetValueExA", "RegSetValueExW", "RegCreateKeyExA", "CreateServiceA", "CreateServiceW", ], } def build_script(presets: list[str]) -> str: lines = ["// x64dbg breakpoint script generated by AnalystAIPack", "// load with: scriptload bp.txt (or run line by line)"] seen: set[str] = set() for preset in presets: apis = PRESETS.get(preset) if not apis: lines.append(f"// unknown preset: {preset}") continue lines.append(f"// --- {preset} ---") for api in apis: if api not in seen: lines.append(f"bp {api}") seen.add(api) lines.append("// set log on hit, e.g.: bplog VirtualAlloc \"alloc size={p1}\"") return "\n".join(lines) + "\n" def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description="Generate x64dbg breakpoint script") sub = parser.add_subparsers(dest="cmd", required=True) p = sub.add_parser("breakpoints") p.add_argument("--preset", action="append", required=True, choices=sorted(PRESETS) + ["all"], help="one or more presets, or 'all'") args = parser.parse_args(argv) presets = sorted(PRESETS) if "all" in args.preset else args.preset sys.stdout.write(build_script(presets)) return 0 if __name__ == "__main__": sys.exit(main())