По дороге к Замку Капибар (On the Road to Capybara Castle)
По дороге к Замку Капибар (On the Road to Capybara Castle)
Platform: hackerlab | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2025-12-27 | Status: Solved Techniques: Cryptographic operation reversal, Reverse engineering of obfuscation algorithm, Static binary analysis with objdump, UPX header repair (anti-unpacking bypass)
Summary
Task: UPX-packed ELF binary with corrupted magic bytes and sequential arithmetic/XOR obfuscation. Solution: Repair UPX header by replacing CDB! with UPX!, unpack, extract target bytes from .data section, and reverse 25 sequential operations.
По дороге к Замку Капибар — hackerlab
Description
На пути к флагу!
Analysis
1. Initial Examination
The downloaded archive contains:
- ELF binary packed with UPX
- AES-encrypted ZIP archive with images ("Рисунки.zip")
2. Detecting Anti-Unpacking Protection
When attempting to unpack the binary with standard upx -d, we get an error. Hex dump analysis shows that the l_info header is corrupted:
Offset 0xec: 43 44 42 21 (CDB!) # Should be UPX!
This is a typical anti-unpacking technique — replacing UPX magic bytes with custom ones.
3. Analyzing the Flag Verification Algorithm
After unpacking, disassembly reveals the flag verification function at address 0x129c. The function applies 25 sequential operations to each input character:
| # | Operation | Value |
|---|---|---|
| 1 | SUB | 0x16 |
| 2 | ADD | 0x6e |
| 3 | XOR | 0xa0 |
| 4 | XOR | 0x5c |
| 5 | XOR | 0x62 |
| 6 | SUB | 0x71 |
| 7 | SUB | 0x14 |
| 8 | ADD | 0x15 |
| 9 | SUB | 0x49 |
| 10 | XOR | 0x4c |
| 11 | XOR | 0x97 |
| 12 | XOR | 0x38 |
| 13 | ADD | 0x66 |
| 14 | ADD | 0x35 |
| 15 | ADD | 0x56 |
| 16 | SUB | 0x63 |
| 17 | ADD | 0x5d |
| 18 | SUB | 0x3a |
| 19 | XOR | 0xe9 |
| 20 | ADD | 0x6d |
| 21 | ADD | 0x1c |
| 22 | XOR | 0xd4 |
| 23 | ADD | 0x61 |
| 24 | XOR | 0xfc |
| 25 | XOR | 0x49 |
| |
Target bytes are located in the .data section at address 0x5010.
Solution
Step 1: Fixing the UPX Header
python read-only • copy allowed#!/usr/bin/env python3 # fix_upx.py - Repair corrupted UPX header with open('task', 'rb') as f: data = bytearray(f.read()) # Replace "CDB!" with "UPX!" at offset 0xec data[0xec:0xf0] = b'UPX!' with open('task_fixed', 'wb') as f: f.write(data) print("[+] UPX header fixed: task_fixed")
Step 2: Unpacking the Binary
bash read-only • copy allowedupx -d task_fixed -o task_unpacked
Step 3: Extracting Target Bytes
From the .data section at address 0x5010:
9206e5fcfbf84a92f949f85bf94ba0f6d54b9049f690a2f69289896d5443
Step 4: Reverse Transformation
python read-only • copy allowed#!/usr/bin/env python3 # solve.py - Reverse the obfuscation algorithm def reverse_transform(b): """Apply all 25 operations in reverse order""" # Reverse of XOR 0x49 (operation 25) b = b ^ 0x49 # Reverse of XOR 0xfc (operation 24) b = b ^ 0xfc # Reverse of ADD 0x61 (operation 23) b = (b - 0x61) & 0xff # Reverse of XOR 0xd4 (operation 22) b = b ^ 0xd4 # Reverse of ADD 0x1c (operation 21) b = (b - 0x1c) & 0xff # Reverse of ADD 0x6d (operation 20) b = (b - 0x6d) & 0xff # Reverse of XOR 0xe9 (operation 19) b = b ^ 0xe9 # Reverse of SUB 0x3a (operation 18) b = (b + 0x3a) & 0xff # Reverse of ADD 0x5d (operation 17) b = (b - 0x5d) & 0xff # Reverse of SUB 0x63 (operation 16) b = (b + 0x63) & 0xff # Reverse of ADD 0x56 (operation 15) b = (b - 0x56) & 0xff # Reverse of ADD 0x35 (operation 14) b = (b - 0x35) & 0xff # Reverse of ADD 0x66 (operation 13) b = (b - 0x66) & 0xff # Reverse of XOR 0x38 (operation 12) b = b ^ 0x38 # Reverse of XOR 0x97 (operation 11) b = b ^ 0x97 # Reverse of XOR 0x4c (operation 10) b = b ^ 0x4c # Reverse of SUB 0x49 (operation 9) b = (b + 0x49) & 0xff # Reverse of ADD 0x15 (operation 8) b = (b - 0x15) & 0xff # Reverse of SUB 0x14 (operation 7) b = (b + 0x14) & 0xff # Reverse of SUB 0x71 (operation 6) b = (b + 0x71) & 0xff # Reverse of XOR 0x62 (operation 5) b = b ^ 0x62 # Reverse of XOR 0x5c (operation 4) b = b ^ 0x5c # Reverse of XOR 0xa0 (operation 3) b = b ^ 0xa0 # Reverse of ADD 0x6e (operation 2) b = (b - 0x6e) & 0xff # Reverse of SUB 0x16 (operation 1) b = (b + 0x16) & 0xff return b # Target bytes from .data section at 0x5010 target_hex = '9206e5fcfbf84a92f949f85bf94ba0f6d54b9049f690a2f69289896d5443' target = bytes.fromhex(target_hex) # Reverse transform each byte flag = ''.join(chr(reverse_transform(b)) for b in target) print(f"Flag: {flag}")
Notes
- Anti-unpacking bypass: Replacing magic bytes is the simplest protection against automatic unpacking. Just find and fix the signature.
- Reverse operations: ADD ↔ SUB, XOR ↔ XOR (XOR is self-inverse)
- Order: When reversing, operations are applied in reverse order (from last to first)
- Modular arithmetic: All arithmetic operations are performed modulo 256 (
& 0xff)