unlink

这个知识点以前就看过了,但之前一直不是很懂,今天再来看的时候,把以前一些盲区扫了

参考资料:

https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/unlink-zh/

从0到1 ctfer书籍

pwnki师傅的博客

这三篇其实讲的也差不多,但是在不同角度上某些东西显的比较清楚

 

原理

所谓的UNlink其实就是链表的一个remove操作,先来看看linux的源码

// 由于 P 已经在双向链表中,所以有两个地方记录其大小,所以检查一下其大小是否一致(size检查)
if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0))      \
      malloc_printerr ("corrupted size vs. prev_size");               \
// 检查 fd 和 bk 指针(双向链表完整性检查)
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                      \
  malloc_printerr (check_action, "corrupted double-linked list", P, AV);  \

  // largebin 中 next_size 双向链表完整性检查 
              if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0)              \
                || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0))    \
              malloc_printerr (check_action,                                      \
                               "corrupted double-linked list (not small)",    \
                               P, AV);
// fd bk
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                      \
  malloc_printerr (check_action, "corrupted double-linked list", P, AV);  \

在这种情况下,如果想利用unlink,那么必须要满足以下条件

此时

  • FD->bk = target addr - 12 + 12=target_addr
  • BK->fd = expect value + 8

那么我们上面所利用的修改 GOT 表项的方法就可能不可用了。但是我们可以通过伪造的方式绕过这个机制。

首先我们通过覆盖,将 nextchunk 的 FD 指针指向了 fakeFD,将 nextchunk 的 BK 指针指向了 fakeBK 。那么为了通过验证,我们需要

  • fakeFD -> bk == P <=> *(fakeFD + 12) == P
  • fakeBK -> fd == P <=> *(fakeBK + 8) == P

当满足上述两式时,可以进入 Unlink 的环节,进行如下操作:

  • fakeFD -> bk = fakeBK <=> *(fakeFD + 12) = fakeBK
  • fakeBK -> fd = fakeFD <=> *(fakeBK + 8) = fakeFD

如果让 fakeFD + 12 和 fakeBK + 8 指向同一个指向 P 的指针,那么:

  • *P = P - 8
  • *P = P - 12

即通过此方式,P 的指针指向了比自己低 12 的地址处。此方法虽然不可以实现任意地址写,但是可以修改指向 chunk 的指针,这样的修改是可以达到一定的效果的。

 

此外,其实如果我们设置 next chunk 的 fd 和 bk 均为 nextchunk 的地址也是可以绕过上面的检测的。但是这样的话,并不能达到修改指针内容的效果。

 

利用思路

条件 

UAF ,可修改 free 状态下 smallbin 或是 unsorted bin 的 fd 和 bk 指针

已知位置存在一个指针指向可进行 UAF 的 chunk

效果 

使得已指向 UAF chunk 的指针 ptr 变为 ptr - 0x18

思路 

设指向可 UAF chunk 的指针的地址为 ptr

修改 fd 为 ptr - 0x18

修改 bk 为 ptr - 0x10

触发 unlink

ptr 处的指针会变为 ptr - 0x18。

 

疑问解答

1、-0x18和-0x10是什么意思?这里的-0x18和-0x10一直是我上次的疑问,后面发现这目的就是为的绕开检查,并且直接对uaf chunk 指针直接进行修改内容

2、为什么ptr会指向ptr-0x18?答:ptr变为ptr-0x18的原因是FD=ptr-0x18 ptr=FD->bk  并且  BK=ptr-0x10    ptr=BK->fd,由于unlink是remove操作,所以BK->fd=FD=ptr-0x18

 

相关例题可以在 ctf wiki上看

posted @ 2020-10-02 16:56  PYozo_free  阅读(231)  评论(0编辑  收藏  举报