Scapy:处理部分 TLS 段

Scapy: Processing partial TLS segments

我正在尝试使用 Scapy 从 pcap 中提取 TLS 元数据。我能够成功解析数据包和单个消息,例如客户端问候、服务器问候等及其字段。当 TLS 记录分布在多个 TCP packets/segments 时,我遇到了麻烦。这主要发生在大型 TLS 消息中,例如应用程序数据,或者当服务器在一个 TLS 帧中发送多个 TLS 消息(服务器问候、证书等)时。在这种情况下,scapy 说它有 TLS/SSLv2 层,但我无法从这些帧中提取任何有意义的信息。当我在 wireshark 中查看相同的 pcap 时,wireshark 显示

Reassembled TCP segments (T bytes): #X (x), #Y(y), #Z(z)

其中 T 是合并总数; X、Y、Z 是帧 ID,x、y、z 是每个帧中占总 T 的字节数。Wireshark 在解析 TLS 帧之前重组整个 TLS 负载。

我的代码中有这样的东西:

if pkt.haslayer(TCP) and pkt.haslayer(TLS):
  parseTLS(pkt)
elif pkt.haslayer(TCP) and pkt.haslayer(SSLv2):
  parseSSLv2(pkt)

当它遇到部分 TLS 数据包时,代码总是会失败到 SSLv2。有没有办法让我准确地将数据包识别为部分 tls 段并累积,然后处理类似于 wireshark 的完整 TLS 帧?如果是这样,我该怎么做。任何指针或帮助表示赞赏。谢谢

不确定是否有更好的解决方案,但这是我为解决问题所做的工作。累积的帧大小似乎与 Wireshark 从多个数据包重组 TLS 帧时所做的一致。

注意:此解决方案假设没有错序的数据包或重复的数据包。此外,此处显示的解决方案并不完整。下面的代码仅展示了当 TLS 帧跨越单个 TCP 流的多个 IP 数据包时如何累积 TLS 帧。请遵循 Janus's 建议(在下面的评论中提到)或想出你自己的解决方案来积累不同的流。

def extractDataFromPcap(pcapfile):
  load_layer("tls")

  try:
    reader = PcapReader(pcapfile)

    # tls frame accumulation related variables.
    tls_accumulate = False
    tls_leftover_len = 0
    tls_blist = list()

    for pkt in reader:
      try:
        if tls_accumulate and pkt.haslayer(TCP):
          ip_tcp_hdr_overhead = ((pkt[IP].ihl*4) + (pkt[TCP].dataofs*4))
          pkt_payload_len = (pkt[IP].len - ip_tcp_hdr_overhead)
          tls_leftover_len = (tls_leftover_len - pkt_payload_len)
          tls_blist.append(raw(pkt[TCP].payload))

          if tls_leftover_len <= 0:
            # got complete TLS frame
            tls_raw_bytes = b''.join(tls_blist)

            # parse accumulated frame.
            tls = TLS(tls_raw_bytes)
            #... process tls object

            # reset accumlation variables.
            tls_accumulate = False
            tls_leftover_len = 0
            tls_blist = list()
          else:
            continue

        if pkt.haslayer(TCP) and pkt.haslayer(TLS):
          if not tls_accumulate:
            # Process new TLS frame.
            # Pkt over head: ip-hdr-len + tcp-hdr-len
            ip_tcp_hdr_overhead = ((pkt[IP].ihl*4) + (pkt[TCP].dataofs*4))
            pkt_payload_len = (pkt[IP].len - ip_tcp_hdr_overhead)
            if pkt[TLS].len > pkt_payload_len:
              # partial TLS frame. Start accumulating.
              tls_accumulate = True
              tls_leftover_len = (pkt[TLS].len - pkt_payload_len)
              tls_blist.append(raw(pkt[TCP].payload))
            else:
              # complete TLS frame
              # ... process complete TLS Frame 
      except Exception as error:
        pkt.show()
        print("tcp-processing error: %s", error)
        sys.exit(-1)

  except Exception as error:
    print("packet processing error: %s", error)
    sys.exit(-1)