=========================
MISC + 喧宾夺主的信号
解题思路
1. 分析流量包
使用 Python 解析 pcap 文件,发现流量包中有两种类型的流量:
1500 个 UDP 数据包:源 IP 192.168.1.100 → 组播地址 239.255.255.250:1900(SSDP)
9 个 TCP 数据包:192.168.1.100 ↔ 45.78.1.1:80
每个 UDP 包携带 28 字节的 base64 编码数据,共 1500 个包(其中 4 个是标记包)。
2. 标记包中的线索
在 UDP 数据包中,第 200、500、800、1100 号数据包(共 4 个)包含相同的 base64 字符串:
U2hlbmdEb25nSmlYaUAzNi0xLTY=
解码后为:
ShengDongJiXi@36-1-6
即成语 “声东击西”(三十六计第6计),暗示这些 UDP 数据包只是佯攻,真正重要的数据在其他地方。
POST /command HTTP/1.1
Host: 45.78.1.1
Content-Type: application/json
Content-Length: 700
{“instruction”: “UEsDBBQAAQA…AAAAAA==”, “note”: “This is the real command.”}
instruction 字段是一个 base64 编码的 ZIP 文件。
4. 解密 ZIP
将 base64 解码后得到一个加密的 ZIP 文件,其中包含 image.png。
使用之前发现的密码 ShengDongJiXi@36-1-6 成功解密 ZIP(注意:Python zipfile 模块对 AES-256 加密的 ZIP 支持有限,需使用 7-Zip 等工具):
7z x encrypted.zip -p"ShengDongJiXi@36-1-6"
提取出一张 100×100 像素的 RGB PNG 图片。
5. PNG 图片隐写分析
检查 PNG 数据,发现图片的 IDAT 块解压后共 30100 字节(每行 301 字节 = 1 字节 filter + 300 字节 RGB 数据)。
关键发现:PNG 使用了行过滤算法(Filter Type 1/Sub、2/Up、4/Paeth),需要先还原过滤才能得到原始的像素值。
图片的 100 行像素中,只有前 3 行包含有效数据,第 4~100 行全黑。
6. 反过滤恢复像素
对前 3 行分别按对应的 filter 类型进行逆运算:
Row 0: Filter 1 (Sub) — raw[x] = filtered[x] + raw[x-1]
Row 1: Filter 4 (Paeth) — raw[x] = filtered[x] + PaethPredictor(…)
Row 2: Filter 4 (Paeth) — raw[x] = filtered[x] + PaethPredictor(…)
恢复后得到 300 个原始像素(3 行 × 100 列)。
7. 提取 LSB
每个像素的 RGB 值都只有两种取值,相差刚好为 1:
通道 值 1 (bit=0) 值 2 (bit=1) R 72 (H) 73 (I) G 108 (l) 109 (m) B 136 137
提取每个通道的 LSB,共 300 × 3 = 900 bits,按 MSB 优先分组为 112 字节,得到 flag。
8. Flag
ISCC{1d3f1c4t10gn_1s_Eth3_k3yl_t0_ivT1ct0ry}
EXP:
(1)
from scapy.all import *
PCAP_PATH = r’C:\Users\ericgao\Desktop\test\ISCC区域\attachment-17.pcapng'
pkts = rdpcap(PCAP_PATH)
udp_pkts = [p for p in pkts if UDP in p]
tcp_pkts = [p for p in pkts if TCP in p]
print(f’总包数: {len(pkts)}')
print(f’UDP 包: {len(udp_pkts)}')
print(f’TCP 包: {len(tcp_pkts)}')
UDP: 目标为 239.255.255.250:1900 的 SSDP 包
print(’\n=== UDP 流量(前 5 包)===')
for pkt in udp_pkts[:5]:
print(f’ {pkt[IP].src}:{pkt[UDP].sport} -> {pkt[IP].dst}:{pkt[UDP].dport}')
TCP: 目标为 45.78.1.1:80 的 C2 通信
print(’\n=== TCP 流量 ===')
for pkt in tcp_pkts:
src = f’{pkt[IP].src}:{pkt[TCP].sport}'
dst = f’{pkt[IP].dst}:{pkt[TCP].dport}'
flags = pkt[TCP].flags
flag_str = []
if flags & 0x02: flag_str.append(‘SYN’)
if flags & 0x10: flag_str.append(‘ACK’)
if flags & 0x08: flag_str.append(‘PSH’)
if flags & 0x01: flag_str.append(‘FIN’)
print(f’ {src} -> {dst} [{",".join(flag_str)}]')
(2)
from scapy.all import *
PCAP_PATH = r’C:\Users\ericgao\Desktop\test\ISCC区域\attachment-17.pcapng'
pkts = rdpcap(PCAP_PATH)
udp_pkts = [p for p in pkts if UDP in p]
tcp_pkts = [p for p in pkts if TCP in p]
print(f’总包数: {len(pkts)}')
print(f’UDP 包: {len(udp_pkts)}')
print(f’TCP 包: {len(tcp_pkts)}')
输出所有 UDP 包内容
print(’\n=== UDP 流量内容 ===')
for i, pkt in enumerate(udp_pkts):
if Raw in pkt:
print(f’[{i}] {bytes(pkt[Raw].load).decode()}')
输出所有 TCP 包内容
print(’\n=== TCP 流量内容 ===')
for i, pkt in enumerate(tcp_pkts):
src = f’{pkt[IP].src}:{pkt[TCP].sport}'
dst = f’{pkt[IP].dst}:{pkt[TCP].dport}'
flags = pkt[TCP].flags
flag_str = []
if flags & 0x02: flag_str.append(‘SYN’)
if flags & 0x10: flag_str.append(‘ACK’)
if flags & 0x08: flag_str.append(‘PSH’)
if flags & 0x01: flag_str.append(‘FIN’)
payload = f’ | {bytes(pkt[Raw].load).decode(errors=“ignore”)}’ if Raw in pkt else ''
print(f’[{i}] {src} -> {dst} [{",".join(flag_str)}]{payload}')
评论