.pcap大有可玩
简易流量分析

.pcap文件结构

.pcap文件是常用的数据报存储形式,不是简单的文本文件,是具有特定结构的二进制文件。

.pcap/.cap文件结构如下:

简易流量分析_数据

Pcap Header

文件头,具有24个字节,而文件头又分成7个部分。

字段 意义
Magic(4字节) 标记文件开始,并用以识别文件和字节顺序。若值为0xa1b2c3d4,表示大端存储模式,依序读取;若值为0xd4c3b2a1,表示小端存储模式,每个存储单元都是从低地址读取至高地址。现行的计算机设计以小端存储模式居多。
Major(2字节) 当前文件的主要版本号,一般为0x0200
Minor(2字节) 当前文件的次要版本号,一般为0x0400
ThisZone(4字节) 当地标准时间,如果使用GMT(格林威治标准时间)则全为0;一般全为0。
SigFigs(4字节) 时间戳经度,一般全为0。
SnapLen(4字节) 最大存储长度,设置所抓取数据包的最大长度。如果所有数据包都需要抓取,将值设定为65535。
LinkType(4字节) 链路类型。解析数据包首先需要判断其链路类型,一般值为1,即以太网。

常用的LinkType(链路类型)如下:

  • 0: BSD loopback devices, except for later OpenBSD
  • 1: Ethernet, and Linux loopback devices
  • 6: 802.5 Token Ring
  • 7: ARCnet
  • 8: SLIP
  • 9: PPP
  • 10: FDDI
  • 100: LLC/SNAP-encapsulated ATM
  • 101: “raw IP”, with no link
  • 102: BSD/OS SLIP
  • 103: BSD/OS PPP
  • 104: Cisco HDLC
  • 105: 802.11
  • 108: later OpenBSD loopback devices (with the AF_value in network byte order)
  • 113: special Linux “cooked” capture
  • 114: LocalTalk

Packet Header

数据包头,具有16个字节,每个数据包头后面都是真正的数据包。数据包头分为4个部分。

字段 意义
Timestamp(4字节) 时间戳高位,精确到秒(seconds),为Unix时间戳。捕获数据包的时间一般以该值为根据。
Timestamp(4字节) 时间戳低位,可以精确到微秒(microseconds)。
Caplen(4字节) 当前数据区的长度,即抓取数据帧的长度,由此可以得到下一数据帧的位置。
Len(4字节) 离线数据长度,网路中实际的数据帧长度,一般不大于Caplen。多数情况下与Caplen值一致。

Packet Data

链路层中的数据帧,长度为在Packet Header中定义的Caplen,即.pcap文件并没有规定抓取的数据帧之间需要间隔字符串。数据帧部分的内容格式为标准的网络协议格式。

开始试验

以下操作基于文件aim.pcap,目标是提取其中的flag。

打印基本信息:

from scapy.all import *


if __name__ == '__main__':
    pcap = rdpcap('./aim.pcap')
    print(pcap)

可以看到结果<aim.pcap: TCP:1088 UDP:87 ICMP:0 Other:5>

打印pcap对象信息:

print(type(pcap))

可得pcap即为scapy库所定义的包列表。

对pcap迭代:

for item in pcap:
        print(repr(item))
        # 或者 print(item.show())

可以看到包信息:

简易流量分析_linux_02

信息筛查

提取HTTP项:

for item in pcap:
    if('TCP' in item) and (item['TCP'].fields['dport']==80):
        print(repr(item))

通过筛选打印出的包体信息,发现对flag的访问目标IP为192.168.0.123,所以再增加筛选条件:

for item in pcap:
    if('TCP' in item) and (item['TCP'].fields['dport']==80) and (item['IP'].fields['dst']='192.168.0.123'):
    	print(repr(item))

至此得到所有关于访问flag的请求包信息(为GET类型)。

将响应信息也打印出来:

for item in pcap:
        if ("TCP" in item) and ("IP" in item):
            src = item['IP'].fields['src']
            dst = item["IP"].fields['dst']
            sport = item['TCP'].fields['sport']
            dport = item['TCP'].fields['dport']
            if (src=='192.168.0.123' and sport==80) or (dst=='192.168.0.123' and dport==80):
                print(repr(item))

简易流量分析_linux_03

在这些信息中就能找到对flag文件成功访问的请求:

请求 响应 内容
/ 200 Hello World
/favicon.ico 404  
/flag 404  
/flag/5 200 None
/flag/2 200 -
/flag/1 200 flag
/flag/4 200 ULRGB}
/flag/3 200 {YKLTG
/flag/100 200 None

得出结果

按照数字顺序拼接,可以得到flag值,即flag-{YKLTGULRGB}。