← Back to Writeups
CUSTOMEasyReversing

Rusty ARM

XESXOR9/2/20262 min read
#reversing#custom#easy#checker_reconstruction#static_reverse_engineering#transform_inversion

Rusty ARM

Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: checker_reconstruction, static_reverse_engineering, transform_inversion

Summary

Walkthrough of the CUSTOM Reversing Rusty ARM. Task: a Rust ARM64 checker reads a line, trims it, transforms each byte through a small closure, and compares the result with a fixed reference_password vector. Solution: reconstruct the exact per-byt

Description

Ржавый ARM

English summary: we are given a Rust ARM64 binary that asks for a password and accepts only the input whose transformed bytes match a hardcoded reference vector.

Analysis

This corrected writeup supersedes the earlier incorrect local/API entry 20260406_hackerlab_rusty_arm, which used the wrong reconstructed bytes and therefore produced the wrong flag.

The main checker flow is straightforward once the Rust standard-library calls are identified:

  1. print a prompt,
  2. call read_line,
  3. call trim,
  4. iterate over password.bytes(),
  5. apply a closure to each byte,
  6. collect the result into Vec<u8>,
  7. compare that vector with reference_password. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The valid reconstructed logic is:

rust
let encrypted_password: Vec<u8> = password.bytes().map(|b| {
    let add_result = b.wrapping_add(0x30);
    let xor_result = add_result ^ 0x45;
    let sub_result = xor_result.wrapping_sub(0x99);
    let qwe = sub_result.wrapping_add(0x35);
    let xor_result2 = qwe ^ 0x45;
    xor_result2
}).collect();

The correct reference_password bytes are:

python
reference_password = [
    0x97, 0x93, 0x88, 0x89, 0x96, 0x2d, 0xcf, 0x26,
    0x86, 0xc7, 0x18, 0x23, 0x2a, 0x84, 0x26, 0x23,
    0x95, 0x26, 0x91, 0x23, 0x3b, 0x3c, 0x94, 0x38,
    0x83, 0xc1,
]

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

Because the transformation is applied independently to each byte, we can reverse it byte by byte without emulating the whole program.

Solution

To invert one output byte, reverse the operations in the opposite order:

  1. XOR 0x45
  2. subtract 0x35
  3. add 0x99
  4. XOR 0x45
  5. subtract 0x30

In code:

python
#!/usr/bin/env python3

reference_password = [
    0x97, 0x93, 0x88, 0x89, 0x96, 0x2d, 0xcf, 0x26,
    0x86, 0xc7, 0x18, 0x23, 0x2a, 0x84, 0x26, 0x23,
    0x95, 0x26, 0x91, 0x23, 0x3b, 0x3c, 0x94, 0x38,
    0x83, 0xc1,
]
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

def invert_byte(x: int) -> int:
    x ^= 0x45
    x = (x - 0x35) & 0xff
    x = (x + 0x99) & 0xff
    x ^= 0x45
    x = (x - 0x30) & 0xff
    return x

flag = bytes(invert_byte(x) for x in reference_password).decode()
print(flag)

Running the script yields:

text
CODEBY{REDACTED}

That matches the expected format and is the correct password accepted by the checker. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Key Takeaways / Lessons

  • Mastering checker_reconstruction, static_reverse_engineering, transform_inversion was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-04-06 • CUSTOM • Rusty ARM • Difficulty: Easy