只出了两个常规 linux 堆 pwn。看了一下 jerry,搜了一下 CVE,束手无策。其它题都没时间做了。算是认识到了自己的短板吧。
最后一秒的 pwn 题:
easypwn
签到题、libc-2.23
功能齐全、漏洞有 UAF、off-by-one 和 bss 段上的溢出(可以溢出到指向 chunk 的指针)。
其它
题目没给 libc(所有的 pwn 题都没给。。。)。我触发了堆上的一个错误,错误信息里有 __libc_start_main
的地址,然后在 libc.rip 上找到了 libc,用 glibc-all-in-one 下载有 debug symbol 的 libc 和 ld。
exp
1 | from pwn import * |
PwnCTFM
off-by-null,但由于 libc 版本为 2.27,引入了 tcache,chunk shrink 利用起来就有些麻烦(libc 里的检查忘得差不多了,搞了好久)。
保护
全开
分析
只有 add、delete 和 show 功能。
这里使用了基于栈的 VLA,memset
多了一字节。
strcpy
会拷贝字符串末尾的 ‘\x00’,造成 off-by-null 漏洞。
利用
off-by-null 可以转化为 unlink,或者可以伪造 pre_size 形成 overlap,又或转化为 chunk shrink。
然而本题有一个比较麻烦的限制。
限制
程序使用 strcpy
将数据拷贝到堆上,意味着数据中不能有 ‘\x00’。这样就不能伪造 pre_size 了(5 月 10 日:NU1L 的 exp 中的做法是,在覆盖 size 域后,多次 delete add 同一 chunk,同时 data 长度递减。这样利用了 strcpy 末尾的 ‘\x00’ 将其它字节清零,从而伪造出 pre_size。这种方法可以布置任意数据,学到了),此外 libc 地址的泄漏也变得比较麻烦。
chunk shrink
chunk shrink 可以转化为 overlap。我当时参考的是 Shrinking Free Chunks 上的图,通俗易懂。但 poc 比较老,不适合现在加了很多检查的 glibc 了(各种检查我都忘得差不多了,又被折磨了一次)。
chunk shrink 要对 unsorted bin 多次进行操作。本题限制了 chunk 的大小最大为 0x200,在 tcache 的范围内;而最多共存 chunk 指针数为 9。因此每次把 chunk 弄进 unsorted bin 就会比较繁琐(我的脑子转不过来,每次都要搞好久)。
其它
ubuntu glibc 2.27 有三个版本,其中 1.4 的加入了 tcache double free 的检测,1.2 的没有(1不知道)。
exp
1 | from pwn import * |
总结
败在了两个方面
- 对 glibc heap 的流程和检查不够熟悉,花了很多时间。
- 新类型的题目(jerry)完全不懂。
之后一定要写一个较完善的各版本 glibc heap 流程、检查、利用方法之间的关系。(以前还觉得没啥必要)慢慢写吧。