如何通过Python或Wireshark API从pcap文件导出DICOM对象?
从网络数据包提取DICOM文件:Python与Wireshark API实现方案
当然可以!不管是借助Wireshark自带的工具/API,还是用纯Python脚本,都能实现从网络数据包里提取DICOM文件的需求,下面给你详细拆解两种可行方案:
方案一:用Wireshark官方工具/API实现
Wireshark本身提供了命令行工具和脚本API,能直接复用它成熟的DICOM解析逻辑,和GUI里的"导出对象=>DICOM"功能效果一致。
1. 用tshark命令行快速导出(最便捷)
tshark是Wireshark的命令行版本,相当于Wireshark的命令行API,一行命令就能完成导出:
tshark -r 你的数据包文件.pcapng --export-objects dicom,./dicom_output
参数解释:
-r:指定要解析的数据包文件--export-objects:后面跟上协议类型(dicom)和输出目录,工具会自动识别包里的DICOM对象并导出到目标文件夹。
2. 用Lua脚本自定义提取(灵活扩展)
如果需要更定制化的逻辑(比如只提取特定设备发送的DICOM文件),可以用Wireshark的Lua脚本API编写插件:
-- 创建DICOM协议监听器 local dicom_tap = Listener.new("dicom") -- 处理每个DICOM数据包 function dicom_tap.packet(pinfo, tvb) -- 获取DICOM对象的原始数据 local dicom_raw = tvb:raw() -- 生成唯一文件名(用数据包编号区分) local filename = string.format("dicom_pkt_%d.dcm", pinfo.number) -- 写入文件 local file = io.open(filename, "wb") if file then file:write(dicom_raw) file:close() print(string.format("已导出DICOM文件:%s", filename)) end end
把这个脚本保存为extract_dicom.lua,然后在Wireshark中通过工具→Lua控制台加载,或者放到Wireshark的插件目录重启软件,就能自动捕获并提取DICOM文件了。
方案二:用Python实现(脱离Wireshark GUI)
如果想在Python项目中集成提取逻辑,有两种常用方式:借助Wireshark解析引擎的pyshark,或者纯Python解析的scapy。
1. 用pyshark调用Wireshark解析引擎
pyshark封装了Wireshark的底层解析库,能直接复用它的DICOM协议解析能力,无需自己处理TCP分片等问题:
首先安装依赖:
pip install pyshark
然后编写提取脚本:
import pyshark import os # 配置输出目录和输入数据包文件 output_dir = "./extracted_dicom" pcap_file = "你的数据包文件.pcapng" os.makedirs(output_dir, exist_ok=True) # 加载数据包并过滤DICOM流量 cap = pyshark.FileCapture(pcap_file, display_filter="dicom") for idx, pkt in enumerate(cap, start=1): # 检查数据包是否包含DICOM数据 if hasattr(pkt, "dicom"): # 获取DICOM原始二进制数据 dicom_raw = pkt.dicom.get_raw_value() # 保存为.dcm文件 save_path = os.path.join(output_dir, f"dicom_{idx}.dcm") with open(save_path, "wb") as f: f.write(dicom_raw) print(f"已保存:{save_path}") cap.close()
2. 用scapy纯Python解析(无Wireshark依赖)
如果需要完全脱离Wireshark环境,可以用scapy手动解析TCP流并提取DICOM文件(需要自己处理TCP分片重组):
首先安装依赖:
pip install scapy
然后编写脚本:
from scapy.all import rdpcap, TCP, Raw, IP import os output_dir = "./scapy_extracted_dicom" pcap_file = "你的数据包文件.pcapng" os.makedirs(output_dir, exist_ok=True) # 读取数据包并重组TCP流 tcp_streams = {} for pkt in rdpcap(pcap_file): if IP in pkt and TCP in pkt and Raw in pkt: # 用(源IP, 源端口, 目标IP, 目标端口)作为流的唯一标识 stream_key = (pkt[IP].src, pkt[TCP].sport, pkt[IP].dst, pkt[TCP].dport) if stream_key not in tcp_streams: tcp_streams[stream_key] = b"" # 累加TCP载荷数据 tcp_streams[stream_key] += pkt[Raw].load # 遍历每个TCP流,查找并提取DICOM文件 stream_idx = 0 for stream_data in tcp_streams.values(): # DICOM文件的特征:前128字节为预留字段,第129-132字节是"DICM"标记 dicm_marker_pos = stream_data.find(b"DICM") if dicm_marker_pos != -1 and dicm_marker_pos >= 128: # 提取完整的DICOM文件(从预留字段开始到流结束) dicom_file_data = stream_data[dicom_marker_pos - 128:] stream_idx += 1 save_path = os.path.join(output_dir, f"dicom_stream_{stream_idx}.dcm") with open(save_path, "wb") as f: f.write(dicom_file_data) print(f"已提取DICOM文件:{save_path}")
方案选择建议
- 如果只是快速导出DICOM文件,tshark命令行是最省心的选择;
- 如果需要在Wireshark中自定义提取逻辑,Lua脚本更灵活;
- 如果要集成到Python项目中,pyshark能复用Wireshark的成熟解析,适合大多数场景;
- 如果需要完全脱离Wireshark环境,scapy是纯Python的解决方案,但需要自己处理更多底层细节。
内容的提问来源于stack exchange,提问作者Furin
相关产品推荐
相关产品推荐

