PatriotCTF 2025 Misc & OSINT & Forensics -- writeup

十一月 24, 2025 / Mnzn / 51阅读 / 0评论/ 分类: CTFwriteup

被带飞太爽了 😋🤓

Misc

Reverse Metadata Part 1

exiftool CVE

https://github.com/UNICORDev/exploit-CVE-2021-22204

反弹shell回来就行 flag在 /flags

Reverse Metadata Part 2

同上 flag在 /proc 删除的文件 grep找就可以

Half-Eaten Metapixels

打开mc文件 是Golly https://golly.sourceforge.io/

Golly 是一款开源的跨平台应用程序,用于探索康威生命游戏和许多其他类型的元胞自动机。

31da213f-8256-44a1-9af9-28cdb911ec66.png
经过一段时间的迭代后 我们得到
57b6d24f-4f5e-44df-89f0-0c34ab6a9f9d.png
到这里陷入了僵局 因为可以发现 flag是不完全的 而且这个迭代的速度是非常缓慢

我到这里大概跑了一个小时 于是开始尝试观察

整个系统由n个小方块组成 我们暂称每个小方块为区块

在初始的Generation=1时,
4abf7214-c6fa-4541-b533-2a3087d9c940.png

d498e268-0b15-4023-bc5c-5e97eddff91a.png

观察到每个区块的左下角 有类似电路板的结构

而有活细胞区块的这部分与无活细胞区块的这部分结构不同

258fce86-a03f-4aba-b328-294ace8a92fb.png

每个应该有东西的区块 左下的ON OFF 区域的 B1-8是ON

没有东西的区块是OFF 并且这个规律与目前迭代出来的都对应上了

我们以其中一个变化的位置作为标志位采样 编写脚本提取全部信息

Golly内置python脚本环境 https://golly.sourceforge.io/Help/python.html

编写脚本来提取标志位

import golly as g
import os

def export_01_grid():
    x_start = 138
    x_end   = 282762
    x_step  = 2048

    y_start = 1496
    y_end   = 21976
    y_step  = 2048

    desktop = os.path.join(os.path.expanduser("~"), "Desktop")
    filepath = os.path.join(desktop, "output.txt")

    with open(filepath, "w") as f:
        y = y_start
        while y <= y_end:
            line_bits = []

            x = x_start
            while x <= x_end:
                state = g.getcell(x, y)
                line_bits.append("1" if state == 1 else "0")
                x += x_step

            f.write("".join(line_bits) + "\n")

            y += y_step

    g.show("Done.")

export_01_grid()

然后将得到的二进制字符串转换为图像

from PIL import Image

# Provided text block
text = """0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000
0011000011001111101111001010000000000110000000100100011100011100000001000000000000000000011000110010000000001000110000011001000001110010100
0100100100100010001000001000000000001010000000101010100010100010000010100000000000000000100101001010000000001001001000101001000010001000100
0100100100100010001000001000100010010010011100100010100000000010000000100111100000001100100101001010000000111001000000101001110010001000100
0100100100000010001110010000100010100010100010100010111000011100000000101000000000010010100101001010000001001001110001001001001001110000010
0111000100100010001000001000010100111110100000100010100000000010000000100111000000010000100101001010000001001001001001111001001010001000100
0100000100100010001000001000010100000010100000100010100000100010111000100000101110010010100101001010111101001001001000001001001010001000100
0100000011000010001000001010001000000010100000100010100000011100000000101111000000001100011000110010000000111000110000001001110001110010100
0000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"""

# Parse lines
lines = text.strip().split("\n")
height = len(lines)
width = len(lines[0])

# scale factor
scale = 8
img = Image.new("RGB", (width * scale, height * scale), "white")
pixels = img.load()

for y, line in enumerate(lines):
    for x, c in enumerate(line):
        color = 0 if c == '1' else 255
        # fill 4x4 block
        for dy in range(scale):
            for dx in range(scale):
                pixels[x*scale+dx, y*scale+dy] = (color, color, color)

# Save image
path = "C:\\Users\\Mnzn\\Desktop\\output_image.png"
img.save(path)

我们就得到了flag图 O(∩_∩)O

96b0ee5e-ab85-4771-aa39-15d29c93291f.png

Mysterious XOR

