It's Not My Fault 1 picoCTF 2021 Solution

Published: April 2, 2026

Description

Hmm, SGX is hard. Can you try to recreate the algorithm? Analyze the provided files to understand the encryption and recover the flag.

Download the provided files (enclave binary, encrypted data, or source).

bash
wget https://mercury.picoctf.net/static/.../fault1.tar.gz && tar xvf fault1.tar.gz
The GDB for CTF guide covers the instruction-skip primitive (set $rip = $rip + N or jump *addr) used here to simulate a fault.
  1. Step 1Identify the fault-injection mode
    This challenge simulates instruction skipping: there is a check inside the enclave that, in a real attack, would be bypassed by glitching power or clock at the exact moment the conditional executes. You reproduce that by jumping past the check in GDB.
    bash
    ls -la fault1/
    bash
    grep -nE 'verify|check|fault|skip' fault1/*.c fault1/*.py 2>/dev/null
    Learn more

    Fault-injection taxonomy:

    • Bit-flip: attacker corrupts a single memory bit (rowhammer, cosmic ray simulation). Useful against key bytes or jump targets.
    • Voltage/clock glitch: drop the CPU's supply voltage or clock for a few nanoseconds, causing one ALU operation to produce a wrong result. Common against signature-verify chains (cmp returns equal even when the buffers differ).
    • Instruction skip: the same glitch tuned more aggressively makes the CPU treat the next instruction as a NOP. Bypasses access-control checks like if (!authenticated) return -1;.

    CTF challenges almost always simulate instruction skip because it's the cleanest to reason about: you find the check in the disassembly and step past it in GDB.

  2. Step 2Examine the provided files
    List and read the extracted files. Look for the encryption algorithm implementation - it may be in a C source file, a compiled enclave binary, or accompanying Python script.
    bash
    ls -la
    bash
    file *
    bash
    cat *.py 2>/dev/null
    bash
    cat *.c 2>/dev/null
    bash
    strings *.so 2>/dev/null | grep -v lib | head -30
    Learn more

    Intel SGX (Software Guard Extensions) creates encrypted, isolated execution environments called enclaves. Code and data inside an enclave are protected from the operating system, hypervisor, and other processes - even the system owner cannot read enclave memory. SGX is used for trusted computing, DRM, and secure key storage.

    In this CTF context, the challenge simulates an SGX-like scenario where an algorithm runs inside a protected environment. You are given the algorithm's description or implementation and asked to either reproduce it, reverse it, or find a weakness in it.

  3. Step 3Analyze and implement the algorithm
    Read the algorithm implementation carefully. Identify the transformation applied to the flag, then implement the inverse in Python to decrypt the provided ciphertext.
    python
    python3 - <<'EOF'
    # Implement the algorithm found in the provided files
    # and reverse it to recover the flag
    
    ciphertext = bytes.fromhex('PASTE_CIPHERTEXT_HERE')
    
    # Example: XOR-based custom cipher
    key = b'PASTE_KEY_OR_DERIVE_IT_HERE'
    flag = bytes(c ^ key[i % len(key)] for i, c in enumerate(ciphertext))
    print(flag.decode('ascii', errors='replace'))
    EOF
    Learn more

    Three reversal patterns by algorithm shape.

    • Self-inverse (XOR-only). If the cipher is c = p XOR k, run the exact same operation on c to recover p. This is true for any byte-wise XOR scheme regardless of how k is generated, because (p XOR k) XOR k = p.
    • Invertible bijection. If the cipher is a sequence of operations like add k, multiply by m mod 256, permute bytes - apply the inverses in reverse order: unpermute, multiply by m^(-1) mod 256, subtract k. The inverse of m mod 256 exists iff gcd(m, 256) = 1 - i.e., m is odd.
    • Known-plaintext key recovery. If the algorithm is c[i] = p[i] XOR k[i % keylen] and you know any plaintext bytes, recover the corresponding key bytes via k[i % keylen] = p[i] XOR c[i]. The flag prefix picoCTF{ is 8 known bytes - enough to recover an 8-byte key directly.

    Worked example. Suppose the algorithm is c[i] = (p[i] * 17 + k[i mod 4]) mod 256 with key k = [3, 7, 11, 13]. Inverse:

    17 mod 256 has inverse 241  (since 17*241 = 4097 = 16*256 + 1)
    
    For each i:
        p[i] = ((c[i] - k[i mod 4]) * 241) mod 256
    
    Verify: encrypt p='A' (65) with k[0]=3:
        c = (65*17 + 3) mod 256 = 1108 mod 256 = 84
    Decrypt:
        p = ((84 - 3) * 241) mod 256 = 19521 mod 256 = 65   ✓

    Why "security through enclave" is not security. Intel SGX hides code from the OS, but the binary on disk is still readable. Reverse-engineering the enclave (Ghidra, IDA, even strings) usually exposes the algorithm. SGX defends only against "cold" OS-level attackers, not against anyone who can analyze the binary - so any cryptographic strength must come from the algorithm itself, not from the wrapper.

  4. Step 4Skip the check in GDB to simulate the fault
    Find the conditional jump that gates the flag print in the disassembly, break right before it, and either skip past the check with set $rip or jump straight to the success branch.
    bash
    gdb -q ./fault1
    bash
    (gdb) disas check_password   # locate the je/jne after cmp
    bash
    (gdb) break *0x401234        # address of the conditional jump
    bash
    (gdb) run
    bash
    (gdb) set $rip = $rip + 2    # skip a 2-byte je instruction
    bash
    # or jump to the success branch directly:
    bash
    (gdb) jump *0x40128a
    bash
    (gdb) continue
    Learn more

    Both primitives, when to use each. set $rip = $rip + N advances the instruction pointer by exactly N bytes - good when you want to skip a single short instruction (a 2-byte je, a 6-byte call) without disturbing surrounding state. jump *addr teleports execution to a specific address; use it when you've identified the start of the success branch and want to leap past several instructions at once.

    Use x/i $rip after the move to confirm you landed on a sane instruction. Landing mid-instruction produces immediate undefined behavior.

Flag

picoCTF{...}

The challenge simulates an instruction-skip fault - jump past the verify branch in GDB and the enclave hands over the flag.

Want more picoCTF 2021 writeups?

Useful tools for Cryptography

Related reading

What to try next