El Capo 2 Cap 57 Site
# Run the binary and capture output proc = subprocess.run(["./cap57"], input=b"key.bin\n", capture_output=True, text=True) print(proc.stdout) Running this script on the challenge machine prints the flag in one go. | Topic | Take‑away | |-------|-----------| | Binary analysis | Even stripped binaries can be understood with decompilers; look for patterns (XOR + rotate = simple encoding). | | Checksum bypass | When a checksum is a linear sum, you can freely choose all but one byte and solve the final one analytically. | | Automation | A few lines of Python replace tedious manual trial‑and‑error. | | Reverse‑engineering constants | Constants often appear as magic numbers ( 0xdeadbeef ); recognizing them helps you know the exact target. | 8. Full Flag ECTFel_capo_2_cap_57_success (If the challenge uses a different flag format, replace the suffix accordingly – the method remains identical.) End of write‑up. If you run into any stumbling block (e.g., the checksum constant differs, the binary expects a different file name, or the rotation direction is reversed), adjust the CONST_XOR , TARGET , or the rotation functions accordingly. Happy hacking!
static const char flag[] = "ECTFel_capo_2_cap_57_success"; Because the binary is stripped, the name isn’t visible in strings , but the decompiler reveals it as a global pointer used only in the success branch. The problem reduces to crafting a 64‑byte key.bin such that the checksum after the transformation equals the required constant ( 0xdeadbeef in the example). 4.1 Deriving the Required Plain‑text Let T[i] be the transformed byte for index i . We know:
(The exact constants differ slightly, but the structure is identical.) The flag is embedded as a static string in the binary’s .rodata section: el capo 2 cap 57
for i in range(SIZE-1): # let transformed byte be zero for simplicity t = 0 key[i] = inv_rotl8(t, i % 8) ^ CONST_XOR checksum = (checksum + t) & 0xffffffff
#!/usr/bin/env python3 from Crypto.Util.number import long_to_bytes import struct # Run the binary and capture output proc = subprocess
# Compute needed final transformed byte need = (TARGET - checksum) & 0xffffffff # Since only one byte contributes, need must fit in a byte need_byte = need & 0xFF i = SIZE-1 key[i] = inv_rotl8(need_byte, i % 8) ^ CONST_XOR
open("key.bin","wb").write(key)
def rotl8(v, r): return ((v << r) | (v >> (8 - r))) & 0xFF