← Back to Writeups
CUSTOMMediumReversing

Movfuscator

XESXOR9/10/20262 min read
#reversing#custom#medium#reverse_engineering#hidden_code_recovery#static_disassembly#transformation_inversion

Movfuscator

Platform: spbctf | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-06-08 | Status: Solved Techniques: reverse_engineering, hidden_code_recovery, static_disassembly, transformation_inversion

Summary

Task: a static stripped ELF pretends to contain only repeated mov rcx, imm64 instructions, hiding the real checker inside immediate payload bytes. Solution: start disassembly at the hidden entrypoint, recover the in-place buf[i] -= i transform and embedded target bytes, then invert the transform to obtain the accepted input and final flag.

Movfuscator — spbctf

Description

Have you heard about the MoVfuscator? It turns any code into a set of just mov instructions! It's kinda magic!

The binary is a 64-bit ELF that looks intentionally misleading: normal disassembly only shows endless mov rcx, imm64 instructions. The goal is to recover the hidden checker logic and derive the accepted input.

Analysis

The first useful clue is the file layout: the ELF is static, stripped, and effectively exposes only a .text section. A naive disassembly is almost useless because it keeps decoding the file as repeated mov rcx, imm64 instructions. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

That is the trick. The real code does not start at the obvious instruction boundaries. It starts at 0x400082, which lands inside the immediate bytes of the first movabs rcx, imm64. From that offset, recursive disassembly reveals a normal x86-64 checker.

The recovered logic is straightforward:

  1. Print the prompt Enter string to check > .
  2. Read up to 0x3f bytes into a stack buffer.
  3. NUL-terminate the input and remove a trailing newline if present.
  4. Transform the buffer in place with:
c
buf[i] = buf[i] - i;

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

  1. Compare the transformed bytes against an embedded constant stored on the stack:
text
74 32 66 5c 69 44 41 41 6c 50 55 62 24 62 41 21 66 22 33 5f 3e 00

This is a 21-byte target plus the terminating NUL. Therefore the original input must satisfy:

text
input[i] - i = target[i]
input[i]     = target[i] + i

Applying that inversion yields:

text
REDACTED

The success path restores the modified buffer and prints it inside the flag format, so the final flag is spbctf{REDACTED}.

Solution

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

  1. Ignore the fake top-level mov rcx, imm64 disassembly.
  2. Start disassembling from the hidden entrypoint at 0x400082.
  3. Recover the input handling and the transformation loop buf[i] -= i.
  4. Extract the embedded comparison bytes.
  5. Invert the transform by adding the index back to each byte.
  6. Submit the recovered string; the program prints spbctf{<input>} on success.
python
#!/usr/bin/env python3

target = bytes.fromhex(
    "74 32 66 5c 69 44 41 41 6c 50 55 62 24 62 41 21 66 22 33 5f 3e"
)
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

candidate = ''.join(chr(b + i) for i, b in enumerate(target))
print(candidate)
print(f"spbctf{{{candidate}}}")

Output:

text
REDACTED
spbctf{REDACTED}

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