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.