def test_structmeta_parent(self): @struct class Sample1(StructMeta): child_field: Select('Sample2.parent_field', cases={ Uint8(0xaa): Uint8, Uint8(0xbb): Uint16, }) @struct class Sample2(StructMeta): parent_field: Uint8 fragment: Sample1 s1 = Sample2(parent_field=Uint8(0xaa), fragment=Sample1(child_field=Uint8(0xff))) s1_byte = bytes.fromhex('aa ff') s2 = Sample2(parent_field=Uint8(0xbb), fragment=Sample1(child_field=Uint16(0xffff))) s2_byte = bytes.fromhex('bb ffff') self.assertEqual(bytes(s1), s1_byte) self.assertEqual(bytes(s2), s2_byte) self.assertEqual(Sample2.from_bytes(bytes(s1)), s1) self.assertEqual(Sample2.from_bytes(bytes(s2)), s2)
class Sample2(StructMeta): type: Uint8 fragment: Select('type', cases={ Uint8(0xaa): Opaque(0), Uint8(0xbb): Sample1, })
def test_structmeta_multiple_parents(self): @struct class Sample1(StructMeta): child_field: Select('Sample3.parent_fieldA', cases={ Uint8(0xaa): Uint8, Uint8(0xbb): Uint16, }) @struct class Sample2(StructMeta): parent_fieldB: Uint8 fragment: Sample1 @struct class Sample3(StructMeta): parent_fieldA: Uint8 fragment: Sample2 s = Sample3(parent_fieldA=Uint8(0xbb), fragment=Sample2( parent_fieldB=Uint8(0x12), fragment=Sample1(child_field=Uint16(0x0101)))) s_byte = bytes.fromhex('bb 12 0101') self.assertEqual(bytes(s), s_byte) self.assertEqual(Sample3.from_bytes(bytes(s)), s)
class ContentType(Enum): elem_t = Uint8 invalid = Uint8(0) change_cipher_spec = Uint8(20) alert = Uint8(21) handshake = Uint8(22) application_data = Uint8(23)
def test_structmeta_default_value(self): @struct class Sample1(StructMeta): fieldA: Uint8 = Uint8(0x01) fieldB: Uint8 s1 = Sample1(fieldA=Uint8(0x01), fieldB=Uint8(0x12)) s2 = Sample1(fieldB=Uint8(0x12)) self.assertEqual(s1, s2)
def test_structmeta_default_lambda(self): @struct class Sample1(StructMeta): length: Uint8 = lambda self: Uint8(len(bytes(self.fragment))) fragment: Opaque(Uint8) s1 = Sample1(fragment=Opaque(Uint8)(b'test')) self.assertEqual(s1.length, Uint8(5))
def test_structmeta_has_parent_ref(self): @struct class Sample1(StructMeta): child_field: Select('Sample3.parent_fieldA', cases={ Uint8(0xaa): Uint8, Uint8(0xbb): Uint16, }) @struct class Sample2(StructMeta): parent_fieldB: Uint8 fragment: Sample1 Sample2s = List(size_t=Uint8, elem_t=Sample2) @struct class Sample3(StructMeta): parent_fieldA: Uint8 fragment: Sample2s s = Sample3(parent_fieldA=Uint8(0xbb), fragment=Sample2s([ Sample2( parent_fieldB=Uint8(0x12), fragment=Sample1(child_field=Uint16(0x0101))) ])) # コンストラクタで構造体を構築した場合 target = s.fragment.get_array()[0].fragment # 最下の子インスタンス self.assertTrue(isinstance(target, Sample1)) self.assertTrue(isinstance(target.parent, Sample2)) self.assertTrue(isinstance(target.parent.parent, Sample3)) # バイト列から構造体を構築した場合 s2 = Sample3.from_bytes(bytes(s)) target = s.fragment.get_array()[0].fragment # 最下の子インスタンス self.assertTrue(isinstance(target, Sample1)) self.assertTrue(isinstance(target.parent, Sample2)) self.assertTrue(isinstance(target.parent.parent, Sample3))
def test_structmeta_select(self): @struct class Sample1(StructMeta): field: Uint16 @struct class Sample2(StructMeta): type: Uint8 fragment: Select('type', cases={ Uint8(0xaa): Opaque(0), Uint8(0xbb): Sample1, }) s1 = Sample2(type=Uint8(0xaa), fragment=Opaque(0)(b'')) self.assertEqual(bytes(s1), bytes.fromhex('aa')) self.assertEqual(Sample2.from_bytes(bytes(s1)), s1) s2 = Sample2(type=Uint8(0xbb), fragment=Sample1(field=Uint16(0x1212))) self.assertEqual(bytes(s2), bytes.fromhex('bb 1212')) self.assertEqual(Sample2.from_bytes(bytes(s2)), s2)
def test_structmeta_eq_neq(self): @struct class Sample1(StructMeta): fieldA: Uint8 fieldB: Uint8 s1 = Sample1(fieldA=Uint8(0x01), fieldB=Uint8(0x12)) s2 = Sample1(fieldA=Uint8(0x01), fieldB=Uint8(0x12)) s3 = Sample1(fieldA=Uint8(0x01), fieldB=Uint8(0x21)) self.assertEqual(s1, s2) self.assertNotEqual(s1, s3)
class CertificateType(Enum): elem_t = Uint8 X509 = Uint8(0) RawPublicKey = Uint8(2)
class HandshakeType(Enum): elem_t = Uint8 #hello_request_RESERVED = Uint8(0) client_hello = Uint8(1) server_hello = Uint8(2) #hello_verify_request_RESERVED = Uint8(3) new_session_ticket = Uint8(4) end_of_early_data = Uint8(5) #hello_retry_request_RESERVED = Uint8(6) encrypted_extensions = Uint8(8) certificate = Uint8(11) #server_key_exchange_RESERVED = Uint8(12) certificate_request = Uint8(13) #server_hello_done_RESERVED = Uint8(14) certificate_verify = Uint8(15) #client_key_exchange_RESERVED = Uint8(16) finished = Uint8(20) #certificate_url_RESERVED = Uint(21) #certificate_status_RESERVED = Uint(22) #supplemental_data_RESERVED = Uint(23) key_update = Uint8(24) message_hash = Uint8(254)
def split_pad(data): for pos, value in zip(reversed(range(len(data))), reversed(data)): if value != 0: break return data[:pos], ContentType(Uint8(value)) #, data[pos+1:]
class Sample1(StructMeta): child_field: Select('Sample3.parent_fieldA', cases={ Uint8(0xaa): Uint8, Uint8(0xbb): Uint16, })
class AlertDescription(Enum): elem_t = Uint8 close_notify = Uint8(0) unexpected_message = Uint8(10) bad_record_mac = Uint8(20) record_overflow = Uint8(22) handshake_failure = Uint8(40) bad_certificate = Uint8(42) unsupported_certificate = Uint8(43) certificate_revoked = Uint8(44) certificate_expired = Uint8(45) certificate_unknown = Uint8(46) illegal_parameter = Uint8(47) unknown_ca = Uint8(48) access_denied = Uint8(49) decode_error = Uint8(50) decrypt_error = Uint8(51) protocol_version = Uint8(70) insufficient_security = Uint8(71) internal_error = Uint8(80) inappropriate_fallback = Uint8(86) user_canceled = Uint8(90) missing_extension = Uint8(109) unsupported_extension = Uint8(110) unrecognized_name = Uint8(112) bad_certificate_status_response = Uint8(113) unknown_psk_identity = Uint8(115) certificate_required = Uint8(116) no_application_protocol = Uint8(120)
class Sample1(StructMeta): child_field: Select('UnknownClass.parent_field', cases={ Uint8(0xaa): Uint8, Uint8(0xbb): Uint16, })
class AlertLevel(Enum): elem_t = Uint8 warning = Uint8(1) fatal = Uint8(2)
class Sample1(StructMeta): fieldA: Uint8 = Uint8(0x01) fieldB: Uint8
server_conn.send_msg(bytes(tlsciphertext)) print('[<<<] Recv:') print(hexdump(buf)) stream = io.BytesIO(buf) while True: firstbyte = stream.read(1) if firstbyte == b'': break stream.seek(-1, io.SEEK_CUR) content_type = \ ContentType(Uint8(int.from_bytes(firstbyte, byteorder='big'))) # Alert受信時 if content_type == ContentType.alert: tlsplaintext = TLSPlaintext.from_fs(stream) for alert in tlsplaintext.get_messages(): print('[-] Recv Alert!') print(alert) sys.exit(1) # ChangeCipherSpecはTLS 1.3では無視する elif content_type == ContentType.change_cipher_spec: # ChangeCipherSpec change_cipher_spec = TLSPlaintext.from_fs(stream) print(change_cipher_spec)
class Sample1(StructMeta): length: Uint8 = lambda self: Uint8(len(bytes(self.fragment))) fragment: Opaque(Uint8)