Description
Another SGX challenge with additional complexity. Analyze the algorithm deeply and recover the flag.
Setup
Download the provided files.
wget https://mercury.picoctf.net/static/.../fault2.tar.gz && tar xvf fault2.tar.gzSolution
Walk me through itjump primitive used to bypass each stage.- Step 1Map the multi-stage check chainDisassemble the verifier and trace the call graph: stage_1 -> stage_2 -> ... -> print_flag. Each stage is a separate gate that must fall in order; skipping a later stage early jumps over uninitialised state. See It's Not My Fault Part 1 for the single-stage baseline.bash
objdump -d fault2 | grep -A2 -E 'call.*stage|jne|je 'bash# Or in GDB: info functions stagebash# (gdb) rbreak ^stageLearn more
Same fault taxonomy as part 1: bit-flip, voltage/clock glitch, instruction skip. The challenge again simulates instruction skip - the only physically-glitchable primitive that maps cleanly to a CTF box. What changes in part 2 is that there are multiple checks in series, each with its own failure side effect.
Order matters because of state. Stage
iusually decrypts material that stagei+1consumes. If you skipstage_2's validation butstage_3reads the bufferstage_2was supposed to fill, you'll get garbage. List the stages in source order, glitch only the verify branches, and let the body of each stage run normally so its side effects propagate. - Step 2Analyze the file structureExamine all provided files. Compare to the Part 1 challenge - this version likely adds encryption layers, multiple rounds, or a more complex key schedule.bash
ls -labashfile *bashcat *.py 2>/dev/nullbashcat *.c 2>/dev/nullbashdiff <(ls fault1/) <(ls fault2/) 2>/dev/null # If both are availableLearn more
Part 2 SGX challenges typically escalate from Part 1 in one of these ways:
- Multi-round cipher: The same transformation is applied multiple times with different round keys derived from a key schedule.
- Compound algorithm: Multiple different ciphers applied in sequence (e.g., AES then XOR then custom substitution).
- Key derivation complexity: The key is not hardcoded but derived from a password or time value using a complex algorithm.
- Fault injection simulation: The challenge simulates Intel SGX fault injection attacks, where an attacker induces computation errors to leak secret key bits.
- Step 3Reverse the encryption algorithmTrace through the algorithm carefully. For multi-round ciphers, implement all rounds in order, then reverse each round's operations in reverse order for decryption.python
python3 - <<'EOF' # Reverse the Part 2 SGX algorithm ciphertext = bytes.fromhex('PASTE_CIPHERTEXT_HERE') # Implement algorithm in forward direction first to verify understanding: def encrypt(plaintext, key): # ... implement forward algorithm ... return ciphertext # Then implement decryption (inverse): def decrypt(ciphertext, key): # Apply inverse operations in reverse order # For each round (in reverse): # undo_round_operation(state) return plaintext key = b'...' # Extract from binary or derive flag = decrypt(ciphertext, key) print(flag.decode('ascii', errors='replace')) EOFLearn more
Block cipher decryption. For a block cipher with N rounds, decryption applies the inverse of round N's operations, then round N-1's, back to round 1. If the round is
SubBytes -> ShiftRows -> MixColumns -> AddRoundKey(AES-style), the inverse round isInvAddRoundKey -> InvMixColumns -> InvShiftRows -> InvSubBytes. Order reverses and each step is replaced by its inverse.Worked toy example: 3-round Feistel. Plaintext
(L0, R0), round functionF, round keysk1, k2, k3. Encryption:Round 1: L1 = R0, R1 = L0 XOR F(R0, k1) Round 2: L2 = R1, R2 = L1 XOR F(R1, k2) Round 3: L3 = R2, R3 = L2 XOR F(R2, k3) Output: C = (L3, R3) Decryption (reverse, same F): Round 3': R2 = L3, L2 = R3 XOR F(L3, k3) Round 2': R1 = L2, L1 = R2 XOR F(L2, k2) Round 1': R0 = L1, L0 = R1 XOR F(L1, k1) Output: P = (L0, R0) ✓Note that Feistel structures use the same round function in both directions - only the order of round keys reverses. AES uses a non-Feistel SPN structure, so each operation needs an explicit inverse (InvSubBytes uses an inverse S-box, InvMixColumns uses a different matrix), but the principle is identical.
Fault injection / differential fault analysis (DFA). If the challenge simulates SGX fault injection: induce a fault during round N-1 (e.g., flip one byte of state), capture both the correct ciphertext
Cand the faulty ciphertextC'. The XOR differenceC XOR C'propagates through the final round, leaking constraints on the last round key. Piret-Quisquater (2003) showed two faulty AES ciphertexts are typically enough to recover the full 128-bit key. The DFA equations look like: for each candidate last-round key bytek, check ifInvSubBytes(C XOR k) XOR InvSubBytes(C' XOR k)matches an expected single-byte fault pattern after InvShiftRows. Only the correctkbyte makes that check pass for both fault pairs.
Flag
picoCTF{...}
Part 2 SGX adds algorithm complexity - carefully implement the full multi-round cipher in forward direction first, then build the decryption by reversing each round's operations in reverse order.