
Uma ISA RISC-V única por sessão — cada inicialização fala um dialeto diferente. Binários antigos tornam-se inválidos. Malware não pode persistir.
Cada boot fala uma linguagem diferente. O binário de ontem é o código morto de hoje.
Um sistema de remapeamento de ISA RISC-V único por sessão. Cada vez que o sistema inicializa, gera uma permutação criptográfica fresca do conjunto de instruções. Binários compilados para uma sessão são criptograficamente rejeitados na seguinte. Malware que sobrevive a uma reinicialização não consegue executar — ele fala um dialeto morto.
ISAs padrão são contratos fixos. Cada programa, cada biblioteca, cada pedaço de malware concorda sobre o que 0x13 significa, qual syscall 64 faz, qual registrador é o stack pointer. O DeadDialect quebra esse contrato a cada sessão.
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
Um binário compilado para o Boot A é sem sentido no Boot B. Ele ou executa as instruções erradas, chama as funções erradas do kernel ou falha na verificação da impressão digital criptográfica — o que acontecer primeiro.
Semente de sessão de 256 bits (os.urandom)
│
├─── permutação de opcodes → /etc/isa/map 12! ≈ 2²⁹
├─── permutação de registradores → /etc/isa/register_keyring 21! ≈ 2⁶⁵
└─── permutação de syscalls → /etc/isa/syscall_keyring 436! ≈ 2³⁰⁰⁰⁺
─────────────
Entropia combinada: 2³⁰⁹⁴⁺
Três camadas independentes. Um atacante que quebra uma ainda enfrenta as outras duas.
┌──────────────────────────────────────────────────────────────┐
│ Binário (.text) │
│ reescrito em tempo de compilação pelo isa_integrate.py │
│ NOPs de impressão digital embutidos em .text+0 │
└─────────────────────────┬────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ QEMU 8.2.0 com patch │
│ │
│ translate.c ← register_mapping.h │
│ ├── verificar impressão digital SHA-256 de 24 bits │
│ │ incompatível → SIGILL antes da primeira instrução │
│ └── remapear 21 registradores embaralháveis │
│ │
│ syscall.c ← syscall_mapping.h │
│ └── traduzir número de syscall permutado → padrão │
│ │
│ [Fase 1/2] ← isa_mapping.h │
│ └── remapear 12 opcodes primários │
└──────────────────────────┬───────────────────────────────────┘
│
▼
Alpine Linux RISC-V (inicializa normalmente)
O sistema operacional não sabe do remapeamento
Todo binário compilado carrega uma impressão digital criptográfica de 24 bits embutida como dois NOPs inofensivos addi x0,x0,N no início do .text. Estes são verdadeiros NOPs RISC-V — eles escrevem no registrador zero e não têm efeito arquitetural — mas codificam a prova da sessão.
QEMU vê NOPs de impressão digital + keyring correto → EXECUTA
QEMU vê NOPs de impressão digital + keyring errado → SIGILL
QEMU não vê impressão digital + keyring ativo → SIGILL ← binário padrão bloqueado
QEMU vê NOPs de impressão digital + keyring vazio → SIGILL ← binário remapeado bloqueado
A impressão digital é derivada de SHA-256(seed). Nenhuma colisão encontrada nas primeiras 100.000 sementes testadas.
DeadDialect/
├── opcode-remapping/ Fase 1 — embaralhamento de 12 opcodes
├── trigger-remapping/ Fase 2 — gatilho ao vivo, sem necessidade de reinicialização
│ └── alpine/ Demonstração Alpine Linux
├── syscall-remapping/ Fase 3 M1 — embaralhamento de 436 syscalls
├── register-remapping/ Fase 3 M2 — embaralhamento de 21 registradores + impressão digital
└── integration/ Fase 3 M3 — todas as camadas simultaneamente
├── isa_integrate.py reescritor unificado
├── register_mapping.h
├── syscall_mapping.h
├── isa_remap_ldso.h patch do musl ld.so (binários dinâmicos)
├── trigger/
│ └── trigger_demo.sh um gatilho rotaciona ambas as camadas atomicamente
├── alpine/
│ ├── boot_alpine.sh inicializar Alpine sob QEMU com patch
│ ├── alpine_demo.sh demonstração ISA completa dentro do Alpine
│ ├── full_alpine_test.sh
│ └── setup_alpine.sh configuração de máquina nova
├── build.sh baixa + aplica patches no QEMU 8.2.0
├── demo.sh
└── audit.sh 51/51 verificações
Requisitos: 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
# Compilar QEMU 8.2.0 com patch (~10 min na primeira vez)
bash build.sh
# Demonstração de segurança
bash demo.sh
# Um gatilho rotaciona ambas as camadas simultaneamente
bash trigger/trigger_demo.sh
# Inicializar Alpine Linux sob QEMU com patch
cd alpine
bash setup_alpine.sh # apenas na primeira vez — baixa kernel + rootfs
bash boot_alpine.sh # inicializa até o prompt ~ # em ~30 segundos
# Demonstrações ISA no Alpine
bash alpine_demo.sh
bash full_alpine_test.sh
T1: Binário padrão, keyrings vazios → executa ✓
T2: Binário integrado, keyrings corretos → executa ✓
T3: Binário padrão, keyrings ativos → SIGILL ✗
T4: Binário integrado, keyrings vazios → SIGILL ✗
T5: Binário com semente errada → SIGILL ✗
T6: Binário com semente correta → executa ✓
Sessão A binário executa SUCESSO ✓
Sessão A malware executa EXECUTOU (esperado — mesma sessão)
── gatilho dispara ──
Sessão B binário antigo BLOQUEADO ✓
Sessão B malware BLOQUEADO ✓
Sessão B novo binário compilado para B SUCESSO ✓
100.000 sementes — zero colisões
Semente 999999999 → BLOQUEADO sob sessão diferente ✓
Semente 2²⁵⁶-1 (máx 256 bits) → BLOQUEADO sob sessão diferente ✓
Keyring corrompido durante execução → BLOQUEADO no keyring corrompido ✓
Adivinhar permutação dos registradores: 1 em 21! ≈ 1 em 51 quintilhões
Adivinhar permutação das syscalls: 1 em 436! ≈ 1 em 10^(1000+)
Adivinhar ambas simultaneamente: não é um ataque viável
-march=rv64g necessário (instruções comprimidas RVC ainda não tratadas)isa_remap_ldso.h)register_mapping.h)21 dos 32 registradores RISC-V são embaralhados. Registradores ABI congelados. Hook do QEMU usa tabela OPCODE_FIELDS — apenas campos reais de registradores são remapeados, imediatos nunca são tocados (correção de Curtis).
| Congelados | Embaralháveis |
|---|---|
| x0 x1 x2 x10-x17 | x3-x9, x18-x31 (21 regs) |
syscall_mapping.h)436 syscalls Linux RISC-V permutadas. Uma linha em do_syscall(). mtime-reload — keyring atualizado sem reiniciar o QEMU.
isa_mapping.h)12 opcodes primários embaralhados. Hook de decodificação em translate.c restaura o opcode padrão antes do decodificador.
isa_remap_ldso.h)Patch do vinculador dinâmico musl — remapeia .text de todo ELF carregado em tempo de carga. Não pode ser contornado via LD_PRELOAD. Requer recompilação do musl do Alpine.
.text do kernel antes da inicializaçãoCurtis Cole
Muhammad Bilal
"Eu sabia que minha ideia era real, mas tenho certeza de que todos achavam que eu era louco." — Curtis Cole
| Marco |
|---|
| Verificações |
|---|
| Status |
|---|
| Remapeamento de gatilho | 37/37 | ✓ |
| Remapeamento de syscalls | 40/40 | ✓ |
| Remapeamento de registradores | 43/43 | ✓ |
| Integração | 51/51 | ✓ |