moectf2020 write up for baby canary
前言
moectf2020的pwn的压轴题,萌新大半夜照着官方题解看了好久,才勉勉强强磕磕碰碰地看明白了QAQ
A3师傅好坏啊,新生赛出这么难的题!
PRE.DEFINITION OF CANARY
我们知道,通常栈溢出的利用方式是通过溢出存在于栈上的局部变量,从而让多出来的数据覆盖 ebp、eip 等,从而达到劫持控制流的目的。栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让 shellcode 能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈底插入 cookie 信息,当函数真正返回的时候会验证 cookie 信息是否合法 (栈帧销毁前测试该值是否被改变),如果不合法就停止程序运行 (栈溢出发生)。攻击者在覆盖返回地址的时候往往也会将 cookie 信息给覆盖掉,导致栈保护检查失败而阻止 shellcode 的执行,避免漏洞利用成功。在 Linux 中我们将 cookie 信息称为 Canary。
由于 stack overflow 而引发的攻击非常普遍也非常古老,相应地一种叫做 Canary 的 mitigation 技术很早就出现在 glibc 里,直到现在也作为系统安全的第一道防线存在。
Canary 不管是实现还是设计思想都比较简单高效,就是插入一个值在 stack overflow 发生的高危区域的尾部。当函数返回之时检测 Canary 的值是否经过了改变,以此来判断 stack/buffer overflow 是否发生。
Canary 与 Windows 下的 GS 保护都是缓解栈溢出攻击的有效手段,它的出现很大程度上增加了栈溢出攻击的难度,并且由于它几乎并不消耗系统资源,所以现在成了 Linux 下保护机制的标配。
大概意思是说在栈上会放一个值…这个值在old ebp和返回地址的前面…要是发生栈溢出修改后面的值的话这个值自然也是会被修改的…因此就能检测到了XD
0x00.安全检查
首先是惯例的checksec
可以看到除了地址随机化以外都开了
当然,看名字就知道这题肯定要考巨难的canary(Or2…
0x01.逆向分析
拖入IDA进行分析
我们可以看到最大读入0x100
字节的输入,可以把整个栈给改写得一塌糊涂,但是会被canary检测发现> <!
唯一的一个可塑的输出点是printf,说明在这里很有可能存在操作空间!
0x02.漏洞利用
canary泄露
canary存在高字节截断,如果我们使用0x4c-0xc+1
的padding覆写掉canary的最高位字节\x00,这样程序在调用printf函数时便会输出canary的值!
也就是partial overwrite
那么我们的第一条payload就出来了:
1 | payload1 = b'A'*(0x4c-0xc+1) |
之后程序在输出完我们的输入之后还会再输出一些东西,而其中的前三个字节便是canary的低三位字节
于是我们便能够得到canary的值了> <!
1 | p.send(payload1) |
ret2libc
得到了canary的值之后我们就可以尽情地溢出了wwwww
同时我们可以发现不存在可以直接getshell的system()
函数或是/bin/sh
字符串
题目给出了libc.so.6
文件,故考虑ret2libc,构造rop链先将函数返回至puts
,输出puts函数的真实地址(储存在got表中),之后计算出libc的基址,再计算出libc中system函数与/bin/sh字符串的真实地址,最后构造rop链执行system("/bin/sh")
即可getshell
exp
最终构造exp如下:
1 | #python3 |
运行exp,成功getshell,撒花花~~🌸🌸🌸
最后我们就能得到flag啦~
1 | moectf{W0w_Y0u_c@n_e5cap3_fr0m_c4nary!} |
moectf2020 write up for baby canary
http://meteorpursuer.github.io/2021/01/15/moectf2020 write up for baby canary/