diff --git a/src/packet/BOOTP.py b/src/packet/BOOTP.py index 075697b5efabeb72d3ffe750ffe464fb4b880db7..c796c1b6fcc50cdd4519477a386114793cd878a2 100644 --- a/src/packet/BOOTP.py +++ b/src/packet/BOOTP.py @@ -69,6 +69,8 @@ class BOOTP(Packet): :return: Dictionary containing tweak information. """ + # Store old hash value + old_hash = self.get_hash() # Get field which will be modified field = random.choice(self.fields) @@ -94,4 +96,4 @@ class BOOTP(Packet): self.update_fields() # Return value: dictionary containing tweak information - return self.get_dict_log(field, old_value, new_value) + return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/packet/CoAP.py b/src/packet/CoAP.py index 1d1d9e0b231d6f30634cf8de78fd949437d25f3c..1855d93bd4f39ca967d70cb7ec41daac125488ba 100644 --- a/src/packet/CoAP.py +++ b/src/packet/CoAP.py @@ -77,6 +77,8 @@ class CoAP(Packet): :return: Dictionary containing tweak information. """ + # Store old hash value + old_hash = self.get_hash() # Get field which will be modified field = random.choice(self.fields) @@ -104,4 +106,4 @@ class CoAP(Packet): self.update_fields() # Return value: dictionary containing tweak information - return self.get_dict_log(field, old_value, new_value) + return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/packet/DNS.py b/src/packet/DNS.py index e147b99fac01593095eabdaba3c32efa6b457f3e..cfb79b95d96df8c88394cc6e21596c1d1f137241 100644 --- a/src/packet/DNS.py +++ b/src/packet/DNS.py @@ -71,6 +71,8 @@ class DNS(Packet): :return: Dictionary containing tweak information. """ + # Store old hash value + old_hash = self.get_hash() # Get field which will be modified field = self.get_field() @@ -123,4 +125,4 @@ class DNS(Packet): self.update_fields() # Return value: dictionary containing tweak information - return self.get_dict_log(field, old_value, new_value) + return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/packet/IGMPv3mr.py b/src/packet/IGMPv3mr.py index 2f1cfc019dd99a9e5e1954fbfc4f6df78c6c22b9..40d3b819312b9f647db5226e1490fc11f9a4cc12 100644 --- a/src/packet/IGMPv3mr.py +++ b/src/packet/IGMPv3mr.py @@ -19,6 +19,8 @@ class IGMPv3mr(Packet): :return: Dictionary containing tweak information. """ + # Store old hash value + old_hash = self.get_hash() # Set random IP address for all group records old_value = "" new_value = "" @@ -38,4 +40,4 @@ class IGMPv3mr(Packet): self.update_fields() # Return value: dictionary containing tweak information - return self.get_dict_log("maddr", old_value, new_value) + return self.get_dict_log("maddr", old_value, new_value, old_hash) diff --git a/src/packet/Packet.py b/src/packet/Packet.py index 2f37f8216a47b633c2636fa157618345a71e94f5..e10779439ab32501fe22cdb8b12f432014d873a5 100644 --- a/src/packet/Packet.py +++ b/src/packet/Packet.py @@ -6,6 +6,7 @@ import re import random from ipaddress import IPv4Address, IPv6Address import scapy.all as scapy +import hashlib class Packet: """ @@ -190,6 +191,15 @@ class Packet: return self.layer_index + def get_hash(self) -> str: + """ + Get packet hash. + + :return: Packet hash. + """ + return hashlib.sha256(bytes(self.packet)).hexdigest() + + def rebuild(self) -> None: """ Rebuild packet, but keep old timestamp. @@ -225,7 +235,7 @@ class Packet: self.rebuild() - def get_dict_log(self, field: str, old_value: str, new_value: str) -> dict: + def get_dict_log(self, field: str, old_value: str, new_value: str, old_hash: str) -> dict: """ Log packet field modification, and return a dictionary containing tweak information. @@ -233,6 +243,7 @@ class Packet: :param field: Field name. :param old_value: Old field value. :param new_value: New field value. + :param old_hash: Old packet hash (before tweak). :return: Dictionary containing tweak information. """ timestamp = self.packet.time @@ -243,7 +254,9 @@ class Packet: "protocol": self.name, "field": field, "old_value": old_value, - "new_value": new_value + "new_value": new_value, + "old_hash": old_hash, + "new_hash": self.get_hash() } return d @@ -255,6 +268,8 @@ class Packet: :return: Dictionary containing tweak information, or None if no tweak was performed. """ + # Store old hash value + old_hash = self.get_hash() # Get field which will be modified field, value_type = random.choice(list(self.fields.items())) # Store old value of field @@ -323,4 +338,4 @@ class Packet: self.update_fields() # Return value: dictionary containing tweak information - return self.get_dict_log(field, old_value, new_value) + return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/packet/Transport.py b/src/packet/Transport.py index 433d82c73f08d4d5d7b648f64bba19e3381f5be2..da73a5e99fbefd2696458b6b0c23c98c47324f3e 100644 --- a/src/packet/Transport.py +++ b/src/packet/Transport.py @@ -27,6 +27,8 @@ class Transport(Packet): :return: Dictionary containing tweak information, or None if no tweak was performed. """ + # Store old hash value + old_hash = self.get_hash() # Check if destination port is a well-known port if self.layer.getfieldval("dport") in self.ports: field = "dport" @@ -53,4 +55,4 @@ class Transport(Packet): self.update_fields() # Return value: dictionary containing tweak information - return self.get_dict_log(field, old_value, new_value) + return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/pcap_tweaker.py b/src/pcap_tweaker.py index d42f28e79777a644d2f39ccf3f148d5a0a618df7..aaacadf0c3286083833778fefc79f690eb768da4 100644 --- a/src/pcap_tweaker.py +++ b/src/pcap_tweaker.py @@ -10,6 +10,7 @@ import csv import scapy.all as scapy from scapy.layers import dhcp, dns, http from scapy.contrib import coap, igmp, igmpv3 +import hashlib from packet.Packet import Packet @@ -59,6 +60,16 @@ def rebuild_packet(packet: scapy.Packet) -> scapy.Packet: return new_packet +def get_packet_hash(packet: scapy.Packet) -> str: + """ + Get the SHA256 hash of a Scapy packet. + + :param packet: Scapy packet + :return: SHA256 hash of Scapy packet + """ + return hashlib.sha256(bytes(packet)).hexdigest() + + def tweak_pcaps(pcaps: list, output: str, random_range: int = 1, packet_numbers: list = None, dry_run: bool = False) -> None: """ Main functionality of the program: @@ -91,7 +102,7 @@ def tweak_pcaps(pcaps: list, output: str, random_range: int = 1, packet_numbers: csv_log = os.path.basename(input_pcap).replace(".pcap", ".edit.csv") csv_log = os.path.join(csv_dir, csv_log) with open(csv_log, "w") as csv_file: - field_names = ["id", "timestamp", "protocol", "field", "old_value", "new_value"] + field_names = ["id", "timestamp", "protocol", "field", "old_value", "new_value", "old_hash", "new_hash"] writer = csv.DictWriter(csv_file, fieldnames=field_names) writer.writeheader()