Scapy: обработка частичных сегментов TLS - PullRequest
2 голосов
/ 15 февраля 2020

Я пытаюсь извлечь метаданные TLS из pcap, используя Scapy. Я могу успешно проанализировать пакеты и отдельные сообщения, такие как client-hello, server-hello et c и их поля. У меня проблемы с тем, когда запись TLS распределяется по нескольким пакетам / сегментам TCP. Это происходит в основном для больших сообщений TLS, таких как данные приложения или когда сервер отправляет несколько сообщений TLS (сервер привет, сертификат и т. Д. c) в одном кадре TLS. В таких случаях scapy говорит, что имеет слой TLS / SSLv2, но я не могу извлечь какую-либо значимую информацию из таких фреймов. Когда я смотрю на тот же pcap в wireshark, wireshark отображает

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

, где T - общая сумма; X, Y, Z - это идентификаторы кадров, а x, y, z - количество байтов в каждом кадре, которые внесли вклад в общую T. Wireshark выполняет повторную сборку всей полезной нагрузки TLS, прежде чем анализирует кадр TLS.

I есть что-то вроде этого в моем коде:

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

Когда он встречает частичный пакет TLS, код всегда падает до SSLv2. Есть ли способ для меня, чтобы точно идентифицировать пакет как частичный tls-сегмент и накапливать, а затем обрабатывать полный кадр TLS, похожий на wireshark? Если так, то как я go об этом. Любые указатели или помощь приветствуется. Спасибо.

1 Ответ

2 голосов
/ 18 февраля 2020

Не уверен, что есть лучшее решение, но вот что я сделал, чтобы обойти мою проблему. Кажется, что накопленные размеры фреймов согласуются с тем, что делает Wireshark, когда он собирает фрейм TLS из нескольких пакетов.

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)
...