From be3733bbecef1663cd5625abea4fe23a1b4e09ac Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Thu, 18 Apr 2019 00:25:26 +0100 Subject: crafted-pkt/tls-handshake-fragments.py: test for bug 3303 Dumb fuzzer for verifying that handshake reassembly works. https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=3303 --- crafted-pkt/tls-handshake-fragments.py | 79 ++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 crafted-pkt/tls-handshake-fragments.py diff --git a/crafted-pkt/tls-handshake-fragments.py b/crafted-pkt/tls-handshake-fragments.py new file mode 100755 index 0000000..2883933 --- /dev/null +++ b/crafted-pkt/tls-handshake-fragments.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +import argparse +import random + +from scapy.all import * + +# msg_type: 1 (Client Hello) +# length: 47 +# client_version: 1.2 +# random: 32 bytes +# session_id: empty +# cipher_suite[1]: 0x002F (TLS_RSA_WITH_AES_128_CBC_SHA) +# compression_method[1]: null +# extensions[1]: 0xAAAA (GREASE) with two values (will be used as identifier) +clientHelloMsg = bytes([ + 0x01, + 0x00, 0x00, 0x31, + 0x03, 0x03, +]) + 32 * b'3' + bytes([ + 0x00, + 0x00, 0x02, 0x00, 0x2f, + 0x01, 0x00, + 0x00, 0x06, 0xaa, 0xaa, 0x00, 0x02, + 0x00, 0x00 +]) +assert len(clientHelloMsg) == 53 +clientHelloMsgBase = clientHelloMsg[:-2] + +def CH(num : int): + '''Returns a Client Hello message with some identifier.''' + return clientHelloMsgBase + num.to_bytes(2, 'big') + +def TLSRecord(data): + # Handshake (22), TLSv1.0 + return b'\x16\x03\x01' + len(data).to_bytes(2, 'big') + data + +parser = argparse.ArgumentParser() +parser.add_argument('--seed', type=int) +parser.add_argument('--count', type=int, default=256, help='Streams count') +parser.add_argument('output_file') +args = parser.parse_args() + +if args.seed is not None: + random.seed(args.seed) + +# Pick a number of messages per stream such that at least the case is triggered +# where a record contains the end of a message, a full message and the start of +# another message. A lot more than three per record will likely not be useful +# since it does not trigger reassembly. +hsPerStream = 10 +maxRecordSize = len(clientHelloMsg) * 4 + +# Fragment handshake message over TLS records, +# fragment TLS records over TCP segments. +packets = [] +for i in range(args.count): + hs = b''.join(CH(hsPerStream * i + j + 1) for j in range(hsPerStream)) + seq = 0x1000 + while hs: + # Does not matter that n > maxRecordSize, it is capped anyway. + n = random.randint(1, maxRecordSize) + recordData, hs = hs[:n], hs[n:] + seg = TLSRecord(recordData) + pkt = IP()/TCP(flags='A', seq=seq, sport=0xc000 + i, dport=443)/seg + packets.append(pkt) + seq += len(seg) + +wrpcap(args.output_file, packets) + +r""" +Test: + + tshark -r hs-frag.pcapng -Tfields -Y tls.handshake.extension.data -e tls.handshake.extension.data | tr , '\n' + +Expected result: for a given 'count' streams, expect hexadecimal numbers 0001 up +to and including 10*count. E.g. for --count=10 the output should match: + + printf '%004x\n' {1..100} +""" -- cgit v1.2.1