当我在pcap文件上执行以下Python代码时:
if tcp.dport == 80:
try:
http=dpkt.http.Request(tcp.data)
except (dpkt.dpkt.NeedData):
continue
except (dpkt.dpkt.UnpackError):
continue
if http.method == 'POST':
print('POST Message')
这些是单个HTTP Post消息,分为两个TCP段,每个消息都在不同的数据包中发送。但是,由于第一个段仅是TCP,第二个段被识别为HTTP,因此当dpkt.http.Request尝试将第一个段读取为HTTP时,它将失败。
到目前为止没有问题。可以失败,因为它实际上不是完整的HTTP消息。但是,问题是它似乎根本没有读取第二段(“ POST消息”未打印)!第二段完全被忽略,好像它不存在一样!!!唯一可能的解释是dpkt会自动读取第二个段,因为它识别到它们都是同一条消息的段。
问题是,尽管同时读取了两个TCP段(按照上述假设),但生成的tcp.data不能识别为HTTP数据包,而是仅将其识别为TCP,因为消息是仅TCP数据包。
那我该怎么做才能读取此类pcap文件的HTTP标头和数据?
答案 0 :(得分:1)
dpkt
仅在数据包级别起作用。 dpkt.http.Request
希望完整的HTTP请求作为输入,而不仅仅是当前数据包中的部分。这意味着您必须从属于该连接的所有数据包中收集输入,即重新组装TCP数据流。
重新组装不仅是将数据包串联起来,而且还要确保没有丢失的数据包,没有重复的数据,并确保以正确的顺序重新组装数据包,而这可能不是线路上的顺序。本质上,您需要先完成OS内核将要执行的所有操作,然后再将提取的有效负载放入套接字缓冲区。
有关如何完成部分操作的示例,请参见Follow HTTP Stream (with decompression)。请注意,此处的示例盲目地假设数据包已经井然有序,完整且没有重复-并在现实生活中无法保证。
答案 1 :(得分:0)
也许有点晚。 @steffen Ullrich提出的观点是正确的。但是,假设您没有这些问题(即没有丢失,重复的pkts等),则可以像我重新组装散布在多个TLS数据包中的TLS框架一样进行一些基本的重组。您可以将类似的逻辑应用于HTTP通信。您可以在我发布的SO question中找到与TLS框架重组相关的类似问题的解决方案。顺便说一句,在我的解决方案中,我正在使用Scapy。
答案 2 :(得分:0)
或者您可以使用Scapy 2.4.3+中的内置功能 https://scapy.readthedocs.io/en/latest/layers/http.html
sniff(session=TCPSession, [...])