Web50 打不过

打开页面,发现只有一个get提交框用来提交密码,并且提交按钮是被禁用的。

前端禁用没有任何影响,直接提交get请求。

但是提交的密码没有给出提示,这时通过查看HTTP头部可以发现多出了一个字段

Str OGM0MzU1NTc3MTdhMTQ4NTc4ZmQ4MjJhYWVmOTYwNzk=

明显的Base64编码,解码后发现是一个32字符的字符串,尝试拿去解md5。

得到密码1931b,提交可得flag。

flag is:flag_Xd{hSh_ctf:XD_aA@lvmM}

Web300 疯狂的js

打开链接,取消promot查看源代码。

发现源码里只有script.js,下载开始分析。

找到入口函数 cal_start(),发现脚本要求输入5次字符串而后传给 filter() 函数进行处理,判断返回值是否是 FLAG,是则发起对服务器的调用。因此可以知道核心是 filter() 函数。

查看 filter() 函数,发现函数首先对输入的5个字符串按第一个字符大小进行排序,而后进行筛选,筛选的标准是 a.indexOf(x) == i,也就是过滤相同的输入。

而后对过滤后的值进行判断是否大于999。为什么是999呢,迷惑居多,如果尝试跑遍999其实吃力不讨好。而且也不一定跑的出来。

然后就是调用cal函数对数组进行处理。对其进行5次判断。而核心就是这5次判断。

这5次判断可以抽象成关于m,i和args的5条不定方程组。

第一条 m[1]+4*i==x.length < 2 描述了m数组中各个数据之间的数值关系,以下等式中至少有2条成立:

m[1] == m[0]
m[1] + 4 == m[1]
m[1] + 8 == m[2]
m[1] + 12 == m[3]
m[1] + 16 == m[4]

第二条也是同理。第四条和第五条则是从另一个角度描述了数值关系。例如第四条 x > m[i-1].length > 2 表示以下不等式中至多2条成立:

m[1] > m[0]
m[2] > m[1]
m[3] > m[2]
m[4] > m[3]

因此,综合1,2,4,5四组方程,可以得出以下结论:

m[0] == m[1] < m[2] < m[3] == m[4]
m[4] = m[3] = m[1] + 12 = m[0] + 12

然后看第3条方程,x == args[i].length < 2,实际上是指 cal(x) == x 这条方程至少需要有2个解。

cal函数太复杂,不需要去理解具体cal函数干了什么。尝试跑一下就知道规律。

发现只能接受 toNumber 为真的字符串,而不能接受其他字符串。因此尝试性跑一下前100。

[1, 1, 5, 1, 3, 6, 11, 2, 5, 4, 9, 6, 5, 12, 11, 2, 7, 6, 13, 4, 3, 10, 9, 6, 15, 6, 13, 4, 11, 12, 19, 2, 9, 8, 7, 6, 7, 14, 15, 4, 11, 4, 13, 10, 9, 10, 17, 6, 9, 8, 15, 6, 5, 14, 14, 5, 15, 12, 13, 10, 10, 20, 17, 2, 11, 10, 17, 8, 7, 8, 15, 6, 16, 8, 7, 14, 13, 16, 15, 4, 12, 12, 12, 4, 3, 14, 13, 10, 11, 10, 17, 8, 9, 18, 15, 6, 18, 10, 11]

可以看出经过 cal() 计算后,结果都不大,没有超过20的结果,因此就假定后面的值的结果也是如此,不会太大。

接下来就是根据上面的结果寻找 cal(x) == x,发现只有两个结果1和6。因此可以推断出

m[0] = m[1] =1
m[2] = 6
m[3] = m[4] = 13

接下来去寻找 cal(x) = 1/6/13 满足的x的值。

args[1] == 1
args[2] == 1
args[4] == 1
args[6] == 6
args[12] == 6
args[18] == 6
args[19] == 13
args[24] == 6
args[26] == 6
args[27] == 13
args[36] == 6
args[43] == 13
args[48] == 6
args[52] == 6
args[59] == 13
args[72] == 6
args[77] == 13
args[87] == 13
args[96] == 6

考虑到排序和必须包含1和6,因此可以选出结果

1, 4, 6, 77, 87

输入,得到flag