-
-
[原创]看雪CTF2018 第三题 WP
-
发表于: 2018-6-21 17:07 3289
-
可以看到开启了NX和Canary
其次在test函数中使用ptrace以达到反调试的效果,为了分析方便我们可以将对test函数的调用nop之。
此外在main函数中也有一些像这样的指令集合,实际执行的时候是顺序执行的,调试时步进即可。
首先解题的第一关是main函数在0x40087F之后便全部被加了密,程序运行时先将main函数所在的内存段权限改为rwx,然后读取用户输入6个字符,然后就到了第一个解密循环
以用户输入的第一个字符为参数对0x40087F开始的数据逐字节xor,直到满足dh=FB and bl=90为止。
我们可以将要解密的数据复制到Python中进行暴力破解,验证是否满足可以靠pwnlib(capstone)的disasm,只要反编译的结果中没有'byte'或'bad'之类的字符即可认为匹配
密钥第一位是'e',解密出来的第一份指令如下
之后剩下的几段被加密的部分和这类似,只有最后一份判断条件少了一个。
首先破坏已经执行过的指令,然后密钥的第一位xor第二位得到第二次解密的参数,然后还是逐字节xor。
同理继续操作即可得到最后的代码
(这里将call +5; pop rax; add rax; jmp rax nop掉了,使得sys_mprotect调用时addr参数为0,不过问题不大)
最后的代码先后做了一下操作:输出wow,清空缓冲,读取26字符,将读取的字符串直接printf,再读取0x200字符,恢复内存权限,栈检查和ret。
这儿明显有格式化字符串漏洞和栈溢出,然而格式化字符串漏洞的格式控制字符长度不够(写入四个字节就需要大约60个格式控制字符),程序开启了Canary,不能直接栈溢出。正确的做法是用格式化字符串读取Canary然后栈溢出。
开始攻击之前先要得到system函数的偏移量,这儿我用了格式化字符串读取了puts和setbuf函数的地址,用通过Libc-database得到了服务器上libc为libc6_2.23-0ubuntu10_amd64
直到版本之后即可发动攻击,先利用格式化字符串得到栈地址和任意一个libc函数地址,然后ROP拼凑出system("/bin/sh\x00")即可GetShell
完事具备,只差脚本
这题做的我感觉自己是智障。。。
虽然开启了NX,但是main函数最后有mprotect调用,可以将将内存权限改为r-x,巧妙的ROP绕过两次栈检测、将栈地址加上执行权限,最后ret到栈上就可以轻松Exec(/bin/sh)了,然后我就把一上午的时间浪费在这个思路上了。
首先遇到的第一个坑是mprotect调用的地址参数要4K对齐,调整之后又发现shellcraft.sh()给出的shellcode不能用
由于此时栈地址已经没有写权限,所以push指令会出错,自己写了一份shellcode终于本地测试成功,但是远程攻击又失败了
程序最开始调用了ptrace,这样程序在调用sys_execve时会通知父进程处理,我为了调试方便把ptrace nop了。。。
也不知道出题人调用ptrace有没有考虑去屏蔽sys_execve。
然后把syscall的方案改成了计算system地址然后直接call,又发现栈没写权限连call也不能执行、system函数肯定也用栈,更不行。。。
吃午饭的时候才想到干嘛要这么麻烦,直接ROP不就行了吗,瞬间感觉自己智障。
挺有趣的一道题,还好没牵扯heap,不然边学边做也来不及。接下来就要忙起来了,不知道还能再做出多少题。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!