Heap exploitation 笔记

第一次执行 malloc

  • size >= 128k:使用 mmap 函数, kernel 中 sys_mmap
  • size < 128k:使用 brk 函数, kernel 中 sys_brk
  • 无论一开始 malloc 多少空间 < 128k , kernel 都会给 132kb 的 heap
    segment(rw) ,这个部分称为 main arena
  • 第一次 malloc 时就会将 heap 切成两块 chunk ,第一块 chunk 就是要分配出去的 chunk ,剩下的空间视为 top chunk ,之后要是分配空间不足时将会由 top chunk 切出去

第二次执行 malloc

  • 只要分配出去的总内存大小不超过 128KB ,则不会再执行 system call 跟系统要空间,超过大小才会用 brk 来跟 kernel 要内存空间
  • 即使将所有 main arena 所分配出去的内存体 free 完,也不会立即还给 kernel
  • 这时的内存空间将由 glibc 管理

main arena header

  • malloc_state
  • 存有 bins 、 fast bin 、 top chunk 等信息
  • 位于 libc 的 bss 段中

Heap overflow

  • 在 heap 段中发生的 buffer overflow
  • 通常无法直接控制 eip ,但可以利用覆盖下一个 chunk heaker ,并利用 unlink 时的行为来间接连成任意位置写入,进而控制 eip
  • using unlink:通过 overflow 覆盖掉 freed chunk 中的 fd 及 bk 指针,再利用 unlink 中 FD->bk = BK 及 BK->fd = FD 来更改任意内存体位置

detection in malloc

  • size 是 fastbin 的情况
    • memory corruption
      • 从 fastbin 取出的第一块 chunk 的 size 不属于该 fastbin 中的
      • 主要检查方式是根据 malloc 的 bytes 大小取得 index 后,到对应的 fastbin 找,取出第一块后检查该 chunk 的 size 是否属于该 fastbin
      • 但实际比较的时候是先以 fastbin 中第一块 size 取得 fastbin 的 index,再去比 index 跟刚刚算的 index 是否相同,不过这取 index 的方式是用 unsigned int。
  • size 是 smallbin 的情况
    • smallbin double linked list corrupted
      • 从相对应的 smallbin 中拿最后一个时,要符合 smallbin 是 double linked list
      • victim == smallbin 最后一块 chunk
      • bck = victim->bk
      • bck->fd = victim
  • unsortbin 中有 chunk
    • memory corruption
      • 取 unsortbin 的最后一块 chunk 作为 victim
      • victim->size 要符合规定
      • size 必须大于 2 x SIZE_SZ ,必须小于 system_mem
  • size 是 large bin 的情况
    • corrupted unsorted chunks
      • 在找到适合的 chunk 切给 user 后,剩下的空间会放到 last remainder,然后加到 unsortbin 中
      • 这时会取 unsortbin 的第一个的 fd 是否等于 unsortbin 的位置

detection in free

  • invalid pointer
    • 检查 alignment
      • chunk address 是否为 8 的倍数
    • 检查 chunk address 是否小于 -size
  • invalid size
    • 检查 chunk size 是否合法
      • size 必须为 8 的倍数
      • 也就是是否符合 alignment
    • size 必须大于 MINSIZE
  • size 是 fastbin 的情况
    • invalid next size(fast)
      • 检查下一块 chunk size 是否合法
      • size 必须大于 MINSIZE
      • size 必须小于 system_mem
    • double free or corruption(fasttop)
      • 检查 fastbin 中第一块 chunk 跟正要 free 的chunk 是否不同
      • 要是相同就会 abort
  • size 是 smallbin & largebin 的情况(非 mmap)
    • double free or corruption(top)
      • 检查正要 free 的 chunk 跟 top chunk 的位置是否不同
      • 要是相同就会 abort
    • double free or corruption(out)
      • 计算出来下一块 chunk 的位置是否超出 heap 的边界
      • 超出 heap 边界就会 abort
    • double free or corruption(!prev)
      • 根据下一块 chunk 的 inuse bit 来检查正要 free 的 chunk 是否已被 free 过
    • invalid next size(normal)
      • size 必须大于 2 x SIZE_SZ
      • size 必须小于 system_mem
    • corrupted unsorted chunks
      • 在 unlink 后要放到 unsortbin 时,会先从 unsortbin 取第一块 chunk 出来 ,然后检查该 chunk 的 bk 是否等于 unsortbin
  • 在做 unlink 时
  • courrupted double linked list
    • 检查 circular doubly linked list 的完整性,指出去在指回来必须指向值及,否则就会表示 corrupted double-linked list 中断
    • P->bk->fd == p
    • P->fd->bk == p

using unlink(modern)

  • bypass the detection
    • 必须伪造 chunk 结构
    • 必须找到指向伪造 chunk 的 pointer 及该 pointer 的 address
    • 因此能直接改的地方有限,通常要间接去读取或写入任意位置
    • 通常 r 会是个 data pointer
    • 可以利用他再去改变其他存在 &r 附近的 pointer 然后在利用这些 pointer 去造成而任意位置读取及写入,如果存在 function pointer 更可直接控制 eip 。

Using malloc maleficarum

  • stack overflow
    • 当 stack overflow 不够覆盖到 ret 时
    • 利用 stack overflow 覆盖要 free 的 ptr 并伪造 chunk
    • 须针对 prev_size 及 size 做处理,通过检查
  • using fastbin
    • 当下次 malloc 时,就会取得伪造的 chunk
  • The House of Spirit
    • 可以做information leak
    • 也可加大 stack voerflow 的距离
    • 要先算算在 stack 中去下一块 chunk 的 size 是否为 8 的倍数, size 的取决是很重要的
  • The House of Force
    • heap overflow 覆盖 top chunk 的 size ,变成一个很大的值
    • 下次 malloc 是,malloc 一个很大的数字(nb),然后 arena header 中的 top chunk 的位置会改变
      • new top chunk = old top + nb + 8
      • nb 可以是负的,因为传进去会被自动转换成很大的数字,只要让 fake szie - nb > 0 就会让 glibc 以为 top 还有空间可以给
    • 这样下次 malloc 的位置将会是 new top chunk 的位置。

Using fastbin

  • 类似 House of Spirit
  • 如果可以改到 fastbin 的 free chunk 可以将 fd 改成 fake chunk 的位置,
    只要符合 size 是属于改 fastbin 就好,因为下次 malloc 只会检查这项
  • 下下次 malloc(size-0x10)时,就会取得该 fake chunk 的位置
  • fake chunk 可以是任意内存体位置

Some useful global variable

  • __free_hook 、 __malloc_hook 、 __realloc_hook
    • free 、 malloc 、 realloc 前会先检查是否上面三个全局变量有值,若有则当 func ptr 执行
  • __malloc_initialize_hook
    • ptmalloc_init 时(第一次执行 malloc 会用),会检查该变量是否有值,若有则当 func ptr 执行
  • __after_morecore_hook
    • 在跟用 brk 跟系统要 heap 空间时,会检查该变量是否有值,若有则当 func ptr 执行

内容来源

Heap exploitation

posted @ 2020-02-23 01:40  PwnKi  阅读(544)  评论(0编辑  收藏  举报