diff --git a/AttackerCalc.py b/AttackerCalc.py index 4b01f9a..6b41a11 100644 --- a/AttackerCalc.py +++ b/AttackerCalc.py @@ -9,8 +9,8 @@ def __init__(self, pcap=None, list_of_packets=None, policy='first_ip', window_si self.filter = filter_ip self.number_of_ip = number_of_ip self.list_of_packets = list_of_packets - assert self.get_number_of_ip() == 1, "La classe non e' ancora implementata per riconoscere piu' attacanti" - assert self.get_window_size() > 0, "Dimensioni della finestra non valide" + assert self.get_number_of_ip() == 1, "Multiple attackers are not supported (yet)" + assert self.get_window_size() > 0, "Invalid window size (it must be >=1)" def compute_attacker(self): policy = self.get_policy() @@ -19,18 +19,18 @@ def compute_attacker(self): elif(policy == "max_in_window"): ip = self.max_in_window_policy() else: - print("Selezionare una policy.") + print("Please select a policy.") return ip def first_ip_policy(self): - assert self.list_of_packets is not None or self.pcap is not None, "Assegnare un pcap o una lista di pacchetti" - print("\n" + "Calcolo attaccante" + "\n") + assert self.list_of_packets is not None or self.pcap is not None, "No PCAP or packets list has been provided" + print("\n" + "Processing attacker information" + "\n") if(self.get_list_of_packets() is not None): pkts = self.get_list_of_packets() elif(self.get_pcap() is not None): pkts = rdpcap(self.get_pcap()) else: - print("Assegnare un pcap o una lista di pacchetti.") + print("No PCAP or packets list has been provided.") return [] ip_list = [] for i in range(0, len(pkts) - 1): @@ -45,14 +45,14 @@ def first_ip_policy(self): return ip_list def max_in_window_policy(self): - assert self.list_of_packets is not None or self.pcap is not None, "Assegnare un pcap o una lista di pacchetti" - print("\n" + "Calcolo attaccante" + "\n") + assert self.list_of_packets is not None or self.pcap is not None, "No PCAP or packets list has been provided" + print("\n" + "Processing attacker information" + "\n") if(self.get_list_of_packets() is not None): pkts = self.get_list_of_packets() elif(self.get_pcap() is not None): pkts = rdpcap(self.get_pcap()) else: - print("Assegnare un pcap o una lista di pacchetti.") + print("No PCAP or packets list has been provided.") return [] ip_dict = {} if(len(pkts) >= self.get_window_size()): @@ -71,7 +71,7 @@ def max_in_window_policy(self): else: pass else: - print("Fornita una finestra troppo piccola.") + print("Window size is too small") return [] def find_max_between_IP(ip_dict): @@ -103,7 +103,7 @@ def get_filter(self): return self.filter def add_ip_to_filter(self, list_of_ip): - assert isinstance(list_of_ip, list), "Inserire gli ip in una lista." + assert isinstance(list_of_ip, list), "IPs must be added to the filter in the form of a list" for ip in list_of_ip: self.filter.append(ip) diff --git a/CreateFeaturesHandler.py b/CreateFeaturesHandler.py index 77911f2..aa5d4a8 100644 --- a/CreateFeaturesHandler.py +++ b/CreateFeaturesHandler.py @@ -4,14 +4,15 @@ from PacketFilter import PacketFilter from AttackerCalc import AttackerCalc import glob +from concurrent.futures import ThreadPoolExecutor class CreateFeaturesHandler(): def __init__(self, pkts_window_size=10, single_csv=True): self.pkts_window_size = pkts_window_size - assert self.pkts_window_size >=1, "Valore per la finestra non valido" + assert self.pkts_window_size >=1, "Invalid window size (it must be >=1)" self.single_csv = single_csv - assert (self.single_csv is True) or (self.single_csv is False), "Valore non valido per il flag single_csv" + assert (self.single_csv is True) or (self.single_csv is False), "Invalid value for the single_csv option (it must be a boolean)" self.featuresCalc = FeaturesCalc(flow_type="malware", min_window_size=pkts_window_size) ip_to_ignore = ["127.0.0.1"] self.filter_1 = PacketFilter(ip_whitelist_filter=[], ip_blacklist_filter=ip_to_ignore, TCP=True) @@ -24,7 +25,7 @@ def __init__(self, pkts_window_size=10, single_csv=True): self.csv.create_empty_csv() self.csv.add_row(self.featuresCalc.get_features_name()) - def compute_features(self): + def compute_features(self, threads=1): def malware_features(): folder_name = "Pcaps_Malware" @@ -33,37 +34,42 @@ def malware_features(): pass else: self.featuresCalc.set_flow_type(flow_type) - for pcap in glob.glob(folder_name + "/" + "*.pcap"): - if(self.single_csv): - csv = self.csv - else: - pcap_name = pcap.split("/") - pcap_name = pcap_name[len(pcap_name)-1].replace(".pcap", "") - csv = CSV(file_name=pcap_name, folder_name="Malware_Features") - csv.create_empty_csv() - csv.add_row(self.featuresCalc.get_features_name()) - array_of_pkts = [] - print("\nCalcolo features di " + pcap + "\n") - attacker = AttackerCalc(pcap=pcap) - ip_to_consider = attacker.compute_attacker() - for filter in self.filters: - filter.set_ip_whitelist_filter(ip_to_consider) - pkts = rdpcap(pcap) - filter_res=[] - for pkt in pkts: + + def task(pcap): + if(self.single_csv): + csv = self.csv + else: + pcap_name = pcap.split("/") + pcap_name = pcap_name[len(pcap_name)-1].replace(".pcap", "") + csv = CSV(file_name=pcap_name, folder_name="Malware_Features") + csv.create_empty_csv() + csv.add_row(self.featuresCalc.get_features_name()) + array_of_pkts = [] + print("\nComputing features for " + pcap + "\n") + attacker = AttackerCalc(pcap=pcap) + ip_to_consider = attacker.compute_attacker() for filter in self.filters: - if(filter.check_packet_filter(pkt)): - filter_res.append(True) - else: - filter_res.append(False) - if(True in filter_res): - array_of_pkts.append(pkt) - if (len(array_of_pkts) >= self.featuresCalc.get_min_window_size()): - features = self.featuresCalc.compute_features(array_of_pkts) - csv.add_row(features) - array_of_pkts.clear() - filter_res.clear() + filter.set_ip_whitelist_filter(ip_to_consider) + pkts = rdpcap(pcap) + filter_res=[] + for pkt in pkts: + for filter in self.filters: + if(filter.check_packet_filter(pkt)): + filter_res.append(True) + else: + filter_res.append(False) + if(True in filter_res): + array_of_pkts.append(pkt) + if (len(array_of_pkts) >= self.featuresCalc.get_min_window_size()): + features = self.featuresCalc.compute_features(array_of_pkts) + csv.add_row(features) + array_of_pkts.clear() + filter_res.clear() + pcaps = glob.glob(folder_name + "/" + "*.pcap") + with ThreadPoolExecutor(max_workers=threads) as executor: + executor.map(task, pcaps) + def legitimate_features(): folder_name = "Pcaps_Legitimate" flow_type = "legitimate" @@ -73,7 +79,8 @@ def legitimate_features(): self.featuresCalc.set_flow_type(flow_type) for filter in self.filters: filter.set_ip_whitelist_filter([]) - for pcap in glob.glob(folder_name + "/" + "*.pcap"): + + def task(pcap): if(self.single_csv): csv = self.csv else: @@ -84,7 +91,7 @@ def legitimate_features(): csv.add_row(self.featuresCalc.get_features_name()) array_of_pkts = [] filter_res = [] - print("\nCalcolo features di " + pcap + "\n") + print("\nComputing features for " + pcap + "\n") pkts = rdpcap(pcap) for pkt in pkts: for filter in self.filters: @@ -99,6 +106,11 @@ def legitimate_features(): csv.add_row(features) array_of_pkts.clear() filter_res.clear() + + pcaps = glob.glob(folder_name + "/" + "*.pcap") + with ThreadPoolExecutor(max_workers=threads) as executor: + executor.map(task, pcaps) + malware_features() legitimate_features() diff --git a/FeaturesCalc.py b/FeaturesCalc.py index 061370d..72f1a6c 100644 --- a/FeaturesCalc.py +++ b/FeaturesCalc.py @@ -9,8 +9,8 @@ class FeaturesCalc(): def __init__(self, flow_type, min_window_size=2): self.flow_type = flow_type self.min_window_size = int(min_window_size) - assert self.flow_type == "malware" or self.flow_type == "legitimate", "Flow_type non valido. Valori validi sono malware o legitimate." - assert self.min_window_size > 0, "Valore non valido per min_windows_size. Deve essere maggiore di 0." + assert self.flow_type == "malware" or self.flow_type == "legitimate", "flow_type is invalid (must be either 'malware' or 'legitimate')" + assert self.min_window_size > 0, "Invalid min_windows_size (it must be >=0)." self.label = None if(self.flow_type == "malware"): self.label = self.malware_label @@ -88,7 +88,7 @@ def DNS_over_TCP_ratio(packets_list): else: total_packet_high_level_list.append(0.0) else: - print("Errore imprevisto in dnsOverTCPRatio()") + print("Unexpected error in dnsOverTCPRatio()") total_packet_high_level = float(sum(total_packet_high_level_list)) if (total_packet_high_level != 0): ratio_list.append(float(total_DNS / total_packet_high_level)) @@ -266,7 +266,7 @@ def compute_tcp_flags(packets_list): return (syn_counter, fin_counter, ack_counter, psh_counter, urg_counter, rst_counter) if(len(packets_list) < self.get_min_window_size()): - print("\nNumero di paccheti troppo basso\n") + print("\nPacket count in list is smaller than the minimum window size\n") return None else: syn_lst, fin_lst, ack_lst, psh_lst, urg_lst, rst_lst = compute_tcp_flags(packets_list) @@ -323,7 +323,7 @@ def get_min_window_size(self): return self.min_window_size def set_flow_type(self, flow_type): - assert self.flow_type == "malware" or self.flow_type == "legitimate", "Flow_type non valido. Valori validi sono malware o legitimate." + assert self.flow_type == "malware" or self.flow_type == "legitimate", "flow_type is invalid (must be either 'malware' or 'legitimate')" self.flow_type = flow_type if(self.flow_type == "malware"): self.label = self.malware_label diff --git a/Main.py b/Main.py index 34c9e0b..ef937af 100644 --- a/Main.py +++ b/Main.py @@ -2,7 +2,7 @@ def main(): cfh = CreateFeaturesHandler(single_csv=False) - cfh.compute_features() + cfh.compute_features(threads=1) if __name__== "__main__": main() \ No newline at end of file diff --git a/README.md b/README.md index 662cd7d..0e50b22 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,16 @@ if ((filter_2.check_packet_filter(pkt) or filter_1.check_packet_filter(pkt)) is ``` This code accepts a packet if it has a TCP Layer or UDP Layer. +## Multithreading +To set the number of threads, edit the following line in Main.py. Replace `` with the amount of threads that you want. Default is `1` thread. +``` +cfh.compute_features(threads=) +``` + ## Example Of Usage In Main.py file there is an example of usage of this program. You can run it with: ``` python3 Main.py ``` This file creates a single csv every run. So if you put 4 pcaps in a generic folder (or in both folders), the Main.py file creates a single csv with features of 4 (or 8) pcaps. +