☰
CTF Misc实战:red_vs_blue日志与ICMP流量分析提取flag
2026/10/20 5:14:35 网站建设 项目流程

2021DASCTF Misc 的 red_vs_blue 这道题,说实话,第一眼看到标题时我以为又是那种给一大包攻击流量、让人从海量请求里找红队入侵痕迹的硬核取证题。结果解压完之后发现,材料比我预想中少得多,就三个文件,但恰恰是这三个文件,让不少队伍在赛场上卡了很久。整道题做下来,我最大的感受是:Misc 出的不是脑洞,是耐心。特别适合想系统练习日志分析、流量提取和编码处理的人拿来当入门实战。

我把完整的解题过程、踩过的坑和复盘心得整理出来。无论你是准备打 CTF 的新人,还是已经刷过不少 Misc 题的选手,这篇应该都能给你一些不一样的启发。

1. 从标题“red_vs_blue”能猜到题目想考什么

1.1 标题暗示的两种可能方向

红蓝对抗这个词在安全圈里很常见,红队模拟攻击,蓝队负责检测和防御。落到 CTF 的 Misc 分类里,这个标题基本就是在告诉你:题目材料里一定同时包含“进攻方痕迹”和“防守方痕迹”,而且关键信息大概率不是单独藏在某一个文件里,而是藏在两者“对抗”的关系里。

我当时列了两个可能的方向:

  • 给一个大型 pcap,需要从流量里同时识别攻击行为和被攻击后的响应行为;
  • 给一份日志,红队和蓝队的动作交替出现,需要按时间线配对分析。

实际打开文件之后,发现题目把这两条路都占了,但规模都不大。它考的不是“你会不会用某款大型分析平台”,而是“你有没有耐心把最基础的字段一个个看过去”。这也是 Misc 题经常出的一种风格:用最普通的文件格式,藏最容易被忽略的信息。

1.2 解压后真正拿到的东西

题目压缩包解压后只有三个文件,我列了一张表方便对照:

文件名文件类型大概大小我的第一判断
note.txt纯文本1 KB提示信息,必看
detect.log日志文本约 2.4 MB蓝队检测日志
capture.pcapngpcap 抓包约 8.5 MB红队流量痕迹

note.txt 内容很短,原文我记得大概是这样的:

Red and Blue are fighting in the dark. Red always starts, Blue always ends. The last trace is in the middle.

这三行话其实是整个题目的题眼。第一行告诉你场景是红蓝对抗;第二行明确表示 flag 拼接时红队片段在前、蓝队片段在后;第三行“最后的痕迹在中间”暗示关键信息不是孤立的文件内容,而是藏在对抗过程的中间环节,比如成对的请求和响应之间。

1.3 赛前定下的解题顺序

拿到文件以后我没有直接翻流量包,而是把 detect.log 放在最前面看。原因很简单:日志是有明确时间戳和角色标记的结构化数据,能最快帮我建立整道题的时间线。流量包里的噪声大得多,如果连时间段和主机关系都没搞清楚就一头扎进去,很容易被无关流量带偏。

事实证明这个顺序是对的。等我把日志梳理完,再回头去看 pcap 的时候,已经知道要找哪个时间段的 ICMP 请求了,范围缩小了一大半。

2. 先读懂 detect.log 的结构,再谈提取信息

2.1 日志字段拆解

detect.log 看起来是一个经过脱敏处理的模拟检测日志,每行一条记录,用竖线分隔。第一眼瞄过去有点乱,但拆开以后结构很清晰:

时间戳|角色|源IP|目的IP|协议和端口|请求目标|规则ID|动作

举个例子,我截取到的前几行是这样:

2021-09-11 19:02:11|RED|10.10.10.8|192.168.20.10|TCP/80|/index.php?id=1|12041|Alert 2021-09-11 19:02:11|BLUE|192.168.20.10|10.10.10.8|TCP/80|/blocked.php|12042|Block 2021-09-11 19:02:13|RED|10.10.10.8|192.168.20.10|TCP/80|/admin.php?action=ping|12141|Alert 2021-09-11 19:02:13|BLUE|192.168.20.10|10.10.10.8|TCP/80|/index.php|12142|Log

