Published on

PCC CTF - ROP Reverse Engineering Challenge Writeup

Authors
  • avatar
    Name
    Muhammad Huzaifa
    Twitter

ROP - Reverse Engineering Challenge Writeup

Challenge Overview

  • Category: Reverse Engineering
  • Challenge: ROP - reverse
  • Description: "You might've thought that this challenge was in the wrong category 😅"
  • Format: PCC{}

Files Provided

  • rop - 64-bit ELF binary
  • rop.chain - Binary file containing encrypted data and ROP chain
  • run.sh - Script that runs ./rop < rop.chain

Initial Analysis

Binary Analysis

The rop binary is a 64-bit ELF executable with the following characteristics:

  • Stripped binary (no debug symbols)
  • Uses standard libc functions: puts, gets, exit, setvbuf, memset
  • Contains many ROP gadgets for various operations

Key Strings Found

"Did, you, really, ROP???"
"????? gg"
"Nope"
"Did you think you'd get a chance to give input?"

ROP Gadgets Available

The binary contains numerous useful ROP gadgets:

  • pop rax; ret (0x4012b7)
  • pop rcx; ret (0x4012b9)
  • pop rdi; ret (0x4012bb)
  • pop rsi; ret (0x4012bd)
  • pop rdx; ret (0x4012bf)
  • mov rdi, rax; ret (0x4012c7)
  • mov r10, rax; ret (0x4012cf)
  • mov cl, [rax]; ret (0x4012e5) - Load byte from memory
  • xor rcx, rax; ret (0x4012e8) - XOR operation
  • cmp rcx, rax; jne ...; ret (0x4012df) - Compare
  • syscall; ret (0x4012ec) - System call
  • And many more...

ROP Chain Analysis

File Structure

The rop.chain file (11,080 bytes) contains:

  1. Encrypted data (first 112 bytes) - This is the flag encrypted with XOR
  2. Padding (0x70 bytes of zeros)
  3. ROP chain (remaining bytes) - Contains the decryption logic

ROP Chain Pattern

The ROP chain implements a decryption algorithm with this pattern:

1. Load address pointer (starts at 0x404038)
2. pop rdi; ret
3. Load data address (0x404038)
4. pop rdx; ret  
5. Load value 1
6. sub rax, rdx; ret (decrement address)
7. mov r10, rax; ret (save address)
8. pop rcx; ret
9. Load value 0
10. mov rax, r10; ret (restore address)
11. inc rax; ret (increment address)
12. mov r10, rax; ret (save address)
13. mov cl, [rax]; ret (load byte from memory)
14. pop rax; ret
15. Load XOR key
16. xor rcx, rax; ret (XOR with key)
17. pop rax; ret
18. Load value 0
19. cmp rcx, rax; jne ...; ret (check if result is 0)

This pattern repeats for each byte of the encrypted data.

Decryption Process

Extracting XOR Keys

The XOR keys are embedded in the ROP chain after pop rax; ret instructions that precede xor rcx, rax; ret gadgets.

Decryption Algorithm

decrypt.py
# Extract XOR keys from ROP chain
xor_keys = []
# Parse ROP chain to find XOR key values...

# Decrypt the data
encrypted_data = rop_chain_file[:112]  # First 112 bytes
decrypted = bytes([encrypted_data[i] ^ xor_keys[i] for i in range(len(encrypted_data))])

Key Insight

The challenge title "ROP - reverse" and description hint that this isn't about exploiting with ROP, but rather reverse engineering what the ROP chain does. The ROP chain itself is the "program" that decrypts the flag!

Solution

Automated Decryption

analyze_rop.py
import struct

# Read the ROP chain
with open('rop.chain', 'rb') as f:
    data = f.read()

# Parse as 64-bit addresses
chain = []
for i in range(0, len(data), 8):
    if i + 8 <= len(data):
        addr = struct.unpack('<Q', data[i:i+8])[0]
        chain.append(addr)

# Extract XOR keys from ROP chain
xor_keys = []
start_idx = 32  # After padding

i = start_idx
while i < len(chain):
    addr = chain[i]
    
    # Look for pattern: pop rax; ret followed by XOR key
    if addr == 0x4012b7 and i+1 < len(chain):
        next_val = chain[i+1]
        # Check if next instruction is xor (0x4012e8)
        if i+2 < len(chain) and chain[i+2] == 0x4012e8:
            xor_keys.append(next_val & 0xFF)
            i += 3
            continue
    i += 1

# Decrypt the data
encrypted = data[:112]
decrypted = bytes([encrypted[i] ^ xor_keys[i] for i in range(len(encrypted))])
print(decrypted.decode())

Flag

PCC{`r3vers31ng_r0p_ch41ns_1s_34s13r_th4n_u_th0ugh7_but_1f_y0u_d1d_7h1s_m4nually_w3lllll_y0u_ar3_1nd33d_4_m4dM4n`}

Key Takeaways

  1. Think Outside the Box: This challenge appears to be about ROP exploitation but is actually about reverse engineering a ROP chain that performs decryption.

  2. ROP as Programming: ROP chains can be used to implement complex algorithms, not just for exploitation.

  3. Pattern Recognition: The ROP chain follows a clear pattern that can be automated for analysis.

  4. Data Hiding: The flag was hidden in plain sight at the beginning of the file, just encrypted with XOR.

  5. Challenge Design: The description "You might've thought that this challenge was in the wrong category" is a hint that this isn't a traditional ROP exploitation challenge.

Tools Used

  • file - Identify file type
  • strings - Extract readable strings
  • objdump - Disassemble binary
  • xxd - View hex dump
  • Python - Parse and decrypt data

This challenge demonstrates that reverse engineering can involve analyzing any form of code execution, including ROP chains used for purposes other than exploitation.