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,93 @@
---
name: emulating-shellcode-with-unicorn
description: 'Emulates position-independent shellcode in a controlled CPU emulator (Unicorn) to
trace executed instructions, memory writes, and decoded second stages without running it on a
real host. Activates for requests to emulate shellcode, trace a decoder stub, or recover a stage
unpacked at runtime by shellcode.'
domain: cybersecurity
subdomain: reverse-engineering
tags:
- reverse-engineering
- shellcode
- emulation
- unicorn
- dynamic-analysis
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1027
- T1620
- T1055
d3fend:
- D3-DA
- D3-SDA
references:
- 'Unicorn CPU emulator framework — https://www.unicorn-engine.org/'
- 'MITRE ATT&CK T1620 Reflective Code Loading — https://attack.mitre.org/techniques/T1620/'
---
# Emulating Shellcode With Unicorn
## When to Use
- You have a raw shellcode blob (decoder stub, egg hunter, staged loader) and want to observe its
behavior via emulation rather than native execution.
- You want to recover a second stage that the shellcode decrypts/decompresses in memory.
**Do not use** native execution for this — emulation contains the code. Unsupported API calls must
be stubbed; emulation is not a full Windows environment.
## Prerequisites
- The shellcode blob and the `unicorn` Python package (degrades gracefully if absent — the script
reports that emulation is unavailable and still does static prep).
## Safety & Handling
- Even under emulation, treat the blob as malicious; run on an isolated VM and store stages
password-protected.
## Workflow
### Step 1: Prepare and validate the blob
```bash
python scripts/analyst.py prep shellcode.bin --arch x64
```
Reports size, detected architecture hints, and whether Unicorn is available.
### Step 2: Emulate with an instruction/memory trace
```bash
python scripts/analyst.py emulate shellcode.bin --arch x64 --max-insns 200000
```
Maps the code into emulator memory, sets up a minimal stack, hooks instruction and memory-write
events, and stops on a self-modified region or instruction budget.
### Step 3: Dump decoded stages
If the shellcode writes a new executable region, dump that buffer for follow-on analysis.
### Step 4: Document
Record the entry behavior, decoded stage offset, and any observed (stubbed) API references.
## Validation
- Emulation halts on the instruction budget or a clear decode-complete signal — never hangs.
- A decoded stage, if produced, has a recognizable header (MZ/known opcode prologue).
- Unsupported instructions/APIs are reported, not silently ignored.
## Pitfalls
- Missing API/syscall environment causing early faults — stub the calls the stub needs.
- Wrong architecture/bitness producing immediate invalid-instruction faults.
- Emulating an anti-emulation stub that detects timing/missing APIs.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the emulator harness.
- Unicorn engine and ATT&CK T1620 (linked in frontmatter).

View File

@@ -0,0 +1,41 @@
# API Reference: Emulating Shellcode With Unicorn
## Overview
`scripts/analyst.py` emulates raw x86/x64 shellcode with the Unicorn engine: it maps the code and a
stack, hooks instruction and memory-write events, runs to an instruction budget, and reports
executed instruction count and self-modified regions (decoded stages). Unicorn is optional; without
it, `prep` still reports availability. Intended for isolated VMs.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| unicorn | latest | CPU emulation (optional; emulate requires it) |
| (stdlib) | — | JSON, file IO |
## Core functions
### `prep(path, arch)`
Reports size, architecture, and whether Unicorn is installed.
### `emulate(path, arch, max_insns)`
Maps and runs the shellcode under Unicorn; returns instruction count, self-modified addresses, and
the stop reason.
## Memory layout
- Code base `0x100000` (2 MiB region), stack at `0x300000` (64 KiB). Adjust for larger payloads.
## Usage
```bash
python scripts/analyst.py prep shellcode.bin --arch x64
python scripts/analyst.py emulate shellcode.bin --arch x64 --max-insns 200000
```
## Sources
- Unicorn CPU emulator framework — https://www.unicorn-engine.org/
- MITRE ATT&CK T1620 Reflective Code Loading — https://attack.mitre.org/techniques/T1620/
- Shellcode emulation methodology (mapping, stack setup, hooks) from public emulation tooling

View File

@@ -0,0 +1,99 @@
#!/usr/bin/env python3
"""Emulate raw shellcode with Unicorn to trace execution and recover decoded stages.
`prep` reports blob size and Unicorn availability. `emulate` maps the shellcode, sets up a stack,
hooks instruction and memory-write events, runs up to an instruction budget, and reports executed
instruction count and written regions. Unicorn is optional; without it the script still does
static prep. Designed for isolated VMs; emulation contains the code rather than running it natively.
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
try:
from unicorn import Uc, UC_ARCH_X86, UC_MODE_32, UC_MODE_64, UC_HOOK_CODE, \
UC_HOOK_MEM_WRITE, UcError
from unicorn.x86_const import UC_X86_REG_RSP, UC_X86_REG_ESP
HAVE_UNICORN = True
except ImportError:
HAVE_UNICORN = False
BASE = 0x100000
STACK = 0x300000
STACK_SIZE = 0x10000
MAP_SIZE = 0x200000
def prep(path: str, arch: str) -> dict:
data = Path(path).read_bytes()
return {
"size": len(data),
"arch": arch,
"unicorn_available": HAVE_UNICORN,
"note": "install 'unicorn' to enable emulation" if not HAVE_UNICORN else "ready",
}
def emulate(path: str, arch: str, max_insns: int) -> dict:
if not HAVE_UNICORN:
return {"error": "unicorn not installed", "unicorn_available": False}
code = Path(path).read_bytes()
mode = UC_MODE_64 if arch == "x64" else UC_MODE_32
sp_reg = UC_X86_REG_RSP if arch == "x64" else UC_X86_REG_ESP
uc = Uc(UC_ARCH_X86, mode)
uc.mem_map(BASE, MAP_SIZE)
uc.mem_map(STACK, STACK_SIZE)
uc.mem_write(BASE, code)
uc.reg_write(sp_reg, STACK + STACK_SIZE // 2)
state = {"insns": 0, "writes": []}
def hook_code(uc_, address, size, user): # noqa: ANN001
state["insns"] += 1
if state["insns"] >= max_insns:
uc_.emu_stop()
def hook_write(uc_, access, address, size, value, user): # noqa: ANN001
if address < BASE or address >= BASE + MAP_SIZE:
return
state["writes"].append(address)
uc.hook_add(UC_HOOK_CODE, hook_code)
uc.hook_add(UC_HOOK_MEM_WRITE, hook_write)
error = None
try:
uc.emu_start(BASE, BASE + len(code))
except UcError as exc:
error = str(exc)
written = sorted(set(state["writes"]))
return {
"executed_instructions": state["insns"],
"self_modified_addresses": [hex(a) for a in written[:50]],
"wrote_into_code_region": bool(written),
"stopped_reason": error or "completed or instruction budget reached",
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Emulate shellcode with Unicorn")
sub = parser.add_subparsers(dest="cmd", required=True)
pp = sub.add_parser("prep")
pp.add_argument("file")
pp.add_argument("--arch", choices=["x86", "x64"], default="x64")
pe = sub.add_parser("emulate")
pe.add_argument("file")
pe.add_argument("--arch", choices=["x86", "x64"], default="x64")
pe.add_argument("--max-insns", type=int, default=200000)
args = parser.parse_args(argv)
if args.cmd == "prep":
print(json.dumps(prep(args.file, args.arch), indent=2))
else:
print(json.dumps(emulate(args.file, args.arch, args.max_insns), indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())