gyctf_2020_signin
info
License
本文引用了部分来自 GNU C Library
的源码,源码取自 GNU C Library
基于 LGPLv2.1.
注:本题目的运行环境使用的 glibc 为 2.27-3ubuntu1_amd64
,但本文中展示的所有 glibc 代码为 2.34
.
WriteUp-gyctf_2020_signin
看到本文的各位师傅,请允许 Y7n05h 又翻出这段各位都熟悉无比的代码.能够发现从非空的 tcache
中取出 chunk
是在 __libc_malloc()
中完成的,而非在 _int_malloc_()
中.
1 | void * |
再看 __libc_calloc()
:
1 | void * |
相信各位都能发现 __libc_calloc()
和 __libc_malloc()
的差别是很小的,通常情况下将 __libc_calloc()
视为 __libc_malloc()
+ memset()
是合理的.但除此之外还有一点区别是 __libc_calloc()
中缺少从非空的 tcache
取出 chunk
的部分,因此 calloc()
将优先从 fastbin
中分配 chunk
.
这也是本题目的利用的核心思路.
错误思路-tcache poisoning
Y7n05h 刚开始也是想采用 tcache poisoning
来完成本题,并寄希望与 free
/malloc
的过程中能清除 cnt
实现第二次 edit
.但很遗憾,此路并不通.通过此方式虽能将 chunk
分配在 ptr
上,但无法修改 ptr 的值.(至少 Y7n05h 没想到)
正确思路
此方式是从 Pwnki 师傅 的博客学来的.在这里感谢 Pwnki 师傅 师傅.
利用思路:
- 分配 8 个大小为 0x80 的 chunk 后全部 free,前 7 个塞满了 tcache,后一个进入 fastbin
- 在分配一个 chunk,这将从 tcache 中取出一个 chunk
- 修改在 1 中放入的 fastbin 中的 chunk 的 fd 的指针为
ptr - 0x10
,注意这个行为使glibc
认为ptr - 0x10
是一个 chunk,则ptr
则是这个chunk
的fd
- 通过执行
backdoor
,调用calloc
从fastbin
取出chunk
并将其fd
指向的ptr - 0x10
作为一个chunk
插入tcache
链表.插入过程中ptr
将作为tcache_entry
的next
字段被修改.
这些过程的相关代码:
1 | typedef struct tcache_entry |
1 |
1 | /* While we're here, if we see other chunks of the same size, |
完整 exp:
1 | from pwn import * |
参考资料
1. Pwnki-gyctf_2020_signin. ↩
2. PYozo_free-gyctf_2020_signin. ↩