engrbilal992/DeadDialect

GitHub: engrbilal992/DeadDialect

一个基于 RISC-V 的会话唯一指令集重映射系统,通过每次启动时随机化操作码、寄存器和系统调用号来彻底阻止恶意软件在重启后持久化执行。

Stars: 4 | Forks: 1

# DeadDialect 一个会话唯一的 RISC-V ISA 重映射系统。每次系统启动时,它都会生成全新的指令集加密置换。为某一个会话编译的二进制文件在下一次会话中会被加密拒绝。能在重启后存活的恶意软件无法执行——它说着一种已消亡的方言。 ## 理念 标准 ISA 是固定的契约。每个程序、每个库、每个恶意软件都一致认同 `0x13` 的含义、系统调用 64 的作用、哪个寄存器是栈指针。DeadDialect 在每次会话中打破了这个契约。 ``` Boot A: addi = 0x13, write = syscall 64, t0 = x5 Boot B: addi = 0x33, write = syscall 178, t0 = x19 Boot C: addi = 0x67, write = syscall 291, t0 = x23 ``` 为引导 A 编译的二进制文件在引导 B 上毫无意义。它要么执行了错误的指令,调用了错误的内核函数,要么无法通过加密指纹检查——以先发生者为准。 ## 架构 ``` 256-bit session seed (os.urandom) │ ├─── opcode permutation → /etc/isa/map 12! ≈ 2²⁹ ├─── register permutation → /etc/isa/register_keyring 21! ≈ 2⁶⁵ └─── syscall permutation → /etc/isa/syscall_keyring 436! ≈ 2³⁰⁰⁰⁺ ───────────── Combined entropy: 2³⁰⁹⁴⁺ ``` 三个独立的层。攻破其中一层的攻击者仍需面对另外两层。 ``` ┌──────────────────────────────────────────────────────────────┐ │ Binary (.text) │ │ rewritten at compile time by isa_integrate.py │ │ fingerprint NOPs embedded at .text+0 │ └─────────────────────────┬────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ Patched QEMU 8.2.0 │ │ │ │ translate.c ← register_mapping.h │ │ ├── verify 24-bit SHA-256 fingerprint │ │ │ mismatch → SIGILL before first instruction │ │ └── remap 21 shuffleable registers │ │ │ │ syscall.c ← syscall_mapping.h │ │ └── translate permuted syscall number → standard │ │ │ │ [Phase 1/2] ← isa_mapping.h │ │ └── remap 12 primary opcodes │ └──────────────────────────┬───────────────────────────────────┘ │ ▼ Alpine Linux RISC-V (boots normally) OS is unaware of the remapping ``` ## 指纹协议 每个编译后的二进制文件都带有一个 24 位的加密指纹,作为两条无害的 `addi x0,x0,N` NOP 嵌入在 `.text` 的开头。这些是真正的 RISC-V NOP——它们写入零寄存器,不产生任何架构效应——但它们编码了会话证明。 ``` QEMU sees fingerprint NOPs + matching keyring → RUN QEMU sees fingerprint NOPs + wrong keyring → SIGILL QEMU sees no fingerprint + active keyring → SIGILL ← standard binary blocked QEMU sees fingerprint NOPs + empty keyring → SIGILL ← remapped binary blocked ``` 该指纹派生自 `SHA-256(seed)`。在测试的前 100,000 个种子中未发现冲突。 ## 仓库结构 ``` DeadDialect/ ├── opcode-remapping/ Phase 1 — 12 opcode shuffle ├── trigger-remapping/ Phase 2 — live trigger, no reboot needed │ └── alpine/ Alpine Linux demo ├── syscall-remapping/ Phase 3 M1 — 436 syscall shuffle ├── register-remapping/ Phase 3 M2 — 21 register shuffle + fingerprint └── integration/ Phase 3 M3 — all layers simultaneously ├── isa_integrate.py unified rewriter ├── register_mapping.h ├── syscall_mapping.h ├── isa_remap_ldso.h musl ld.so patch (dynamic binaries) ├── trigger/ │ └── trigger_demo.sh one trigger rotates both layers atomically ├── alpine/ │ ├── boot_alpine.sh boot Alpine under patched QEMU │ ├── alpine_demo.sh full ISA demo inside Alpine │ ├── full_alpine_test.sh │ └── setup_alpine.sh fresh machine setup ├── build.sh downloads + patches QEMU 8.2.0 ├── demo.sh └── audit.sh 51/51 checks ``` ## 快速开始 **需求:** Ubuntu 22.04, `clang`, `lld`, `python3`, `wget`, `ninja-build`, `libglib2.0-dev`, `libpixman-1-dev`, `libslirp-dev` ``` git clone https://github.com/engrbilal992/DeadDialect.git cd DeadDialect/integration # 构建已修补的 QEMU 8.2.0(首次运行约 10 分钟) bash build.sh # 安全演示 bash demo.sh # 一个触发器同时旋转两个层 bash trigger/trigger_demo.sh # 在已修补的 QEMU 下启动 Alpine Linux cd alpine bash setup_alpine.sh # first time only — downloads kernel + rootfs bash boot_alpine.sh # boots to ~ # prompt in ~30 seconds # Alpine ISA 演示 bash alpine_demo.sh bash full_alpine_test.sh ``` ## 演示结果 ### 6 场景安全性证明 ``` T1: Standard binary, empty keyrings → runs ✓ T2: Integrated binary, correct keyrings → runs ✓ T3: Standard binary, active keyrings → SIGILL ✗ T4: Integrated binary, empty keyrings → SIGILL ✗ T5: Wrong-seed binary → SIGILL ✗ T6: Correct seed binary → runs ✓ ``` ### 触发演示 ``` Session A binary runs SUCCESS ✓ Session A malware runs EXECUTED (expected — same session) ── trigger fires ── Session B old binary BLOCKED ✓ Session B malware BLOCKED ✓ Session B new binary compiled for B SUCCESS ✓ ``` ### 压力测试 ``` 100,000 seeds — zero collisions Seed 999999999 → BLOCKED under different session ✓ Seed 2²⁵⁶-1 (max 256-bit) → BLOCKED under different session ✓ Keyring corrupted mid-run → BLOCKED on corrupted keyring ✓ ``` ## 审计结果 | 里程碑 | 检查项 | 状态 | |---|---|---| | 触发重映射 | 37/37 | ✓ | | Syscall 重映射 | 40/40 | ✓ | | 寄存器重映射 | 43/43 | ✓ | | 集成 | 51/51 | ✓ | ## 安全属性 ### 它能阻止什么 - **恶意软件持久化**——来自前一个会话的任何二进制文件在下次引导时都会失效 - **预编译漏洞利用**——针对固定 ISA 的 shellcode 会立即失效 - **重放攻击**——来自某一个会话的二进制文件无法在另一个会话中执行 - **标准 QEMU 执行**——重映射的二进制文件需要打过补丁的执行器 ### 为什么熵很重要 ``` Guessing register permutation: 1 in 21! ≈ 1 in 51 quintillion Guessing syscall permutation: 1 in 436! ≈ 1 in 10^(1000+) Guessing both simultaneously: not a viable attack ``` ### POC 范围 - 需要 `-march=rv64g`(目前尚未处理 RVC 压缩指令) - 测试程序仅支持静态二进制文件(通过 `isa_remap_ldso.h` 提供动态支持) - 未涉及在单个会话内完成的攻击 ## 各层工作原理 ### 寄存器 (`register_mapping.h`) 32 个 RISC-V 寄存器中的 21 个被打乱。ABI 寄存器被冻结。QEMU hook 使用 `OPCODE_FIELDS` 表——仅重映射实际的寄存器字段,永远不触碰立即数(Curtis 的修复)。 | 冻结 | 可打乱 | |---|---| | x0 x1 x2 x10-x17 | x3-x9, x18-x31 (21 个寄存器) | ### Syscall(`syscall_mapping.h`) 436 个 Linux RISC-V 系统调用被置换。`do_syscall()` 中的一行代码。mtime 重载——无需重启 QEMU 即可更新密钥环。 ### 操作码 (`isa_mapping.h`) 12 个主操作码被打乱。`translate.c` 中的解码 hook 在解码器之前恢复标准操作码。 ### ld.so(`isa_remap_ldso.h`) musl 动态链接器补丁——在加载时重映射每个已加载 ELF 的 `.text`。无法通过 `LD_PRELOAD` 绕过。需要重新构建 Alpine musl。 ## 未来方向 - ARM 支持(相同概念,不同的固定 ISA 契约) - 内核 `.text` 预引导重映射 - 硬件 FPGA 实现 - Hacker News / 学术出版物 ## 作者与协作者 **Curtis Cole** **Muhammad Bilal** *"我知道我的想法是真实的,但我很确定大家都认为我疯了。"* — Curtis Cole
标签:0day挖掘, APT防御, ASLR, Cutter, ISA重映射, RISC-V, syscall随机化, TLS抓取, 内核安全, 动态二进制, 反恶意代码, 反持久化, 地址空间布局随机化, 子域名枚举, 安全工程, 寄存器混淆, 密码学, 手动系统调用, 指令集架构, 指令集混淆, 熵增, 系统启动, 系统安全, 编译器技术, 网络安全, 软件安全, 逆向工具, 逆向工程对抗, 防恶意软件, 随机化指令集, 隐私保护, 高级持续威胁防御