观察报文,发现存在大量字符 g

结合题目描述 One byte is all you ever need. 和题目的 XOR
提取出原始字节流 与字符 ‘g’ 进行异或 得到ELF文件

接下来是对ELF文件的逆向分析

写exp

import socket

from datetime import datetime, timezone

def cur_dt_bytes():

    """
    cur_dt: "YYYYMMDDTHHMMZ" (UTC)
    """
    now_utc = datetime.now(timezone.utc)
    s = now_utc.strftime("%Y%m%dT%H%MZ")
    return s.encode()

def build_v8():

    """
    v8 = "/tmp/" + cur_dt(...)
    """

    base = b"/tmp/"
    dt = cur_dt_bytes()
    v8 = base + dt
    return v8

def build_v11():

    """
    xsp(v8, "1337", v11)
    - v11[0..18] = v8[i] XOR key[i]
    - v11[19]    = '\n'
    """
    v8 = build_v8()
    key = b"1337" + b" " * (19 - 4)  # "1337" + 15 个空格
  
    out = bytearray(20)
    for i in range(19):
        out[i] = v8[i] ^ key[i]
    out[19] = 0x0A  # '\n'
    return bytes(out)

payload = build_v11()

Forensics

Word Sea Adventures

解压docx 得到三张图片

steghide提取出三段信息

Mr Crabs heard that his cashier may be hiding some money and maybe a flag somewhere.
Spongebob is so chill! Why would he be hiding any flags?
I guess you found handsome squidward… even his looks can’t hide the flag.
pctf{w0rD_f1le5_ar3_als0_z1p

We Go Gym

此题为TTL
统计出所有交互ip 次数最多的ip的TTL经过ascii解码后为flag

from scapy.all import rdpcap, IP

from collections import Counter, defaultdict

  

pcap_file = "wegogym.pcap"

  

packets = rdpcap(pcap_file)

  

ttl_per_src = defaultdict(Counter)

src_counter = Counter()

  

for pkt in packets:

    if IP in pkt:

        src = pkt[IP].src

        ttl = pkt[IP].ttl

        ttl_per_src[src][ttl] += 1

        src_counter[src] += 1

  

# 自动选择出现最多包的源 IP

target_src, _ = src_counter.most_common(1)[0]

print("Selected source IP:", target_src)

  

# 选择该源IP中出现次数最多的 TTL 作为 base_ttl

ttl_counter = ttl_per_src[target_src]

base_ttl, _ = ttl_counter.most_common(1)[0]

print("Base TTL:", base_ttl)

  

# 提取异常 TTL

raw_ttls = [pkt[IP].ttl for pkt in packets

            if IP in pkt and pkt[IP].src == target_src and pkt[IP].ttl != base_ttl]

  

# 去重

clean_ttls = []

for t in raw_ttls:

    if not clean_ttls or clean_ttls[-1] != t:

        clean_ttls.append(t)

  

# 转 ASCII

flag = ''.join(chr(t) for t in clean_ttls)

print("Decoded:", flag)

Burger King

给了一个svg文件和zip

看到算法是 ZipCrypto Store就可以锁定明文攻击了
.svg内容为 <svg xmlns="http://www.w3.org/2000/svg"
是svg文件对应的类似魔数的声明 就 <!DOCTYPE HTML> 一样
bkcrack撞一下就出了

在Hole.svg中

OSINT

Where’s Legally

整个系列都是常规的图寻 从谷歌地球里面翻GMU校园就都能找到了 很好找

Waldo’s Nignt Out

给了三套图 分别对应三个地点
也算是常规图寻 主要是看题目说的 Virginia 全都在弗吉尼亚
附件不在了只能陈述回忆了
location 1 是废弃的Skyzone,可以找到相关废弃地点探险的帖子
location 2 识图到的
location 3 有一张图片有两个电话号码 能通过其他图片推断出是酒店
带着下面的电话号码和hotel就能搜到了

Kittiez!!!

题目给了一个 hash
拿到hint 和 malware有关
上x搜kitty malware 能搜到一个组织

https://vx-underground.org/
在他的主页 有一个网盘 archive 里有很多猫猫图片 下载下来遍历 md5 找到对应图片就可以
图片在压缩包3中

#wp(10)

评论