Misc 流量分析 - 1 Challenge 我需要你流量分析😡
首次发起端口扫描的 IP 是?
将答案经过 md5 32 位加密后小写形式放入 CM {} 中
以下是附件链接:
通过网盘分享的文件:抓取流量.pcapng 链接: https://pan.baidu.com/s/1ye0KLzXGqyCYec2kGSlPMw?pwd=CM66 提取码: CM66 -- 来自百度网盘超级会员 v5 的分享
Solution 192.168.37.3
1 CM{d28ee9d60772acbcd4eca38e1a3c94b8}
流量分析 - 2 Challenge 扫描次数最多的 IP?
将答案经过 md5 32 位加密后小写形式放入 CM {} 中
Solution
192.168.37.3
1 CM{d28ee9d60772acbcd4eca38e1a3c94b8}
流量分析 - 3 Challenge 扫描次数第二的 IP?
将答案经过 md5 32 位加密后小写形式放入 CM {} 中
Solution 图同上题
192.168.37.1
1 CM{1edaa78b26c43a0cf438b4437f6ceeb3}
流量分析 - 4 Challenge 哪个 IP 用了 AWVS?
将答案经过 md5 32 位加密后小写形式放入 CM {} 中
Solution IP 数量很少,试一下就出来了
192.168.37.1
1 CM{1edaa78b26c43a0cf438b4437f6ceeb3}
流量分析 - 6 Challenge 有 IP 进行了 WEB 登录爆破😲,提交其 IP?
将答案经过 md5 32 位加密后小写形式放入 CM {} 中
hint: 登录页面为 login.php
Solution 直接搜索字符串 POST /login.php
,一条条看发现 192.168.37.87
多次连续出现
1 CM{83779b479698b76581244f6ac8acd8a6}
流量分析 - 7 Challenge 有 IP 进行了 WEB 登录爆破,提交其爆破次数
(将爆破次数比如 55, 进行加密)
将答案经过 md5 32 位加密后小写形式放入 CM {} 中
Solution
1 ip.src == 192.168.37.87 && http contains "login.php"
筛选导出得到 107 条数据,除去第 1 条 GET 请求,剩下的 106 条全都是
1 CM{f0935e4cd5920aa6c7c996a5ee53a70f}
流量分析 - 8 Challenge 提交攻击者登录成功 admin 用户的 IP 和密码,以 & 连接
(示例:答案为 192.168.92.111&CM666, 将上述内容进行加密)
将答案经过 md5 32 位加密后小写形式放入 CM {} 中
Solution
192.168.37.200&zhoudi123
1 CM{3ca6dd54928fcfe47289ae62439116dd}
段涵涵学姐最爱的音乐 Challenge 王振宇从学姐闺蜜那边了解到学姐最爱的歌手是 Taylor Swift,猜猜这个音频有什么秘密吧
flag 格式为 CM
Solution
OSINT 杜浩学姐の朋友圈 Challenge 王阵雨辗转反侧,突然刷到了杜浩学姐朋友圈的一张图,猜猜这是在哪里呢
flag 格式为 CM
例:CM
Solution 发现玻璃反射泄露信息,将图片水平镜像后放大发现这两处关键信息
首先是右边的 City花园城
,搜索发现它改名为招商花园城
了,因此后续的搜索中使用关键词招商花园城
然后是左边盒马
的广告,说明这附近有盒马
的店,并且极大概率就开设在招商花园城
内
因此搜索盒马 招商花园城
发现这篇文章盒马鲜生南京新店开业 市民多了新消费地标_腾讯新闻
文中提到的是南京招商花园城
使用手机高德地图搜索南京招商花园城
后搜索其附近的地铁站
Web 小猿口算签到重生版 Challenge 考验手速和脑速的挑战
Solution 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 import requestsdef main (): generate_url = "http://27.25.151.40:32926/generate" verify_url = "http://27.25.151.40:32926/verify" with requests.Session() as session: try : response = session.get(generate_url) response.raise_for_status() data = response.json() expression = data.get("expression" ) if not expression: print ("未获取到有效的表达式" ) return print (f"获取到的表达式: {expression} " ) expression_to_eval = expression.replace("=?" , "" ) try : result = eval (expression_to_eval) except Exception as e: print (f"表达式计算失败: {e} " ) return print (f"计算结果: {result} " ) payload = { "user_input" : str (result) } verify_response = session.post(verify_url, json=payload) verify_response.raise_for_status() verify_data = verify_response.json() print (f"验证结果: {verify_data} " ) except requests.exceptions.RequestException as e: print (f"网络请求失败: {e} " ) if __name__ == "__main__" : main()
1 flag{CAD709DE7E0B803D8BA72A55C4EB8C50}
lottery 签到重生版 Challenge 抽抽抽
flag 格式为 CM {xxxxxx}!
Solution 找了一圈都没线索,所以就试着爆破一下
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 import requestsimport timeURL = "http://27.25.151.40:33411/spin" MAX_ATTEMPTS = 200 def spin_the_wheel (): """ 发送POST请求到 /spin 接口 """ try : headers = {'Content-Type' : 'application/json' } response = requests.post(URL, headers=headers, data='{}' , timeout=10 ) if response.status_code == 200 : return response.json() else : print (f"请求失败,状态码: {response.status_code} " ) return None except requests.exceptions.RequestException as e: print (f"请求发生错误: {e} " ) return None def main (): print (f"[*] 开始爆破,目标URL: {URL} " ) print (f"[*] 最大尝试次数: {MAX_ATTEMPTS} " ) print ("-" * 30 ) for i in range (1 , MAX_ATTEMPTS + 1 ): print (f"[*] 正在进行第 {i} 次尝试..." ) result = spin_the_wheel() if result: print (f" [+] 收到结果: {result} " ) if 'flagContent' in result: print ("\n" + "=" * 40 ) print (result['flagContent' ]) print ("=" * 40 + "\n" ) return time.sleep(0.1 ) if __name__ == "__main__" : main()
结果到了第 178 次就爆出来了
1 flag{B4F8EC958F70E3EE2245F97068D00109}
Reverse IDA Challenge flag 格式为 CM {xxxxxx}!
Solution
1 CM{W3lc0me_2_R3ver5e_h@v3_fun!}
Xor Challenge flag 格式为 CM {xxxxxx}!
Solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 flag = [ 0x5F , 0x55 , 0x58 , 0x5E , 0x42 , 0x61 , 0x09 , 0x6B , 0x66 , 0x08 , 0x4A , 0x66 , 0x0F , 0x79 , 0x4A , 0x08 , 0x5A , 0x66 , 0x5F , 0x09 , 0x4B , 0x66 , 0x6B , 0x0A , 0x4F , 0x5C , 0x4B , 0x0C , 0x5C , 0x18 , 0x44 ] key = 57 original_input = '' .join([chr (byte ^ key) for byte in flag]) print ("原始输入字符串为:" , original_input)
1 CM{X0R_1s_6@s1c_f0r_R3ver5e!}
maze Challenge 点击。。。?就。。。?送。。。?诶这些 01 仿佛组成了一条路
Solution 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 import syssys.setrecursionlimit(2000 ) MAP_STRING = "$11111111100111111111010000111001011011101101101110000110111111110011111111011111111101111111110000#" WIDTH = 10 HEIGHT = len (MAP_STRING) // WIDTH def solve_maze (): """ 解析并解决迷宫问题 """ maze = [] for i in range (HEIGHT): row = list (MAP_STRING[i * WIDTH : (i + 1 ) * WIDTH]) maze.append(row) print ("--- Maze Layout ---" ) for row in maze: print ("" .join(row)) print ("--------------------" ) start_pos = (0 , 0 ) def find_path (x, y, path, visited ): if not (0 <= x < WIDTH and 0 <= y < HEIGHT): return None if maze[y][x] == '1' : return None if (x, y) in visited: return None if maze[y][x] == '#' : if len (path) == 28 : print (f"[*] Path found with length {len (path)} !" ) return path else : return None if len (path) > 28 : return None new_visited = visited.copy() new_visited.add((x, y)) solution = find_path(x, y + 1 , path + 'S' , new_visited) if solution: return solution solution = find_path(x + 1 , y, path + 'D' , new_visited) if solution: return solution solution = find_path(x - 1 , y, path + 'A' , new_visited) if solution: return solution solution = find_path(x, y - 1 , path + 'W' , new_visited) if solution: return solution return None print ("[*] Searching for a path of length 28..." ) solution_path = find_path(start_pos[0 ], start_pos[1 ], "" , set ()) if solution_path: print ("\n[+] Success! Found the correct input:" ) print (solution_path) else : print ("\n[-] Failed to find a valid path of length 28." ) if __name__ == "__main__" : solve_maze()
1 CM{SDSSASSDDDWWWDDDSSSSASSSDDDD}
sw1f7’s TEA Challenge 相传 sw1f7 学姐喜欢做甜点,我猜她应该也喜欢泡茶,只有她认可的人才能喝到茶
flag 格式为 CM {xxxxxx}!
Solution 把 checkdebug 给 nop 掉,然后在第 19 行下断点
动调拿到密文
1 2 3 4 .data:0000000000404020 flag dd 5B5C5F08h, 2766AE05h, 8C4D477Dh, 554F7F8Dh, 0E20BD674h .data:0000000000404020 ; DATA XREF: sub_114514(void)+1D↑w .data:0000000000404020 ; sub_114514(void)+57↑o ... .data:0000000000404034 dd 0BE678AAh, 0F44B5224h, 0CA619F04h
然后 AI 一把梭
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 import structdef decrypt (v, k ): """ 这是提供的 encrypt 函数的逆函数。 它将一个 8 字节的数据块 v (拆分为 v0, v1) 进行 32 轮解密。 参数: v (tuple): 一个包含2个32位无符号整数的元组 (v0, v1)。 k (tuple): 一个包含4个32位无符号整数的元组,代表密钥 (k0, k1, k2, k3)。 返回: tuple: 解密后的 (v0, v1) 元组。 """ v0, v1 = v k0, k1, k2, k3 = k delta = 1640531527 current_sum = (0 - (32 * delta)) & 0xFFFFFFFF for i in range (32 ): term_v1 = (((v0 + current_sum) & 0xFFFFFFFF ) ^ (k2 + (v0 << 4 )) ^ (((v0 >> 5 ) & 0xFFFFFFFF ) + k3)) & 0xFFFFFFFF v1 = (v1 - term_v1) & 0xFFFFFFFF term_v0 = (((v1 + current_sum) & 0xFFFFFFFF ) ^ (k0 + (v1 << 4 )) ^ (((v1 >> 5 ) & 0xFFFFFFFF ) + k1)) & 0xFFFFFFFF v0 = (v0 - term_v0) & 0xFFFFFFFF current_sum = (current_sum + delta) & 0xFFFFFFFF return (v0, v1) def solve (): """ 主求解函数,整合所有信息并执行解密。 """ key = (36 , 66 , 82 , 118 ) print (f"[*] 使用密钥: {key} " ) encrypted_flag_words = [ 0x5B5C5F08 , 0x2766AE05 , 0x8C4D477D , 0x554F7F8D , 0xE20BD674 , 0x0BE678AA , 0xF44B5224 , 0xCA619F04 ] encrypted_flag_bytes = b'' .join([struct.pack('<L' , word) for word in encrypted_flag_words]) print (f"[*] 待解密的密文 (hex): {encrypted_flag_bytes.hex ()} " ) decrypted_result = b'' print ("\n[+] 开始解密..." ) num_blocks = len (encrypted_flag_bytes) // 8 for i in range (num_blocks): block_start = i * 8 block_end = block_start + 8 encrypted_block = encrypted_flag_bytes[block_start:block_end] v = struct.unpack('<II' , encrypted_block) decrypted_v = decrypt(v, key) decrypted_block = struct.pack('<II' , decrypted_v[0 ], decrypted_v[1 ]) decrypted_result += decrypted_block print (f" - 块 {i+1 } 解密完成,得到: {decrypted_block.decode('ascii' , errors='ignore' )} " ) final_flag = decrypted_result.decode('ascii' ).strip('\x00' ) print (f"\n{final_flag} " ) if __name__ == "__main__" : solve()
得到输出:
1 2 3 4 5 6 7 8 9 10 [*] 使用密钥: (36, 66, 82, 118) [*] 待解密的密文 (hex): 085f5c5b05ae66277d474d8c8d7f4f5574d60be2aa78e60b24524bf4049f61ca [+] 开始解密... - 块 1 解密完成,得到: flag{sw1 - 块 2 解密完成,得到: f7's_Tea - 块 3 解密完成,得到: _is_clas - 块 4 解密完成,得到: sical!!} flag{sw1f7's_Tea_is_classical!!}
1 CM{sw1f7's_Tea_is_classical!!}
sw1f7’s XXTEA Challenge sw1f7 学姐的茶被喝了,这次她决定泡一壶更浓厚的茶,在走之前放了个盖子
flag 格式为 CM {xxxxxx}!
Solution AI 一把梭了
加密算法是 XXTEA
密文 (Ciphertext) : 存储在 flag 地址的数据。
1 2 .data:0000000000403020 flag dd 19EA7A62h, 5BE6801h, 0D2AD8A17h, 1A1456A1h .data:0000000000403030 dd 843B635Bh, 0E2369508h, 0BF552654h, 0FC87047Ch
这些是 32 位的 DWORD(双字),在小端序(Little-Endian)的 x86 架构中,内存中的字节序是反的。不过,当我们将它们作为 uint32_t 数组处理时,数值就是这些。 ciphertext = [0x19EA7A62, 0x05BE6801, 0xD2AD8A17, 0x1A1456A1, 0x843B635B, 0xE2369508, 0xBF552654, 0xFC87047C]
密钥 (Key) :key =
参数 :n = 8,rounds = 12
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 import structdef decrypt (v, n, key ): """ XXTEA解密函数 v: uint32_t 整数列表,代表密文数据 n: 数据块的数量 key: uint32_t 整数列表,代表密钥 """ ROUNDS = 52 // n + 6 DELTA = 0x9E3779B9 sum_val = (ROUNDS * DELTA) & 0xFFFFFFFF y = v[0 ] for _ in range (ROUNDS): e = (sum_val >> 2 ) & 3 for p in range (n - 1 , 0 , -1 ): z = v[p - 1 ] term1 = (y ^ sum_val) term2 = (z ^ key[(p & 3 ) ^ e]) term3 = ((y << 2 ) ^ (z >> 5 )) & 0xFFFFFFFF term4 = ((y >> 3 ) ^ (z << 4 )) & 0xFFFFFFFF v[p] = (v[p] - ((term1 + term2) ^ (term3 + term4))) & 0xFFFFFFFF y = v[p] z = v[n - 1 ] term1 = (y ^ sum_val) term2 = (z ^ key[(0 & 3 ) ^ e]) term3 = ((y << 2 ) ^ (z >> 5 )) & 0xFFFFFFFF term4 = ((y >> 3 ) ^ (z << 4 )) & 0xFFFFFFFF v[0 ] = (v[0 ] - ((term1 + term2) ^ (term3 + term4))) & 0xFFFFFFFF y = v[0 ] sum_val = (sum_val - DELTA) & 0xFFFFFFFF return v def main (): ciphertext = [ 0x19EA7A62 , 0x05BE6801 , 0xD2AD8A17 , 0x1A1456A1 , 0x843B635B , 0xE2369508 , 0xBF552654 , 0xFC87047C ] key = [36 , 66 , 82 , 118 ] n = len (ciphertext) decrypted_data = decrypt(ciphertext, n, key) print (f"解密后的整数数组: { [hex (x) for x in decrypted_data] } " ) plaintext_bytes = b'' for dword in decrypted_data: plaintext_bytes += struct.pack('<I' , dword) try : flag = plaintext_bytes.decode('utf-8' ) print (f"\n[+] 成功找到Flag: {flag} " ) except UnicodeDecodeError: print (f"\n[-] 解码失败,原始字节: {plaintext_bytes} " ) if __name__ == '__main__' : main()
得到输出:
1 2 3 解密后的整数数组: ['0x67616c66', '0x3177737b', '0x73273766', '0x5458585f', '0x695f6165', '0x6f6d5f73', '0x79666964', '0x7d676e69'] [+] 成功找到Flag: flag{sw1f7's_XXTea_is_modifying}
1 CM{sw1f7's_XXTea_is_modifying}
Mobile base_android Challenge flag 格式为 CM {xxxxxxx}!
Solution 逆向发现程序从 assets 文件夹中读取 timg_2.zip 文件的内容,然后将这些内容一字不差地写入到 /data/data/com.example.test.ctf02/databases/img.jpg 文件中
因此手动将 assets/timg_2.zip
提取出来,然后把.zip
后缀改为.jpg