def test_getmarker_nested(self): buf = MsgBuffer(b"\x00\x0b\x03foo\x06barfoo") with buf.new_marker("Outer"): sub_buf = buf.get_opaque(2) self.assertEqual(sub_buf.data, b"\x03foo\x06barfoo") with sub_buf.new_marker("Inner1"): subsub_buf = sub_buf.get_opaque(1) self.assertEqual(subsub_buf.data, b"foo") with sub_buf.new_marker("Inner2"): subsub_buf = sub_buf.get_opaque(1) self.assertEqual(subsub_buf.data, b"barfoo") expect = { "Outer": (0, 13), "Inner1": (2, 6), "Inner2": (6, 13), } fulfilled = set() for marker in buf.markers: if expect.get(marker.text) is not None: (expected_start, expected_end) = expect[marker.text] self.assertEqual(expected_start, marker.startoffset) self.assertEqual(expected_end, marker.endoffset) fulfilled.add(marker.text) self.assertEqual(len(fulfilled), len(expect))
def rx_packet(self, layered_pkt): self._msgs["server"][layered_pkt.application.packet_type()].append( layered_pkt.application) pkt = layered_pkt.application ptype = pkt.packet_type() self._log.debug("<- %s" % (str(layered_pkt.application))) if ptype is HandshakeType.ServerHello: self._srandom = pkt.random elif ptype is HandshakeType.ServerKeyExchange: server_cert_der = self._msgs["server"][ HandshakeType.Certificate][0].get_cert(0) server_cert = X509Certificate.fromderobj(server_cert_der) signed_kex_params = MsgBuffer() signed_kex_params += self._msgs["client"][ HandshakeType.ClientHello][0].random signed_kex_params += self._msgs["server"][ HandshakeType.ServerHello][0].random signed_kex_params += pkt.get_signedpayload() explanation = ExplainedSteps( "Verification of ServerKeyExchange parameters") explanation.append( ExplainedValueStep("Signed KEX parameters", signed_kex_params)) sig_valid = server_cert.publickey.verify_md5sha1( signed_kex_params.data, pkt.signature.data, explain=explanation) self._conn.explain(explanation) if not sig_valid: raise Exception("Signature check failed for KEX parameters.") elif ptype is HandshakeType.ServerHelloDone: print("TODO")
def _readpkt(self, filename): f = open(filename, "r") data = bytearray() for line in f: line = line.rstrip("\r\n") line = line.replace("-", "") data += bytes.fromhex(line) return MsgBuffer(data)
def test_decode_nested(self): buf = MsgBuffer(b"\x00\x04\x03\xaa\xbb\xcc") uints = [] with buf.new_marker("Sub1"): sub1 = buf.get_opaque(2) with sub1.new_marker("Sub2"): sub2 = sub1.get_opaque(1) for i in range(3): with sub2.new_marker("Value%d" % (i)): uints.append(sub2.get_uint8()) self.assertEqual(uints, [0xaa, 0xbb, 0xcc]) expect_depths = [0, 1, 2, 2, 3, 4, 4, 5, 5, 5] depths = [marker.depth for marker in buf.markers] self.assertEqual(depths, expect_depths)
def test_getint(self): buf = MsgBuffer() buf.add_uint24(1234567) buf.add_uint24(7654321) buf.seek(0) self.assertEqual(buf.get_uint24(), 1234567) self.assertEqual(buf.get_uint24(), 7654321)
def rx_from_peer(self, data): self._connlog.rx_rawdata(data) self._rxbuffer.put(data) while True: next_pkt = self._rxbuffer.getrecordlayerpkt() if next_pkt is None: return next_pkt = MsgBuffer(next_pkt) layered_pkt = self._protocol.parse(next_pkt) self._connlog.rx_packet(layered_pkt) self._handler.rx_packet(layered_pkt)
def test_nesting(self): buf = MsgBuffer(bytes.fromhex("05 aabbccddee 03 112233 02 0815")) with buf.new_marker("integers"): with buf.new_marker("a") as marker: value = int(buf.get_opaque(1)) marker.add_comment("0x%x" % (value)) self.assertEqual(value, 0xaabbccddee) with buf.new_marker("b") as marker: value = int(buf.get_opaque(1)) marker.add_comment("0x%x" % (value)) self.assertEqual(value, 0x112233) with buf.new_marker("c") as marker: value = int(buf.get_opaque(1)) marker.add_comment("0x%x" % (value)) self.assertEqual(value, 0x0815) self.assertEqual([marker.depth for marker in buf.markers], [0, 1, 2, 3, 3, 2, 3, 3, 2, 3, 3])
def test_decode_very_simple(self): buf = MsgBuffer(bytes.fromhex("03 aa bb cc")) with buf.new_marker("SubStructure"): sub = buf.get_opaque(1) with sub.new_marker("ValA"): sub.get_uint8() with sub.new_marker("ValB"): sub.get_uint8() with sub.new_marker("ValC"): sub.get_uint8() expect_depths = [0, 1, 2, 2, 3, 3, 3] depths = [marker.depth for marker in buf.markers] self.assertEqual(depths, expect_depths) expect_offsets = [(0, 4), (0, 4), (0, 1), (1, 4), (1, 2), (2, 3), (3, 4)] offsets = [(marker.startoffset, marker.endoffset) for marker in buf.markers] self.assertEqual(offsets, expect_offsets)
def test_addint(self): buf = MsgBuffer() buf.add_uint24_be(123456) self.assertEqual(buf.data, b"\x01\xe2\x40") buf.add_uint32_be(123456789) self.assertEqual(buf.data, b"\x01\xe2\x40\x07\x5b\xcd\x15")
def test_setmarker(self): buf = MsgBuffer(b"\x03foo\x00\x04bar!\x00\x00\x06mookoo") with buf.new_marker("0:4:<"): self.assertEqual(buf.get_opaque(1).data, b"foo") with buf.new_marker("4:10:<"): self.assertEqual(buf.get_opaque(2).data, b"bar!") with buf.new_marker("10:19:<"): self.assertEqual(buf.get_opaque(3).data, b"mookoo") for marker in buf.markers: if (marker.text is not None) and marker.text.endswith(":<"): hints = marker.text.split(":") expected_start = int(hints[0]) expected_end = int(hints[1]) self.assertEqual(expected_start, marker.startoffset) self.assertEqual(expected_end, marker.endoffset)
def test_decode_complex(self): buf = MsgBuffer( bytes.fromhex("33 0c 44 0a 55 66 77 06 88 03 aa bb cc 99")) # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 # ^ ^ ^ ^ with buf.new_marker("Value_0"): buf.get_uint8() with buf.new_marker("Sub_1"): sub1 = buf.get_opaque(1) with sub1.new_marker("Value_1"): sub1.get_uint8() with sub1.new_marker("Sub_2"): sub2 = sub1.get_opaque(1) with sub2.new_marker("Value_A"): sub2.get_uint16() with sub2.new_marker("Value_B"): sub2.get_uint8() with sub2.new_marker("Sub_3"): sub3 = sub2.get_opaque(1) with sub3.new_marker("Value_X"): sub3.get_uint8() with sub3.new_marker("Sub_4"): sub4 = sub3.get_opaque(1) with sub4.new_marker("Sub_R"): sub4.get_uint8() with sub4.new_marker("Sub_S"): sub4.get_uint8() with sub4.new_marker("Sub_T"): sub4.get_uint8() with sub3.new_marker("Value_Y"): sub3.get_uint8() expect_depths = [ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 7 ] depths = [marker.depth for marker in buf.markers] self.assertEqual(depths, expect_depths) expect_offsets = [(0, 14), (0, 1), (1, 14), (1, 2), (2, 14)] expect_offsets += [(2, 3), (3, 14), (3, 4), (4, 14)] expect_offsets += [(4, 6), (6, 7), (7, 14), (7, 8), (8, 14)] expect_offsets += [(8, 9), (9, 13), (9, 10), (10, 13), (10, 11), (11, 12), (12, 13), (13, 14)] offsets = [(marker.startoffset, marker.endoffset) for marker in buf.markers] self.assertEqual(offsets, expect_offsets)
def initiate_handshake(self): #chello = ClientHelloPkt(SSLVersion.ProtocolTLSv1_2) chello = ClientHelloPkt(SSLVersion.ProtocolSSLv3_0) #csdir = CipherSuiteDirectory().kwfilter(sig_alg = "RSA", kex_alg = "DHE", kex_pfs = True, cipher_name = "AES", cipher_keylen = 128) csdir = CipherSuiteDirectory().kwfilter(sig_alg="RSA", kex_alg="DH", kex_pfs=True, cipher_name="AES", cipher_keylen=128, cipher_opmode="CBC") for cs in csdir: self._log.debug("Adding cipher suite: 0x%x = %s" % (int(cs.csid), cs.csid.name)) chello.add_cipher_suite(cs.csid) #chello.add_cipher_suite(CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA) #chello.add_cipher_suite(CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) chello.add_compression_method(CompressionMethod.null) chello.add_extension(HelloExtensionSignatureAlgs().add_algorithm( SignatureAlgorithm.ECDSA, HashAlgorithm.sha256)) chello.add_extension( BaseHelloExtension(ExtensionType.heartbeat, MsgBuffer(b"\x01"))) self._conn.send_pkt(chello) self._crandom = chello.random
def test_emptybuf(self): buf = MsgBuffer() self.assertEqual(buf.data, b"")
def test_concat(self): sub_buf = MsgBuffer() with sub_buf.new_marker("IntA"): sub_buf.add_opaque(1, b"ABC") with sub_buf.new_marker("IntB"): sub_buf.add_opaque(1, b"DEF") buf = MsgBuffer() with buf.new_marker("X"): buf.add_opaque(1, sub_buf) with buf.new_marker("Y"): buf.add_opaque(1, sub_buf) buf.markers.dump()
def rx_packet(self, layered_pkt): self._msgs["client"][layered_pkt.application.packet_type()].append( layered_pkt.application) self._log.debug("<- %s" % (str(layered_pkt.application))) pkt = layered_pkt.application if layered_pkt.application.packet_type() is HandshakeType.ClientHello: # Issue a server hello as a response rsp = ServerHelloPkt(SSLVersion.ProtocolTLSv1_0) rsp.set_compression_method(CompressionMethod.null) rsp.set_cipher_suite(CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA) self._conn.send_pkt(rsp) # Then send the server certificate server_cert = pem_readfile("server.crt", "CERTIFICATE") rsp = CertificatePkt() rsp.add_cert(server_cert) self._conn.send_pkt(rsp) # Then prepare the server key exchange explanation = ExplainedSteps("Server key exchange") dh_params = pem_readfile("dhp.pem", "DH PARAMETERS") kex_params = DHModPKexParams.parse(dh_params) rsp = ServerKeyExchangePkt(KeyExchangeAlgorithm.DHE_RSA) rsp.set_kex_params(kex_params) rsp.set_kex_session(kex_params.new_session().randomize()) # Sign the server key exchange message signed_kex_params = MsgBuffer() signed_kex_params += self._msgs["client"][ HandshakeType.ClientHello][0].random signed_kex_params += self._msgs["server"][ HandshakeType.ServerHello][0].random signed_kex_params += rsp.get_signedpayload() signed_kex_params.hexdump() priv_key = PrivateKey.from_der( pem_readfile("server.key", "PRIVATE KEY")) signature = priv_key.sign_md5sha1(signed_kex_params.data) rsp.set_signature(signature) # Explain it first self._conn.explain(explanation) # And send it to the client self._conn.send_pkt(rsp) # Then send the ServerHelloDone rsp = ServerHelloDonePkt() self._conn.send_pkt(rsp) elif layered_pkt.application.packet_type( ) is ChangeCipherSpecType.ChangeCipherSpec: explanation = ExplainedSteps("Key agreement") ske = self._msgs["server"][HandshakeType.ServerKeyExchange][0] cke = self._msgs["client"][HandshakeType.ClientKeyExchange][0] session = ske.kexsession shared_secret = session.establish(cke.kexparam) server_rnd = self._msgs["server"][ HandshakeType.ServerHello][0].random.data client_rnd = self._msgs["client"][ HandshakeType.ClientHello][0].random.data premaster_secret_part1 = shared_secret[:64] master_secret_part1 = PreMasterSecret.pms_to_ms( PMSPRF.MD5, PMSCalcLabel.MasterSecret, premaster_secret_part1, server_rnd, client_rnd, explain=explanation) premaster_secret_part2 = shared_secret[64:] master_secret_part2 = PreMasterSecret.pms_to_ms( PMSPRF.SHA1, PMSCalcLabel.MasterSecret, premaster_secret_part2, server_rnd, client_rnd, explain=explanation) master_secret = MsgBuffer(master_secret_part1) ^ MsgBuffer( master_secret_part2) master_secret.hexdump() self._conn.explain(explanation)
def test_mkmarker_nested(self): buf = MsgBuffer() with buf.add_opaque_deferred(2): buf.add_uint16(0x1122) buf.add_uint32(0xaabbccdd) buf.add_uint8(0xff) with buf.add_opaque_deferred(3): buf.add_uint16(0xaaaa) buf.add_uint16(0xbbbb) buf.add_uint16(0xcccc) buf.add_uint8(0x55) self.assertEqual( buf.data, bytes.fromhex("0011 1122 aabbccdd ff 000007 aaaa bbbb cccc 55"))
def test_setopaque(self): buf = MsgBuffer() buf.add_opaque(1, b"foo") buf.add_opaque(2, b"bar!") buf.add_opaque(3, b"mookoo") self.assertEqual(buf.data, b"\x03foo\x00\x04bar!\x00\x00\x06mookoo")
def test_mkopaque_annotated(self): buf = MsgBuffer() with buf.new_marker("MainPayload"), buf.add_opaque_deferred(2): with buf.new_marker("AnimalCounts"), buf.add_opaque_deferred(2): with buf.new_marker("CowCount"): buf.add_uint16(9000) with buf.new_marker("SheepCount"): buf.add_uint16(4321) with buf.new_marker("ChickenCount"): buf.add_uint32(12345678) with buf.new_marker("VehicleCounts"), buf.add_opaque_deferred(2): with buf.new_marker("CarCount"): buf.add_uint24(133) with buf.new_marker("TrainCount"): buf.add_uint24(92)
def test_addbuf(self): buf = MsgBuffer() buf += b"foobar" buf += b"mookoo" self.assertEqual(buf.data, b"foobarmookoo")
def test_decode_seq(self): buf = MsgBuffer(bytes.fromhex("03 aaaaaa 03 bbbbbb 03 cccccc")) with buf.new_marker("Chunk1"): buf.get_opaque(1) with buf.new_marker("Chunk2"): buf.get_opaque(1) with buf.new_marker("Chunk3"): buf.get_opaque(1)