Search code examples
python-3.xsslscapy

Cannot read tls section even after calling load_layer('tls') in scapy


This question explains how to read the TLS section of a packet using scapy.

However, my program is not able to read it. All it returns is a bunch of hexadecimal characters

>>> from scapy.all import *
>>> load_layer('tls')
>>> cap = rdpcap('tls.pcap')
>>> p1=cap[0]
>>> p1
<Ether  dst=14:cc:20:51:33:ea src=f4:f2:6d:93:51:f1 type=0x800 |<IP  version=4 ihl=5 tos=0x0 len=146 id=62970 flags=DF frag=0 ttl=64 proto=tcp chksum=0x50a0 src=192.168.1.143 dst=54.254.250.149 |<TCP  sport=49335 dport=50443 seq=549695462 ack=200962336 dataofs=5 reserved=0 flags=PA window=4380 chksum=0xb0ac urgptr=0 |<Raw  load="\x17\x03\x01\x00 \xf2\x10\xfd\x95N'\xf2\xaf\x99tp\x93\xbc\xe9\x81w\x91\x1b\xe0\xc9M:\x9a!]\xb0!\xae\xd2\x86\xb0>\x17\x03\x01\x00@d>\x0b\xee\xf0\xab\xded\x02E)\x0e0\xbb\xe6\x82uU\xb22\x87\xd6\xe4n[\x1d\x18\xe8\xd6\x1c\x00N_C\xe6\xdd\xbe\x89@6p\xd9\xaf\x19\xb3s\x07H\xdeF\x88\xdar\x0f\x8a\n!4\xeb\xd3F\xefgH" |>>>>

I want to get the tls record version, tls record length and the tls record content type.

This is screenshot of the packet opened in wireshark. enter image description here

Can somepne please show me what I am doing wrong and how to read the tls content properly?

I am using Python3.6, and thus am not able to use stable scapy-ssl_tls, which is currently limited to Python 2.


Solution

  • You are so close. You just need to use TLS(pkt.load).

    Download a TLS Capture

    For this example, use this tls capture from Wireshark's Bugzilla.

    We can see that packet 4 is the TLS Client Hello:

    tshark -r DNS-over-TLS.pcapng -Y "frame.number==4"
        4   0.122267 133.93.28.45 → li280-151.members.linode.com TLSv1  384 Client 
    Hello 00:00:5e:00:01:18 ← 48:d7:05:df:86:0b
    

    Load with Scapy

    Make sure that you have the cryptography library installed, as it's required for loading TLS captures.

    >>> import cryptography
    >>> # No errors
    

    Reproducing what you have so far with this capture:

    >>> from scapy.all import *
    >>> load_layer('tls')
    >>> cap = rdpcap('DNS-over-TLS.pcapng')
    >>> tls_client_hello=cap[3] # Wireshark numbers packets starting at 1, scapy at 0
    >>> tls_client_hello
    <Ether  dst=14:cc:20:51:33:ea src=f4:f2:6d:93:51:f1 type=0x800 |<IP  version=4 
    ihl=5 tos=0x0 len=146 id=62970 flags=DF frag=0 ttl=64 proto=tcp chksum=0x50a0 
    src=192.168.1.143 dst=54.254.250.149 |<TCP  sport=49335 dport=50443 seq=549695462 
    ack=200962336 dataofs=5 reserved=0 flags=PA window=4380 chksum=0xb0ac urgptr=0 |
    <Raw  load="\x17\x03\x01\x00 
    \xf2\x10\xfd\x95N'\xf2\xaf\x99tp\x93\xbc\xe9\x81w\x91\x1b\xe0\xc9M:\x9a!]\xb0!\xa
    e\xd2\x86\xb0>\x17\x03\x01\x00@d>\x0b\xee\xf0\xab\xded\x02E)\x0e0\xbb\xe6\x82uU\x
    b22\x87\xd6\xe4n[\x1d\x18\xe8\xd6\x1c\x00N_C\xe6\xdd\xbe\x89@6p\xd9\xaf\x19\xb3s\
    x07H\xdeF\x88\xdar\x0f\x8a\n!4\xeb\xd3F\xefgH" |>>>>
    

    Note that the part that we want to view is called Raw load. To access this part of the packet, you use tls_client_hello.load. Keep in mind that TLS will take a bytes object that contains the data, but not an entire packet.

    >>> TLS(tls_client_hello.load)
    <TLS  type=handshake version=TLS 1.0 len=313 iv=b'' msg=[<TLSClientHello  
    msgtype=client_hello msglen=309 version=TLS 1.2 gmt_unix_time=Tue, 18 May 2077 
    23:20:52 +0000 (3388605652) 
    random_bytes=d6d533aca04dca42db8b123b0a143dcd580079147122e4de095c15cf sidlen=0 
    sid='' cipherslen=182 ciphers=[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 
    < TLS output truncated ... >
    

    Further Reading

    I highly recommend looking at Scapy TLS Notebooks that do a good job of documenting scapy+TLS usage.