← Back to Writeups
CUSTOMEasyReversing

Reverse Me

XESXOR9/2/20264 min read
#reversing#custom#easy#identity_transform_detection#static_string_extraction#xor_cancellation

Reverse Me

Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: identity_transform_detection, static_string_extraction, xor_cancellation

Summary

Walkthrough of the CUSTOM Reversing Reverse Me. Task: ELF binary that checks a flag using XOR and hex encoding. Solution: Recognized that double XOR with same key and hex encode/decode pair form an identity function, so the hardcoded string in .rod

Description

We found a binary that checks a flag. The program takes a string, does something with it, and reports whether the flag is correct or not. Find the flag.

Files: secret.tb — ELF 64-bit LSB PIE executable, x86-64, dynamically linked, not stripped

Analysis

Step 1: File Identification

bash
file secret.tb
# secret.tb: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, not stripped

The binary is not stripped — all symbols are present, which significantly simplifies analysis. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Step 2: String Search

bash
strings secret.tb
# ...
# Enter flag:
# TB{REDACTED}
# Correct! Flag is ...
# Wrong!
# %02x
# ...

A suspicious string TB{REDACTED} is immediately visible in the .rodata section. But we need to verify that this is actually the flag and not a decoy.

Step 3: Static Analysis of the Algorithm

Using objdump and radare2, the complete program logic was reconstructed:

3.1 Input

The program outputs "Enter flag: " and reads user input via getline.

3.2 First XOR Loop

Loads the hardcoded string TB{REDACTED} from .rodata and XORs each byte with key 0x42: ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

for i in range(len(s)):
    s[i] ^= 0x42

3.3 Hex Encoding

Each XORed byte is converted to a 2-character hex string via snprintf("%02x", ...):

byte 0x16 → "16"
byte 0x00 → "00"
...

3.4 hex_decode Function

The hex string is converted back to raw bytes — complete inversion of the previous step:

"16" → byte 0x16
"00" → byte 0x00
...

3.5 Second XOR Loop

Each decoded byte is XORed again with 0x42 — complete inversion of the first XOR:

for i in range(len(s)):
    s[i] ^= 0x42

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

3.6 Comparison

The result is compared with user input. If it matches — "Correct!".

Step 4: Mathematical Proof

The entire transformation chain is an identity function:

input → XOR(0x42) → hex_encode → hex_decode → XOR(0x42) → output

XOR(XOR(x, 0x42), 0x42) = x          (XOR property: a ⊕ b ⊕ b = a)
hex_decode(hex_encode(x)) = x         (inverse operations)

Result: output = input

The obfuscation is a red herring. The expected input = the original hardcoded string.

Solution

python
#!/usr/bin/env python3
"""
Reverse Me — TaipanByte CTF
Proof that the transformation is an identity function.
"""
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Hardcoded string from .rodata
flag = "TB{REDACTED}"

# Verify: XOR → hex_encode → hex_decode → XOR = identity
key = 0x42

# Step 1: XOR with 0x42
xored = bytes([b ^ key for b in flag.encode()])
print(f"After XOR(0x42):  {xored.hex()}")

# Step 2: hex_encode (already done by .hex())
hex_encoded = xored.hex()
print(f"After hex_encode: {hex_encoded}")

# Step 3: hex_decode
hex_decoded = bytes.fromhex(hex_encoded)
print(f"After hex_decode: {hex_decoded.hex()}")

# Step 4: XOR with 0x42 again
result = bytes([b ^ key for b in hex_decoded])
print(f"After XOR(0x42):  {result.decode()}")
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Verify: result == original string
assert result.decode() == flag
print(f"\nFlag: {flag}")

Tools

ToolUsage
fileBinary type identification
stringsSearch for readable strings in .rodata
objdumpDisassembly for flow analysis
radare2Detailed static analysis of functions
xxdViewing hex dump of sections
Python 3Algorithm verification and identity proof

Techniques

  • XOR Cancellation — double XOR with the same key = identity (a ⊕ k ⊕ k = a)
  • Static String Extraction — extracting hardcoded strings from .rodata
  • Identity Transform Detection — recognizing chains of operations that mutually cancel out ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Key Takeaways / Lessons

  • Mastering identity_transform_detection, static_string_extraction, xor_cancellation was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-02-14 • CUSTOM • Reverse Me • Difficulty: Easy