class ArpPacketParser(PacketParserInterface): def __init__(self, config: ConfigurationData): self.config = config self.ip_utils = IpAddrUtils() self.mac_utils = MacAddressUtils() def extract_data(self, packet: ARP) -> Munch: data = Munch() try: data.arp_request_src = packet.op data.arp_src_mac = self.mac_utils.convert_hexadecimal_mac_to_readable_mac( packet.sha) data.arp_src_ip = self.ip_utils.inet_to_str(packet.spa) data.arp_dst_mac = self.mac_utils.convert_hexadecimal_mac_to_readable_mac( packet.tha) data.arp_dst_ip = self.ip_utils.inet_to_str(packet.tpa) if self.config.use_numeric_values is True: data.arp_src_mac = self.mac_utils.mac_to_int(data.arp_src_mac) data.arp_dst_mac = self.mac_utils.mac_to_int(data.arp_dst_mac) data.arc_src_ip = self.ip_utils.ip_to_int(data.arp_src_ip) data.arc_dst_ip = self.ip_utils.ip_to_int(data.arp_src_ip) except BaseException as ex: logging.warning('Unable to extract ARP from `%s`. Error: `%s`', type(packet), ex) raise ex return data
def validate(cls, value): mac_utils = MacAddressUtils() if mac_utils.is_valid_mac(value) is False: raise ValueError( 'Invalid mac address format: expected format : or - separated, provided: {}' .format(value)) return value
class EthernetFrameParserTests(BasePacketParserTests): def __init__(self, *args, **kwargs): super(EthernetFrameParserTests, self).__init__(*args, **kwargs) self.eth_frame_parser = EthernetFrameParser(config=self.config) self.mac_utils = MacAddressUtils() def test_extract_data_works_as_expected(self): mock_src_mac = '01:23:45:67:89:ab' mock_dst_mac = 'ab:cf:ef:01:23:45' mock_data = b'1234' eth_frame = dpkt.ethernet.Ethernet() eth_frame.src = self.mac_utils.convert_string_mac_to_byte_array( mock_src_mac) eth_frame.dst = self.mac_utils.convert_string_mac_to_byte_array( mock_dst_mac) eth_frame.type = 2048 eth_frame.data = mock_data eth_data = self.eth_frame_parser.extract_data(eth_frame) self.assertIsInstance(eth_data, Munch) self.assertEqual(eth_data.src_mac, mock_src_mac) self.assertEqual(eth_data.dst_mac, mock_dst_mac) self.assertEqual(eth_data.eth_type, 'ipv4') self.assertEqual(eth_data.eth_payload_size, len(mock_data)) def test_get_eth_type_name_returns_protocol_abbrv(self): eth_frame = dpkt.ethernet.Ethernet() eth_frame.type = 2048 self.assertEqual(self.eth_frame_parser.get_eth_type_name(eth_frame), 'ipv4') def test_get_eth_type_name_returns_protocol_hex_if_no_abbrv_found(self): eth_hex = '0x901' eth_frame = dpkt.ethernet.Ethernet() eth_frame.type = int(eth_hex, 0) self.assertEqual(self.eth_frame_parser.get_eth_type_name(eth_frame), eth_hex[2:]) def test_extract_src_dst_mac_from_eth_frame_works_as_expected(self): mock_src_mac = '01:23:45:67:89:ab' mock_dst_mac = 'ab:cf:ef:01:23:45' eth_frame = dpkt.ethernet.Ethernet() eth_frame.src = self.mac_utils.convert_string_mac_to_byte_array( mock_src_mac) eth_frame.dst = self.mac_utils.convert_string_mac_to_byte_array( mock_dst_mac) src_mac, dst_mac = self.eth_frame_parser.extract_src_dest_mac_from_eth_frame( eth_frame) self.assertEqual(src_mac, mock_src_mac) self.assertEqual(dst_mac, mock_dst_mac)
class EthernetFrameParser(PacketParserInterface): def __init__(self, config: ConfigurationData, static_data: StaticData = None): self.config = config self.mac_utils = MacAddressUtils() self.static_data = static_data or StaticData() def extract_data(self, packet: Ethernet) -> Munch: data = Munch() try: data.src_mac, data.dst_mac = self.extract_src_dest_mac_from_eth_frame(eth_frame=packet) data.eth_type = self.get_eth_type_name(packet) data.eth_payload_size = len(packet.data) except BaseException as ex: logging.warning('Unable to extract ETH from `%s`. Error: `%s`', type(packet), ex) raise ex return data def get_eth_type_name(self, eth_frame: Ethernet) -> Union[int, str]: eth_type = str(hex(eth_frame.type)[2:]) if self.config.use_numeric_values is True: return hex_to_integer(eth_type) eth_type_str = self.static_data.ether_types_data.get(eth_type, {}).get('protocol_abbrv', '').lower() if not eth_type_str: eth_type_str = eth_type return eth_type_str def extract_src_dest_mac_from_eth_frame(self, eth_frame: Ethernet) -> Tuple: src_mac = self.mac_utils.convert_hexadecimal_mac_to_readable_mac(eth_frame.src) dst_mac = self.mac_utils.convert_hexadecimal_mac_to_readable_mac(eth_frame.dst) if self.config.use_numeric_values is True: return self.mac_utils.mac_to_int(src_mac), self.mac_utils.mac_to_int(dst_mac) return src_mac, dst_mac
def __init__(self, config: ConfigurationData, static_data: StaticData = None): self.config = config self.mac_utils = MacAddressUtils() self.static_data = static_data or StaticData()
def __init__(self, config: ConfigurationData): self.config = config self.ip_utils = IpAddrUtils() self.mac_utils = MacAddressUtils()
def __init__(self, *args, **kwargs): super(MacUtilsTests, self).__init__(*args, **kwargs) self.mac_utils = MacAddressUtils()
class MacUtilsTests(unittest.TestCase): def __init__(self, *args, **kwargs): super(MacUtilsTests, self).__init__(*args, **kwargs) self.mac_utils = MacAddressUtils() def test_mac_regex_validation(self): for mac_addr in MAC_ADDRESSES: self.assertTrue(self.mac_utils.is_valid_mac(mac_addr)) def test_int2mac_returns_valid_mac(self): for mac_addr in MAC_ADDRESSES: self.assertIsInstance(self.mac_utils.mac_to_int(mac_addr), int) def test_mac_to_int_to_mac_works_as_expected(self): for mac_addr in MAC_ADDRESSES: integer_mac = self.mac_utils.mac_to_int(mac_addr) self.assertEqual(mac_addr, self.mac_utils.int_to_mac(integer_mac)) def test_convert_hexadecimal_mac_to_readable_mac_works_as_expected(self): for mac_addr in MAC_ADDRESSES: byte_mac = self.mac_utils.convert_string_mac_to_byte_array(mac_addr) self.assertIsInstance(byte_mac, bytearray) self.assertEqual(mac_addr, self.mac_utils.convert_hexadecimal_mac_to_readable_mac(byte_mac)) def test_convert_hexadecimal_mac_to_readable_mac_as_expected(self): for mac_addr in MAC_ADDRESSES: byte_mac = self.mac_utils.convert_string_mac_to_byte_array(mac_addr) self.assertIsInstance(byte_mac, bytearray) self.assertEqual(mac_addr, self.mac_utils.convert_hexadecimal_mac_to_readable_mac(byte_mac)) def test_get_mac_address_to_byte_str_returns_none_given_mac_is_invalid(self): self.assertIsNone(self.mac_utils.convert_string_mac_to_byte_array(mac_address=None)) # MAC is None self.assertIsNone(self.mac_utils.convert_string_mac_to_byte_array(mac_address='')) # MAC is empty self.assertIsNone(self.mac_utils.convert_string_mac_to_byte_array(mac_address='invalidmac')) # MAC is invalid
def __init__(self, *args, **kwargs): super(BasePacketParserTests, self).__init__(*args, **kwargs) self.ip_utils = IpAddrUtils() self.mac_utils = MacAddressUtils() self.config = CONFIGURATION_OBJ self.static_data = StaticData()
def __init__(self, config: ConfigurationData, static_data: StaticData = None): self.mac_utils = MacAddressUtils() self.ip_utils = IpAddrUtils() self.ether_type_data = StaticData.load_ether_types_data() self.config = config self.static_data = static_data or StaticData()
class DpktUtils: def __init__(self, config: ConfigurationData, static_data: StaticData = None): self.mac_utils = MacAddressUtils() self.ip_utils = IpAddrUtils() self.ether_type_data = StaticData.load_ether_types_data() self.config = config self.static_data = static_data or StaticData() def extract_data_from_eth_frame(self, eth_frame: Ethernet, packet_data: PacketData) -> PacketData: eth_frame_parser = EthernetFrameParser(config=self.config, static_data=self.static_data) eth_data = eth_frame_parser.extract_data(packet=eth_frame) packet_data = self.load_protocol_data_to_packet_data(eth_data, packet_data) return packet_data def load_layer3_packet(self, eth_frame: Ethernet) -> Optional[Packet]: """ Take an ethernet frame and parse its data as layer3 packet. Currently supported protocols are IPv4, IPv6, ARP, LLC, IEEE80211 """ if eth_frame.type == dpkt.ethernet.ETH_TYPE_IP: # IPv4 Packet return IpPacketParser.load_ip_packet_from_ethernet_frame(eth_frame.data) if eth_frame.type == dpkt.ethernet.ETH_TYPE_IP6: # IPv6 Packet return eth_frame.data if eth_frame.type == dpkt.ethernet.ETH_TYPE_ARP: # ARP packet return eth_frame.data if isinstance(eth_frame.data, dpkt.llc.LLC): # IEEE 802.3 Logical Link Control return eth_frame.data if eth_frame.type == IEEE80211_PROTOCOL_NUMBER: # IEEE 802.1X Authentication return eth_frame.data # TODO: Handle other layer 3 packets, e.g. TDLS discovery requests _protocol = self.ether_type_data.get(str(hex(eth_frame.type)[2:])) if _protocol is None: logging.warning('Unable to get protocol from ether_type (int): `%s`', _protocol) return None def extract_data_from_layer3_packet(self, layer3_packet, packet_data: PacketData) -> PacketData: data = Munch() if isinstance(layer3_packet, IP): # IPv4 Packet data = self.extract_data_from_ip4_packet(ip_packet=layer3_packet) if isinstance(layer3_packet, IP6): # IPv6 Packet data = self.extract_data_from_ip6_packet(ip6_packet=layer3_packet) if isinstance(layer3_packet, ARP): # ARP packet data = self.extract_data_from_arp_packet(arp_packet=layer3_packet) if isinstance(layer3_packet, LLC): # IEEE 802.3 Logical Link Control data = self.extract_data_from_llc_packet(llc_packet=layer3_packet) if isinstance(layer3_packet, IEEE80211): # IEEE 802.1X Authentication data = self.extract_data_from_80211_packet(layer3_packet) return self.load_protocol_data_to_packet_data(data, packet_data) def extract_data_from_ip4_packet(self, ip_packet: IP) -> Union[Munch, dict]: ip_packet_parser = IpPacketParser(config=self.config, static_data=self.static_data) return ip_packet_parser.extract_data(packet=ip_packet) def extract_data_from_ip6_packet(self, ip6_packet: IP6) -> Union[Munch, dict]: ip6_packet_parser = Ip6PacketParser(config=self.config) return ip6_packet_parser.extract_data(packet=ip6_packet) def extract_data_from_llc_packet(self, llc_packet: LLC) -> Union[Munch, dict]: llc_packet_parser = LlcPacketParser(config=self.config) return llc_packet_parser.extract_data(llc_packet) def extract_data_from_80211_packet(self, ieee80211_packet: IEEE80211) -> Union[Munch, dict]: ieee80211_packet_parser = IEEE80211PacketParser(config=self.config) return ieee80211_packet_parser.extract_data(ieee80211_packet) def extract_data_from_arp_packet(self, arp_packet: ARP) -> Union[Munch, dict]: arp_packet_parser = ArpPacketParser(config=self.config) return arp_packet_parser.extract_data(packet=arp_packet) def load_layer4_packet(self, layer3_packet: Packet) -> Optional[Packet]: if layer3_packet is None: return None packet_data = None if layer3_packet.p == dpkt.ip.IP_PROTO_TCP: # TCP packet packet_data = layer3_packet.data elif layer3_packet.p == dpkt.ip.IP_PROTO_UDP: # UDP packet packet_data = layer3_packet.data elif layer3_packet.p == dpkt.ip.IP_PROTO_ICMP: # ICMP packet packet_data = layer3_packet.data elif layer3_packet.p == dpkt.ip.IP_PROTO_ICMP6: # ICMPv6 packet packet_data = layer3_packet.data elif layer3_packet.p == dpkt.ip.IP_PROTO_IGMP: # IGMP packet packet_data = layer3_packet.data else: logging.warning( 'Unidentified Protocol. Proto Num: `%s`, Type: `%s`', layer3_packet.p, type(layer3_packet.data) ) return packet_data def extract_data_from_layer4_packet(self, layer4_packet: Packet, packet_data: PacketData) -> PacketData: data = None if isinstance(layer4_packet, TCP): # TCP packet data = self.extract_data_from_tcp_packet(layer4_packet) elif isinstance(layer4_packet, UDP): # UDP packet data = self.extract_data_from_udp_packet(layer4_packet) elif isinstance(layer4_packet, ICMP): data = self.extract_data_from_icmp_packet(layer4_packet) elif isinstance(layer4_packet, ICMP6): data = self.extract_data_from_icmp6_packet(layer4_packet) elif isinstance(layer4_packet, IGMP): data = self.extract_data_from_igmp_packet(layer4_packet) return self.load_protocol_data_to_packet_data(data, packet_data) def extract_data_from_tcp_packet(self, tcp_packet: TCP) -> Union[Munch, dict]: tcp_packet_parser = TcpPacketParser(config=self.config, static_data=self.static_data) return tcp_packet_parser.extract_data(packet=tcp_packet) def extract_data_from_udp_packet(self, udp_packet: UDP) -> Union[Munch, dict]: udp_packet_parser = UDPPacketParser(config=self.config, static_data=self.static_data) return udp_packet_parser.extract_data(packet=udp_packet) def extract_data_from_icmp_packet(self, icmp_packet: ICMP) -> Union[Munch, dict]: icmp_packet_parser = IcmpPacketParser(config=self.config) return icmp_packet_parser.extract_data(icmp_packet) def extract_data_from_icmp6_packet(self, icmp6_packet: ICMP6) -> Union[Munch, dict]: icmp6_packet_parser = Icmp6PacketParser(config=self.config) return icmp6_packet_parser.extract_data(icmp6_packet) def extract_data_from_igmp_packet(self, igmp_packet: IGMP) -> Union[Munch, dict]: igmp_packet_parser = IgmpPacketParser(config=self.config) return igmp_packet_parser.extract_data(igmp_packet) def extract_tcp_syn_signature(self, ip_packet: IP, packet_data: PacketData) -> PacketData: syn_packet_parser = SynPacketParser(config=self.config) syn_packet_data = syn_packet_parser.extract_data(ip_packet) packet_data = self.load_protocol_data_to_packet_data(syn_packet_data, packet_data) return packet_data def load_layer7_packet(self, layer4_packet: Packet, packet_data: PacketData) -> Optional[Union[Natpmp, Packet]]: if not isinstance(layer4_packet, UDP): return None layer7_packet = None if packet_data.src_port == 5351 or packet_data.dst_port == 5351: # This is a NAT-PMP packet. layer7_packet = Natpmp(buf=layer4_packet.data) elif packet_data.src_port == 53 or packet_data.dst_port == 53: # DNS packet layer7_packet = DnsPacketParser.load_dns_packet_from_udp_packet(layer4_packet) elif packet_data.src_port == 123 or packet_data.dst_port == 123: # NTP packet layer7_packet = NtpPacketParser.load_ntp_packet_from_udp_packet(layer4_packet) elif packet_data.src_port in UPNP_PORTS or packet_data.dst_port in UPNP_PORTS: # UPnP packet layer7_packet = UpnpPacketParser.load_upnp_packet_from_udp_packet(layer4_packet) elif packet_data.src_port in MDNS_PORTS or packet_data.dst_port in MDNS_PORTS: # mDNS packet layer7_packet = MdnsPacketParser.load_mdns_packet_from_udp_packet(layer4_packet) elif packet_data.src_port in DHCP_PORTS or packet_data.dst_port in DHCP_PORTS: # DHCP packet layer7_packet = DhcpPacketParser.load_dhcp_from_udp_packet(layer4_packet) return layer7_packet def extract_data_from_layer7_packet(self, layer7_packet: Packet, packet_data: PacketData) -> PacketData: """Currently supported Layer 7 protocols are DHCP, UPNP, MDNS, DNS, NTP""" data = Munch() # This needs to be the first in order if isinstance(layer7_packet, Natpmp): # NAT-PMP packet data = self.extract_data_from_natpmp_packet(layer7_packet) elif isinstance(layer7_packet, DNS): # DNS packet data = self.extract_data_from_dns_packet(layer7_packet) elif isinstance(layer7_packet, Mdns): # mDNS packet data = self.extract_data_from_mdns_packet(layer7_packet) elif isinstance(layer7_packet, NTP): # NTP packet data = self.extract_data_from_ntp_packet(layer7_packet) elif isinstance(layer7_packet, (UpnpRequest, dpkt.http.Response)): # UPnP packet data = self.extract_data_from_upnp_packet(layer7_packet) elif isinstance(layer7_packet, DHCP): # DNS packet data = self.extract_data_from_dhcp_packet(layer7_packet) return self.load_protocol_data_to_packet_data(data, packet_data) def extract_data_from_ntp_packet(self, ntp_packet: NTP) -> Union[Munch, dict]: ntp_packet_parser = NtpPacketParser(config=self.config) return ntp_packet_parser.extract_data(ntp_packet) def extract_data_from_dns_packet(self, dns_packet: DNS) -> Union[Munch, dict]: dns_packet_parser = DnsPacketParser(config=self.config) return dns_packet_parser.extract_data(dns_packet) def extract_data_from_upnp_packet(self, upnp_packet: Union[UpnpRequest, dpkt.http.Response]) -> Union[Munch, dict]: upnp_packet_parser = UpnpPacketParser(config=self.config) return upnp_packet_parser.extract_data(upnp_packet) def extract_data_from_mdns_packet(self, mdns_packet: Mdns) -> Union[Munch, dict]: mdns_packet_parser = MdnsPacketParser(config=self.config) return mdns_packet_parser.extract_data(mdns_packet) def extract_data_from_dhcp_packet(self, dhcp_packet: DHCP) -> Union[Munch, dict]: dhcp_packet_parser = DhcpPacketParser(config=self.config) return dhcp_packet_parser.extract_data(dhcp_packet) def extract_data_from_natpmp_packet(self, natpmp_packet: Natpmp) -> Union[Munch, dict]: nat_packet_parser = NatpmpPacketParser(config=self.config) return nat_packet_parser.extract_data(natpmp_packet) def parse_byte_data_as_ethernet_headers(self, packet_data: bytes) -> Munch: data = Munch() decoded_data = binascii.hexlify(packet_data).decode('utf-8') data.src_mac = hex_to_integer(decoded_data[:12]) data.dst_mac = hex_to_integer(decoded_data[12:24]) data.eth_type = hex_to_integer(decoded_data[24:28]) data.payload_size = len(decoded_data[28:])/2 if self.config.use_numeric_values is False: data.src_mac = self.mac_utils.int_to_mac(data.src_mac) data.dst_mac = self.mac_utils.int_to_mac(data.dst_mac) data.eth_type = decoded_data[24:28] return data def load_protocol_data_to_packet_data( self, protocol_data: Optional[Union[dict, Munch]], packet_data: PacketData ) -> PacketData: if protocol_data is None or not isinstance(protocol_data, dict): logging.debug('Unable to load protocol data from `%s` object. <dict> expected', type(protocol_data)) return packet_data for key, value in protocol_data.items(): if packet_data.is_valid_value(value): # If it is valid value, load it to packet data if hasattr(packet_data, key) and not callable(getattr(packet_data, key)): setattr(packet_data, key, value) else: logging.warning( 'Trying to set invalid or callable property `%s` in `%s` object', key, type(packet_data) ) return packet_data
from pathlib import Path # noqa import os import sys sys.path.append(os.getcwd()) # pylint: disable=wrong-import-position from core.lib.mac_utils import MacAddressUtils # noqa from core.lib.common import print_json # noqa from core.pandas_utils.split_csv_data import extract_data_as_separate_csv # noqa if __name__ == '__main__': scripts_dir_path = Path(os.path.abspath(__file__)).parent project_dir_path = scripts_dir_path.parent input_file_path = project_dir_path / 'fixtures/results/results.csv' result_dir_path = project_dir_path / 'fixtures/results/splitted/' summary = extract_data_as_separate_csv( file_path=input_file_path, result_folder=result_dir_path, filter_columns=['src_mac', 'dst_mac'], sort_by_columns=['timestamp'], transform_function=MacAddressUtils().int_to_mac) print_json(summary)
def __init__(self, *args, **kwargs): super(EthernetFrameParserTests, self).__init__(*args, **kwargs) self.eth_frame_parser = EthernetFrameParser(config=self.config) self.mac_utils = MacAddressUtils()
def __init__(self, *args, **kwargs): super(DpktUtilsTest, self).__init__(*args, **kwargs) self.dpkt_utils = DpktUtils(config=CONFIGURATION_OBJ) self.mac_utils = MacAddressUtils()
class DpktUtilsTest(unittest.TestCase): def __init__(self, *args, **kwargs): super(DpktUtilsTest, self).__init__(*args, **kwargs) self.dpkt_utils = DpktUtils(config=CONFIGURATION_OBJ) self.mac_utils = MacAddressUtils() def test_extract_data_from_eth_frame_works_as_expected(self): src_mac = "3d:d5:31:0b:01:15" dst_mac = "9b:b0:7c:bb:f4:09" eth_frame = dpkt.ethernet.Ethernet() eth_frame.src = self.mac_utils.convert_string_mac_to_byte_array( src_mac) eth_frame.dst = self.mac_utils.convert_string_mac_to_byte_array( dst_mac) eth_frame.data = '1234' eth_frame.type = 2048 packet_data = self.dpkt_utils.extract_data_from_eth_frame( eth_frame, PacketData()) self.assertEqual(src_mac, packet_data.src_mac) self.assertEqual(dst_mac, packet_data.dst_mac) self.assertEqual('ipv4', packet_data.eth_type) self.assertNotEqual(0, packet_data.eth_payload_size) def test_extract_data_from_layer3_packet_works_as_expected_for_ip6_packets( self): mock_src_ip6 = '786b:a7d6:fc04:1d14:dfcd:5005:655e:f092' mock_dst_ip6 = '7112:76d5:8e4f:82d7:e384:eedd:20e0:a6ab' ip_packet = dpkt.ip6.IP6() ip_packet.src = socket.inet_pton(socket.AF_INET6, mock_src_ip6) ip_packet.dst = socket.inet_pton(socket.AF_INET6, mock_dst_ip6) ip_packet.p = 2048 ip_packet.data = b'abcdef0123456789' ip_packet.all_extension_headers = [] packet_data = self.dpkt_utils.extract_data_from_layer3_packet( ip_packet, PacketData()) self.assertEqual(mock_src_ip6, packet_data.src_ip) self.assertEqual(mock_dst_ip6, packet_data.dst_ip) self.assertEqual(ip_packet.p, packet_data.ip_proto) self.assertEqual(len(ip_packet.data), packet_data.ip_payload_size) def test_extract_data_from_layer3_packet_works_as_expected_for_ip_packets( self): mock_src_ip = '192.168.100.1' mock_dst_ip = '192.168.100.2' ip_packet = dpkt.ip.IP() ip_packet.src = socket.inet_aton(mock_src_ip) ip_packet.dst = socket.inet_aton(mock_dst_ip) ip_packet.p = 2048 ip_packet.data = b'abcdef0123456789' ip_packet.ttl = 60 ip_packet.tos = 2 packet_data = self.dpkt_utils.extract_data_from_layer3_packet( layer3_packet=ip_packet, packet_data=PacketData()) self.assertEqual(mock_src_ip, packet_data.src_ip) self.assertEqual(mock_dst_ip, packet_data.dst_ip) self.assertEqual(str(ip_packet.p), packet_data.ip_proto) self.assertEqual(len(ip_packet.data), packet_data.ip_payload_size) self.assertEqual(ip_packet.ttl, packet_data.ip_ttl) self.assertIsInstance(packet_data.ip_more_fragment, bool) def test_extract_data_from_layer3_packet_works_as_expected_for_arp_packets( self): src_mac = "d3:d5:01:0b:31:15" dst_mac = "9b:b0:01:bb:7c:09" src_ip = '192.168.100.1' dst_ip = '192.168.100.2' arp_packet = dpkt.arp.ARP() arp_packet.sha = self.mac_utils.convert_string_mac_to_byte_array( src_mac) arp_packet.tha = self.mac_utils.convert_string_mac_to_byte_array( dst_mac) arp_packet.spa = socket.inet_aton(src_ip) arp_packet.tpa = socket.inet_aton(dst_ip) arp_packet.op = 2 packet_data = self.dpkt_utils.extract_data_from_layer3_packet( layer3_packet=arp_packet, packet_data=PacketData()) self.assertEqual(src_mac, packet_data.arp_src_mac) self.assertEqual(dst_mac, packet_data.arp_dst_mac) self.assertEqual(arp_packet.op, packet_data.arp_request_src) self.assertEqual(src_ip, packet_data.arp_src_ip) self.assertEqual(dst_ip, packet_data.arp_dst_ip) def test_extract_data_from_layer4_packet_works_as_expected_for_tcp_packet( self): tcp_packet = dpkt.tcp.TCP() tcp_packet.sport = 50000 tcp_packet.dport = 80 tcp_packet.flags = 0x100 tcp_packet.data = 'dummy_data' packet_data = self.dpkt_utils.extract_data_from_layer4_packet( layer4_packet=tcp_packet, packet_data=PacketData()) self.assertTrue(packet_data.outgoing) self.assertEqual(80, packet_data.dst_port) self.assertEqual(50000, packet_data.src_port) self.assertNotEqual(0, packet_data.layer4_payload_size) self.assertEqual('http', packet_data.layer7_proto) # HTTP uses port 80 def test_extract_data_from_layer4_packet_works_as_expected_for_udp_packet( self): udp_packet = dpkt.udp.UDP() udp_packet.sport = 50000 udp_packet.dport = 800 udp_packet.data = b'dummy_data' packet_data = self.dpkt_utils.extract_data_from_layer4_packet( layer4_packet=udp_packet, packet_data=PacketData()) self.assertTrue(packet_data.outgoing) self.assertEqual(udp_packet.dport, packet_data.dst_port) self.assertEqual(udp_packet.sport, packet_data.src_port) self.assertNotEqual(0, packet_data.layer4_payload_size) self.assertEqual('mdbe', packet_data.layer7_proto) # mdbe uses port 800 def test_extract_data_from_layer7_packet_works_for_dns_packet(self): mock_ans_1 = dpkt.dns.DNS.RR() mock_ans_1.type = dpkt.dns.DNS_CNAME mock_ans_1.ttl = 60 mock_ans_1.name = 'mock_cname_ans' mock_dns_packet = DNS() mock_dns_packet.an = [mock_ans_1] mock_dns_packet.qr = dpkt.dns.DNS_R packet_data = self.dpkt_utils.extract_data_from_layer7_packet( mock_dns_packet, PacketData()) self.assertEqual(mock_ans_1.name, packet_data.dns_ans_cname) self.assertEqual(mock_ans_1.ttl, packet_data.dns_ans_cname_ttl) self.assertIsNone(packet_data.dns_ans_name) self.assertIsNone(packet_data.dns_ans_ip) self.assertIsNone(packet_data.dns_ans_ttl) def test_extract_data_from_layer7_packet_works_for_ntp_packet(self): ntp_packet = NTP() mock_ntp_reference = '1.2.3.4' ntp_packet.id = socket.inet_aton(mock_ntp_reference) ntp_packet.mode = 1 ntp_packet.stratum = 2 ntp_packet.interval = 5 packet_data = PacketData(dst_port=123) packet_data = self.dpkt_utils.extract_data_from_layer7_packet( ntp_packet, packet_data) self.assertEqual(mock_ntp_reference, packet_data.ntp_reference_id) self.assertEqual(ntp_packet.mode, packet_data.ntp_mode) self.assertEqual(ntp_packet.stratum, packet_data.ntp_stratum) self.assertEqual(ntp_packet.interval, packet_data.ntp_interval) def test_extract_data_from_ntp_packet_works_as_expected(self): ntp_packet = NTP() mock_ntp_reference = '1.2.3.4' ntp_packet.id = socket.inet_aton(mock_ntp_reference) ntp_packet.mode = 1 ntp_packet.stratum = 2 ntp_packet.interval = 5 data = self.dpkt_utils.extract_data_from_ntp_packet(ntp_packet) self.assertEqual(mock_ntp_reference, data.ntp_reference_id) self.assertEqual(ntp_packet.mode, data.ntp_mode) self.assertEqual(ntp_packet.stratum, data.ntp_stratum) self.assertEqual(ntp_packet.interval, data.ntp_interval) def test_extract_data_from_dns_packet_works_as_expected(self): mock_ans_1 = dpkt.dns.DNS.RR() mock_ans_1.type = dpkt.dns.DNS_CNAME mock_ans_1.ttl = 60 mock_ans_1.name = 'mock_cname_ans' mock_dns_packet = DNS() mock_dns_packet.an = [mock_ans_1] mock_dns_packet.qr = dpkt.dns.DNS_R data = self.dpkt_utils.extract_data_from_dns_packet(mock_dns_packet) self.assertEqual(mock_ans_1.name, data.dns_ans_cname) self.assertEqual(mock_ans_1.ttl, data.dns_ans_cname_ttl) self.assertEqual('', data.dns_ans_name) self.assertEqual('', data.dns_ans_ip) self.assertIsNone(data.dns_ans_ttl)