ctfshow西瓜杯wp
本来想最后十分钟偷别人的塔没成想最后一分钟被人偷塔了,喜提第二QaQ
MISC
你是我的眼
将程序拖入jadx中,查看main函数
将-替换为/base64解密
二维码拼图
没什么说的,直接手动在线拼图
SignIn
打开他给的网站
https://qrcode.antfu.me/
点击verify上传附件图片进行验证
一直点击 random tries和narrow down,每次会获得不同的flag片段,拼起来得到flag
crypto
奇怪的条形码
把电脑盖子对着眼睛即可得到flag
简单密码
将密文分为两个一组,观察到偏后的十六进制数比较大,猜测是要减去i(i为第几个十六进制数)
1 | 647669776d757e83817372816e707479707c888789757c92788d84838b878d9d |
1 | hex_string = "647669776d757e83817372816e707479707c888789757c92788d84838b878d9d" |
factor
factordb秒了
1 | from Crypto.Util.number import inverse, long_to_bytes |
混合密码体系
用了多种加密,直接让gpt写脚本即可
1 | from Crypto.Util.number import long_to_bytes, inverse |
RE
pe
pe头缺失,运行不了,但是直接拖进ida中可以获得明文flag
一个西瓜切两半你一半我一半
这个直接用uncompyle6进行反编译pyc文件可得flag
这里有个key,很明显是附件txt中的一个西瓜切两半你一半我一半,编写解密脚本
1 | pythonflag = "" |
easy_re
拿到ida中反编译
可以看到这里输入先是拿到了decrypt函数中解密code,然后执行解密后的字节码
这里我盲猜解密后的字节码是明文存储flag的,因此,直接爆破三位英文字母然后匹配ctfshow字样
1 | def decrypt(code, string): |
探索进制的奥秘
如题,十六进制转10进制
1 | hex_string = "647669776d757e83817372816e707479707c888789757c92788d84838b878d9d" |
E
放入ida中查看
看到这里有疑似base64编码的内容
成功解出flag
WEB
CodeInject
签到题,没什么好说的
tpdoor
代码审计,发现可以操控request_cache_key
全局搜索request_cache_key
查看./vendor/topthink/framework/src/think/middleware/CheckRequestCache.php
发现这里将request_cache_key一分为二,| 标识符前面的是key,后面的是fun
往下看
这里居然直接执行fun|key,那么我们就可以传这样的参数读取flag
https://7876945b-30c2-47b7-8bde-b7d27cbefbbb.challenge.ctf.show/?isCache=cat%20/000f1ag.txt|system
easy_polluted
原题,python原型链污染,可以参考大佬博客,我比赛的时候直接按照博客里的步骤,把%改成#就打通了233
大佬博客:https://www.cnblogs.com/gxngxngxn/p/18264279
PWN
嘘嘘嘘
这里大致的逻辑就是读一个数,然后根据这个偏移输出一些数据,然后再读一个数,根据偏移来读入数据
最后执行一个结构体0x10处储存的函数
我们发现读入偏移的时候居然可以读入负数造成越界读,那么我们首先读入负数泄露elf程序基址,然后写入那个结构体保存函数指针的位置为exec函数在.data.rel.ro段中的地址,同时传入0x1234使其满足判断条件
1 | from pwn import * |
没主意了
赛后发现show函数有个格式化字符串漏洞,可怜我比赛时根本没往这方面想,一直研究那个realpath从而错失良机QwQ
Do_it!
这里很明显有越界写漏洞,但是只能执行两次,怎么办呢?
改函数的返回地址肯定是来不及,那么我们考虑劫持main函数的返回地址,于是:第一次越界写改函数的返回地址为main函数中call这个函数的地址0x40130A,第二次在我们main函数的返回地址处写rop链,接下来一直重复即可
正常打ret2libc即可
1 | from pwn import * |
Echo
在iso-2022-cn-ext.c中有如下代码
1 | // iconvdata/iso-2022-cn-ext.c |
当需要进行字符集切换时会发出转移序列,其中,程序仅仅检查了第一个块的转移序列,并未对大小为2或3的转移序列进行检查
因此,我们可以利用这一点进行利用。
回到题目,我们发现这里输入最多可以输入0x38的大小,然而查阅得知,iconv的输出长度参数soutput只有0x26,而且s到canary的距离是0x28,所以这里我们的思路是前面填充垃圾数据,最后触发长度为3字节的转义序列,填充剩下的两位以及canary的末位,从而在接下来的输出中泄露canary。
䂚这个字就可以触发三字节的转移序列,因此,我们首先填充0x25字节的垃圾数据,接着填充䂚这个字,发生栈溢出,读到canary后最后打ret2libc即可。
exp:
1 | from pwn import * |
Large_watermelon
程序只有add和delete功能,看来爆破stdout是免不了了
delete处有uaf漏洞
那么我们首先double free,将同一个堆块两次放入tcache中
,接着申请相同大小的堆块,内容为heap_addr-0x10,这样就构造出了堆块交叉,像这样
接着申请一堆堆块,并且将第一块的size精心计算好的unsortedbins大小,接着释放0,将堆块放入到unsortedbin中去
然后故技重施,继续double free,然后申请一块chunk,让unsortedbins的残留地址下移到doublefree的地方,接着申请出之前doublefree的一块堆块,将其最后两位改成\x60\x17,这是stdout的地址,但是由于1kb对齐,我们需要爆破这个最高字节,因此脚本打通的成功率是1/16
接着将stdout的前几个字节改成p64(0xfbad1800)+p64(0)*3+b”\x58”即可正常输出消息了,接下来就是常规的打free_hook了
1 | from pwn import * |
一个又一个
有次数限制的格式化字符串漏洞思路是在bss段上布置rop链,然后栈迁移到bss上
因为有close(1)通过修改stdout为stderr即可显示输出
最后orw即可
1 | from pwn import * |