A licença tem dois campos que se verificam mutuamente. Entender um não basta — você precisa dos dois.
Sistema de licença corporativa. Formato PRODCODE:CHECKSUM — 8 hex chars, dois pontos, 2 hex chars.
O PRODCODE pode ser qualquer valor de 32 bits. O CHECKSUM deve ser exatamente o CRC-8 do PRODCODE, XORado com uma constante mágica escondida no binário.
Você vai reconstruir o CRC-8 e encontrar a constante.
0x07. O resultado é um checksum de 1 byte — frequente em protocolos de comunicação.crc8(prod) ^ MAGIC onde MAGIC = 0xDE. O XOR com uma constante é um padrão clássico pra ofuscar checksums — mas a constante está hardcoded no binário.strtoul. DEADBEEF vira o inteiro 0xDEADBEEF — depois o CRC processa os bytes do mais significativo ao menos.0xDE aparece como imediato num xor ou mov. objdump | grep 0xde ou a view de constantes do Ghidra acha em segundos.
Olha o disassembly de expected_checksum.
Depois do call crc8, tem uma instrução com um operando de 1 byte.
Esse byte é o MAGIC. Com ele em mãos, o keygen tem duas linhas.
objdump -d ./challenge | grep -A 10 "<expected_checksum>:"401262 <expected_checksum>: 401276: e8 7b ff ff ff call 4011f6 <crc8> 40127b: 34 de xor $0xde,%al ← MAGIC = 0xDE
34 de é o opcode de xor al, 0xde.
O byte imediato 0xDE é a constante MAGIC. Com ela e com a lógica do CRC-8, você tem tudo.
crc8 processa 4 bytes do inteiro, do mais significativo ao menos:; para cada byte (i de 3 a 0): ; para cada bit (7 a 0): ; if (crc ^ byte) & 0x80: crc = (crc << 1) ^ 0x07 ; else: crc = (crc << 1) ; byte <<= 1
#!/usr/bin/env python3 # keygen.py — CRACKLAB #07 import sys MAGIC = 0xDE def crc8(value: int) -> int: crc = 0 for i in range(3, -1, -1): byte = (value >> (i * 8)) & 0xFF for _ in range(8): if (crc ^ byte) & 0x80: crc = ((crc << 1) ^ 0x07) & 0xFF else: crc = (crc << 1) & 0xFF byte = (byte << 1) & 0xFF return crc def keygen(prod: int) -> str: checksum = crc8(prod) ^ MAGIC return f"{prod:08X}:{checksum:02X}" # testa com alguns valores for prod in [0xDEADBEEF, 0x12345678, 0xCAFEBABE]: print(keygen(prod))
printf "CAFEBABE:56\n" | ./challenge # ✓ LICENÇA VÁLIDA
| variação | o que faz |
|---|---|
| patch do checksum | Trocar o jne final em 0x40141e por NOP. Aceita qualquer entrada. Mais rápido, mas não entende nada. |
| keygen correto | Reproduz CRC-8 + XOR. Funciona pra qualquer PRODCODE de 32 bits — ~4 bilhões de licenças válidas. |
| brutar MAGIC | Com um par (prod, check) conhecido — que o programa revela no output de erro — você pode deduzir MAGIC em 256 tentativas. O programa entrega ele de graça. |
O programa exibe o checksum esperado quando você erra: "Esperado: 14, recebido: 00". Isso torna o keygen completamente desnecessário — uma única tentativa errada já te dá a resposta. Que lição de design de segurança isso demonstra?