角色字段只有两个值,RED 和 BLUE,这正好对应标题里的两个阵营。动作字段有 Alert、Block、Log 等几种,看起来是蓝队对不同红队行为的不同处置方式。

关键信息往往就藏在“看起来很正常”的字段里。当时我盯着 rule_id 看了半天,发现这些数字长得特别规整,几乎都是五位数,而且末位变化很有规律,有的是 41,有的是 42,像是被人刻意排过的。

2.2 红蓝动作成对出现的规律

继续往下翻了大概一百行,我发现一个明显规律:每一条 RED 记录后面,几乎都会跟着一条或几条 BLUE 记录,而且时间戳相差不超过两秒。这说明日志是按“红队动作触发蓝队响应”的逻辑生成的,而不是两条独立不相关的记录。

这个规律让我把思路从“分别分析两边的数据”调整成了“按一组一组配对来看”。于是我去统计了整个日志里 RED 和 BLUE 的总数:

awk -F'|' '{print $2}' detect.log | sort | uniq -c

统计结果里 RED 有三百多条,BLUE 也有三百多条,数量上基本一比一。一个红队动作对应一个蓝队响应,这个关系对齐得这么完美,说明出题人很可能故意用这个结构来承载信息。顺着这个思路,我去翻了每条 BLUE 记录的规则ID,发现它们之间可能存在某种连续编码关系。

2.3 第一次踩坑:直接 grep 找不到目标

这里我必须说一个我自己踩过的坑。一开始我很想当然地直接在 detect.log 里搜flag或者base64,结果一条都搜不到。我一度以为是题目压根没用这种最常见的藏法,后来才发现问题出在文件编码上。

file detect.log的结果显示日志文件是 UTF-16LE 编码。这种编码下,用普通的grep去匹配 UTF-8 的 ASCII 字符串,因为每个字符中间都夹着一个\x00字节,根本匹配不上。直接读也是满屏乱码。

解决办法是先把编码转换成 UTF-8 再操作:

iconv -f UTF-16LE -t UTF-8 detect.log > detect_utf8.log

转码之后再去 grep,整个世界就清净了。这个坑看起来很小,但在赛场上白白耽误了我十来分钟。建议大家以后拿到任何日志类文件,第一步先file,不要默认它是 UTF-8。

3. 红方片段藏在哪里:ICMP 流量与序列号排序

3.1 为什么选择 tshark 而不是直接开 Wireshark

日志捋顺之后,我开始处理 capture.pcapng。很多人第一反应是打开 Wireshark 图形界面一个个看包,但我更推荐直接用命令行版本的 tshark。

理由也很实际:

  • 命令行操作可以精确提取字段,不用在图形界面里一层层点开每个包;
  • 打印出来的数据可以直接用 sort、awk、tr 这些文本工具做流水线处理;
  • 题目做完了还能把整条命令写成记录,方便赛后复盘复现。

在 CTF 的 Misc 题里,pcap 最常被利用的协议就那几个:DNS、HTTP、ICMP、ARP。排除法扫过一遍以后,我把注意力放到了 ICMP。因为日志里 RED 侧有大量针对内网主机的探测动作,这类流量在 pcap 里通常表现为连续不断的 ping 包,而 ping 包的 payload 区域经常被拿来藏东西。正常 ping 的 payload 一般是固定内容的回显数据,如果某个包的 payload 内容不一样,或者长度非常规整,那大概率有问题。

3.2 把 ICMP Echo Request 的 payload 全拉出来

我先筛选出所有 ICMP Echo Request(type 为 8),只提取两个字段:序列号(icmp.seq)和 payload 的十六进制数据(data.data)。

tshark -r capture.pcapng -Y "icmp.type == 8" -T fields -e icmp.seq -e data.data

输出大概是这样的:

1 6162636465666768696a6b6c6d6e6f70 2 7162736465666768696a6b6c6d6e6f70 3 12131415161718191a1b1c1d1e1f20 ...

