diff --git a/.ci_scripts/run-all-pcaps.sh b/.ci_scripts/run-all-pcaps.sh index 8f75b0029278f620aef050dce92600830c619331..53446e7df36d149299e2343eff067e9091cf4ff3 100755 --- a/.ci_scripts/run-all-pcaps.sh +++ b/.ci_scripts/run-all-pcaps.sh @@ -4,8 +4,8 @@ EXITCODE=0 for pcap in $GITHUB_WORKSPACE/traces/*.pcap do - # Run pcap_tweaker script on pcap file - python3 $GITHUB_WORKSPACE/src/pcap_tweaker.py $pcap + # Run pcap_fuzzer script on pcap file + python3 $GITHUB_WORKSPACE/src/pcap_fuzzer.py $pcap # If the exit code is not 0, set EXITCODE to 1 if [[ $? -ne 0 ]] then diff --git a/README.md b/README.md index ec46c0b22ff52a8d04e1ac66a0091f10aed288bd..e88d7660f328f857cb10aa22e94103361b41dde9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# pcap-tweaker +# pcap-fuzzer This program randomly edits packets from a PCAP file, one field per edited packet. @@ -22,7 +22,7 @@ pip install -r requirements.txt ## Usage ```bash -python3 pcap_tweaker.py [-h] [-o OUTPUT] [-r RANDOM_RANGE] [-n PACKET_NUMBER] [-d] pcap [pcap ...] +python3 pcap_fuzzer.py [-h] [-o OUTPUT] [-r RANDOM_RANGE] [-n PACKET_NUMBER] [-d] pcap [pcap ...] ``` The program produces new PCAP file with the same name as the input files, diff --git a/src/packet/ARP.py b/src/packet/ARP.py index d3a95541c302caa910d397ba35dacc42cb509362..e03788717a5d2dd6c7dd38a7b63453f6c471e070 100644 --- a/src/packet/ARP.py +++ b/src/packet/ARP.py @@ -1,4 +1,3 @@ -import scapy.all as scapy from packet.Packet import Packet class ARP(Packet): diff --git a/src/packet/BOOTP.py b/src/packet/BOOTP.py index c796c1b6fcc50cdd4519477a386114793cd878a2..a88730e0ad10af1aab596596e7ed7f037e5c0fc9 100644 --- a/src/packet/BOOTP.py +++ b/src/packet/BOOTP.py @@ -1,8 +1,6 @@ -import logging from typing import Tuple import random import scapy.all as scapy -from scapy.layers import dhcp from packet.Packet import Packet class BOOTP(Packet): @@ -61,13 +59,13 @@ class BOOTP(Packet): self.dhcp_options.setfieldval("options", dhcp_options) - def tweak(self) -> dict: + def fuzz(self) -> dict: """ Randomly edit a BOOTP/DHCP field, among the following: - chaddr (client hardware address) - message-type (DHCP message type) - :return: Dictionary containing tweak information. + :return: Dictionary containing fuzz information. """ # Store old hash value old_hash = self.get_hash() @@ -95,5 +93,5 @@ class BOOTP(Packet): # Update checksums self.update_fields() - # Return value: dictionary containing tweak information + # Return value: dictionary containing fuzz information 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 1855d93bd4f39ca967d70cb7ec41daac125488ba..b274a7d48fb49258196136368ea08ba1771ea5a3 100644 --- a/src/packet/CoAP.py +++ b/src/packet/CoAP.py @@ -1,7 +1,4 @@ -import logging import random -import scapy.all as scapy -from scapy.contrib import coap from packet.Packet import Packet class CoAP(Packet): @@ -68,14 +65,14 @@ class CoAP(Packet): return result - def tweak(self) -> dict: + def fuzz(self) -> dict: """ Randomly edit one field of the CoAP packet, among the following: - type - code - uri - :return: Dictionary containing tweak information. + :return: Dictionary containing fuzz information. """ # Store old hash value old_hash = self.get_hash() @@ -105,5 +102,5 @@ class CoAP(Packet): # Update checksums self.update_fields() - # Return value: dictionary containing tweak information + # Return value: dictionary containing fuzz information 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 cfb79b95d96df8c88394cc6e21596c1d1f137241..213974041e92362f055edfa9beaf47d11459e8f9 100644 --- a/src/packet/DNS.py +++ b/src/packet/DNS.py @@ -1,5 +1,4 @@ import random -import scapy.all as scapy from scapy.layers import dns from packet.Packet import Packet @@ -62,14 +61,14 @@ class DNS(Packet): return random.choice(self.fields) - def tweak(self) -> dict: + def fuzz(self) -> dict: """ Randomly edit one DNS field, among the following: - QR flag - Query type - Query name - :return: Dictionary containing tweak information. + :return: Dictionary containing fuzz information. """ # Store old hash value old_hash = self.get_hash() @@ -124,5 +123,5 @@ class DNS(Packet): # Update checksums self.update_fields() - # Return value: dictionary containing tweak information + # Return value: dictionary containing fuzz information return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/packet/HTTP_Request.py b/src/packet/HTTP_Request.py index 83ca1518b880aaaf0395fca7fb7f91489565190c..6d5665f9e556d5dcd9d9fb11aefd0192d1d4c583 100644 --- a/src/packet/HTTP_Request.py +++ b/src/packet/HTTP_Request.py @@ -1,5 +1,3 @@ -import scapy.all as scapy -from scapy.layers import http from packet.Packet import Packet class HTTP_Request(Packet): diff --git a/src/packet/ICMP.py b/src/packet/ICMP.py index 4cdb3c45c27ba7b5deccfa95bcfbf790db154bb1..8d4879f431ef839c788710215e77d4d6dfedd877 100644 --- a/src/packet/ICMP.py +++ b/src/packet/ICMP.py @@ -1,4 +1,3 @@ -import scapy.all as scapy from packet.Packet import Packet class ICMP(Packet): diff --git a/src/packet/IGMP.py b/src/packet/IGMP.py index b413787d68452909abc851b088ce9ae3617755ea..0afe978b15aec089f83c07d324a148f7fff6d57a 100644 --- a/src/packet/IGMP.py +++ b/src/packet/IGMP.py @@ -1,5 +1,3 @@ -import scapy.all as scapy -from scapy.contrib import igmp from packet.Packet import Packet class IGMP(Packet): diff --git a/src/packet/IGMPv3mr.py b/src/packet/IGMPv3mr.py index 40d3b819312b9f647db5226e1490fc11f9a4cc12..874b0d857755cfc68947ff40a3433ef0af40ff0a 100644 --- a/src/packet/IGMPv3mr.py +++ b/src/packet/IGMPv3mr.py @@ -1,5 +1,3 @@ -import logging -import scapy.all as scapy from scapy.contrib import igmpv3 from packet.Packet import Packet @@ -12,12 +10,12 @@ class IGMPv3mr(Packet): name = "IGMPv3mr" - def tweak(self) -> dict: + def fuzz(self) -> dict: """ - Tweak the IGMPv3 Membership Report packet, + fuzz the IGMPv3 Membership Report packet, by randomizing all group addresses. - :return: Dictionary containing tweak information. + :return: Dictionary containing fuzz information. """ # Store old hash value old_hash = self.get_hash() @@ -39,5 +37,5 @@ class IGMPv3mr(Packet): # Update checksums self.update_fields() - # Return value: dictionary containing tweak information + # Return value: dictionary containing fuzz information return self.get_dict_log("maddr", old_value, new_value, old_hash) diff --git a/src/packet/IPv4.py b/src/packet/IPv4.py index 47be7673468a479feb26b1ae893d5e3c73be9a9e..06363358d8910b145ceadd43db67af3a528b4c9f 100644 --- a/src/packet/IPv4.py +++ b/src/packet/IPv4.py @@ -1,4 +1,3 @@ -import scapy.all as scapy from packet.Packet import Packet class IPv4(Packet): diff --git a/src/packet/IPv6.py b/src/packet/IPv6.py index acc1aa174558365dfaa9af59ac5c4586d9c826bb..0d8703a0a9c7580793f6fe64ed0ab368db3e0cc0 100644 --- a/src/packet/IPv6.py +++ b/src/packet/IPv6.py @@ -1,4 +1,3 @@ -import scapy.all as scapy from packet.Packet import Packet class IPv6(Packet): diff --git a/src/packet/Packet.py b/src/packet/Packet.py index 43f9064545710355f46d9297ec01080a63dd8a23..11fadcb798af714f054209b40526d948824db8c7 100644 --- a/src/packet/Packet.py +++ b/src/packet/Packet.py @@ -269,13 +269,13 @@ class Packet: 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. + and return a dictionary containing fuzz information. :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. + :param old_hash: Old packet hash (before fuzz). + :return: Dictionary containing fuzz information. """ timestamp = self.packet.time logging.info(f"Packet {self.id}, timestamp {timestamp}: {self.name}.{field} = {old_value} -> {new_value}") @@ -292,12 +292,12 @@ class Packet: return d - def tweak(self) -> dict: + def fuzz(self) -> dict: """ Randomly edit one packet field. - :return: Dictionary containing tweak information, - or None if no tweak was performed. + :return: Dictionary containing fuzz information, + or None if no fuzz was performed. """ # Store old hash value old_hash = self.get_hash() @@ -368,5 +368,5 @@ class Packet: # Update checksums self.update_fields() - # Return value: dictionary containing tweak information + # Return value: dictionary containing fuzz information return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/packet/TCP.py b/src/packet/TCP.py index 590b7295ac7fcebe139ec01133c5b1c994408c94..0a19fedd2adca47287364956ee506013584e8ede 100644 --- a/src/packet/TCP.py +++ b/src/packet/TCP.py @@ -1,4 +1,3 @@ -import scapy.all as scapy from packet.Transport import Transport class TCP(Transport): diff --git a/src/packet/Transport.py b/src/packet/Transport.py index da73a5e99fbefd2696458b6b0c23c98c47324f3e..d6e147376a6a018156fd5c90cf1da081a17c6d8d 100644 --- a/src/packet/Transport.py +++ b/src/packet/Transport.py @@ -1,6 +1,4 @@ import random -import scapy.all as scapy -from scapy.layers import http from packet.Packet import Packet class Transport(Packet): @@ -18,14 +16,14 @@ class Transport(Packet): ports = [] - def tweak(self) -> dict: + def fuzz(self) -> dict: """ 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. + :return: Dictionary containing fuzz information, + or None if no fuzz was performed. """ # Store old hash value old_hash = self.get_hash() @@ -36,7 +34,7 @@ class Transport(Packet): elif self.layer.getfieldval("sport") in self.ports: field = "sport" else: - # No well-known port, do not tweak + # No well-known port, do not fuzz return None # Store old value of field @@ -54,5 +52,5 @@ class Transport(Packet): # Update checksums, if needed self.update_fields() - # Return value: dictionary containing tweak information + # Return value: dictionary containing fuzz information return self.get_dict_log(field, old_value, new_value, old_hash) diff --git a/src/packet/UDP.py b/src/packet/UDP.py index 5c6f444c1cfedd2250c04602449c13a540dbf129..c2e586b34812c2fbb1bb58618ecb66e3835016f1 100644 --- a/src/packet/UDP.py +++ b/src/packet/UDP.py @@ -1,4 +1,3 @@ -import scapy.all as scapy from packet.Transport import Transport class UDP(Transport): diff --git a/src/packet/mDNS.py b/src/packet/mDNS.py index 1c566b47f20e82f77d62f214bbd117335445ad5a..55abe5159f2c67fe1440544a7d81239f8eece34b 100644 --- a/src/packet/mDNS.py +++ b/src/packet/mDNS.py @@ -1,6 +1,5 @@ import random import scapy.all as scapy -from scapy.layers import dns from packet.DNS import DNS class mDNS(DNS): diff --git a/src/pcap_tweaker.py b/src/pcap_fuzzer.py similarity index 97% rename from src/pcap_tweaker.py rename to src/pcap_fuzzer.py index 521d9f0812691f9b68fc4402c54aaaacf8f8575e..f8ddfdd3026c272b2a81423c5655b47764d416c0 100644 --- a/src/pcap_tweaker.py +++ b/src/pcap_fuzzer.py @@ -45,7 +45,7 @@ def must_edit_packet(i: int, packet_numbers: list, random_range: int) -> bool: return is_specified or is_random -def tweak_pcaps(pcaps: list, output: str, random_range: int = 1, packet_numbers: list = None, dry_run: bool = False) -> None: +def fuzz_pcaps(pcaps: list, output: str, random_range: int = 1, packet_numbers: list = None, dry_run: bool = False) -> None: """ Main functionality of the program: (Randomly) edit packet fields in a (list of) PCAP file(s). @@ -95,7 +95,7 @@ def tweak_pcaps(pcaps: list, output: str, random_range: int = 1, packet_numbers: new_packets.append(Packet.rebuild_packet(packet)) break else: - d = my_packet.tweak() + d = my_packet.fuzz() if d is None: # Packet was not edited, try editing one layer lower last_layer_index = my_packet.get_layer_index() - 1 @@ -162,7 +162,7 @@ if __name__ == "__main__": ### MAIN PROGRAM ### - tweak_pcaps( + fuzz_pcaps( pcaps=args.input_pcaps, output=args.output, random_range=args.random_range,