使用 Python 解压缩数据包的 gzip 有效负载

Del*_*lta 3 python compression gzip scapy packet

我目前正在开发一个程序,该程序采用 .pcap 文件并使用 scapy 包按 ip 分离出所有数据包。我想解压缩使用 gzip 包压缩的有效负载。我可以判断有效负载是否经过 gzip 压缩,因为它包含

\n\n
Content-Encoding: gzip\n
Run Code Online (Sandbox Code Playgroud)\n\n

我正在尝试使用

\n\n
fileStream = StringIO.StringIO(payload)\ngzipper = gzip.GzipFile(fileobj=fileStream)\ndata = gzipper.read()\n
Run Code Online (Sandbox Code Playgroud)\n\n

解压缩有效负载,其中

\n\n
payload = str(pkt[TCP].payload)\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我尝试这样做时,我收到错误

\n\n
IOError: Not a gzipped file\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我打印第一个有效负载时,我得到

\n\n
HTTP/1.1 200 OK\nCache-Control: private, max-age=0\nContent-Type: text/html; charset=utf-8\nP3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND"\nVary: Accept-Encoding\nContent-Encoding: gzip\nDate: Sat, 30 Mar 2013 19:23:33 GMT\nContent-Length: 15534\nConnection: keep-alive\nSet-Cookie: _FS=NU=1; domain=.bing.com; path=/\nSet-Cookie: _SS=SID=F2652FD33DC443498CE043186458C3FC&C=20.0; domain=.bing.com; path=/\nSet-Cookie: MUID=2961778241736E4F314E732240626EBE; expires=Mon, 30-Mar-2015 19:23:33 GMT; domain=.bing.com; path=/\nSet-Cookie: MUIDB=2961778241736E4F314E732240626EBE; expires=Mon, 30-Mar-2015 19:23:33 GMT; path=/\nSet-Cookie: OrigMUID=2961778241736E4F314E732240626EBE%2c532012b954b64747ae9b83e7ede66522; expires=Mon, 30-Mar-2015 19:23:33 GMT; domain=.bing.com; path=/\nSet-Cookie: SRCHD=D=2758763&MS=2758763&AF=NOFORM; expires=Mon, 30-Mar-2015 19:23:33 GMT; domain=.bing.com; path=/\nSet-Cookie: SRCHUID=V=2&GUID=02F43275DC7F435BB3DF3FD32E181F4D; expires=Mon, 30-Mar-2015 19:23:33 GMT; path=/\nSet-Cookie: SRCHUSR=AUTOREDIR=0&GEOVAR=&DOB=20130330; expires=Mon, 30-Mar-2015 19:23:33 GMT; domain=.bing.com; path=/\n\n?}k{?H????+0?#!?,_???$?:?7vf?w?Hb???\xc6\x8aG???9???/9U?\\$;3{9g?ycA\xd3\x97???????W{?o?~?FZ?e ]>??<??n????\xd7\xbb?????????d?t??a?3?\n?2?p??eBI?e??????\xdc\x92?P??-?Q?-L?????\xc7\xbcR?\xc2\xb3?\xd7\xaf??%\'\n?2Kf?7???c?Y?I?1+c??,ae]?????<{?=\xc6\x9e,?^?J?\xc4\x8f???y??6O?_?z????_?\xde\x9e~?_?????Bo%]???_?????W=?\n
Run Code Online (Sandbox Code Playgroud)\n\n

有关其他信息,这是一个已隔离的数据包,因为它包含来自项目提供的示例 .pcap 文件的 Content-Encoding: gzip。

\n

Luk*_*raf 5

为了解码 gzip 压缩的 HTTP 响应,您只需解码响应正文而不是标头。

在您的情况下payload,是整个 TCP 有效负载,即包括标头和正文的整个 HTTP 消息。

HTTP 消息(请求和响应)是RFC 822消息(与电子邮件消息 (RFC 2822) 所基于的通用消息格式相同)。

822消息的结构非常简单:

  • 零个或多个标题行(由 分隔的键/值对:),以 CRLF 终止
  • 空行(CRLF(回车、换行等'\r\n'
  • 消息正文

您现在可以自己解析此消息以隔离正文。但我宁愿建议你使用Python已经为你提供的工具。该httplib模块 (Python 2.x) 包含内部HTTPMessage用于httplib解析 HTTP 响应的类。它并不意味着直接使用,但在这种情况下我可能仍然会使用它 - 它将为您处理一些 HTTP 特定细节。

以下是如何使用它来将正文与标题分开:

>>> from httplib import HTTPMessage
>>>
>>> f = open('gzipped_response.payload')
>>>
>>> # Or, if you already have the payload in memory as a string:
... # f = StringIO.StringIO(payload)
...
>>> status_line = f.readline()
>>> msg = HTTPMessage(f, 0)
>>> body = msg.fp.read()
Run Code Online (Sandbox Code Playgroud)

该类HTTPMessage的工作方式与以下类似rfc822.Message

  • 首先,您需要读取(或丢弃)状态行 ( HTTP/1.1 200 OK),因为它不是 RFC822 消息的一部分,也不是标头。

  • 然后,您HTTPMessage使用打开文件的句柄进行实例化,并将seekable参数设置为0。文件指针存储为msg.fp

  • 实例化后,它调用msg.readheaders(),读取所有标题行,直到遇到空行 (CRLF)。
  • 此时,msg.fp已经前进到标题结束和正文开始的位置。因此,您可以致电msg.fp.read()阅读消息的其余部分 - 正文。

之后,解压缩 gzip 正文的代码就可以正常工作:

>>> body_stream = StringIO.StringIO(body)
>>> gzipper = gzip.GzipFile(fileobj=body_stream)
>>> data = gzipper.read()
>>>
>>> print data[:25]
<!DOCTYPE html>
<html>
Run Code Online (Sandbox Code Playgroud)