Writeup
Power of Statistics — Writeup
Power of Statistics — Writeup
This writeup explains how to solve the Power of Statistics hardware challenge using CPA (Correlation Power Analysis) on power traces to recover a 16‑byte key, then invert the cipher to decrypt the encrypted flag. The firmware is given as a decompiled listing and an ELF, plus plaintexts and traces.
Summary
The device applies an 8‑round, 16‑byte block transform built from an S‑box. Each round computes sbox[key[i] ^ pt[i]] for i=0..7, rotates those outputs into the first 8 bytes, and mixes them into bytes 8..15 with an XOR against another S‑box output. The trigger is raised around this computation, giving clean side‑channel alignment.
We use a Hamming‑weight model on the S‑box output for each key byte, correlate against the traces, select the best key guess per byte, and then invert the round function 8 times to decrypt the ciphertext. The final flag is recovered (redacted below).
Files Provided
crypto_firmware.elf— binary containing the S‑boxplaintext.npy— 1000 plaintexts (shape 1000×16)traces.npy— 1000 traces (shape 1000×1500)encrypted_flag— 16‑byte ciphertext blockcrypto_firmware_decompiled.txt— decompiled firmware from dogbolt.org
Firmware Analysis
Core encryption in get_pt()
The encryption happens in get_pt(). The decompiled code shows a loop with 8 rounds and the power trigger:
trigger_high();int32_t i_1 = 8;do { char r8_1 = sbox[key[0] ^ *pt]; char lr_1 = sbox[key[1] ^ pt[1]]; char r12_1 = sbox[key[2] ^ pt[2]]; char r7_1 = sbox[key[3] ^ pt[3]]; char r6_1 = sbox[key[4] ^ pt[4]]; char r0 = sbox[key[5] ^ pt[5]]; char r1_7 = sbox[key[6] ^ pt[6]]; uint8_t r2_17 = sbox[key[7] ^ pt[7]];
*pt = r2_17; pt[1] = r8_1; pt[2] = lr_1; pt[3] = r12_1; pt[4] = r7_1; pt[5] = r6_1; pt[6] = r0; pt[7] = r1_7;
pt[8] = r8_1 ^ sbox[key[8] ^ pt[8]]; pt[9] = lr_1 ^ sbox[key[9] ^ pt[9]]; pt[0xa]= r12_1 ^ sbox[key[0xa]^ pt[0xa]]; pt[0xb]= r7_1 ^ sbox[key[0xb]^ pt[0xb]]; pt[0xc]= r6_1 ^ sbox[key[0xc]^ pt[0xc]]; pt[0xd]= r0 ^ sbox[key[0xd]^ pt[0xd]]; pt[0xe]= r1_7 ^ sbox[key[0xe]^ pt[0xe]]; pt[0xf]= r2_17 ^ sbox[key[0xf]^ pt[0xf]];} while (i != 1);trigger_low();Key observations:
- The sensitive computation is the S‑box output
sbox[key[i] ^ pt[i]]. - This is the textbook target for CPA with a Hamming‑weight leakage model.
- The trigger surrounds the entire 8‑round block, so the traces are well aligned.
S‑box location
The decompiled reset handler copies the S‑box from flash into RAM:
while (&sbox[r1] < &__TMC_END__){ *(&sbox + r1) = *(0x80014c0 + r1); r1 += 4;}From the ELF layout, 0x080014c0 maps to file offset 0x020000, so the first 256 bytes at that offset in crypto_firmware.elf are the S‑box.
Side‑Channel Attack (CPA)
Leakage model
We assume Hamming‑weight leakage on the S‑box output:
L ≈ HW(SBOX[pt_byte ^ key_guess])We compute, for each byte index 0..15:
- For each key guess
kin0..255, compute the hypothesis vector:h = HW(SBOX[pt[:,byte] ^ k]) - Correlate
hwith every time sample in the trace. - Use the max absolute correlation across time as the score.
- Select the
kwith the highest score.
Why this works
The trigger isolates the S‑box computation, and each trace corresponds to a known plaintext, so the correlation peak appears when the hypothetical S‑box output matches the real device state.
Key Recovery
Running CPA over all 16 bytes yields a full 16‑byte key. (Key intentionally omitted in this write‑up.)
Cipher Inversion
We invert one round analytically using the S‑box inverse.
Let the output state be q[0..15]. From the round structure:
q[0] = a7,q[1] = a0,q[2] = a1, …,q[7] = a6q[8] = a0 ^ sbox[key8 ^ p8]q[9] = a1 ^ sbox[key9 ^ p9]- …
q[15] = a7 ^ sbox[key15 ^ p15]
Recover the previous state:
p0 = key0 ^ sbox_inv[a0]p1 = key1 ^ sbox_inv[a1]...p7 = key7 ^ sbox_inv[a7]
p8 = key8 ^ sbox_inv[q8 ^ a0]p9 = key9 ^ sbox_inv[q9 ^ a1]...p15 = key15 ^ sbox_inv[q15 ^ a7]Apply this inverse 8 times to the encrypted_flag block.
Final Result
The decrypted plaintext yields the flag.
Flag (redacted): FlagY{***********}
Notes
- The attack succeeds with just 1000 traces because the S‑box output is a strong, single‑byte leakage point.
- The cipher is not AES; it’s a custom 8‑round S‑box permutation + XOR mix.
- The trigger makes this a clean CPA target with minimal preprocessing.