reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -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

View File

@@ -0,0 +1,88 @@
---
name: extracting-config-from-a-running-sample
description: 'Extracts an embedded malware configuration (C2 hosts, ports, campaign IDs, keys) from
a process memory dump by locating decrypted config structures and decoding common obfuscation
layers. Activates for requests to extract malware config from a memory dump, recover C2 settings
from a running sample, or decode an in-memory configuration block.'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware-analysis
- config-extraction
- memory
- c2
- dynamic-analysis
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1027
- T1140
- T1071
d3fend:
- D3-SDA
- D3-DA
references:
- 'MITRE ATT&CK T1140 Deobfuscate/Decode Files or Information — https://attack.mitre.org/techniques/T1140/'
- 'MITRE ATT&CK T1027 Obfuscated Files or Information — https://attack.mitre.org/techniques/T1027/'
---
# Extracting Config From a Running Sample
## When to Use
- You have a process memory dump of a detonated sample whose config is decrypted in memory.
- You need to recover C2 endpoints, ports, campaign/botnet IDs, mutexes, and keys.
**Do not use** this to detonate the sample — it consumes a dump already captured in an isolated
sandbox. For static-only config decryption, use the dedicated config-decryptor workflow.
## Prerequisites
- A process memory dump (`.dmp`/raw region) captured after the config was decrypted.
## Safety & Handling
- Treat the dump as malicious data; read it inertly and defang recovered endpoints.
## Workflow
### Step 1: Hunt config indicators
```bash
python scripts/analyst.py hunt process.dmp
```
Scans for URLs, IPv4:port pairs, mutex-like tokens, base64 blobs, and printable key/value
candidates in decrypted regions.
### Step 2: Decode obfuscation layers
For candidate blobs, try common transforms (single-byte XOR brute force, base64) and re-scan the
decoded output for endpoints.
### Step 3: Structure and validate the config
Assemble recovered fields into a structured config and sanity-check (valid hosts, plausible
ports, consistent campaign IDs).
### Step 4: Defang and report
Defang hosts/URLs and document the offsets where the config was recovered.
## Validation
- Recovered endpoints are real, parseable hosts/ports — not random byte noise.
- XOR/base64 decode is confirmed by the decoded output containing new endpoints/strings.
- The final config is defanged before sharing.
## Pitfalls
- Mistaking unrelated in-memory URLs (browser, OS) for C2 — corroborate with the sample's region.
- Single-byte XOR brute force producing coincidental strings; require multiple corroborating hits.
- Reporting raw, live C2 endpoints without defanging.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the hunter/decoder.
- ATT&CK T1140 and T1027 (linked in frontmatter).

View File

@@ -0,0 +1,38 @@
# API Reference: Extracting Config From a Running Sample
## Overview
`scripts/analyst.py` scans a process memory dump for config indicators (URLs, IPv4:port pairs,
mutex tokens) and attempts base64 and single-byte XOR decoding of candidate blobs to surface
hidden endpoints. It reads bytes statically, defangs hosts, and executes nothing.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| (stdlib) | — | base64, regex, JSON, file IO |
## Core functions
### `hunt(path)`
Returns defanged URLs, IP:port pairs, mutex tokens, and base64-decoded endpoints.
### `_xor_scan(blob)`
Brute-forces single-byte XOR keys and returns decoded URL/IP:port hits with the key used.
## Commands
- `hunt <dump>` — broad indicator sweep + base64 decode.
- `xor <dump>` — single-byte XOR brute force across the whole dump (noisier; corroborate hits).
## Usage
```bash
python scripts/analyst.py hunt process.dmp
```
## Sources
- MITRE ATT&CK T1140 Deobfuscate/Decode Information — https://attack.mitre.org/techniques/T1140/
- MITRE ATT&CK T1027 Obfuscated Files or Information — https://attack.mitre.org/techniques/T1027/
- Common malware config patterns (Global\\ mutexes, XOR/base64 blobs) from public family teardowns

View File

@@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""Hunt for malware configuration indicators in a process memory dump.
Scans a raw memory dump for URLs, IPv4:port pairs, mutex-like tokens, and base64 blobs, and
attempts single-byte XOR / base64 decoding of candidate blobs to surface hidden endpoints.
Reads bytes statically; executes nothing. Defangs recovered hosts.
"""
from __future__ import annotations
import argparse
import base64
import binascii
import json
import re
import sys
from pathlib import Path
RE_URL = re.compile(rb"https?://[\x21-\x7e]{4,}")
RE_IPPORT = re.compile(rb"\b(?:\d{1,3}\.){3}\d{1,3}:\d{1,5}\b")
RE_MUTEX = re.compile(rb"(?:Global|Local)\\[\x21-\x7e]{4,40}")
RE_B64 = re.compile(rb"[A-Za-z0-9+/]{24,}={0,2}")
def _defang(s: str) -> str:
return s.replace("http", "hxxp").replace(".", "[.]")
def _xor_scan(blob: bytes) -> list[str]:
found = []
for key in range(1, 256):
dec = bytes(b ^ key for b in blob)
for m in RE_URL.findall(dec) + RE_IPPORT.findall(dec):
found.append(f"xor:{key:#04x} {_defang(m.decode('ascii', 'ignore'))}")
return sorted(set(found))[:20]
def hunt(path: str) -> dict:
data = Path(path).read_bytes()
urls = sorted({_defang(m.decode("ascii", "ignore")) for m in RE_URL.findall(data)})
ipports = sorted({_defang(m.decode("ascii", "ignore")) for m in RE_IPPORT.findall(data)})
mutexes = sorted({m.decode("ascii", "ignore") for m in RE_MUTEX.findall(data)})
decoded_hits = []
for blob in RE_B64.findall(data)[:2000]:
try:
raw = base64.b64decode(blob, validate=True)
except (binascii.Error, ValueError):
continue
for m in RE_URL.findall(raw) + RE_IPPORT.findall(raw):
decoded_hits.append("b64 " + _defang(m.decode("ascii", "ignore")))
return {
"urls": urls[:50],
"ip_port_pairs": ipports[:50],
"mutexes": mutexes[:50],
"base64_decoded_endpoints": sorted(set(decoded_hits))[:50],
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Hunt config indicators in a memory dump")
sub = parser.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("hunt")
p.add_argument("dump")
p2 = sub.add_parser("xor")
p2.add_argument("dump")
args = parser.parse_args(argv)
if args.cmd == "xor":
print(json.dumps({"xor_endpoints": _xor_scan(Path(args.dump).read_bytes())}, indent=2))
else:
print(json.dumps(hunt(args.dump), indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())