6.1.19 pwn HITBCTF2018 gundam
题目复现
$ file gundam
gundam: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=5643cd77b84ace35448d38fc49e4d3668ef45fea, stripped
$ checksec -f gundam
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH Yes 0 4 gundam
$ strings libc-2.26.so | grep "GNU C"
GNU C Library (Ubuntu GLIBC 2.26-0ubuntu2.1) stable release version 2.26, by Roland McGrath et al.
Compiled by GNU CC version 6.4.0 20171010.保护全开,也默认 ASLR 开。libc 版本 2.26,所以应该还是考察 tcache(参考章节4.14)。
玩一下:
$ ./gundam
... # 创建了两个 gundam
1 . Build a gundam
2 . Visit gundams
3 . Destory a gundam
4 . Blow up the factory
5 . Exit
Your choice : 2
Gundam[0] :AAAA
Type[0] :Freedom
Gundam[1] :BBBB
Type[1] :Strike Freedom
1 . Build a gundam
2 . Visit gundams
3 . Destory a gundam
4 . Blow up the factory
5 . Exit
Your choice : 3
Which gundam do you want to Destory:0 # 第一次销毁 gundam 0,成功
1 . Build a gundam
2 . Visit gundams
3 . Destory a gundam
4 . Blow up the factory
5 . Exit
Your choice : 3
Which gundam do you want to Destory:0 # 第二次销毁 gundam 0,成功
1 . Build a gundam
2 . Visit gundams
3 . Destory a gundam
4 . Blow up the factory
5 . Exit
Your choice : 2 # 此时剩下 gundam 1
Gundam[1] :BBBB
Type[1] :Strike Freedom
1 . Build a gundam
2 . Visit gundams
3 . Destory a gundam
4 . Blow up the factory
5 . Exit
Your choice : 4 # 销毁 factory
Done!
1 . Build a gundam
2 . Visit gundams
3 . Destory a gundam
4 . Blow up the factory
5 . Exit
Your choice : 2 # gundam 1 没有变化
Gundam[1] :BBBB
Type[1] :Strike Freedom
1 . Build a gundam
2 . Visit gundams
3 . Destory a gundam
4 . Blow up the factory
5 . Exit
Your choice : 3 # 第三次销毁 gundam 0,失败
Which gundam do you want to Destory:0
Invalid choice根据上面的结果也能猜出一些东西。比如在没有销毁 factory 的情况下,可以多次销毁 gundam。而销毁 factory 不会对没有销毁的 gundam 造成影响。
题目解析
main
一个典型的 switch-case 跳转结构。
Build a gundam
通过分析这个函数,可以得到 gundam 结构体(大小为0x28)和 factory(地址0x002020a0) 数组:
另外 gundam->name 指向一块 0x100 大小的空间。gundam 的数量存放在 0x0020208c。
从读入 name 的操作中我们发现,程序并没有在末尾设置 \x00,可能导致信息泄漏(以\x0a结尾)。
Visit gundams
该函数先判断 gundam_num 是否为 0,如果不是,再根据 factory[i] 和 factory[i]->flag 判断某个 gundam 是否存在,如果存在,就将它的 name 和 type 打印出来。
Destory a gundam
该函数用于销毁 gundam,它先将 gundam->flag 置为 0,再释放掉 gundam->name。
这里有几个问题:
该函数是通过 factory[i] 来判断某个 gundam 是否存在,而在销毁 gundam 后并没有将 factory[i] 置空,导致 factory[i]->name 可能被多次释放
name 指针没有被置空,可能导致 UAF
销毁 gundam 后没有将 gundam_num 减 1
Blow up the factory
该函数会找出所有 factory[i] 不为 0,且 factory[i]->flag 为 0 的 gundam,然后将该 gundam 结构体释放掉,factory[i] 置为 0,最后 gundam_num 每次减 1。
经过这个过程,销毁 gundam 留下的问题基本解决了,除了 name 指针依然存在。
Exploit
所以利用过程如下:
利用被放入 unsorted bin 的 chunk 泄漏 libc 基址,可以计算出
__free_hook和system的地址。利用 double free,将
__free_hook修改为system。当调用
free的时候就会调用system,获得 shell。
leak
chunk 被放进 unsorted bin 时:
可以看到对应的 tcache bin 中已经放满了 7 个 chunk,所以第 8 块 chunk 被放进了 unsorted bin。
再次 malloc 之后:
可以看到程序并没有在字符串后加 \x00 隔断,所以可以将 unsorted bin 的地址泄漏出来,然后通过计算得到 libc 基址。
overwrite
触发 double free 时:
其 fd 指针指向了它自己。
接下来的 malloc 将改写 __free_hook 的地址:
pwn
Bingo!!!
exploit
完整的 exp 如下:
参考资料
Last updated
Was this helpful?