[DawgCTF 2025] [RE] ShinyClean™ Rust Remover Pro™ Edition

TL;DR
0x100byte blob -> lookup table -> SBOX
additive key stream, decoding = inverse tble + modular substraction

1. i skimmed the instructions and found an instereting loop
1745301671239-png.4


2. right be4 the loop a counter and starting key was inited
1745301709881-png.5


3. identified how key is being transformed
1745301799470-png.6


wrapping add_assign from rust -> mod-256 addition
key = (key + byte) & 0xFF

4. and found the lookup table
1745301915895-png.7


5. Well now its all about understanding the algo, dumping the data and decoding
Python:
mov     byte ptr [rsp+…+var_121], 75h   ; initial key = 0x75 ('u')
…
loop:
    byte = Receiver<u8>::recv()         ; get next plaintext byte
    if byte == 0 || recv_failed: exit
    key  = (key + byte) & 0xFF          ; 8‑bit wrapping add
    enc  = lookup_table[key]            ; index into 256‑byte table
    Sender<u8>::send(enc)               ; forward encoded byte
    counter++ (max 0x15 = 21 bytes)

Heres the wrapping additon math: keyₙ = 0x75 + Σ flag (mod 256)

Python:
key = 0x75
plain = []
for enc in encoded:
    idx   = rev[enc]            # key after addition
    ch    = (idx - key) & 0xFF  # undo wrapping add
    plain.append(ch)
    key   = idx                 # next loop
flag = bytes(plain).decode()

Wrap up
well pretty trivial challenge considering it should be a hard one
wrapping add_assign from rust reveals the mod-256 addition
theres also a bound check which limits flag to 21bytes (cmp .., 0x15)
seeing initial key pretty trivial, identifying the loop and algo pretty easy
chall would have been a lil better with some sort of flow obfuscation, which requries actual understanding

Flag:> DawgCTF{S0000_CL43N!}
 

Attachments

  • 1745301671239.png
    41.5 KB · Views: 29
  • 1745301709881.png
    6 KB · Views: 28
  • 1745301799470.png
    8.2 KB · Views: 28
  • 1745301915895.png
    6.5 KB · Views: 28
Back
Top