enkomio/shrun
GitHub: enkomio/shrun
一个用 Rust 编写的最小化 Windows PE 构建器,将原始 shellcode 封装为独立可执行文件以便于调试和分析。
Stars: 13 | Forks: 1
# Shellcode Runner
一个用 Rust 编写的最小化 Windows PE 构建器。它接收原始的 shellcode 文件(或十六进制字符串),并生成一个独立的 `.exe`,将 shellcode 封装在单个 RWX `.text` 节中——准备好加载到你喜欢的调试器中。
专为 shellcode 分析和调试设计。没有外部依赖,没有运行时,除了 `KERNEL32.VirtualAlloc` 之外没有任何导入——只有一个裸 PE 文件,你的字节从 `ImageBase + 0x1000` 开始。
## 用法
```
shrun.exe [32|64]
```
| 参数 | 描述 |
|----------|-------------|
| `input` | 原始 shellcode 二进制文件的路径,**或**十六进制编码的字符串 |
| `32\|64` | 输出 PE 的位数。默认:`64` |
## 示例
### 从二进制文件
```
# 64-bit PE (默认)
.\shrun.exe .\shellcode.bin
# 32-bit PE
.\shrun.exe .\shellcode.bin 32
```
输出:
```
[*] input: C:\Users\user\Desktop\shellcode.bin
[*] mode: PE64 (64-bit)
[*] payload: 42 bytes
[*] output: C:\Users\user\Desktop\shellcode_sh.exe
[*] shellcode: 0x0000000180001000 (= BASE_ADDRESS → rcx)
[+] done — entry/stub: 0x000000018000102a
```
### 从十六进制字符串
如果第一个参数不是已存在的文件,它将被解码为十六进制字符串并直接用作 shellcode payload。
```
# x64: xor rax,rax / inc rax / ret
.\shrun.exe 4831c048ffc0c3 64
# x86: xor eax,eax / inc eax / ret
.\shrun.exe 31c040c3 32
# 接受 0x 前缀
.\shrun.exe 0x4831c048ffc0c3
```
输出:
```
[*] input:
[*] mode: PE64 (64-bit)
[*] payload: 7 bytes
[*] output: C:\Users\user\Desktop\shellcode_sh.exe
[*] shellcode: 0x0000000180001000 (= BASE_ADDRESS → rcx)
[+] done — entry/stub: 0x0000000180001007
```
## 构建
```
# 64-bit 主机 (Windows 上默认)
cargo build --release --target x86_64-pc-windows-msvc
# 32-bit 目标
cargo build --release --target i686-pc-windows-msvc
```
## 功能
- 从头构建最小化的 PE32 或 PE32+ 可执行文件(硬编码头部,无需链接器)
- 接受原始二进制文件**或**十六进制字符串作为输入
- 同时支持 **32 位** (PE32 / x86) 和 **64 位** (PE32+ / x86-64) 输出
- 禁用 ASLR — `DllCharacteristics = 0x0000`(无 `DYNAMIC_BASE`)
- 禁用 DEP — 无 `NX_COMPAT`,`.text` 节标记为 `RWX` (`0xE0000020`)
- Shellcode 放置在 `ImageBase + RVA 0x1000` 处(节起始处,始终页对齐)
- 在 shellcode 之后附加一个小型的**位置无关 stub** 并将其设置为入口点;它会将 `ImageBase + 0x1000`(shellcode 地址)作为第一个参数传递,然后跳转到 shellcode
- 从 `KERNEL32.DLL` 导入三个函数(导入表位于 `.rdata` 中):`VirtualAlloc`、`LoadLibraryA`、`GetProcAddress`
### PE 布局
```
File offset 0x000 PE headers (padded to 0x200)
File offset 0x200 .text RVA 0x1000 — RWX
[shellcode bytes]
[stub 17–18 bytes] ← AddressOfEntryPoint
File offset 0x200+ .rdata — import table (VirtualAlloc, LoadLibraryA, GetProcAddress)
```
### Stub 行为
| 步骤 | x64 | x86 |
|------|-----|-----|
| 恢复 shellcode 地址 | `CALL $+5` / `POP RCX` / `SUB RCX, imm32` | `CALL $+5` / `POP EAX` / `SUB EAX, imm32` |
| 作为第一个参数传递 | 值位于 **RCX** | **PUSH EAX** |
| 转移控制权 | `JMP rel32` → shellcode | `JMP rel32` → shellcode |
减法常数在构建时计算为 `shellcode_len + 5`,因此无论 payload 大小如何,结果始终为 `ImageBase + RVA_TEXT`。
标签:DNS 反向解析, PE构建, Rust, Shellcode执行器, 可视化界面, 恶意代码调试, 网络流量审计, 通知系统