PWN 100
先分析下源码:
1 | int __cdecl main() |
这里父进程fork了一个子进程,然后当返回在子进程中时就进入do()函数,返回在父进程中时就阻塞,然后子进程结束后再fork子进程
跟进子进程函数
很明显是个base64解码,再看看输入时的判断,那么程序的功能就知道了
然后再来找漏洞,base64解码后长度变为原来的四分之三,我们可以输入的最大长度为512,解码后保存在一个长度为257的字符数组,那么很明显这里存在一个缓冲区溢出
再来看下程序的保护机制:
发现有canary,那么得绕过,这里有种针对fork进程的爆破方法
http://0x48.pw/2017/03/14/0x2d/
http://veritas501.space/2017/04/28/%E8%AE%BAcanary%E7%9A%84%E5%87%A0%E7%A7%8D%E7%8E%A9%E6%B3%95/
对fork而言,作用相当于自我复制,每一次复制出来的程序,内存布局都是一样的,当然canary值也一样。那我们就可以逐位爆破,如果程序GG了就说明这一位不对,如果程序正常就可以接着跑下一位,直到跑出正确的canary。
另外有一点就是canary的最低位是0x00,这么做为了防止canary的值泄漏。比如在canary上面是一个字符串,正常来说字符串后面有0截断,如果我们恶意写满字符串空间,而程序后面又把字符串打印出来了,那个由于没有0截断canary的值也被顺带打印出来了。设计canary的人正是考虑到了这一点,就让canary的最低位恒为零,这样就不存在上面截不截断的问题了。
那么编写exp:
1 | from pwn import * |
运行:
PWN 200
分析源码,一个格式化字符串漏洞
那么直接调试找偏移
可以发现,偏移是7,那么我们把puts_got地址上的值printf出来,就能够得出puts函数地址,然后就能得到system函数地址,再然后我们需要调用system函数,这里可以把atoi函数got上的值改为system函数地址,然后传入”bin/sh”,当调用atoi函数时,就能getshell了
exp:
1 | from pwn import* |
运行:
ps:关于fmtstr_payload
的用法以及源码参考:
http://docs.pwntools.com/en/stable/fmtstr.html
PWN 300
存在栈溢出
、动态调试一下,算下需要填充的padding的长度
0xbfe17d98-0xbfe17d5c = 0x3c = 60
然后再加上ebp的长度就是64
另外这个程序时静态链接的,那么ROP就在程序自身找找
还有就是这个程序只能输入无符号类型的10进制数
那么就需要把shellcode修改一下
最后编写exp:
1 | from pwn import * |