DASCTF 7月部分pwn
Comment这次比赛有点短小啊(滑稽),三个pwn题,做了两个。其中的一道堆质量还挺不错。
2020-7-27:(eg32已经复现)
签到
真·签到
这道题法子太多了,不论是printf的格式化字符串还是gets的栈溢出都是致命的。
只是要注意的是32位的main函数结束的时候有一节汇编用到了ebp,就导致了直接覆盖ebp从而覆盖返回地址就是不可行的了。
相关代码:
1 | .text:080485F8 mov eax, 0 |
所以需要先泄露ebp
1 | # -*- coding: utf-8 -* |
eg32
这个没做出来,后来复现的了。
利用思路也很简单,就是爆破。
syscall在调用失败后并不会报段错误而是eax返回!=0的值,我们利用eax的值来判断爆破是否成功,
具体实现为利用write打印某页地址。如果eax!=0,那么地址+一个标准页,如果eax=0,exit。
1 | # -*- coding: utf-8 -* |
bigbear
这个题还是蛮不错的,至少让我知道了在libc2.29以后用setcontext
来控制寄存器需要控制edx而不是edi了。
查找漏洞
漏洞点,简单粗暴。
1 | void del() |
如图,在free之后没有清空指针,形成UAF
利用思路
开了沙盒,不能直接shell
1 | line CODE JT JF K |
由于在libc.2.30下setcontext的汇编段变成了rdx来控制寄存器的恢复,如下图所示
1 | .text:000000000005803D mov rsp, [rdx+0A0h] |
如图,我们发现libc2.30里面的setcontext
代码块变成了rdx,这就导致了我们通过更改free_hook来执行setcontext
这段汇编从而控制所有寄存器的方法不可行了。
这里,我们用劫持返回地址的方法来打印出flag
具体步骤为:
1.泄露libc地址
2.泄露栈地址
3.更改返回地址
具体实现
首先我们泄露libc地址,这个我们直接填满tcache,利用UAF来打印出libc指针
1 | for i in range(8): |
然后泄露栈地址。
1 | edit(6,p64(environ_addr-0x10)) |
libc里面的environ结构体里储存着栈的指针,我们利用UAF来打印出来
这里我把environ-0x10放入tcache链。
然后构造堆块,更改返回地址即可
这里我们要知道,在libc2.30里面tcache的链条增加了double free的判断。添加了key结构,每次将堆块free时都会查看同一个key上有没有相同的堆块,
这里我们通过修改已经free的chunk的key来实现绕过
1 | free(9) |
这里我顺便打印了heap的地址,通过计算偏移找到返回地址,而后劫持就可以。
exp:
1 | # -*- coding: utf-8 -* |
总结
主要就是堆那个是我之前没想到的,导致我一开始去改free_hook
去了,浪费了一点时间。另外pwn2俺没做出来,想复现,求做出来的师傅们带带弟弟。(联系下弟弟0rz)
Orz。