xec412/PebWalker
GitHub: xec412/PebWalker
演示 Windows x64 位置无关 shellcode 开发的教学项目,通过 PEB 遍历和导出表解析实现运行时 API 动态解析。
Stars: 1 | Forks: 0
# PebWalker
自定义位置无关 shellcode,通过 PEB 遍历和导出表解析在运行时解析 Windows API,而不依赖 `GetModuleHandle` 或 `GetProcAddress`。
这是在学习 [MalDev Academy](https://maldevacademy.com) 课程时作为练习构建的项目。
## 概述
PebWalker 演示了 Windows x64 位置无关代码 (PIC) 开发的核心构建块:
- **PEB 遍历** — 遍历进程环境块以在内存中定位已加载的模块 (DLL),无需任何 API 调用
- **导出表解析** — 手动解析 PE 导出目录以解析函数地址,替代 `GetProcAddress`
- **修改版 djb2 哈希** — 使用非标准种子和乘数的自定义 djb2 哈希算法在运行时解析 API 和模块名称,避免二进制文件中出现明文字符串
- **基于栈的字符串** — 所有字符串都作为字符数组在栈上构造,以防止它们被放入 `.rdata`,确保它们在 `.text` 节提取后仍然存在
- **x64 调用约定合规性** — 包含一个汇编桩代码 (`Start`),在执行主逻辑之前强制执行 16 字节栈对齐并分配影子空间
作为概念验证,该 shellcode 通过 `WinExec` 启动 `calc.exe`。相同的技术和结构可以扩展到解析任何 Windows API。
## 截图
### Shellcode 执行

### Shellcode 提取

## 项目结构
```
PebWalker/
├── include/
│ ├── shellcode.h # Hash defines, macros, and function prototypes
│ └── Native.h # Windows internal structure definitions (PEB, LDR, PE headers)
├── src/
│ └── shellcode.c # Main shellcode source (Start stub, PEB walking, export parsing, hash function)
├── tools/
│ ├── Extract.c # PE parser that extracts raw shellcode from the .text section
│ └── Hasher.c # Standalone hash generation tool for computing API/module hashes
├── docs/
│ └── screenshots/
├── README.md
└── LICENSE
```
## 技术细节
### 哈希算法
采用自定义参数修改的 djb2 实现,以规避特征检测:
| 参数 | 标准 djb2 | 本实现 |
|------------|----------------|----------------------|
| 种子 | 5381 | 5785 |
| 乘数 | 33 (`<< 5`) | 129 (`<< 7`) |
哈希函数在单个实现中同时处理 ANSI 字符串(以空字符结尾,用于函数名)和 UNICODE 字符串(长度受限,用于来自 PEB 的模块名)。所有比较均不区分大小写。
### Shellcode 流程
```
Start (asm)
│ Stack alignment (16-byte) + shadow space (0x20)
▼
Main()
│
├─ LdrModulePeb(HMODULE_KERNEL32)
│ Walks: TEB → PEB → Ldr → InLoadOrderModuleList
│ Compares each module's BaseDllName hash
│ Returns: kernel32.dll base address
│
├─ LdrFunctionAddress(kernel32, HAPI_WINEXEC)
│ Parses: DOS Header → NT Header → Export Directory
│ Iterates: AddressOfNames → hash compare → AddressOfOrdinals → AddressOfFunctions
│ Returns: WinExec function pointer
│
└─ WinExec("calc.exe", SW_SHOW)
```
## 构建
### 前置条件
- [w64devkit](https://github.com/skeeto/w64devkit) 或 MinGW-w64 (GCC 交叉编译器)
- Visual Studio (用于构建 Extract.c 和 Hasher.c,或使用 GCC)
### 编译 Shellcode
```
gcc src/shellcode.c -o shellcode.exe -Iinclude -masm=intel -Os -fno-asynchronous-unwind-tables -fno-ident -falign-functions=1 -fno-align-jumps -fno-align-loops -fno-align-labels -s -nostdlib -e Start "-Wl,--file-alignment,16" "-Wl,--section-alignment,16"
```
### 提取原始 Shellcode
构建提取工具并对编译后的 shellcode 运行它:
```
gcc tools/Extract.c -o Extract.exe
Extract.exe shellcode.exe calc.bin
```
### 生成哈希
构建哈希工具并为新模块或 API 生成定义:
```
gcc tools/Hasher.c -o Hasher.exe
Hasher.exe kernel32.dll
Hasher.exe WinExec
```
将输出的定义复制到 `include/shellcode.h` 中。
## 扩展
要解析额外的 API,请按照以下步骤操作:
1. 使用 `Hasher.exe` 生成哈希:
Hasher.exe LoadLibraryA → #define HAPI_LOADLIBRARYA (0x...)
Hasher.exe MessageBoxA → #define HAPI_MESSAGEBOXA (0x...)
2. 将定义添加到 `include/shellcode.h`
3. 在 `src/shellcode.c` 中为目标函数签名创建一个 typedef
4. 在 `Main()` 中解析并调用它:
pLoadLibraryA = LdrFunctionAddress(Kernel32, HAPI_LOADLIBRARYA);
User32 = pLoadLibraryA(User32String);
pMessageBoxA = LdrFunctionAddress(User32, HAPI_MESSAGEBOXA);
pMessageBoxA(NULL, TextString, TitleString, 0);
## 致谢
- [MalDev Academy](https://maldevacademy.com) — 课程大纲和方法论
- [C5pider](https://github.com/Cracked5pider) — MalDev Academy 挑战作者,原始 shellcode 模板以及 `Native.h` 结构体 ([Stardust](https://github.com/Cracked5pider/Stardust))
## 免责声明
本项目严格仅用于**教育和研究目的**。旨在作为 MalDev Academy 课程的一部分,演示底层 Windows 内部结构和位置无关代码技术。作者不纵容将这些技术用于未经授权的访问或恶意活动。请负责任地使用,并且仅在你拥有或获得明确测试权限的环境中使用。
## 作者
**Xec** ([@Xec0xCC](https://github.com/Xec0xCC))
## 许可证
详情请参阅 [LICENSE](LICENSE)。
标签:API动态解析, djb2哈希, DNS 反向解析, GetProcAddress替代, PEB Walking, PIC, PoC, Shellcode开发, Windows底层安全, WinExec, x64汇编, 中高交互蜜罐, 位置无关代码, 免杀技术, 内存遍历, 后门技术, 客户端加密, 客户端加密, 导出表解析, 恶意软件开发, 暴力破解, 暴力破解检测, 红队开发, 运行时解析, 黑客工具库