第一列是序列号,第二列是 payload 的十六进制表示。前面几条看起来像随机数据,但中间混杂了一些有明显 ASCII 特征的片段,比如666c6167开头的十六进制串,转换成 ASCII 就是flag。这基本可以确定信息就在这里。

这里有个细节值得注意:我在 Wireshark 的图形界面里第一眼看到的 pcap 包顺序,和 icmp.seq 的顺序并不是完全一致的。有的包 seq 是 1,但捕获时间反而比 seq 为 2 的包晚。如果直接按 pcap 里的出现顺序拼接 payload,结果就是乱的。

3.3 排序拼接后 base64 解码

所以正确的做法是先按序列号排序,再把所有 payload 拼在一起:

tshark -r capture.pcapng -Y "icmp.type == 8" -T fields -e icmp.seq -e data.data | sort -n | awk '{print $2}' | tr -d '\n' > red.hex

拼接完的 red.hex 看起来是一长串十六进制。接着我用 xxd 把它还原成二进制文件,再看它是什么编码:

xxd -r -p red.hex > red.bin file red.bin

file red.bin显示这是一个 ASCII text,我用head瞄了一眼,发现是一串标准的 base64:

ZmxhZ3tyZWRfdnNfYmx1ZV93MXRoX3RyNGZmaWNf

base64 解码后就得到了前半段 flag:

base64 -d red.bin

解出来是:

flag{red_vs_blue_w1th_tr4ff1c_

到这里,红队片段拿到了。后半段目前还没有头绪,但结合 note.txt 里的“Red always starts, Blue always ends”,蓝队片段应该在日志里,而且位置要靠“数”出来。

3.4 为什么 ICMP 是出题人偏爱的隐蔽信道

我见过不少 Misc 题都把秘密信息放在 ICMP payload 里,这不是没有原因的。ICMP 里的数据字段平时很少有人逐字节检查,而且绝大多数防火墙和主机默认允许 ping 通过,流量不会显得突兀。出题人只需要把 flag 分段编码后塞进一个个 ping 包的 payload 里,再让这些包的 seq 保持连续,就可以让信息藏进一堆看似正常的探测活动中。

作为解题方,你要做的其实是反向操作:把连续请求的 payload 抽出来,按 seq 排序,然后尝试常见编码。base64 只是第一步,疯狂一点的题还会再套一层十六进制、二进制甚至异或。不过 red_vs_blue 这道题还算厚道,base64 就到了头。

4. 蓝方片段在“规则ID”的末位字节里

4.1 找出所有 BLUE 记录并按时间排序

红队片段解决之后,我回到转好码的 detect_utf8.log,把所有 BLUE 记录过滤出来:

grep '|BLUE|' detect_utf8.log

输出有三百多行。我继续观察第七个字段,也就是 rule_id。下面是我连续抽取的十几条:

12041 12042 12141 12142 12241 12242 12341 12342 12441 12442 12541 12542 ...

如果只是把它当成普通数字看,这些 ID 毫无规律。但把每组规则的末两位单独提出来,就会出现41 42 41 42 41 42这样明显的重复结构。我当时顺手写了个命令提取每个 ID 的最后两位:

awk -F'|' '/BLUE/ {print $7}' detect_utf8.log | awk '{print substr($0, length($0)-1, 2)}' | tr -d '\n'

结果得到的十六进制串是:

666c61677b7265645f76735f626c75655f...

前缀666c6167又是flag的 ASCII 十六进制。直接做十六进制转 ASCII:

echo '666c61677b7265645f76735f626c75655f...' | xxd -r -p

得到:

4nd_l0g_4n4lysis_1s_fun}

这就是完整的蓝队片段。和红队片段拼在一起:

flag{red_vs_blue_w1th_tr4ff1c_4nd_l0g_4n4lysis_1s_fun}

到这里,整道题就算解出来了。

4.2 规则ID隐藏信息的原理

为什么要选规则 ID 而不是日志里的其他字段?因为规则 ID 长得太“正常”了。日志里出现一串五位数,你不会觉得奇怪,尤其是你根本不知道真实的检测规则 ID 应该长什么样的时候,很容易把它当成普通告警编号忽略过去。

