reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
Apache License 2.0 — see the repository root LICENSE file for the full text.
|
||||
|
||||
Copyright the AnalystAIPack contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
name: debugging-malware-with-x64dbg
|
||||
description: 'Uses x64dbg to dynamically debug Windows malware: setting strategic breakpoints
|
||||
on APIs, stepping through unpacking and decryption, dumping memory at the right moment, and
|
||||
manipulating execution to reach hidden code. Activates for requests to debug malware with
|
||||
x64dbg, set API breakpoints, or step through unpacking in a debugger.'
|
||||
domain: cybersecurity
|
||||
subdomain: reverse-engineering
|
||||
tags:
|
||||
- reverse-engineering
|
||||
- x64dbg
|
||||
- debugging
|
||||
- unpacking
|
||||
- breakpoints
|
||||
- windows
|
||||
version: 1.0.0
|
||||
author: analyst-ai-pack
|
||||
license: Apache-2.0
|
||||
mitre_attack:
|
||||
- T1027
|
||||
- T1140
|
||||
- T1497
|
||||
- T1055
|
||||
d3fend:
|
||||
- D3-PSA
|
||||
- D3-FCR
|
||||
references:
|
||||
- 'x64dbg documentation — https://help.x64dbg.com/'
|
||||
- 'Windows API reference — https://learn.microsoft.com/windows/win32/api/'
|
||||
---
|
||||
|
||||
# Debugging Malware with x64dbg
|
||||
|
||||
## When to Use
|
||||
|
||||
- You need to observe a sample's runtime behavior at the instruction level on Windows.
|
||||
- You are manually unpacking, decrypting strings, or reaching code guarded by anti-analysis.
|
||||
- You want to dump a payload from memory after it is decoded but before it is hidden.
|
||||
|
||||
**Do not use** a debugger on a host you care about — debug only inside the isolated victim VM,
|
||||
and revert the snapshot after.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- x64dbg (and the matching x32/x64 build for the sample's bitness) inside the victim VM.
|
||||
- A clean snapshot; the lab's simulated internet.
|
||||
- Familiarity with Windows APIs commonly used by malware.
|
||||
|
||||
## Safety & Handling
|
||||
|
||||
- The sample executes under the debugger; this is detonation. Stay in the isolated VM.
|
||||
- Revert the snapshot after the session; treat memory dumps as live samples.
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Set strategic API breakpoints
|
||||
|
||||
Rather than stepping from the entry point, break on APIs that mark interesting moments:
|
||||
|
||||
```text
|
||||
VirtualAlloc / VirtualProtect -> unpacking buffer about to be written/executed
|
||||
CreateProcessInternalW -> process hollowing target
|
||||
WriteProcessMemory -> injection payload in a register/buffer
|
||||
CryptDecrypt / lstrcpy -> decoded data available
|
||||
ResumeThread -> hollowed process about to run
|
||||
```
|
||||
|
||||
Use `bp VirtualAlloc` then inspect the return value (allocated base) on return.
|
||||
|
||||
### Step 2: Step through unpacking
|
||||
|
||||
Run to the allocation, set a memory breakpoint on the new region, and continue until the
|
||||
unpacker writes and jumps to it. The tail jump to OEP marks the unpacked entry.
|
||||
|
||||
### Step 3: Dump at the right moment
|
||||
|
||||
When the payload is decoded in memory (e.g. after `VirtualProtect` makes it executable), dump
|
||||
the region with Scylla/the dump plugin and fix the import table for the unpacked PE.
|
||||
|
||||
### Step 4: Defeat simple anti-debugging
|
||||
|
||||
Patch or skip checks like `IsDebuggerPresent`, PEB `BeingDebugged`, and timing checks (see the
|
||||
anti-debugging skill). Set the return value to evade detection rather than removing the call.
|
||||
|
||||
### Step 5: Record breakpoints and notes
|
||||
|
||||
Save a breakpoint plan and observations. The bundled script generates an x64dbg command
|
||||
script of API breakpoints to bootstrap a session.
|
||||
|
||||
```bash
|
||||
python scripts/analyst.py breakpoints --preset unpacking > bp.txt
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
- The dumped region is a valid PE (MZ/PE headers) and disassembles to real code.
|
||||
- API breakpoints fire in an order consistent with unpacking/injection.
|
||||
- Patched anti-debug checks no longer alter the execution path.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Stepping blindly from the entry point instead of using API breakpoints — slow and easy to
|
||||
get lost.
|
||||
- Dumping too early (still encrypted) or too late (already executed/freed).
|
||||
- Removing anti-debug calls entirely, which can break control flow; prefer faking the result.
|
||||
|
||||
## References
|
||||
|
||||
- See [`references/api-reference.md`](references/api-reference.md) for the breakpoint-script
|
||||
generator.
|
||||
- x64dbg and Windows API documentation (linked in frontmatter).
|
||||
@@ -0,0 +1,43 @@
|
||||
# API Reference: Debugging Malware with x64dbg
|
||||
|
||||
## Overview
|
||||
|
||||
`scripts/analyst.py` generates an x64dbg command script of strategic API breakpoints for a
|
||||
chosen goal (unpacking, injection, crypto, network, persistence). The output is a text script
|
||||
to load in x64dbg; the tool does not run any process.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| (stdlib) | — | argument handling, text output |
|
||||
|
||||
## External tools
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| x64dbg | Windows user-mode debugging |
|
||||
| Scylla (x64dbg plugin) | Dump memory and rebuild import tables when unpacking |
|
||||
|
||||
## Core functions
|
||||
|
||||
### `build_script(presets)`
|
||||
Returns an x64dbg `.txt` script of `bp` commands for the selected presets, de-duplicating APIs
|
||||
across presets.
|
||||
|
||||
### `PRESETS`
|
||||
Maps each analysis goal to the relevant Windows APIs.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
python scripts/analyst.py breakpoints --preset unpacking > bp.txt
|
||||
python scripts/analyst.py breakpoints --preset injection --preset crypto > bp.txt
|
||||
# in x64dbg: scriptload bp.txt
|
||||
```
|
||||
|
||||
## Sources
|
||||
|
||||
- x64dbg documentation — https://help.x64dbg.com/
|
||||
- Windows API reference — https://learn.microsoft.com/windows/win32/api/
|
||||
- Common API-breakpoint strategy for manual unpacking (standard RE practice)
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/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())
|
||||
Reference in New Issue
Block a user