[队伍名] - 友情&羁绊 [ranking] - 3

image-20250608212018240

碎碎念

感觉最近有点倦怠了,博客更新的也少了)以后会考虑搞点有深度的更技术的玩意,一位的写wp也不是办法 这次也是很开心能参加H&NCTF2025,题目质量我觉得蛮不错的,挺有意思,虽然有几题我实在是没研究出来,前一天出去了几乎没怎么打,后面是通宵补上的(身体要不行了) 也是感谢队友带飞最终取得了第三的好成绩qwq

Misc:

芙宁娜的图片

给了文档和图片,图片lsb藏了一个key,随波逐流直接梭出来

1749388261627

文档内容brainfuck得到一个加密的flag

1749388271869

拿bugku的维吉尼亚解密即可

1749388282525

星辉骑士

得到一个docx文档,修改zip后缀,在media里找到一个压缩包,然后随波梭哈修改伪加密

1749388293337

解压得到一堆文档,打开可以看到是垃圾邮件隐写

1749388303774

一个个解一下隐写即可https://spammimic.com/decode.cgi

1749388311414

乱成一锅粥了

wireshark打开分析,导出http对象可以发现有好几个压缩包,全部拉出来后,解压发现每个压缩包里都有50个txt文档,而且命名都一样

观察发现名字都是32位的小写字母和数字,猜测是md5值,所以去cmd5解密一下发现是50以内的shu猜到是逆出序号后按照序号拼接,写脚本处理即可:

 1import os
 2import re
 3import hashlib
 4
 5# 1. 构建数字 1–50 到对应 md5 值的映射
 6#    数字 <10 时使用两位格式 01-09,其余正常
 7
 8def build_md5_map():
 9    md5_map = {}
10    for i in range(1, 51):
11        # 小于10时补0
12        s = f"{i:02d}" if i < 10 else str(i)
13        h = hashlib.md5(s.encode('utf-8')).hexdigest()
14        md5_map[h] = i
15    return md5_map
16
17# 2. 主函数:遍历、筛选并重命名
18
19def rename_files_by_md5(input_dir, output_dir):
20    """
21    遍历 input_dir 下的所有.txt文件,
22    匹配文件名是否为32位小写十六进制MD5,
23    并根据映射生成 outputs 目录下对应序号的文件
24    """
25    os.makedirs(output_dir, exist_ok=True)
26    md5_map = build_md5_map()
27    pattern = re.compile(r"^[0-9a-f]{32}$")
28
29    for fname in os.listdir(input_dir):
30        if not fname.lower().endswith('.txt'):
31            continue
32
33        name = fname[:-4].strip().lower()
34        if not pattern.fullmatch(name):
35            continue
36
37        num = md5_map.get(name)
38        if num is None:
39            print(f"Warning: 未找到对应序号的MD5:{name}.txt")
40            continue
41
42        src = os.path.join(input_dir, fname)
43        dst = os.path.join(output_dir, f"{num}.txt")
44
45        with open(src, 'r', encoding='utf-8') as f_src:
46            content = f_src.read()
47        with open(dst, 'w', encoding='utf-8') as f_dst:
48            f_dst.write(content)
49
50        print(f"生成: {num}.txt")
51
52
53if __name__ == '__main__':
54    INPUT_DIR = 'txt/End/End'  # 包含 MD5 文件的目录
55    OUTPUT_DIR = 'outputs'
56    rename_files_by_md5(INPUT_DIR, OUTPUT_DIR)
 1import os
 2
 3def merge_txt_files(input_dir, output_file='merged.txt'):
 4    with open(output_file, 'w', encoding='utf-8') as outfile:
 5        for i in range(1, 51):
 6            filename = os.path.join(input_dir, f'{i}.txt')
 7            try:
 8                with open(filename, 'r', encoding='utf-8') as infile:
 9                    content = infile.read()
10                    outfile.write(content)
11                    # outfile.write('\n')  # 可选:每个文件之间加一个换行
12            except FileNotFoundError:
13                print(f'Warning: {filename} not found, skipping.')
14
15if __name__ == '__main__':
16    # 示例路径:请替换为你的目录路径
17    input_directory = 'outputs'
18    merge_txt_files(input_directory, output_file='merged.txt')

拼完一个厨子一下得到二维码一部分,拼完剩下的即可

1749388333454

1749388346513

Forensics:

ez_game

给了一个vhd硬盘镜像,直接拿ufs分析一下,发现两个部分都放了内容,全部提取出来

1749388381450

根据txt的内容确定是要用jpg作为密钥挂载,挂载后得到一个虚拟机文件

1749388389230

老样子ufs分析,在root目录找到bash_history,得到两个关键信息,分别为两个key

1749388400055

一开始暂时不确定上面那个是什么,用下面那个重新挂载提取的vera容器,读取到隐藏空间发现藏了个加密压缩包

而密码就是上面提到的内容,他的意思就是按住shift后从`按到+即为密码(也就是~!@#$%^&*()_+)

解压后得到一个drawio文件,问问gpt是什么然后得到一个在线网站丢进去即可得到flag

1749388408461

OSINT:

Chasing Freedom 1

1H&NCTF{0503-丁鼻垄}

时间都在图片的属性里,图片有一个船,可以看到船号是闽平渔65599

1749388447809

百度一搜,第一个就是一个pdf文件

1749388451742

打开搜索65599确定这个船的所有人地址

1749388464223

然后搜一下就发现旁边有个叫丁鼻垄的地方,交一下发现对了

1749388472804

Chasing Freedom 2

1H&NCTF{0504-东庠岛灯塔}

时间都在图片的属性里,将图片的灯塔截取出来百度搜图就能找到事东庠岛的灯塔了

1749388484607

Chasing Freedom 3

1H&NCTF{0504-流水码头-岚庠渡3号}

时间都在图片的属性里,图片下面可以看到是岚庠渡

1749388511019

微信一搜,码头和船号都有了,遍历一下就好了

1749388519898