KarpelesLab/univdreams
GitHub: KarpelesLab/univdreams
一款基于 Rust 的通用反编译与编译套件,通过可读的 .ud 中间语言实现对 ELF、PE、Mach-O 等多种格式二进制文件的字节级精确往返转换。
Stars: 1 | Forks: 1
# univdreams
一个通用的编译器**与**反编译器套件。其前提是:
**在浏览器中试用:**
大多数反编译器只是意译。它们丢失了编译器做出的选择——寄存器分配、指令编码、指令顺序、填充、跳转表布局——而对其输出进行重新编译后,虽然结构上相似,但与输入并不完全一致。univdreams 将这些选择视为源语言中的一等信息:它们存在于属性/指令中,在输出时将编译器锁定回相同的形态。
## 状态
**标题特性已在每次推送时正常运行并受到保护,适用于所有格式:**
```
lower_to_{elf,pe,macho,raw}(parse(decompile_to_text(bin))) == bin-bytes
```
对于每个已提交的测试用例,整个文件——包括头部、段/节表、每个节的内容、每个间隙的填充,以及代码签名数据块——在通过 `.ud` 源语言进行往返处理后,实现字节级一致。语料库包含 15 个二进制文件,总计约 **490 KB**,外加 420 KB 的 `wmpcdcs8-mpg4c32.dll`(Windows msmpeg4 编解码器)作为可选的外部测试用例。
目前已完成的功能:
- **跨 ELF64、PE/COFF 和精简 Mach-O(x86-64 + arm64),以及 6502 原始映像的字节级一致往返处理**。
- **架构**:通过 `iced-x86` 支持 x86-64 + i386,AArch64(解码与提升),6502(完整的汇编器 + 反汇编器)。
- **结构化语句提升**,而不仅仅是 `@asm()` 的倾倒:`if`/`switch`/`goto`、以寄存器命名的局部变量、`dword ptr [global] = expr` 存储、`lea` 作为 `&` 取地址、带有 stdcall/cdecl push 链折叠的 `sub_foo(arg_8, arg_c)` 调用、用于尾跳转的 `tail_F(args)`、序言/尾声自动生成、SSA 表达式组合。
- **PE / Mach-O 可读性**可与 Ghidra 的 Headers + Memory Map + Symbol Table + Listing 面板相媲美:加载命令的结构化解码(`LC_SEGMENT_64`、`LC_SYMTAB`、`LC_MAIN`、`LC_BUILD_VERSION`、`LC_LOAD_DYLIB` 等)、内联反汇编注释、IAT 解析的导入(`GetDriverModuleHandle(arg_c)`)。
- **DWARF 读取器**,用于读取带类型的函数签名(从 `.debug_info` 获取参数和返回类型)。
- **函数发现**,分层覆盖 `.symtab`、`.dynsym`、`.eh_frame`、PE 导出表、字节模式签名(CRT 辅助函数),以及对无符号二进制文件的大小填充。
- **WASM 实验环境**位于 ,在浏览器中运行完整流程。
- **17 个 crate 中的 250 个测试**,在每次推送时都受到 fmt + clippy + tests 的保护。
尚未完成的功能:
- 更高级的反编译:将 `goto` 转换为 `for`/`while` 循环、从偏移模式命名结构体字段、在缺少 DWARF 时从访问模式恢复类型。
- 超出当前 CRT 辅助函数集的 libc / Win32 / Foundation 运行时签名数据库。
- 胖(通用)Mach-O 包装器;32 位 Mach-O。
- 编辑后的 Mach-O 代码签名重新生成(目前签名数据块作为不透明字节存在——编辑源码会破坏签名,这与任何二进制编辑是一样的)。
- 编辑语义:重新编码长度发生变化的 `@asm` 编辑尚未发出警告。
有关已完成功能的详细信息和下一步计划,请参阅 [docs/roadmap.md](docs/roadmap.md)。
## 目前它能做什么
将二进制文件反编译为规范的 `.ud` 源码:
```
$ ud decompile testdata/external/wmpcdcs8-mpg4c32.dll
@module {
arch: "x86",
format: "pe",
bits: 0x20,
endian: "little",
build: { … coff, sections, optional_header, padding, file_size … },
}
fn DriverProc() #[abi="stdcall", autogen_pro] {
let arg_8: u32;
let arg_c: u32;
let arg_10: u32;
let arg_14: u32;
let arg_18: u32;
let eax: u32, edx: u32, ecx: u32 @reg;
eax = arg_10 [0x8b, 0x45, 0x10]
edx = arg_14 [0x8b, 0x55, 0x14]
ecx = 0x4004 [0xb9, 0x04, 0x40, 0x00, 0x00]
if (eax >u ecx) goto label_2116;
if (eax == ecx) goto label_2103;
ecx = &[eax - 1]
switch (ecx) {
case 0: goto label_209d;
case 1: goto label_20fb;
…
}
label_209d:
if (dword ptr [0x1c262194] == 0) {
GetDriverModuleHandle(arg_c)
[0x1c262194] = eax
}
dword ptr [0x1c26219c] = dword ptr [0x1c26219c] + 1
goto label_20fb;
label_2288:
eax = arg_14
pushed_args([eax], [eax + 4], [eax + 8], [eax + 0x24], [eax + 0x28], …, [eax + 0x20])
sub_3469(arg_8)
goto label_2466;
…
}
```
对比 Mach-O 的相同概念:
```
$ ud decompile testdata/hello-clang-macho-x86_64
@module {
arch: "x86_64", abi: "macho", format: "macho", …
build: {
commands: [
{ cmd: 0x19, segment: { name: "__TEXT", sections: [
{ name: "__text", addr: 0x100000470, size: 0x23, … },
{ name: "__stubs", addr: 0x100000494, … },
{ name: "__cstring", … },
] } },
{ cmd: 0xe, dylinker: { name: "/usr/lib/dyld", … } },
{ cmd: 0x1b, uuid: "E567B4F0-B55D-3028-B141-EA1067085478" },
{ cmd: 0x80000028, main: { entryoff: 0x470, stacksize: 0 } },
{ cmd: 0xc, dylib: { name: "/usr/lib/libSystem.B.dylib", … } },
…
],
},
}
// ── symbols ── (decoded from LC_SYMTAB; informational, not round-trip source)
// 0x0000000100000470 SECT EXT sect=1 _main
// 0x0000000000000000 UNDF EXT sect=0 _puts
// ── disassembly of __text @ 0x100000470 (35 bytes) ──
// 0x0000000100000470 55 push rbp
// 0x0000000100000471 48 89 e5 mov rbp,rsp
// 0x0000000100000474 48 83 ec 10 sub rsp,10h
// 0x0000000100000478 c7 45 fc 00 00 00 00 mov dword ptr [rbp-4],0
// 0x000000010000047f 48 8d 3d 14 00 00 00 lea rdi,[10000049Ah]
// 0x0000000100000486 e8 09 00 00 00 call 0000000100000494h
// 0x000000010000048b 31 c0 xor eax,eax
// 0x000000010000048d 48 83 c4 10 add rsp,10h
// 0x0000000100000491 5d pop rbp
// 0x0000000100000492 c3 ret
```
将相同的 `.ud` 源码重新编译回字节级完全一致的二进制文件:
```
$ ud roundtrip --through-source testdata/external/wmpcdcs8-mpg4c32.dll \
--out /tmp/mpg4c32.rebuilt
source round-trip ok: testdata/external/wmpcdcs8-mpg4c32.dll == /tmp/mpg4c32.rebuilt (420240 bytes)
```
## 目标
| 级别 | 格式 | 架构 | 状态 |
|------|--------|---------------|--------|
| **v1(正常工作中)** | ELF64 | x86-64 (SysV), x86 (32位), aarch64 | ✅ 全二进制源码往返处理;DWARF;结构化提升 |
| **v1(正常工作中)** | PE/COFF | x86-64, x86 (Windows MSVC + MinGW) | ✅ 全二进制源码往返处理;导入 + 签名 |
| **v1(正常工作中)** | Mach-O (精简) | x86-64, arm64 (macOS) | ✅ 全二进制源码往返处理;Ghidra 风格的列表 |
| **v1(正常工作中)** | raw / flat | 6502 (Apple I / WozMon) | ✅ 往返处理 + 提升 |
| 2 | Mach-O fat | 通用二进制文件 | 先解复用为精简格式 |
| 2 | ARM / Thumb | 32位 ARM | 尚未支持 |
| 3 | 高级提升 | 循环、类型、结构体字段 | 部分 —— 见路线图 |
已达到 v1 复杂度标准:**来自 gcc / clang / MSVC / MinGW 的标量代码,带或不带调试信息**。自动向量化、LTO/PGO、手写优化汇编和加壳二进制文件明确是 v1 的非目标。
## 驱动设计的用例
- **逆向工程与修补**:编辑一个函数,重新编译,发布一个除了你的修改外与原始文件毫无区别的二进制文件。
- **教育 / 研究 / CTF**:在一个能够自我解释的语言中,了解编译器实际做了什么。
- **可重现构建验证**(后期):独立编译供应商的源代码并验证其是否与他们发布的二进制文件相匹配。
跨架构的二进制移植在 v1 中**不支持**。在一个架构上实现高保真的往返处理是未来跨架构移植的先决条件。
## 实现语言
Rust。简要原因如下:
- 强大的类型系统能够捕获那些原本会悄无声息存在的 IR 转换错误。
- 生态系统最为契合:使用 [`iced-x86`](https://crates.io/crates/iced-x86) 进行 x86 编码/解码,使用 [`gimli`](https://crates.io/crates/gimli) 处理 DWARF / `.eh_frame`,手工编写的 ELF / PE / Mach-O 读写器以控制往返过程。
- 在解析不受信任的二进制文件时,内存安全性至关重要。
## 仓库布局
```
.
├── README.md
├── Cargo.toml # workspace
├── docs/
│ ├── architecture.md # pipeline, IR, how directives preserve info
│ ├── roadmap.md # phased milestones, what's done
│ ├── source-language.md # the .ud language, directives, examples
│ └── round-trip-contract.md # what "identical bytes" means precisely
└── crates/
├── ud-core/ # shared types: VAddr, Result, byte helpers
├── ud-format-elf/ # ELF64 reader + writer (byte-identical)
├── ud-format-pe/ # PE/COFF reader + writer (byte-identical)
├── ud-format-macho/ # thin 64-bit Mach-O reader + writer
├── ud-format-raw/ # raw / flat-image fixtures (6502)
├── ud-arch-x86/ # x86 decode + lift + Intel formatter + call-site analyzer
├── ud-arch-aarch64/ # AArch64 decode + lift
├── ud-arch-6502/ # 6502 decode + lift + assembler
├── ud-ir/ # Function, BasicBlock, Terminator (generic over arch)
├── ud-analysis/ # function discovery (symtab / eh_frame / signatures)
├── ud-signatures/ # byte-pattern DB (CRT helpers)
├── ud-debug/ # DWARF reader → typed signatures
├── ud-ast/ # .ud AST + canonical pretty-printer
├── ud-compile/ # .ud parser + lower_to_{elf,pe,macho,raw}
├── ud-decompile/ # binary → AST pipeline (all formats)
├── ud-cli/ # the `ud` binary
└── ud-wasm/ # wasm-bindgen bindings for the browser playground
```
## 快速开始
```
# Build
cargo build --workspace
# 在测试语料库上运行端到端字节一致的双向转换
cargo test --workspace
# Decompile 任何受支持的二进制文件为 .ud(自动检测 ELF / PE / Mach-O / 6502)
cargo run --bin ud -- decompile path/to/binary
# 源码双向转换:decompile → emit → parse → lower → 检查字节一致性
cargo run --bin ud -- roundtrip --through-source path/to/binary
# 验证 .ud 文件的 @asm 行解码为规范的 Intel-syntax 形式
cargo run --bin ud -- verify path/to/file.ud
```
## 如何阅读本仓库
如果你只是粗略浏览,请阅读本 README 并浏览 [docs/source-language.md](docs/source-language.md) —— 示例中的指令是核心概念。
如果你想了解完整的设计和当前状态:
1. [docs/architecture.md](docs/architecture.md) —— 流程、crate 职责、各部分如何协同工作。
2. [docs/round-trip-contract.md](docs/round-trip-contract.md) —— 我们承诺保留的内容以及在哪个层次进行测试。
3. [docs/source-language.md](docs/source-language.md) —— 指令词汇表及详细示例。
4. [docs/roadmap.md](docs/roadmap.md) —— 已发布的内容、正在进行的内容、以及未来的计划。
## 许可证
MIT。版权所有 (c) 2026 Karpeles Lab Inc. 详见 [LICENSE](LICENSE)。
标签:6502, AArch64, ELF, Mach-O, PE, Rust语言, VPS部署, Wayback Machine, x86-64, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 代码安全, 代码重构, 反汇编, 反编译器, 可视化界面, 字节码完全一致, 汇编, 源语言, 漏洞枚举, 编译器, 解析器, 解析引擎, 软件分析, 软件逆向, 逆向工程, 通知系统, 静态分析