Wireshark流量分析实战:从网络数据包中提取与还原PNG图像

发布时间:2026/7/16 4:57:19
Wireshark流量分析实战:从网络数据包中提取与还原PNG图像 1. 项目概述从流量包中挖掘隐藏的宝藏在CTFCapture The Flag竞赛或者日常的安全分析工作中我们常常会面对一个看似杂乱无章、充满二进制数据的Wireshark流量包文件。新手可能会感到无从下手但经验告诉我们这些数据流里往往藏着解题的关键线索比如一张被分割、编码甚至加密隐藏起来的PNG图片。这个项目就是一次典型的“数字考古”实战我们拿到一个流量包目标是从海量的网络通信数据中定位、提取并最终还原出一张隐藏的PNG图像。这不仅仅是简单的文件导出更是一个融合了协议分析、数据重组、十六进制Hex解码乃至基础密码学知识的综合挑战。掌握这套技巧你不仅能解决CTF中的特定题型更能深刻理解网络数据在传输过程中的各种形态变换提升你的数字取证和协议分析能力。对于安全研究员、网络工程师或是CTF爱好者来说这都是一项非常实用的核心技能。整个过程就像侦探破案你需要根据蛛丝马迹协议特征、数据流模式、异常编码来还原事件的真相完整的图片文件。接下来我将以一个模拟的实战场景为例带你一步步拆解这个过程中的每一个技术环节、工具使用的心得以及那些容易踩坑的细节。2. 核心思路与前期分析确定搜索方向面对一个几百MB甚至上GB的流量包文件盲目搜索无异于大海捞针。第一步永远不是直接动手而是静下心来进行系统的思路规划和前期分析。2.1 理解PNG文件的结构特征PNGPortable Network Graphics作为一种无损压缩的位图格式有其非常明确的文件结构这是我们进行搜索和识别的“指纹”。文件头签名这是PNG文件的“身份证”固定的8个字节十六进制表示为89 50 4E 47 0D 0A 1A 0A。在ASCII视图下对应的字符是.PNG....注意第一个字节0x89是不可见字符。在任何数据流中一旦发现这连续的8个字节就极有可能是一个PNG文件的开始。数据块Chunk结构PNG文件由一系列的数据块组成。每个块包含四个部分长度Length4字节大端序指明数据域的长度。块类型Chunk Type4字节由ASCII字母组成标识块的用途如IHDR图像头、IDAT图像数据、IEND图像结束。数据域Chunk Data可变长度存储实际数据。循环冗余校验CRC4字节用于校验块数据的完整性。IEND结束块固定的12个字节内容是00 00 00 00 49 45 4E 44 AE 42 60 82。其中IEND是块类型后面是CRC。实操心得在流量分析中完整的文件头签名89 50 4E 47 0D 0A 1A 0A是最可靠的初始定位点。但出题人往往会将其拆分、编码或伪装所以我们需要灵活运用搜索功能并熟悉其各种可能的表现形式。2.2 Wireshark过滤与搜索策略打开Wireshark载入流量包后首要任务是缩小搜索范围。协议过滤如果图片是通过HTTP协议传输的可以尝试过滤http。但注意可能使用的是HTTPS加密的HTTP此时直接过滤http是看不到应用层数据的。你需要关注TLS协议的数据包。如果图片是通过FTP传输的过滤ftp或ftp-data。更通用的方法是先关注数据量较大的TCP流。在Packet List面板的“Length”列排序优先查看那些携带大量数据的包。图片传输通常会产生连续多个长度较大的TCP包。搜索十六进制值这是定位隐藏PNG头的关键操作。在Wireshark中按下CtrlF打开查找对话框。选择“分组字节流”作为搜索范围。选择“十六进制值”作为搜索类型。在输入框中输入PNG文件头的十六进制值89 50 4e 47 0d 0a 1a 0a不区分大小写空格可选。点击查找。如果直接找到那么恭喜你题目比较简单。但更常见的情况是搜不到。这说明文件头可能被修改、编码或拆分了。搜索字符串如果十六进制搜索无果可以尝试搜索字符串。将搜索类型改为“字符串”。尝试搜索PNG注意大小写因为50 4E 47对应的就是这三个字母。这有可能在数据域的某个地方被发现。也可以搜索PNG数据块的类型如IHDR、IDAT、IEND。注意事项Wireshark的搜索功能有时会受到显示过滤器的影响。如果你应用了过滤器搜索可能只在过滤后的数据包中进行。为了全面搜索最好先清除所有显示过滤器点击过滤器输入框右侧的“×”。2.3 关注异常协议与编码如果常规搜索一无所获就要考虑数据是否经过了处理。Base64编码这是最常用的编码方式之一用于在文本协议如HTTP、电子邮件中安全传输二进制数据。Base64编码后的数据特征明显由A-Z, a-z, 0-9, , /以及填充字符组成的一长串字符串。在Wireshark的Packet Details或Packet Bytes面板的ASCII视图下如果你看到这样规整的字符串就要高度怀疑。Hex编码十六进制文本另一种常见编码将每个字节用两个十六进制数字0-9, A-F的文本表示。例如PNG头89 50 4E 47的Hex编码就是字符串89504E47或89 50 4e 47。在流量中如果看到大量连续的、成对的十六进制数字字符可能就是Hex编码的数据。异或XOR加密在CTF中简单的单字节或多字节异或加密也很常见。加密后的数据会失去原有特征PNG头签名会变成一堆乱码。你需要通过分析流量上下文比如是否有密钥交换过程或尝试常见的异或密钥如0xAA, 0xFF等来破解。数据分割与重组PNG文件可能被分割成多个TCP包甚至被故意打乱顺序。你需要通过TCP的序列号Sequence Number和确认号Acknowledgment Number来跟踪一个完整的数据流TCP Stream。3. 实战操作定位、提取与重组数据假设我们通过搜索在某个TCP流中发现了疑似经过Base64编码的PNG数据。接下来进入实战操作环节。3.1 跟踪TCP流并提取原始数据定位到包含可疑数据的TCP包在Packet List中右键点击该数据包。选择“追踪流” - “TCP流”。这会弹出一个新窗口显示这个TCP连接中所有双向的数据。在TCP流窗口的底部你会看到数据以ASCII、十六进制、C数组等多种格式显示。关键步骤来了你需要将显示格式切换到“原始数据”Raw。这样你看到的就是最原始的、未经Wireshark任何渲染的字节序列。仔细浏览这个“原始数据”视图。你的目标是从中精准地复制出那段经过编码的数据。它可能是一整段Base64字符串也可能是一段Hex文本。Base64特征以结尾或由64个字符组成的连续字符串没有空格或换行但出题人有时会加入换行。Hex特征由0-9和a-f/A-F组成的连续字符串可能带空格也可能不带。避坑技巧复制数据时务必小心。不要多复制一个空格或换行符也不要少复制一个字符。对于Base64开头的data:image/png;base64,这类前缀需要去掉只复制真正的Base64编码部分。一个验证方法是复制的Base64字符串长度应该是4的倍数因为Base64将3个字节编码为4个字符。3.2 解码与文件还原提取出编码后的字符串后我们需要将其解码还原成原始的二进制数据也就是PNG文件。方法一使用Linux/Unix命令行工具推荐高效精准假设你复制出的Base64字符串保存在一个文本文件encoded.txt中。# 1. 去除可能存在的换行符如果复制时带了 tr -d \n encoded.txt encoded_no_newline.txt # 2. 进行Base64解码并输出为PNG文件 base64 -d encoded_no_newline.txt recovered.png如果数据是Hex编码例如字符串89504E47...保存到hex.txt。# 使用 xxd 工具将Hex文本反转回二进制 # -r 表示反转-p 表示处理纯连续的十六进制字符串无空格分隔 xxd -r -p hex.txt recovered.png方法二使用Python脚本灵活可处理复杂情况创建一个Python脚本decode.pyimport base64 import codecs import sys def decode_base64(input_file, output_file): with open(input_file, r) as f: data f.read().replace(\n, ).replace( , ) # 清理空格和换行 # 尝试解码 try: decoded_data base64.b64decode(data) with open(output_file, wb) as f: # 注意是wb写入二进制 f.write(decoded_data) print(f[] Base64解码成功文件已保存为 {output_file}) except Exception as e: print(f[-] Base64解码失败: {e}) def decode_hex(input_file, output_file): with open(input_file, r) as f: hex_string f.read().strip().replace( , ).replace(\n, ) # 确保是有效的十六进制字符串 if not all(c in 0123456789abcdefABCDEF for c in hex_string): print([-] 输入不是有效的十六进制字符串) return try: decoded_data codecs.decode(hex_string, hex) with open(output_file, wb) as f: f.write(decoded_data) print(f[] Hex解码成功文件已保存为 {output_file}) except Exception as e: print(f[-] Hex解码失败: {e}) if __name__ __main__: if len(sys.argv) 4: print(用法: python decode.py input_file output_file mode: base64|hex) sys.exit(1) input_file sys.argv[1] output_file sys.argv[2] mode sys.argv[3].lower() if mode base64: decode_base64(input_file, output_file) elif mode hex: decode_hex(input_file, output_file) else: print([-] 模式错误请选择 base64 或 hex)使用方式python decode.py encoded.txt output.png base64 python decode.py hex.txt output.png hex方法三使用在线工具或Hex编辑器快速验证对于快速检查可以使用在线的Base64或Hex解码工具。但强烈不建议在CTF比赛或处理敏感数据时使用不明在线工具存在数据泄露风险。本地的Hex编辑器如010 Editor、WinHex或HxD也提供强大的编码解码和二进制编辑功能。实操心得解码后得到的recovered.png文件先用file命令检查一下file recovered.png如果输出PNG image data, ...说明解码基本成功。如果输出data或其他信息说明文件可能仍不完整或还需进一步处理如修复文件头、去除多余数据。3.3 处理“脏数据”与文件修复很多时候从流量中提取的数据并不“干净”可能夹杂着协议头、尾或其他无关数据。你需要手动修复。使用Hex编辑器进行手术用010 Editor或HxD打开你解码得到的文件。检查文件头看最开始的8个字节是不是89 50 4E 47 0D 0A 1A 0A。如果不是你需要手动修正。也许出题人只是修改了其中一个字节例如把第一个字节89改成了88你需要根据PNG规范改回来。检查文件尾滚动到文件末尾看最后12个字节是不是00 00 00 00 49 45 4E 44 AE 42 60 82。如果不是可能数据被截断或附加了其他内容。你可以尝试补全IEND块。去除多余数据如果数据中间夹杂了明显的非PNG数据块例如在Hex视图中看到一段规律的、非图像数据的ASCII字符串你需要精确地选中并删除这些部分。这需要对PNG数据块结构有一定了解确保不破坏IDAT数据块。使用pngcheck工具诊断这是一个非常棒的工具可以详细检查PNG文件的完整性。pngcheck -v recovered.png它会告诉你文件哪里出了问题比如“CRC error”、“invalid chunk length”等根据提示去Hex编辑器中定位修复。4. 进阶技巧与深度分析当基础方法失效时就需要动用一些更高级的分析手段。4.1 分析数据流模式与协议交互回到Wireshark仔细分析包含可疑数据的TCP流前后的通信内容。寻找“线索”包在传输“加密”或“编码”数据之前客户端和服务器之间是否有过特殊的通信例如是否发送过一个看似随机的字符串可能是密钥是否有特殊的命令如“ENCRYPT”、“XOR 0xAA”分析应用层协议如果使用的是自定义协议或非标准端口尝试理解其报文结构。也许第一个4字节是数据长度后面跟着类型再后面是载荷。你需要根据这种结构手动从TCP流中分割出一个个完整的“消息”。关注文件传输的完整性通过统计一个TCP流中所有应用层数据包的长度总和你可以估算出传输文件的大致大小。如果这个大小和你解码后得到的文件大小相差甚远说明你可能漏掉了一些包或者数据被分散在多个TCP流中。4.2 尝试常见的加密与编码变换如果数据看起来是乱码且排除了Base64和Hex可以尝试简单的密码学攻击。单字节XOR爆破这是CTF中最常见的简单加密。原理是一个字节0-255与明文的所有字节进行异或。你可以写一个简单的Python脚本用0到255的所有值作为密钥去尝试解密数据然后观察输出中是否出现了可读的字符串或PNG签名。import sys data open(encrypted.bin, rb).read() for key in range(256): decrypted bytes([b ^ key for b in data]) if bPNG in decrypted[:100]: # 检查解密后的数据头部是否包含PNG特征 print(fPotential key found: {key} (0x{key:02x})) with open(fdecrypted_key_{key}.png, wb) as f: f.write(decrypted)多位循环XOR密钥是多个字节循环使用。例如密钥是SECRET那么明文的第1、7、13...字节与S异或第2、8、14...字节与E异或以此类推。破解这个需要更多上下文来猜测密钥长度和内容。其他编码如URL编码%89%50%4E%47、HTML实体编码等但这些在网络流量中作为图片传输载体的情况相对较少。4.3 利用Wireshark的导出对象功能对于标准的HTTP协议传输的文件Wireshark提供了一个非常便捷的功能“导出对象”。应用显示过滤器http。点击菜单栏的“文件” - “导出对象” - “HTTP”。在弹出的列表中Wireshark会列出所有它识别出的通过HTTP传输的文件。你可以按照内容类型Content-Type排序寻找image/png。选中它点击“保存”即可直接导出原始的PNG文件。注意事项这个功能只对未加密的HTTP协议有效。如果流量是HTTPSTLS加密或者使用了非HTTP协议此功能将无法直接使用。此时就需要回到我们前面讲的手动提取和解码流程。5. 常见问题排查与解决实录在实际操作中你一定会遇到各种奇怪的问题。下面是我总结的一些典型场景和解决方案。问题现象可能原因排查步骤与解决方案file命令显示data文件头不正确或文件不完整。1. 用Hex编辑器检查文件头8字节。2. 用pngcheck -v查看详细错误。3. 检查从Wireshark复制的数据是否完整是否包含了多余的空格、换行或协议头。pngcheck报CRC错误数据块在传输或提取过程中被篡改或者加密/编码未完全还原。1. 确认解码过程无误。2. 在Hex编辑器中找到报错的数据块根据其长度和数据域重新计算CRC并修正。可以使用pngcheck -f尝试修复但手动修复更可靠。图片能打开但显示不全或花屏IDAT数据块可能损坏、顺序错乱或被截断。1. 确认提取的TCP流是否完整是否漏掉了最后一个包。2. 检查PNG的IHDR块中的宽高信息是否合理。3. 尝试用图像处理软件如GIMP的“打开为”功能有时能忽略错误强制打开。Wireshark搜索不到PNG头1. 头被修改。2. 数据被编码如Base64。3. 数据被加密如XOR。4. 数据被压缩。1. 尝试搜索PNG字符串。2. 搜索IHDR。3. 在Packet Bytes面板的ASCII视图下寻找大段的Base64特征字符串。4. 分析TCP流看是否有规律的可打印字符。Base64解码失败Incorrect paddingBase64字符串长度不是4的倍数或包含了非法字符。1. 检查并去除所有换行符和空格。2. 确保没有包含data:image/png;base64,这样的前缀。3. 如果字符串末尾的填充不正确可以尝试补上或去掉一个再试。Python的base64.b64decode函数有validateFalse参数可以尝试但不推荐。从TCP流复制数据后无法解码复制时包含了非数据部分如TCP/IP头信息或者复制格式不对。关键步骤在Wireshark的“追踪TCP流”窗口中务必将显示格式切换到“原始数据”Raw然后只选中并复制那一段连续的编码数据Base64串或Hex串。绝对不要用“ASCII”、“十六进制转储”等格式复制。怀疑是XOR加密但不知道密钥密钥未知。1. 尝试单字节爆破脚本如上。2. 如果数据足够长可以尝试频率分析但针对PNG这种非文本文件效果有限。3.最有效的方法在流量包中寻找密钥交换的过程。仔细查看可疑TCP流之前的所有通信特别是客户端发送的短字符串、登录凭证等它们可能就是密钥。个人经验之谈在CTF中这类题目往往不是考察最复杂的密码学而是考察你的细心和综合能力。80%的问题都出在数据提取不干净和解码步骤错误上。养成好习惯1) 始终用“原始数据”视图复制2) 解码前先用cat -ALinux或记事本查看复制的内容确认没有隐藏字符3) 每完成一步都用file或pngcheck验证一下结果。另一个重要的心态是不要只盯着一个TCP流。有时数据被故意分散在多个连接中你需要把几个流的数据按顺序拼接起来。Wireshark的“端点”Endpoints和“对话”Conversations统计视图可以帮助你快速理清主机之间的所有通信关系。