
세션 고유의 RISC-V ISA — 부트할 때마다 다른 방언을 사용합니다. 기존 바이너리는 무효가 됩니다. 멀웨어는 지속될 수 없습니다.
매 부팅은 다른 언어를 말한다. 어제의 바이너리는 오늘의 죽은 코드다.
세션 고유의 RISC-V ISA 재매핑 시스템. 시스템이 부팅될 때마다 명령어 집합의 새로운 암호화 순열을 생성합니다. 한 세션용으로 컴파일된 바이너리는 다음 세션에서 암호학적으로 거부됩니다. 재부팅 후에도 살아남는 멀웨어는 실행될 수 없습니다 — 죽은 방언을 말하기 때문입니다.
표준 ISA는 고정된 계약입니다. 모든 프로그램, 모든 라이브러리, 모든 멀웨어는 0x13의 의미, syscall 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
모든 컴파일된 바이너리는 .text 시작 부분에 두 개의 무해한 addi x0,x0,N NOP으로 삽입된 24비트 암호화 지문을 가지고 있습니다. 이는 진정한 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
# Build patched QEMU 8.2.0 (~10 min first run)
bash build.sh
# Security demo
bash demo.sh
# One trigger rotates both layers simultaneously
bash trigger/trigger_demo.sh
# Boot Alpine Linux under patched QEMU
cd alpine
bash setup_alpine.sh # first time only — downloads kernel + rootfs
bash boot_alpine.sh # boots to ~ # prompt in ~30 seconds
# Alpine ISA demos
bash alpine_demo.sh
bash full_alpine_test.sh
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 ✓
| 단계 | 검사 수 |
|---|
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
-march=rv64g 필수 (RVC 압축 명령어는 아직 처리되지 않음)isa_remap_ldso.h를 통해)register_mapping.h)32개의 RISC-V 레지스터 중 21개가 셔플됩니다. ABI 레지스터는 고정됩니다. QEMU 훅은 OPCODE_FIELDS 테이블을 사용합니다 — 실제 레지스터 필드만 재매핑되고 즉시 값은 절대 건드리지 않습니다 (Curtis의 수정).
| 고정 | 섞을 수 있음 |
|---|---|
| x0 x1 x2 x10-x17 | x3-x9, x18-x31 (21 regs) |
syscall_mapping.h)436개의 Linux RISC-V 시스템 호출이 순열됩니다. do_syscall()의 한 줄. mtime-reload — QEMU 재시작 없이 키링 업데이트 가능.
isa_mapping.h)12개의 기본 opcode가 셔플됩니다. translate.c의 디코드 훅이 디코더 전에 표준 opcode를 복원합니다.
isa_remap_ldso.h)musl 동적 링커 패치 — 로드 시점에 모든 로드된 ELF의 .text를 재매핑합니다. LD_PRELOAD로 우회할 수 없습니다. Alpine musl 재빌드 필요.
.text 재매핑Curtis Cole
Muhammad Bilal
"내 아이디어가 진짜라는 걸 알았지만, 모두가 나를 미쳤다고 생각한 게 확실해." — Curtis Cole
| 상태 |
|---|
| Trigger remapping | 37/37 | ✓ |
| Syscall remapping | 40/40 | ✓ |
| Register remapping | 43/43 | ✓ |
| Integration | 51/51 | ✓ |