diff --git a/src/packet/Packet.py b/src/packet/Packet.py index 9808fe0df9e8c43cfc4e2e1478f9b525fb733510..85d3d20ff5fdacf1e5694f789cbc312dbd648ff1 100644 --- a/src/packet/Packet.py +++ b/src/packet/Packet.py @@ -97,17 +97,20 @@ class Packet: @classmethod - def init_packet(c, packet: scapy.Packet, id: int = 0) -> Packet: + def init_packet(c, packet: scapy.Packet, id: int = 0, last_layer_index: int = -1) -> Packet: """ Factory method to create a packet of a given protocol. :param packet: Scapy Packet to be edited. - :param id: Packet integer identifier. + :param id: [Optional] Packet integer identifier. Default is 0. + :param last_layer_index: [Optional] Index of the last layer of the packet. + If not specified, it will be calculated. :return: Packet of given protocol, or generic Packet if protocol is not supported. """ # Try creating specific packet if possible - last_layer_index = Packet.get_last_layer_index(packet) + if last_layer_index == -1: + last_layer_index = Packet.get_last_layer_index(packet) for i in range(last_layer_index, -1, -1): layer = packet.getlayer(i) try: @@ -120,7 +123,7 @@ class Packet: protocol = Packet.protocols.get(protocol, protocol) module = importlib.import_module(f"packet.{protocol}") cls = getattr(module, protocol) - return cls(packet, id) + return cls(packet, id, i) except ModuleNotFoundError: # Layer protocol not supported continue @@ -128,19 +131,21 @@ class Packet: raise ValueError(f"No supported protocol found for packet: {packet.summary()}") - def __init__(self, packet: scapy.Packet, id: int = 0) -> None: + def __init__(self, packet: scapy.Packet, id: int = 0, last_layer_index: int = -1) -> None: """ Generic packet constructor. :param packet: Scapy Packet to be edited. :param id: Packet integer identifier. + :param last_layer_index: [Optional] Index of the last layer of the packet. + If not specified, it will be calculated. """ self.id = id self.packet = packet - try: - self.layer = packet.getlayer(self.name) - except AttributeError: - self.layer = packet.lastlayer() + self.layer_index = last_layer_index if last_layer_index != -1 else Packet.get_last_layer_index(packet) + self.layer = packet.getlayer(self.name) + if self.layer is None: + self.layer = packet.getlayer(self.layer_index) def get_packet(self) -> scapy.Packet: @@ -171,6 +176,15 @@ class Packet: return len(self.packet.getlayer(layer)) + def get_layer_index(self) -> int: + """ + Get packet layer index. + + :return: Packet layer index. + """ + return self.layer_index + + def rebuild(self) -> None: """ Rebuild packet. diff --git a/src/packet/Transport.py b/src/packet/Transport.py index 444149de15a154abac2d53c70c9cfef1f4d7016e..9109baca31060a1f57382fad35ef4856181c4322 100644 --- a/src/packet/Transport.py +++ b/src/packet/Transport.py @@ -20,8 +20,9 @@ class Transport(Packet): def tweak(self) -> dict: """ - Randomly edit destination or source port, - in this order of priority. + If one of the ports is a well-known port, + randomly edit destination or source port, + in this respective order of priority. :return: Dictionary containing tweak information, or None if no tweak was performed. diff --git a/src/pcap_tweaker.py b/src/pcap_tweaker.py index 47a7df5ba043b80f7ff71945eb811d6e8cfe8977..16dbd65960b5d721388c5ed06d3d3c8e3fabd2b4 100644 --- a/src/pcap_tweaker.py +++ b/src/pcap_tweaker.py @@ -96,25 +96,30 @@ def tweak_pcaps(pcaps: list, output: str, random_range: int = 1, packet_numbers: if must_edit_packet(i, packet_numbers, random_range): # Edit packet, if possible - try: - my_packet = Packet.init_packet(packet, i) - except ValueError: - # No supported protocol found in packet, skip it - new_packets.append(rebuild_packet(packet)) - pass - else: - d = my_packet.tweak() - new_packets.append(my_packet.get_packet()) - if d is not None: - writer.writerow(d) - finally: - i += 1 + last_layer_index = Packet.get_last_layer_index(packet) + while True: + try: + my_packet = Packet.init_packet(packet, i, last_layer_index) + except ValueError: + # No supported protocol found in packet, skip it + new_packets.append(rebuild_packet(packet)) + break + else: + d = my_packet.tweak() + if d is None: + # Packet was not edited, try editing one layer lower + last_layer_index = my_packet.get_layer_index() - 1 + else: + # Packet was edited + new_packets.append(my_packet.get_packet()) + writer.writerow(d) + break else: # Packet won't be edited - # Go to next packet - i += 1 new_packets.append(rebuild_packet(packet)) + i += 1 + # Write output PCAP file output_pcap = "" if output is not None and len(pcaps) == 1: diff --git a/traces/udp-stream.pcap b/traces/udp-stream.pcap new file mode 100644 index 0000000000000000000000000000000000000000..c9a4ab0e54dce3380a0474f3a3db09733a2174a9 Binary files /dev/null and b/traces/udp-stream.pcap differ