TexSaw2025 XORer writeup - Pez1181/CTF GitHub Wiki
XORer — Binary Reversing Writeup
Challenge Type: Reverse Engineering
Vulnerability: XOR-based password obfuscation
Protection Bypassed: None — just logic, mate.
Tools Used: Ghidra, Python, xor.pw, terminal
Difficulty: Introductory
🧭 Recon
We were given a stripped 64-bit ELF binary named XORer. Running the binary prompts us to input a password. If correct, we’re rewarded with a texsaw{...} flag.
$ ./XORer
Enter password:
No output hints — so it’s time to open up the binary and see what’s under the hood.
🔬 Vulnerability Analysis
Loading the binary into Ghidra, we quickly hone in on the check_password() function. Here's the important snippet:
local_1c[0] = 0xcb;
local_1c[1] = 0x95;
local_1c[2] = 0xd1;
...
local_1c[11] = 0xc2;
if (((int)param_1[i] ^ 0xa5U) != (uint)local_1c[i]) {
puts("Wrong password!");
return;
}
So each input character is XORed with 0xA5, then compared to a hardcoded byte.
This is textbook reversible logic:
If a ^ k = b, then b ^ k = a.
🧨 Exploit Strategy
We simply need to reverse the XOR operation on the byte array:
decoded_char = encoded_byte ^ 0xA5
Do that for all 12 bytes and we’ve got the password.
🧑💻 Exploit Script
Here’s a Python script that automates the decryption:
# xor_decoder.py
def xor_decrypt(encoded_bytes, key):
return ''.join(chr(b ^ key) for b in encoded_bytes)
if __name__ == "__main__":
# XOR-obfuscated password bytes from the binary
encoded = [0xcb, 0x95, 0xd1, 0xfa,
0xd1, 0xcd, 0x96, 0xfa,
0xc3, 0xc9, 0x91, 0xc2]
key = 0xA5 # XOR key used in the binary
password = xor_decrypt(encoded, key)
print(f"[+] Decoded password: {password}")
🖥️ Example Output
$ python3 xor_decoder.py
[+] Decoded password: l3t_m3_1n
Using the password:
$ ./XORer
Enter password: n0t_th3_fl4g
Correct! Here's your flag: texsaw{n0t_th3_fl4g}
🧪 Final Notes
- XOR challenges like this are common in beginner RE/CTF tasks.
- If you're new to this, https://xor.pw is an excellent online tool to visualize XORing.
- Always check for constants like
0xA5,0xDEADBEEF, or even0x1337— they often indicate intentional obfuscation or comparisons.
Maybe move on to patching the binary to always print the flag, or try extracting the logic dynamically using angr, unicorn, or a GDB script.