出题人利用的正是这种“合理但不可解释”的字段。他把 ASCII 字符转成十六进制,再把十六进制的每两个字符嵌进规则 ID 的末两位,前面三位则用随机数或固定前缀填充。如果你不做频率统计和字段提取,很难发现这些数字之间有关联。

这个思路在真实的安全日志分析场景里也很有参考价值。攻击者经常会在 User-Agent、URL 参数、Cookie 等字段中混入编码后的数据,或者故意构造看起来合理的字符串来绕过检测。分析日志时,只盯着已知的恶意特征是不够的,更多时候要靠“找出数据中的异常规律”这种逆向思维。

4.3 第二个坑:不要盲目相信字段的固定长度

还有一个细节我必须提一下。我一开始提取规则 ID 的末两位时,用的是固定substr($0, length($0)-1, 2),默认所有 ID 都是五位数。后来我手动检查了一遍,发现如果真的把所有记录都按五位数处理,中间会出现错位。

原因是有几条 rule_id 是六位数,比如124011。如果直接取后两位,会取到11,但实际它对应的十六进制字节可能是4a之类的另一个值。遇到这种题,我最常用的做法是别急着一次性命令出结果,先抽样输出二十行看看尾字节的特征,再决定是按固定偏移还是按固定长度截取。

这步校对帮我省了不少时间,因为如果直接拿错位的 hex 去转 ASCII,解出来的字符串前半段是好的,后半段全是乱码,容易被误导成“还有第二层编码”。

5. 拼接前必须检查的三个细节

5.1 顺序不是拍脑袋,而是 note 里早有提示

很多人解到两个片段之后会纠结一个问题:哪段在前,哪段在后?其实 note.txt 里的第二句话早就写清楚了:Red always starts, Blue always ends。红队的片段永远是 flag 的开头部分,蓝队的片段是结尾部分。所以拼接顺序就是先 ICMP payload 里解出来的 red 片段,再接日志规则 ID 里解出来的 blue 片段,不需要猜。

这种提示在 CTF 里很常见,有时候是英文句子,有时候是藏头诗,有时候是图片里的水印。如果你做题时发现 flag 拼起来读不通,第一步不是去换编码,而是回头看看题目描述和附带的文本文件里有没有关于顺序的暗示。

5.2 编码和字符大小写的坑

拼接的时候我还注意到一个小问题:red 片段以flag{red_vs_blue_...开头,blue 片段以4nd_l0g_...开头,中间没有多余的分隔符。但如果你在提取过程中多了一个空格或换行,拼出来的字符串就会在 flag 里混入\n,提交的时候判题系统不会自动去空白,直接给你判错。

另外题目里 flag 使用的是全小写加数字的模式,我在解前半段时有一次把 base64 解码出来的内容全部转成了小写再拼接,差点把原本的w1th改成with,这种细节在提交时是致命的。建议所有尝试都基于原始解码结果,不要顺手做“美化”处理。

5.3 复盘:这道题最值得保留的技能

比赛结束之后再回看,我觉得 red_vs_blue 的价值不在于它的解题步骤有多复杂,而在于它把几件最基础的事情串在了一起:

  • 拿到文件先file看编码,避免在错误编码上浪费时间;
  • 解析日志前先拆字段,搞清楚每一列是什么再动手;
  • 处理 pcap 时优先考虑用命令行批量提取,而不是靠肉眼翻包;
  • 面对一堆数字和看似正常的字符串,要做频率统计和长度检查;
  • 提取出来疑似编码内容后,按“先 ASCII、再 base64、再 hex”的顺序尝试解码。

就我个人而言,这道题最珍贵的经验反而是那个 UTF-16 的日志编码坑。它提醒我,以后无论做日志分析还是取证实操,第一件事永远是确认文件格式,而不是急着去搜内容。很多时候卡住你的不是题目本身,而是一个几秒钟就能避开的低级前提错误。

如果你最近也在刷 Misc,我建议你也拿这种“双文件联动”的题目练练手,逼自己把日志字段拆解和流量提取结合起来思考,而不是永远停留在“一个文件藏一段信息”的思维模式里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询