← Back to Writeups
CUSTOMEasyReversing

trialver

XESXOR9/10/20263 min read
#reversing#custom#easy#binary_patching#loop_bound_patch#qemu_amd64_emulation#linux

trialver

Platform: spbctf | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-06-30 | Status: Solved Techniques: binary_patching, loop_bound_patch, qemu_amd64_emulation

Summary

Task: Tigress-obfuscated 64-bit PIE ELF that prints only the trial prefix SPbCTF{ then a 'buy the full version' message; the per-char decryptor is intact but the output loop is capped at 7 chars. Solution: single-byte patch of the loop-bound operand (cmp [rbp-0x4],0x6 -> 0x26) to emit all 39 chars, run under linux/amd64 emulation.

trialver — spbctf

Description

Trial period expired. To get the full flag please buy professional version of this program.

A 64-bit, non-stripped, PIE x86-64 ELF (trialver.elf), dynamically linked (Debian GCC 9.3.0). When run, it prints only SPbCTF{ followed by the trial message above. The goal is to recover the full flag, not just the prefix.

Source: https://rev-kids20.forkbomb.ru/files/rev/new7/trialver.elf

Recon

bash
file trialver.elf      # ELF 64-bit LSB pie executable, x86-64, not stripped, GCC 9.3.0
strings trialver.elf   # tigress.c, the "Trial period expired" message
nm trialver.elf        # megaInit, obfuscated_setup, obfuscated_encrypt_char,
                       # obfuscated_decrypt_char, _1_obfuscated_*_$array / _$strings
objdump -d -M intel trialver.elf

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

Key recon facts:

  • The binary is Tigress-obfuscated — the tigress.c source name appears in strings, and the symbol table contains megaInit, obfuscated_setup, obfuscated_encrypt_char, obfuscated_decrypt_char plus their _1_obfuscated_*_$array / _$strings data blobs.
  • The only meaningful human-readable string is the "Trial period expired" message. Imports include srand, rand, putchar, puts.

Analysis

main (at 0x116c) does the following:

  1. Calls megaInit, then obfuscated_setup (at 0x1d21), which returns a key stored in [rbp-0x10].
  2. Stores 39 encrypted dwords into a stack array spanning [rbp-0xb0] .. [rbp-0x18] — (0xb0-0x18)/4 + 1 = 39 elements. Many values look like sign-extended small ints (e.g. 0xff9c6577, 0x5fe30f, ...).
  3. Loops over the array, calling obfuscated_decrypt_char(enc[i], key) and then putchar() on each decrypted byte. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The crucial detail is that the loop is artificially capped — this is the "trial" limitation:

asm
133c:  83 7d fc 06     cmp  dword [rbp-0x4], 0x6   ; counter <= 6 ?
1340:  7e ...          jle  130b                   ; loop body

Only indices 0..6 are emitted — that is exactly 7 characters, SPbCTF{. The decryption routine obfuscated_decrypt_char itself is fully functional (a Tigress dispatch / VM-style switch driven by a byte table at _1_obfuscated_decrypt_char_$array); only the loop counter is capped. All 39 plaintext bytes are already present in the binary — they just are never printed. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The flag content is itself the hint: "don't need to buy buggy software" — you exploit the buggy trial limit instead of paying for the "professional version".

Solution

No need to reverse the Tigress VM. Since the decryptor works correctly and only the loop bound is too small, a single-byte patch of the bound operand emits the full flag. Change 0x06 (7 iterations) to 0x26 (= 38, so indices 0..38, all 39 chars).

python
#!/usr/bin/env python3
# Patch the loop-bound operand and emit all 39 decrypted characters.
data = bytearray(open('trialver.elf', 'rb').read())
i = data.find(bytes([0x83, 0x7d, 0xfc, 0x06]))  # cmp dword [rbp-0x4], 0x6
print(hex(i))                                    # 0x133c
data[i + 3] = 0x26                               # 0x06 -> 38 (print indices 0..38)
open('patched.elf', 'wb').write(data)

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

The host here is macOS on ARM, so the amd64 ELF is run under x86-64 emulation via Docker:

bash
$ python3 patch.py
0x133c

$ docker run --rm --platform linux/amd64 -v "$PWD":/w -w /w \
      debian:bullseye-slim ./patched.elf
SPbCTF{REDACTED}

Trial period expired. To get the full flag please buy professional version of this program.

The patched binary now decrypts and prints all 39 characters before reaching the trial message. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