From 2558938092109a78d7f684548ebf870d32d8d2bb Mon Sep 17 00:00:00 2001 From: Oxbian Date: Mon, 11 Nov 2024 12:22:29 -0500 Subject: [PATCH 01/18] feat: add demo docker-compose --- Demo/architecture.png | Bin 0 -> 73776 bytes Demo/docker-compose.yml | 84 ++++++++++++++++++++++++++++++++++++++++ README.md | 46 ++++++++++------------ 3 files changed, 104 insertions(+), 26 deletions(-) create mode 100644 Demo/architecture.png create mode 100644 Demo/docker-compose.yml diff --git a/Demo/architecture.png b/Demo/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f627471816eaea2589f98f59501be8c875e07d GIT binary patch literal 73776 zcmZU*1ys~)_dO2d07DO@C`fmUba!`13aCgoC_{ItbV`FDC4xvxgVHS_4bn(=|DU<< zz3+X$zyDfu*S(87e3&QBIs5Fr&qQdb$>U-@z(PSm!Btd{(LzDFV~2tQk%6IupV%xH zG@+nSp(x5o>L5)1WT2%JuaI?8ZmtW|e>0MZaln*Jh|!2a-?$6U`z9$tfN4#W7Q5*Zj2Cyvz20ovp37kKb0= zfF0Q+>F2A)(l3Dz=I2h5cEgS?7ydXlMmO62+VJydm<$N)hcZTJ)1f-j?p>X`3c4(Z z&(yzC9!M9YP3AOBvYq(cogwVLJp4ia;Loqe`-g{Lz3wbwIY`cSp`FOL ^^I6erh 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 Date: Mon, 11 Nov 2024 12:30:01 -0500 Subject: [PATCH 02/18] fix: redis -> mysql --- Demo/architecture.png | Bin 73776 -> 76180 bytes README.md | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Demo/architecture.png b/Demo/architecture.png index f9f627471816eaea2589f98f59501be8c875e07d..08bc882a5a53f9c511c43b43db63178acdae9557 100644 GIT binary patch literal 76180 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

cgVw$_$pMTwi9tb8%mK7 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 literal 73776 zcmZU*1ys~)_dO2d07DO@C`fmUba!`13aCgoC_{ItbV`FDC4xvxgVHS_4bn(=|DU<< zz3+X$zyDfu*S(87e3&QBIs5Fr&qQdb$>U-@z(PSm!Btd{(LzDFV~2tQk%6IupV%xH zG@+nSp(x5o>L5)1WT2%JuaI?8ZmtW|e>0MZaln*Jh|!2a-?$6U`z9$tfN4#W7Q5*Zj2Cyvz20ovp37kKb0= zfF0Q+>F2A)(l3Dz=I2h5cEgS?7ydXlMmO62+VJydm<$N)hcZTJ)1f-j?p>X`3c4(Z z&(yzC9!M9YP3AOBvYq(cogwVLJp4ia;Loqe`-g{Lz3wbwIY`cSp`FOL ^^I6erh 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 Date: Mon, 11 Nov 2024 14:13:06 -0500 Subject: [PATCH 03/18] feat: update docker compose & adding dockerfiles for each docker --- Demo/Dockerfiles/Dockerfile.attaquant | 13 +++++++++++ Demo/Dockerfiles/Dockerfile.cible | 12 +++++++++++ Demo/Dockerfiles/Dockerfile.idps | 12 +++++++++++ Demo/Dockerfiles/Dockerfile.ids | 12 +++++++++++ Demo/docker-compose.yml | 31 ++++++++++++++++++--------- README.md | 10 +++++++-- 6 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 Demo/Dockerfiles/Dockerfile.attaquant create mode 100644 Demo/Dockerfiles/Dockerfile.cible create mode 100644 Demo/Dockerfiles/Dockerfile.idps create mode 100644 Demo/Dockerfiles/Dockerfile.ids diff --git a/Demo/Dockerfiles/Dockerfile.attaquant b/Demo/Dockerfiles/Dockerfile.attaquant new file mode 100644 index 0000000..aa5466f --- /dev/null +++ b/Demo/Dockerfiles/Dockerfile.attaquant @@ -0,0 +1,13 @@ +FROM python:alpine3.20 + +# Installation des paquets nécessaires pour scapy +RUN apk -U upgrade && \ + apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev nmap +RUN pip install scapy + +# Copier le script d'attaque +#COPY attack.py /attack.py + +# Lancer le script d'attaque +#CMD ["python", "/attack.py"] + diff --git a/Demo/Dockerfiles/Dockerfile.cible b/Demo/Dockerfiles/Dockerfile.cible new file mode 100644 index 0000000..c10bf58 --- /dev/null +++ b/Demo/Dockerfiles/Dockerfile.cible @@ -0,0 +1,12 @@ +FROM python:alpine3.20 + +# Installation des paquets nécessaires pour scapy +RUN apk -U upgrade && \ + apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev +RUN pip install scapy + +# Copier le script de détection d'attaques +#COPY cible.py /cible.py + +# Lancer le script de détection +#CMD ["python", "/cible.py"] diff --git a/Demo/Dockerfiles/Dockerfile.idps b/Demo/Dockerfiles/Dockerfile.idps new file mode 100644 index 0000000..0f84f02 --- /dev/null +++ b/Demo/Dockerfiles/Dockerfile.idps @@ -0,0 +1,12 @@ +FROM python:alpine3.20 + +# Installation des paquets nécessaires pour scapy +RUN apk -U upgrade && \ + apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev +RUN pip install scapy + +# Copier le script de l'idps +#COPY idps.py /idps.py + +# Lancer le script de détection +#CMD ["python", "/idps.py"] diff --git a/Demo/Dockerfiles/Dockerfile.ids b/Demo/Dockerfiles/Dockerfile.ids new file mode 100644 index 0000000..201b37f --- /dev/null +++ b/Demo/Dockerfiles/Dockerfile.ids @@ -0,0 +1,12 @@ +FROM python:alpine3.20 + +# Installation des paquets nécessaires pour scapy +RUN apk -U upgrade && \ + apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev +RUN pip install scapy + +# Copier le script de la sonde IDS +#COPY ids.py /ids.py + +# Lancer le script de la sonde IDS +#CMD ["python", "/ids.py"] diff --git a/Demo/docker-compose.yml b/Demo/docker-compose.yml index 1197f5d..ccc268a 100644 --- a/Demo/docker-compose.yml +++ b/Demo/docker-compose.yml @@ -2,7 +2,9 @@ version: "3.8" services: # Attaquant 1 atk1: - image: python:alpine3.20 + build: + context: Dockerfiles/. + dockerfile: Dockerfile.attaquant container_name: attaquant1 command: sleep infinity networks: @@ -12,7 +14,9 @@ services: # IDPS idps: - image: python:alpine3.20 + build: + context: Dockerfiles/. + dockerfile: Dockerfile.idps container_name: idps command: sleep infinity cap_add: @@ -27,7 +31,9 @@ services: # Cible cible: - image: python:alpine3.20 + build: + context: Dockerfiles/. + dockerfile: Dockerfile.cible container_name: cible command: sleep infinity networks: @@ -37,7 +43,9 @@ services: # Attaquant 2 atk2: - image: python:alpine3.20 + build: + context: Dockerfiles/. + dockerfile: Dockerfile.attaquant container_name: attaquant2 command: sleep infinity networks: @@ -45,16 +53,19 @@ services: ipv4_address: 172.20.2.4 restart: unless-stopped + # Sonde IDS ids: - image: python:alpine3.20 + build: + context: Dockerfiles/. + dockerfile: Dockerfile.ids container_name: ids command: sleep infinity cap_add: - NET_ADMIN - NET_RAW - networks: - net_private: - ipv4_address: 172.20.2.5 + #networks: + #net_private: + #ipv4_address: 172.20.2.5 # Network mode host obligatoire pour que la sonde puisse sniffer le réseau network_mode: host restart: unless-stopped @@ -74,11 +85,11 @@ services: networks: net_public: driver: bridge - ipam: + ipam: config: - subnet: 172.20.1.0/24 net_private: driver: bridge - ipam: + ipam: config: - subnet: 172.20.2.0/24 diff --git a/README.md b/README.md index 82e9ae2..90dc920 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,16 @@ Puis executer le script `tests/cef-generator.py` avec le python3 du l'environnem Ce projet étant réaliser dans le cadre d'un cours à l'université, une démonstration est donc nécessaire. Ci-dessous, le schéma de l'architecture réseau de la démonstration: -![Architecture réseau démo](Demo/architecture.png) +![Architecture réseau démo](Demo/architecture.png) -Cette démonstration peut être déployer facilement grâce à un docker-compose `Demo/docker-compose.yml`. +Cette démonstration peut être déployer facilement grâce à un docker-compose `Demo/docker-compose.yml`. +Pour lancer cette démonstration, il faudra avoir `docker` & `docker compose` d'installer. Puis executer les commandes suivantes: + +```bash +cd Demo/ +docker compose up -d +``` ## TODO From 19d007dfffcb1b2eaf3a45ebb41b1c965e58882d Mon Sep 17 00:00:00 2001 From: Oxbian Date: Thu, 14 Nov 2024 12:08:34 -0500 Subject: [PATCH 04/18] =?UTF-8?q?feat:=20idps=20+=20d=C3=A9tection=20scan?= =?UTF-8?q?=20TCPConnect,=20SynScan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Demo/Dockerfiles/Dockerfile.idps | 13 ++- Demo/docker-compose.yml | 8 +- README.md | 2 +- idps/main.py | 108 +++++++++++++++++++++++ idps/rules/TCP/Scan/synscan.py | 8 ++ idps/rules/TCP/Scan/tcpconnectscan.py | 8 ++ idps/tcp.py | 118 ++++++++++++++++++++++++++ 7 files changed, 257 insertions(+), 8 deletions(-) create mode 100644 idps/main.py create mode 100644 idps/rules/TCP/Scan/synscan.py create mode 100644 idps/rules/TCP/Scan/tcpconnectscan.py create mode 100644 idps/tcp.py diff --git a/Demo/Dockerfiles/Dockerfile.idps b/Demo/Dockerfiles/Dockerfile.idps index 0f84f02..84a1179 100644 --- a/Demo/Dockerfiles/Dockerfile.idps +++ b/Demo/Dockerfiles/Dockerfile.idps @@ -6,7 +6,14 @@ RUN apk -U upgrade && \ RUN pip install scapy # Copier le script de l'idps -#COPY idps.py /idps.py +WORKDIR /app -# Lancer le script de détection -#CMD ["python", "/idps.py"] +# Copier le contenu du répertoire 'idps' du contexte de build vers '/app/idps' dans le conteneur +COPY idps /app/idps + +# Autres commandes nécessaires pour ton projet +# Par exemple, pour installer des dépendances : +# RUN pip install -r /app/idps/requirements.txt (si applicable) + +# Commande par défaut +CMD ["python", "/app/idps/main.py"] diff --git a/Demo/docker-compose.yml b/Demo/docker-compose.yml index ccc268a..af62119 100644 --- a/Demo/docker-compose.yml +++ b/Demo/docker-compose.yml @@ -3,8 +3,8 @@ services: # Attaquant 1 atk1: build: - context: Dockerfiles/. - dockerfile: Dockerfile.attaquant + context: .. + dockerfile: Demo/Dockerfiles/Dockerfile.attaquant container_name: attaquant1 command: sleep infinity networks: @@ -15,8 +15,8 @@ services: # IDPS idps: build: - context: Dockerfiles/. - dockerfile: Dockerfile.idps + context: .. + dockerfile: Demo/Dockerfiles/Dockerfile.idps container_name: idps command: sleep infinity cap_add: diff --git a/README.md b/README.md index 90dc920..0706ab2 100644 --- a/README.md +++ b/README.md @@ -62,4 +62,4 @@ docker compose up -d - Noyau d'analyse de l'IDS - Interface web pour visualiser les alertes / rechercher dedans -- Moteur de corrélation des alertes (récupération + renvoi dans MySQL). +- Moteur de corrélation des alertes (récupération + renvoi dans MySQL). diff --git a/idps/main.py b/idps/main.py new file mode 100644 index 0000000..d5d1849 --- /dev/null +++ b/idps/main.py @@ -0,0 +1,108 @@ +from scapy.all import sniff, TCP, IP +from scapy.config import conf +conf.debug_dissector = 2 +import importlib.util +import os +import time +import tcp + + +def load_rules(rules_dirpath = "/app/idps/rules"): + """Charger les fonctions de règles du répertoire de règles et des sous répertoires""" + + if not os.path.exists(rules_dirpath): + raise ValueError(f"Le chemin spécifié n'existe pas: {rules_dirpath}") + + if not os.path.isdir(rules_dirpath): + raise ValueError(f"Le chemin spécifié n'est pas un répertoire: {rules_dirpath}") + + rules_functions = {} + # Liste de répertoires à explorer + dirs_to_explore = [rules_dirpath] + + # Explorer chaque répertoire / sous répertoire à la rechercher de fichier de règles + while dirs_to_explore: + current_dir = dirs_to_explore.pop() + + try: + for entry in os.scandir(current_dir): + # Ignorer les liens symboliques + if entry.is_symlink(): + continue + + # Ajouter les répertoires dans la liste à explorer + if entry.is_dir(): + dirs_to_explore.append(entry.path) + elif entry.is_file() and entry.name.endswith(".py"): + # Suppression de l'extension .py + module_name = entry.name[:-3] + + # Déterminer le protocole à partir du répertoire parent + if "TCP" in entry.path: + parent_dir = "TCP" + else: + parent_dir = "WTF" + + if parent_dir not in rules_functions: + rules_functions[parent_dir] = [] + + # Chargement du module + spec = importlib.util.spec_from_file_location(module_name, entry.path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + + # Vérification que le module possède bien la fonction rule + if hasattr(module, "rule"): + rules_functions[parent_dir].append(module.rule) + + except PermissionError: + print(f"Permission refusée pour accéder au répertoire: {current_dir}") + except OSError as e: + print(f"Erreur lors de l'accès au répertoire {current_dir}: {e}") + + return rules_functions + + +def check_frame_w_rules(packet, rules_functions, packets): + """Appliquer chaque règle des fonctions au paquet capturé.""" + + for rule_func in rules_functions: + try: + rule_func(packet, packets) + except Exception as e: + print(f"Erreur lors de l'exécution de la règle : {e}") + + +def packet_callback(packet, rules_functions, tcp_packets): + #print(packet) + if IP in packet and TCP in packet: + tcp_packets.add_packet(packet[IP].src, packet[TCP].sport, packet[IP].dst, packet[TCP].dport, packet[TCP].flags, time.time()) + #print(tcp_packets[packet[IP].src]) + check_frame_w_rules(packet, rules_functions['TCP'], tcp_packets) + tcp_packets.clean_old_packets() + + +def start_idps(IDS_IFACES = ["eth0","eth1"]): + """Charge les règles et démarre l'IDPS""" + print(f"Chargement des règles...") + rules_functions = load_rules() + print(f"Les règles sont chargées") + + # Opti possible: charger les règles par protocole, permettant des filtrages et donc optimiser + # le nombre de fonctions vérifiant le paquet (snort s'arrête à la première corrélation par exemple) + + tcp_packets = tcp.TCP(300) + + # Lancer scapy & envoyer le paquet à chaque règle de l'IDPS + sniff(iface=IDS_IFACES, prn=lambda packet: packet_callback(packet, rules_functions, tcp_packets), store=0) + #wrpcap("idps.pcap", capture) + + +def main(): + print(f"Démarrage de l'IDPS") + start_idps() + print(f"IDPS opérationel") + + +if __name__ == "__main__": + main() diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py new file mode 100644 index 0000000..7f3b45f --- /dev/null +++ b/idps/rules/TCP/Scan/synscan.py @@ -0,0 +1,8 @@ +# Seuils +TIME_WINDOW = 180 +NB_SEUIL = 5 + + +def rule(packet, tcp_packets): + if (tcp_packets.count_packet_of_type("RA", TIME_WINDOW) + tcp_packets.count_packet_of_type("SA", TIME_WINDOW)) + tcp_packets.count_packet_of_type("R", TIME_WINDOW) >= NB_SEUIL: + print(f"Alerte, seuil dépassés, risque de SynScan") diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py new file mode 100644 index 0000000..ddcba16 --- /dev/null +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -0,0 +1,8 @@ +# Seuils +TIME_WINDOW = 180 # 180 secondes pour avoir X paquets +NB_SEUIL = 5 + + +def rule(packet, tcp_packets): + if (tcp_packets.count_packet_of_type("A", TIME_WINDOW) + tcp_packets.count_packet_of_type("RA", TIME_WINDOW)) >= NB_SEUIL: + print(f"Alerte, seuils dépassés, risque de TCPConnectScan") diff --git a/idps/tcp.py b/idps/tcp.py new file mode 100644 index 0000000..a2ea321 --- /dev/null +++ b/idps/tcp.py @@ -0,0 +1,118 @@ +import time + + +class TCP: + def __init__(self, clean_time=300): + """Constructeur de la classe TCP + @param clean_time: temps avant qu'un paquet soit nettoyé""" + + self.packets = {} + self.clean_time = clean_time + + def add_packet(self, ip_src, port_src, ip_dst, port_dst, flags, timestamp): + """Ajoute le suivi d'un paquet dans le dictionnaire""" + + # Initialisation de la liste de paquets pour l'IP source + if ip_src not in self.packets: + self.packets[ip_src] = [] + + if flags == "S": + self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + return + + elif flags == "SA": + i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S", True) + + if i is not None: + self.packets[ip_dst][i][3] = "SA" + self.packets[ip_dst][i][4] = timestamp + return + else: + self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + return + + elif flags == "A": + i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "SA") + if i is None: + i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "R", True) + + if i is not None: + self.packets[ip_src][i][3] = "A" + self.packets[ip_src][i][4] = timestamp + return + else: + self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + return + + elif flags == "RA": + i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") + + if i is None: + i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") + + if i is not None: + self.packets[ip_src][i][3] = "RA" + self.packets[ip_src][i][4] = timestamp + return + else: + self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + return + + elif flags == "R": + i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") + + if i is None: + i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") + + if i is not None: + self.packets[ip_src][i][3] = "R" + self.packets[ip_src][i][4] = timestamp + return + else: + self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + return + + def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags, reverse=False): + """Cherche l'indice du paquet dont le flag doit être remplacé""" + if reverse is True: + ip_src, ip_dst = ip_dst, ip_src + port_src, port_dst = port_dst, port_src + + for i, [p_s, ip_d, p_d, f, stamp] in enumerate(self.packets[ip_src]): + if p_s == port_src and ip_d == ip_dst and p_d == port_dst and f == flags: + return i + return None + + def clean_old_packets(self): + """Supprime les paquets qui date de plus longtemps que le temps de clean""" + current_timestamp = time.time() + + # Parcours chaque ip_source de la liste + for ip_src in list(self.packets.keys()): + + # Vérification si le paquet doit être supprimé ou non + i = 0 + while i < len(self.packets[ip_src]): + packet = self.packets[ip_src][i] + if packet[4] <= current_timestamp - self.clean_time: + del self.packets[ip_src][i] + else: + i += 1 + + # Suppression de la case de l'ip source si elle n'existe plus + if not self.packets[ip_src]: + del self.packets[ip_src] + + def count_packet_of_type(self, flag, time_treshold): + """Compte les paquets qui ont le flag choisi et qui sont dans la fenêtre de temps""" + count = 0 + + current_timestamp = time.time() + for ip in list(self.packets.keys()): + for packet in self.packets[ip]: + if packet[3] == flag and packet[4] >= current_timestamp - time_treshold: + count += 1 + return count + + def __getitem__(self, src_ip): + return self.packets.get(src_ip, None) From dbc65f13bce05def78f11ab3c00f5be659bb9cf1 Mon Sep 17 00:00:00 2001 From: SofianeElNaggar Date: Thu, 14 Nov 2024 16:34:17 -0500 Subject: [PATCH 05/18] Create base.sql --- BDD/base.sql | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 BDD/base.sql diff --git a/BDD/base.sql b/BDD/base.sql new file mode 100644 index 0000000..ed72cee --- /dev/null +++ b/BDD/base.sql @@ -0,0 +1,19 @@ +CREATE TABLE alertes ( + id SERIAL PRIMARY KEY, -- Identifiant unique pour chaque alerte + cef_version VARCHAR(10) DEFAULT 'CEF:0', -- Version du format CEF utilisé + date_alerte TIMESTAMP(3) NOT NULL, -- Date et heure de l'alerte avec une précision de millisecondes + event_gravite INT CHECK (event_gravite >= 0 AND event_gravite <= 10), -- Niveau de gravité de l'alerte sur une échelle de 0 à 10 + device_product VARCHAR(63), -- Nom du produit à l'origine de l'alerte + device_vendor VARCHAR(63), -- Nom du fournisseur ou fabricant du produit + device_version VARCHAR(31), -- Version du produit ou dispositif ayant généré l'alerte + alerte_name VARCHAR(512), -- Nom descriptif de l'alerte + destinationAddress VARCHAR(45), -- Adresse IP de destination impliquée dans l'alerte + sourceAddress VARCHAR(45), -- Adresse IP source impliquée dans l'alerte + destinationPort INT, -- Port de destination utilisé pour l'événement ou l'alerte + sourcePort INT, -- Port source de l'événement ou de l'alerte + protocol VARCHAR(10), -- Protocole réseau impliqué (ex : TCP, UDP) + applicationProtocol VARCHAR(20), -- Protocole applicatif impliqué (ex : HTTP, FTP) + reason TEXT, -- Description de la raison de l'alerte expliquant pourquoi elle a été générée + action VARCHAR(50), -- Action entreprise en réponse à l'alerte (ex : bloqué, alerté uniquement, ...) + commentaire TEXT -- Champ texte pour des notes ou commentaires additionnels concernant l'alerte +); From 2d25387fde16dd905612c73cbc83ca293dee9870 Mon Sep 17 00:00:00 2001 From: Oxbian Date: Mon, 18 Nov 2024 17:59:10 -0500 Subject: [PATCH 06/18] feat: config file + database connection / dockerfile --- Demo/Dockerfiles/Dockerfile.db | 5 + Demo/Dockerfiles/Dockerfile.idps | 5 +- Demo/Dockerfiles/Dockerfile.ids | 14 ++- Demo/docker-compose.yml | 11 +- config.json | 13 +++ idps/database.py | 64 +++++++++++ idps/main.py | 65 ++++++++--- idps/rules/TCP/Scan/synscan.py | 14 ++- idps/rules/TCP/Scan/tcpconnectscan.py | 15 ++- idps/tcp.py | 27 +++-- requirements.txt | 4 +- sql/adduser.sql | 5 + sql/cef-generator.py | 156 ++++++++++++++++++++++++++ BDD/base.sql => sql/db-schema.sql | 12 +- sql/init.sql | 35 ++++++ tests/cef-generator.py | 102 ----------------- 16 files changed, 397 insertions(+), 150 deletions(-) create mode 100644 Demo/Dockerfiles/Dockerfile.db create mode 100644 config.json create mode 100644 idps/database.py create mode 100644 sql/adduser.sql create mode 100644 sql/cef-generator.py rename BDD/base.sql => sql/db-schema.sql (80%) create mode 100644 sql/init.sql delete mode 100644 tests/cef-generator.py diff --git a/Demo/Dockerfiles/Dockerfile.db b/Demo/Dockerfiles/Dockerfile.db new file mode 100644 index 0000000..27ab9f8 --- /dev/null +++ b/Demo/Dockerfiles/Dockerfile.db @@ -0,0 +1,5 @@ +FROM mysql:latest + +# Copier le script SQL dans l'image +COPY sql/init.sql /docker-entrypoint-initdb.d/ + diff --git a/Demo/Dockerfiles/Dockerfile.idps b/Demo/Dockerfiles/Dockerfile.idps index 84a1179..330bba4 100644 --- a/Demo/Dockerfiles/Dockerfile.idps +++ b/Demo/Dockerfiles/Dockerfile.idps @@ -3,7 +3,7 @@ FROM python:alpine3.20 # Installation des paquets nécessaires pour scapy RUN apk -U upgrade && \ apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev -RUN pip install scapy +RUN pip install scapy mysql-connector-python # Copier le script de l'idps WORKDIR /app @@ -11,6 +11,9 @@ WORKDIR /app # Copier le contenu du répertoire 'idps' du contexte de build vers '/app/idps' dans le conteneur COPY idps /app/idps +# Copie du fichier de configuration +COPY config.json /app/config.json + # Autres commandes nécessaires pour ton projet # Par exemple, pour installer des dépendances : # RUN pip install -r /app/idps/requirements.txt (si applicable) diff --git a/Demo/Dockerfiles/Dockerfile.ids b/Demo/Dockerfiles/Dockerfile.ids index 201b37f..2a91158 100644 --- a/Demo/Dockerfiles/Dockerfile.ids +++ b/Demo/Dockerfiles/Dockerfile.ids @@ -3,10 +3,16 @@ FROM python:alpine3.20 # Installation des paquets nécessaires pour scapy RUN apk -U upgrade && \ apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev -RUN pip install scapy +RUN pip install scapy mysql-connector-python -# Copier le script de la sonde IDS -#COPY ids.py /ids.py +# Copier le script de l'idps +WORKDIR /app + +# Copier le contenu du répertoire 'idps' du contexte de build vers '/app/idps' dans le conteneur +COPY idps /app/ids + +# Copie du fichier de configuration +COPY config.json /app/config.json # Lancer le script de la sonde IDS -#CMD ["python", "/ids.py"] +CMD ["python3", "/app/ids/ids.py"] diff --git a/Demo/docker-compose.yml b/Demo/docker-compose.yml index af62119..596459f 100644 --- a/Demo/docker-compose.yml +++ b/Demo/docker-compose.yml @@ -56,8 +56,8 @@ services: # Sonde IDS ids: build: - context: Dockerfiles/. - dockerfile: Dockerfile.ids + context: .. + dockerfile: Demo/Dockerfiles/Dockerfile.ids container_name: ids command: sleep infinity cap_add: @@ -72,11 +72,14 @@ services: # BDD d'alertes alert_db: - image: mysql:5.7 + build: + context: .. + dockerfile: Demo/Dockerfiles/Dockerfile.db container_name: alert_db environment: MYSQL_ROOT_PASSWORD: root - MYSQL_DATABASE: alert_db + ports: + - "3306:3306" networks: net_private: ipv4_address: 172.20.2.10 diff --git a/config.json b/config.json new file mode 100644 index 0000000..10aac78 --- /dev/null +++ b/config.json @@ -0,0 +1,13 @@ +{ + "rules_dirpath": "/app/idps/rules", + "ifaces": ["eth0", "eth1"], + "db_host": "172.20.2.10", + "db_database": "sidps", + "db_user": "sidps", + "db_password": "SUPERPASSWORD", + "db_port": "3306", + "synscan_time": 180, + "synscan_count": 5, + "tcpconnectscan_time": 180, + "tcpconnectscan_count": 5 +} diff --git a/idps/database.py b/idps/database.py new file mode 100644 index 0000000..291c595 --- /dev/null +++ b/idps/database.py @@ -0,0 +1,64 @@ +import mysql.connector + + +class Database: + """Classe pour effectuer les actions liées à la base de données (envoi d'alertes...)""" + + def __init__(self, config): + """Connexion à la base de données à partir des identifiants dans la config""" + self.conn = mysql.connector.connect(host=config["db_host"], database=config["db_database"], user=config["db_user"], password=config["db_password"], port=config["db_port"]) + self.config = config + + def send_alert(self, alert): + """Ajoute une alerte dans la base de données + @param alert: Alerte à rajouter dans la BDD""" + + try: + cursor = self.conn.cursor() + sql_query = """ + INSERT INTO alertes ( + cef_version, date_alerte, event_gravite, device_product, + device_vendor, device_version, alerte_name, sourceAddress, + destinationAddress, destinationPort, sourcePort, protocol, + applicationProtocol, reason, action, commentaire + ) VALUES ( + %(cef_version)s, %(date_alerte)s, %(event_gravite)s, %(device_product)s, + %(device_vendor)s, %(device_version)s, %(alerte_name)s, %(src)s, + %(dst)s, %(destinationPort)s, %(sourcePort)s, %(protocol)s, + %(applicationProtocol)s, %(reason)s, %(action)s, %(commentaire)s + ); + """ + + # Paramètres pour la requête SQL + params = { + "cef_version": alert["CEF"], + "date_alerte": alert["datetime"], + "event_gravite": alert["agent_severity"], + "device_product": alert["Device Product"], + "device_vendor": alert["Device Vendor"], + "device_version": alert["Device Version"], + "alerte_name": alert["name"], + "src": alert["src"], + "dst": alert["dst"], + "destinationPort": alert["dstPort"], + "sourcePort": alert["srcPort"], + "protocol": alert["protocol"], + "applicationProtocol": alert["applicationProtocol"], + "reason": alert["reason"], + "action": alert["action"], + "commentaire": alert["commentaire"] + } + + # Exécution de la requête d'insertion + cursor.execute(sql_query, params) + self.conn.commit() + cursor.close() + except mysql.connector.Error as err: + print("Erreur lors de l'envoi de l'alerte: {}".format(err)) + + def get_key(self, key, default_val): + """Donne le contenue d'un paramètre spécifique de la config + @param key: clé du paramètre souhaité + @param default_val: valeur par défaut si la clé n'existe pas""" + + return self.config.get(key, None) diff --git a/idps/main.py b/idps/main.py index d5d1849..664bb47 100644 --- a/idps/main.py +++ b/idps/main.py @@ -1,14 +1,19 @@ from scapy.all import sniff, TCP, IP from scapy.config import conf conf.debug_dissector = 2 + import importlib.util import os import time import tcp +import database +import json def load_rules(rules_dirpath = "/app/idps/rules"): - """Charger les fonctions de règles du répertoire de règles et des sous répertoires""" + """Charger les fonctions de règles du répertoire de règles et des sous répertoires + @param rules_dirpath: Répertoire contenant les fichiers python de règles + """ if not os.path.exists(rules_dirpath): raise ValueError(f"Le chemin spécifié n'existe pas: {rules_dirpath}") @@ -56,52 +61,84 @@ def load_rules(rules_dirpath = "/app/idps/rules"): rules_functions[parent_dir].append(module.rule) except PermissionError: - print(f"Permission refusée pour accéder au répertoire: {current_dir}") + raise PermissionError(f"Permission refusée pour accéder au répertoire: {current_dir}") except OSError as e: - print(f"Erreur lors de l'accès au répertoire {current_dir}: {e}") + raise OSError(f"Erreur lors de l'accès au répertoire {current_dir}: {e}") return rules_functions -def check_frame_w_rules(packet, rules_functions, packets): - """Appliquer chaque règle des fonctions au paquet capturé.""" +def check_frame_w_rules(packet, rules_functions, packets, db): + """Appliquer chaque règle des fonctions au paquet capturé. + @param packet: Paquet actuel à analyser + @param rules_functions: liste de fonctions de règles + @param packets: liste des paquets précédents (utile pour TCP) + @param db: Objet database pour envoyer les alertes à la BDD + """ for rule_func in rules_functions: try: - rule_func(packet, packets) + rule_func(packet, packets, db) except Exception as e: print(f"Erreur lors de l'exécution de la règle : {e}") -def packet_callback(packet, rules_functions, tcp_packets): +def packet_callback(packet, rules_functions, tcp_packets, db): + """Callback réception d'un paquet + @param packet: Paquet actuel à classer + @param rules_functions: liste des fonctions de règles + @param tcp_packets: Objet contenant une liste des paquets tcp précédents + @param db: Objet database pour envoyer des alertes à la BDD + """ + #print(packet) if IP in packet and TCP in packet: tcp_packets.add_packet(packet[IP].src, packet[TCP].sport, packet[IP].dst, packet[TCP].dport, packet[TCP].flags, time.time()) - #print(tcp_packets[packet[IP].src]) - check_frame_w_rules(packet, rules_functions['TCP'], tcp_packets) + print(tcp_packets[packet[IP].src]) + check_frame_w_rules(packet, rules_functions['TCP'], tcp_packets, db) tcp_packets.clean_old_packets() -def start_idps(IDS_IFACES = ["eth0","eth1"]): +def read_config(config_filepath='config.json'): + """Charge les configurations depuis le fichier de config""" + + try: + with open(config_filepath, 'r', encoding='utf-8') as file: + config = json.load(file) + return config + except FileNotFoundError: + raise FileNotFoundError(f"Le fichier JSON {config_filepath} n'a pas été trouvé.") + except json.JSONDecodeError: + raise json.JSONDecodeError("Erreur lors de la lecture du fichier JSON. Le format peut être incorrect.") + + +def start_idps(): """Charge les règles et démarre l'IDPS""" + + print(f"Récupération des configurations") + config = read_config() + print(f"Configurations chargées") + print(f"Chargement des règles...") - rules_functions = load_rules() + rules_functions = load_rules(config["rules_dirpath"]) print(f"Les règles sont chargées") + print(f"Connexion à la base de données") + db = database.Database(config) + print(f"Connexion réussite à la base de données") + # Opti possible: charger les règles par protocole, permettant des filtrages et donc optimiser # le nombre de fonctions vérifiant le paquet (snort s'arrête à la première corrélation par exemple) tcp_packets = tcp.TCP(300) # Lancer scapy & envoyer le paquet à chaque règle de l'IDPS - sniff(iface=IDS_IFACES, prn=lambda packet: packet_callback(packet, rules_functions, tcp_packets), store=0) - #wrpcap("idps.pcap", capture) + sniff(iface=config["ifaces"], prn=lambda packet: packet_callback(packet, rules_functions, tcp_packets, db), store=0) def main(): print(f"Démarrage de l'IDPS") start_idps() - print(f"IDPS opérationel") if __name__ == "__main__": diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py index 7f3b45f..de69fc5 100644 --- a/idps/rules/TCP/Scan/synscan.py +++ b/idps/rules/TCP/Scan/synscan.py @@ -1,8 +1,12 @@ -# Seuils -TIME_WINDOW = 180 -NB_SEUIL = 5 +def rule(packet, tcp_packets, db): + """Règle SYNScan: + Un SYNScan va envoyer des requêtes TCP avec le flag SYN + Si le port est ouvert alors le serveur répondra: Syn ACK, puis le client Reset la connexion + Sinon le port est fermé et le serveur répondera: Reset ACK + """ + time_window = db.get_key("synscan_time", 180) + seuil = db.get_key("synscan_count", 5) -def rule(packet, tcp_packets): - if (tcp_packets.count_packet_of_type("RA", TIME_WINDOW) + tcp_packets.count_packet_of_type("SA", TIME_WINDOW)) + tcp_packets.count_packet_of_type("R", TIME_WINDOW) >= NB_SEUIL: + if (tcp_packets.count_packet_of_type("RA", time_window) + tcp_packets.count_packet_of_type("SA", time_window)) + tcp_packets.count_packet_of_type("R", time_window) >= seuil: print(f"Alerte, seuil dépassés, risque de SynScan") diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py index ddcba16..b21bffa 100644 --- a/idps/rules/TCP/Scan/tcpconnectscan.py +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -1,8 +1,11 @@ -# Seuils -TIME_WINDOW = 180 # 180 secondes pour avoir X paquets -NB_SEUIL = 5 +def rule(packet, tcp_packets, db): + """Règle TCPConnect Scan: + Un scan TCP connect va effectuer une connexion TCP en entier sur chaque port scanné. + Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset -> ACK + Sinon le port est fermé et le serveur refusera la connexion SYN -> Reset ACK + """ + time_window = db.get_key("tcpconnectscan_time", 180) + seuil = db.get_key("tcpconnectscan_count", 5) - -def rule(packet, tcp_packets): - if (tcp_packets.count_packet_of_type("A", TIME_WINDOW) + tcp_packets.count_packet_of_type("RA", TIME_WINDOW)) >= NB_SEUIL: + if (tcp_packets.count_packet_of_type("A", time_window) + tcp_packets.count_packet_of_type("RA", time_window)) >= seuil: print(f"Alerte, seuils dépassés, risque de TCPConnectScan") diff --git a/idps/tcp.py b/idps/tcp.py index a2ea321..b113495 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -17,18 +17,18 @@ class TCP: self.packets[ip_src] = [] if flags == "S": - self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) return elif flags == "SA": i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S", True) if i is not None: - self.packets[ip_dst][i][3] = "SA" + self.packets[ip_dst][i][3].append("SA") self.packets[ip_dst][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) return elif flags == "A": @@ -37,11 +37,11 @@ class TCP: i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "R", True) if i is not None: - self.packets[ip_src][i][3] = "A" + self.packets[ip_src][i][3].append("A") self.packets[ip_src][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) return elif flags == "RA": @@ -51,11 +51,11 @@ class TCP: i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - self.packets[ip_src][i][3] = "RA" + self.packets[ip_src][i][3].append("RA") self.packets[ip_src][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) return elif flags == "R": @@ -65,11 +65,11 @@ class TCP: i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - self.packets[ip_src][i][3] = "R" + self.packets[ip_src][i][3].append("R") self.packets[ip_src][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, flags, timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) return def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags, reverse=False): @@ -78,8 +78,11 @@ class TCP: ip_src, ip_dst = ip_dst, ip_src port_src, port_dst = port_dst, port_src + if ip_src not in self.packets.keys(): + return None + for i, [p_s, ip_d, p_d, f, stamp] in enumerate(self.packets[ip_src]): - if p_s == port_src and ip_d == ip_dst and p_d == port_dst and f == flags: + if p_s == port_src and ip_d == ip_dst and p_d == port_dst and f in flags: return i return None @@ -110,9 +113,11 @@ class TCP: current_timestamp = time.time() for ip in list(self.packets.keys()): for packet in self.packets[ip]: - if packet[3] == flag and packet[4] >= current_timestamp - time_treshold: + if flag in packet[3] and packet[4] >= current_timestamp - time_treshold: count += 1 return count def __getitem__(self, src_ip): + """Retourne la liste des paquets liés à une adresse IP, pour du déboggage""" + return self.packets.get(src_ip, None) diff --git a/requirements.txt b/requirements.txt index f6832c6..6429e50 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -hiredis==3.0.0 -redis==5.2.0 +mysql-connector-python==9.1.0 +scapy=2.6.1 diff --git a/sql/adduser.sql b/sql/adduser.sql new file mode 100644 index 0000000..072ffed --- /dev/null +++ b/sql/adduser.sql @@ -0,0 +1,5 @@ +CREATE DATABASE sidps DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +CREATE USER 'sidps'@'localhost' IDENTIFIED BY 'SUPERPASSWORD'; +GRANT ALL PRIVILEGES ON sidps.* TO 'sidps'@'localhost'; +FLUSH PRIVILEGES; +use sidps; diff --git a/sql/cef-generator.py b/sql/cef-generator.py new file mode 100644 index 0000000..edd512b --- /dev/null +++ b/sql/cef-generator.py @@ -0,0 +1,156 @@ +# Générateur d'alertes CEF (Common Event Format) +# Pratique pour le moteur de corrélation et le site web + +# Une alerte CEF est formattée de cette façon: +# CEF:Version|Device Vendor|Device Product|Device Version|Device Event Class ID|Name|Severity|[Extension] + +import mysql.connector +import time +import random +from datetime import datetime + + +def generate_alert(alert_type): + # Dictionnaire pour différents types d'alertes réseau et fichiers + alert_templates = { + "network": { + "Syn Flood": { + "Device_event_class_id": "1001", + "name": "Syn Flood Detected", + "src": f"{generate_ip()}", + "dst": f"{generate_ip()}", + "agent_severity": "8" + }, + "Port Scanning": { + "Device_event_class_id": "1002", + "name": "Port Scanning Activity", + "src": f"{generate_ip()}", + "dst": f"{generate_ip()}", + "cs1": f"{generate_ports()}", + "agent_severity": "5" + } + }, + "file": { + "Suspicious File Creation": { + "Device_event_class_id": "2001", + "name": "Suspicious File Created", + "fname": f"{generate_filename()}", + "fsize": f"{random.randint(10, 1000)}kb", + "agent_severity": "7" + }, + "Critical File Deletion Attempt": { + "Device_event_class_id": "2002", + "name": "Critical File Deletion Attempt", + "fname": f"{generate_filename()}", + "agent_severity": "9" + } + } + } + + # Sélectionner le bon template en fonction du type d'alerte + category = "network" if alert_type in alert_templates["network"] else "file" + alert_info = alert_templates[category].get(alert_type, {}) + + if not alert_info: + raise ValueError(f"Unknown alert type: {alert_type}") + + return alert_info + +def generate_ip(): + # Générer une adresse IP aléatoire + return ".".join(str(random.randint(0, 255)) for _ in range(4)) + +def generate_ports(): + # Générer une liste de ports scannés + return ",".join(str(random.randint(20, 1024)) for _ in range(5)) + +def generate_filename(): + # Générer un nom de fichier aléatoire + filenames = ["config.txt", "database.db", "system32.dll", "passwd", "shadow", "sensitive_data.doc"] + return random.choice(filenames) + +def generate_alerts(conn, cursor, main_headers): + # Récupérer ces données depuis une fonction + alertes = ["Syn Flood", "Port Scanning", "Suspicious File Creation", "Critical File Deletion Attempt"] + + while True: + data = generate_alert(random.choice(alertes)) + merged = main_headers.copy() + merged.update(data) + + # Préparer la requête SQL d'insertion + sql_query = """ + INSERT INTO alertes ( + cef_version, date_alerte, event_gravite, device_product, + device_vendor, device_version, alerte_name, sourceAddress, + destinationAddress, destinationPort, sourcePort, protocol, + applicationProtocol, reason, action, commentaire + ) VALUES ( + %(cef_version)s, %(date_alerte)s, %(event_gravite)s, %(device_product)s, + %(device_vendor)s, %(device_version)s, %(alerte_name)s, %(src)s, + %(dst)s, %(destinationPort)s, %(sourcePort)s, %(protocol)s, + %(applicationProtocol)s, %(reason)s, %(action)s, %(commentaire)s + ); + """ + + # Paramètres pour la requête SQL + params = { + "cef_version": merged["CEF"], + "date_alerte": datetime.now(), + "event_gravite": int(merged["agent_severity"]), + "device_product": merged["Device Product"], + "device_vendor": merged["Device Vendor"], + "device_version": merged["Device Version"], + "alerte_name": merged["name"], + "src": merged["src"], + "dst": merged["dst"], + "destinationPort": None, # A définir si disponible + "sourcePort": None, # A définir si disponible + "protocol": "TCP", # Par défaut, à adapter si besoin + "applicationProtocol": "N/A", # À ajuster en fonction des besoins + "reason": "Suspicious activity detected", # Exemple, à adapter + "action": "Alerted", # Exemple d'action + "commentaire": "" # Optionnel + } + + # Exécution de la requête d'insertion + cursor.execute(sql_query, params) + conn.commit() + + # Attente avant de générer la prochaine alerte + time.sleep(random.randint(1, 10)) + +def main(): + # Connexion à la base de données MySQL/MariaDB + conn = mysql.connector.connect( + host="172.20.2.10", # À adapter selon votre configuration + database="sidps", # Nom de la base de données + user="sidps", # Nom d'utilisateur + password="SUPERPASSWORD", # Mot de passe + port=3306 # Port MySQL par défaut (peut être 3306 ou autre selon la configuration) + ) + + cursor = conn.cursor() + + # En-têtes généraux + CEF_version = 1 + Device_vendor = "ArKa" + Device_product = "SIDPS" + Device_version = "vAlpha" + + main_headers = { + "CEF": CEF_version, + "Device Vendor": Device_vendor, + "Device Product": Device_product, + "Device Version": Device_version + } + + # Lancer la génération d'alertes + generate_alerts(conn, cursor, main_headers) + + # Fermer la connexion à la base de données + cursor.close() + conn.close() + +if __name__ == "__main__": + main() diff --git a/BDD/base.sql b/sql/db-schema.sql similarity index 80% rename from BDD/base.sql rename to sql/db-schema.sql index ed72cee..e33ff05 100644 --- a/BDD/base.sql +++ b/sql/db-schema.sql @@ -1,6 +1,16 @@ +#----------------------------------------------- +# Nettoyage des tables dans la base de données +#----------------------------------------------- + +DROP TABLE IF EXISTS alertes; + +#----------------------------------------------- +# Table: alertes +#---------------------------------------------- + CREATE TABLE alertes ( id SERIAL PRIMARY KEY, -- Identifiant unique pour chaque alerte - cef_version VARCHAR(10) DEFAULT 'CEF:0', -- Version du format CEF utilisé + cef_version VARCHAR(10) DEFAULT 'CEF:1', -- Version du format CEF utilisé date_alerte TIMESTAMP(3) NOT NULL, -- Date et heure de l'alerte avec une précision de millisecondes event_gravite INT CHECK (event_gravite >= 0 AND event_gravite <= 10), -- Niveau de gravité de l'alerte sur une échelle de 0 à 10 device_product VARCHAR(63), -- Nom du produit à l'origine de l'alerte diff --git a/sql/init.sql b/sql/init.sql new file mode 100644 index 0000000..c9677cf --- /dev/null +++ b/sql/init.sql @@ -0,0 +1,35 @@ +CREATE DATABASE IF NOT EXISTS sidps DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +CREATE USER 'sidps'@'%' IDENTIFIED BY 'SUPERPASSWORD'; +GRANT ALL PRIVILEGES ON sidps.* TO 'sidps'@'%'; +FLUSH PRIVILEGES; +use sidps; + +#----------------------------------------------- +# Nettoyage des tables dans la base de données +#----------------------------------------------- + +DROP TABLE IF EXISTS alertes; + +#----------------------------------------------- +# Table: alertes +#---------------------------------------------- + +CREATE TABLE alertes ( + id SERIAL PRIMARY KEY, -- Identifiant unique pour chaque alerte + cef_version VARCHAR(10) DEFAULT 'CEF:1', -- Version du format CEF utilisé + date_alerte TIMESTAMP(3) NOT NULL, -- Date et heure de l'alerte avec une précision de millisecondes + event_gravite INT CHECK (event_gravite >= 0 AND event_gravite <= 10), -- Niveau de gravité de l'alerte sur une échelle de 0 à 10 + device_product VARCHAR(63), -- Nom du produit à l'origine de l'alerte + device_vendor VARCHAR(63), -- Nom du fournisseur ou fabricant du produit + device_version VARCHAR(31), -- Version du produit ou dispositif ayant généré l'alerte + alerte_name VARCHAR(512), -- Nom descriptif de l'alerte + destinationAddress VARCHAR(45), -- Adresse IP de destination impliquée dans l'alerte + sourceAddress VARCHAR(45), -- Adresse IP source impliquée dans l'alerte + destinationPort INT, -- Port de destination utilisé pour l'événement ou l'alerte + sourcePort INT, -- Port source de l'événement ou de l'alerte + protocol VARCHAR(10), -- Protocole réseau impliqué (ex : TCP, UDP) + applicationProtocol VARCHAR(20), -- Protocole applicatif impliqué (ex : HTTP, FTP) + reason TEXT, -- Description de la raison de l'alerte expliquant pourquoi elle a été générée + action VARCHAR(50), -- Action entreprise en réponse à l'alerte (ex : bloqué, alerté uniquement, ...) + commentaire TEXT -- Champ texte pour des notes ou commentaires additionnels concernant l'alerte +); diff --git a/tests/cef-generator.py b/tests/cef-generator.py deleted file mode 100644 index b228105..0000000 --- a/tests/cef-generator.py +++ /dev/null @@ -1,102 +0,0 @@ -# Générateur d'alertes CEF (Common Event Format) -# Pratique pour le moteur de corrélation et le site web - -# Une alerte CEF est formattée de cette façon: -# CEF:Version|Device Vendor|Device Product|Device Version|Device Event Class ID|Name|Severity|[Extension] - -import redis -import time -import random - -def generate_alert(alert_type): - # Dictionnaire pour différents types d'alertes réseau et fichiers - alert_templates = { - "network": { - "Syn Flood": { - "Device_event_class_id": "1001", - "name": "Syn Flood Detected", - "src" : f"{generate_ip()}", - "dst" : f"{generate_ip()}", - "agent_severity": "8" - }, - "Port Scanning": { - "Device_event_class_id": "1002", - "name": "Port Scanning Activity", - "src" : f"{generate_ip()}", - "dst" : f"{generate_ip()}", - "cs1" : f"{generate_ports()}", - "agent_severity": "5" - } - }, - "file": { - "Suspicious File Creation": { - "Device_event_class_id": "2001", - "name": "Suspicious File Created", - "fname" : f"{generate_filename()}", - "fsize" : f"{random.randint(10,1000)}kb", - "agent_severity": "7" - }, - "Critical File Deletion Attempt": { - "Device_event_class_id": "2002", - "name": "Critical File Deletion Attempt", - "fname" : f"{generate_filename()}", - "agent_severity": "9" - } - } - } - - # Sélectionner le bon template en fonction du type d'alerte - category = "network" if alert_type in alert_templates["network"] else "file" - alert_info = alert_templates[category].get(alert_type, {}) - - if not alert_info: - raise ValueError(f"Unknown alert type: {alert_type}") - - return alert_info - -def generate_ip(): - # Générer une adresse IP aléatoire - return ".".join(str(random.randint(0, 255)) for _ in range(4)) - -def generate_ports(): - # Générer une liste de ports scannés - return ",".join(str(random.randint(20, 1024)) for _ in range(5)) - -def generate_filename(): - # Générer un nom de fichier aléatoire - filenames = ["config.txt", "database.db", "system32.dll", "passwd", "shadow", "sensitive_data.doc"] - return random.choice(filenames) - -def generate_alerts(db, main_headers): - # Récupérer ces données depuis une fonction - alertes = ["Syn Flood", "Port Scanning", "Suspicious File Creation", "Critical File Deletion Attempt"] - - while (1): - data = generate_alert(random.choice(alertes)) - merged = main_headers.copy() - merged.update(data) - - # Ajout dans redis - response = db.xadd("logs:alertes", merged) - time.sleep(random.randint(1, 10)) - - -def main(): - - # Connexion à Redis (si besoin changer l'host et le port) - db = redis.Redis(host='localhost', port=6379, decode_responses=True) - - # Pour une db en production (https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/) - #db = redis.Redis(host="my-redis.cloud.redislabs.com", port=6379, username="default", password="secret", ssl=True, ssl_certfile="./redis_user.crt", ssl_keyfile="./redis_user_private.key", ssl_ca_certs="./redis_ca.pem") - - CEF_version=1 - Device_vendor="ArKa" - Device_product="SIDPS" - Device_version="vAlpha" - - main_headers = {"CEF": CEF_version, "Device Vendor" : Device_vendor, "Device Product" : Device_product, "Device_version" : Device_version} - - generate_alerts(db, main_headers) - -if __name__ == "__main__": - main() From 48e9554d38b916c09387eb52c5abfdcac3c5fb84 Mon Sep 17 00:00:00 2001 From: Oxbian Date: Mon, 18 Nov 2024 21:49:08 -0500 Subject: [PATCH 07/18] feat: rewrite sql + alert sent to sql db from idps --- README.md | 4 +- config.json | 4 ++ idps/database.py | 71 +++++++++++++++++---------- idps/rules/TCP/Scan/synscan.py | 3 ++ idps/rules/TCP/Scan/tcpconnectscan.py | 5 +- idps/tcp.py | 4 +- sql/adduser.sql | 5 -- sql/cef-generator.py | 52 +++++++++----------- sql/db-schema.sql | 25 +++++----- sql/init.sql | 24 ++++----- 10 files changed, 110 insertions(+), 87 deletions(-) delete mode 100644 sql/adduser.sql diff --git a/README.md b/README.md index 0706ab2..d8bd344 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ La base de données SQL est structurée de la façon suivante: ## Interface de tests d'alertes -Un script python `tests/cef-generator.py` permet de générer des alertes CEF dans la base de données SQL. +Un script python `sql/cef-generator.py` permet de générer des alertes CEF dans la base de données SQL. Ce script peut être utile pour le développement d'interface d'affichage des alertes. Pour l'utiliser il faut une base de donnée sql, et mettre les identifiants dans le script. De plus, ce script à besoin de la librairie `sql` pour pouvoir ajouter / faire des requêtes à la base de données MySQL. @@ -39,7 +39,7 @@ pip install -r requirements.txt Puis executer le script `tests/cef-generator.py` avec le python3 du l'environnement virtuel. ```bash -.venv/bin/python3 tests/cef-generator.py +.venv/bin/python3 sql/cef-generator.py ``` ## Demo diff --git a/config.json b/config.json index 10aac78..5f69321 100644 --- a/config.json +++ b/config.json @@ -6,6 +6,10 @@ "db_user": "sidps", "db_password": "SUPERPASSWORD", "db_port": "3306", + "cef_version": 1, + "device_product": "SIDPS", + "device_vendor": "ArKa", + "device_version": "vAlpha", "synscan_time": 180, "synscan_count": 5, "tcpconnectscan_time": 180, diff --git a/idps/database.py b/idps/database.py index 291c595..bba8130 100644 --- a/idps/database.py +++ b/idps/database.py @@ -9,44 +9,61 @@ class Database: self.conn = mysql.connector.connect(host=config["db_host"], database=config["db_database"], user=config["db_user"], password=config["db_password"], port=config["db_port"]) self.config = config - def send_alert(self, alert): + def send_alert(self, date_alert = None, agent_severity = None, device_event_class_id = None, + name = None, src = None, dst = None, dpt = None, spt = None, msg = None, + proto = None, bytesin = None, bytesout = None, reason = None, act = None): """Ajoute une alerte dans la base de données - @param alert: Alerte à rajouter dans la BDD""" + @param date_alert: Timestamp de l'alerte + @param agent_severity: Criticité de l'alerte (0 - 10) + @param device_event_class_id: Identifiant de signature, pour le moteur de corrélation + @param name: Nom descriptif de l'alerte + @param src: Adresse IP source + @param dst: Adresse IP destination + @param dpt: Port de destination + @param spt: Port source + @param msg: Champ de texte pour des notes ou commentaires additionnels + @param proto: Protocol couche 4 (réseau) utilisé + @param bytesin: Quantité de bytes (8 bits ici) entrants + @param bytesout: Quantité de bytes (8 bits ici) sortants + @param reason: Description de la raison de l'alerte + @param act: Action prise en réponse de l'alerte + """ try: cursor = self.conn.cursor() sql_query = """ INSERT INTO alertes ( - cef_version, date_alerte, event_gravite, device_product, - device_vendor, device_version, alerte_name, sourceAddress, - destinationAddress, destinationPort, sourcePort, protocol, - applicationProtocol, reason, action, commentaire + cef_version, date_alerte, agent_severity, device_event_class_id, + device_product, device_vendor, device_version, name, dst, src, + dpt, spt, msg, proto, bytesin, bytesout, reason, act ) VALUES ( - %(cef_version)s, %(date_alerte)s, %(event_gravite)s, %(device_product)s, - %(device_vendor)s, %(device_version)s, %(alerte_name)s, %(src)s, - %(dst)s, %(destinationPort)s, %(sourcePort)s, %(protocol)s, - %(applicationProtocol)s, %(reason)s, %(action)s, %(commentaire)s + %(cef_version)s, %(date_alerte)s, %(agent_severity)s, %(device_event_class_id)s, + %(device_product)s, %(device_vendor)s, %(device_version)s, %(name)s, %(dst)s, + %(src)s, %(dpt)s, %(spt)s, %(msg)s, %(proto)s, %(bytesin)s, %(bytesout)s, + %(reason)s, %(act)s ); """ # Paramètres pour la requête SQL params = { - "cef_version": alert["CEF"], - "date_alerte": alert["datetime"], - "event_gravite": alert["agent_severity"], - "device_product": alert["Device Product"], - "device_vendor": alert["Device Vendor"], - "device_version": alert["Device Version"], - "alerte_name": alert["name"], - "src": alert["src"], - "dst": alert["dst"], - "destinationPort": alert["dstPort"], - "sourcePort": alert["srcPort"], - "protocol": alert["protocol"], - "applicationProtocol": alert["applicationProtocol"], - "reason": alert["reason"], - "action": alert["action"], - "commentaire": alert["commentaire"] + "cef_version": self.get_key("cef_version", 1), + "date_alerte": date_alert, + "agent_severity": agent_severity, + "device_event_class_id": device_event_class_id, + "device_product": self.get_key("device_product", "SIDPS"), + "device_vendor": self.get_key("device_vendor", "ArKa"), + "device_version": self.get_key("device_version", "vAlpha"), + "name": name, + "src": src, + "dst": dst, + "dpt": dpt, + "spt": spt, + "msg": msg, + "proto": proto, + "bytesin": bytesin, + "bytesout": bytesout, + "reason": reason, + "act": act } # Exécution de la requête d'insertion @@ -61,4 +78,4 @@ class Database: @param key: clé du paramètre souhaité @param default_val: valeur par défaut si la clé n'existe pas""" - return self.config.get(key, None) + return self.config.get(key, default_val) diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py index de69fc5..2b0e729 100644 --- a/idps/rules/TCP/Scan/synscan.py +++ b/idps/rules/TCP/Scan/synscan.py @@ -1,3 +1,5 @@ +from datetime import datetime + def rule(packet, tcp_packets, db): """Règle SYNScan: Un SYNScan va envoyer des requêtes TCP avec le flag SYN @@ -9,4 +11,5 @@ def rule(packet, tcp_packets, db): seuil = db.get_key("synscan_count", 5) if (tcp_packets.count_packet_of_type("RA", time_window) + tcp_packets.count_packet_of_type("SA", time_window)) + tcp_packets.count_packet_of_type("R", time_window) >= seuil: + db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset ACK et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuil dépassés, risque de SynScan") diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py index b21bffa..7629158 100644 --- a/idps/rules/TCP/Scan/tcpconnectscan.py +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -1,3 +1,5 @@ +from datetime import datetime + def rule(packet, tcp_packets, db): """Règle TCPConnect Scan: Un scan TCP connect va effectuer une connexion TCP en entier sur chaque port scanné. @@ -8,4 +10,5 @@ def rule(packet, tcp_packets, db): seuil = db.get_key("tcpconnectscan_count", 5) if (tcp_packets.count_packet_of_type("A", time_window) + tcp_packets.count_packet_of_type("RA", time_window)) >= seuil: - print(f"Alerte, seuils dépassés, risque de TCPConnectScan") + db.send_alert(datetime.now(), 5, None, "TCPConnect Scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset->ACK et Syn->Reset ACK", act="Alerte") + print(f"Alerte, seuils dépassés, risque de TCPConnectScan") diff --git a/idps/tcp.py b/idps/tcp.py index b113495..0869f13 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -12,6 +12,8 @@ class TCP: def add_packet(self, ip_src, port_src, ip_dst, port_dst, flags, timestamp): """Ajoute le suivi d'un paquet dans le dictionnaire""" + timestamp = int(timestamp) + # Initialisation de la liste de paquets pour l'IP source if ip_src not in self.packets: self.packets[ip_src] = [] @@ -82,7 +84,7 @@ class TCP: return None for i, [p_s, ip_d, p_d, f, stamp] in enumerate(self.packets[ip_src]): - if p_s == port_src and ip_d == ip_dst and p_d == port_dst and f in flags: + if p_s == port_src and ip_d == ip_dst and p_d == port_dst and flags in f: return i return None diff --git a/sql/adduser.sql b/sql/adduser.sql deleted file mode 100644 index 072ffed..0000000 --- a/sql/adduser.sql +++ /dev/null @@ -1,5 +0,0 @@ -CREATE DATABASE sidps DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; -CREATE USER 'sidps'@'localhost' IDENTIFIED BY 'SUPERPASSWORD'; -GRANT ALL PRIVILEGES ON sidps.* TO 'sidps'@'localhost'; -FLUSH PRIVILEGES; -use sidps; diff --git a/sql/cef-generator.py b/sql/cef-generator.py index edd512b..affabda 100644 --- a/sql/cef-generator.py +++ b/sql/cef-generator.py @@ -9,7 +9,6 @@ import time import random from datetime import datetime - def generate_alert(alert_type): # Dictionnaire pour différents types d'alertes réseau et fichiers alert_templates = { @@ -71,7 +70,7 @@ def generate_filename(): def generate_alerts(conn, cursor, main_headers): # Récupérer ces données depuis une fonction - alertes = ["Syn Flood", "Port Scanning", "Suspicious File Creation", "Critical File Deletion Attempt"] + alertes = ["Syn Flood", "Port Scanning"] #, "Suspicious File Creation", "Critical File Deletion Attempt"] while True: data = generate_alert(random.choice(alertes)) @@ -81,15 +80,14 @@ def generate_alerts(conn, cursor, main_headers): # Préparer la requête SQL d'insertion sql_query = """ INSERT INTO alertes ( - cef_version, date_alerte, event_gravite, device_product, - device_vendor, device_version, alerte_name, sourceAddress, - destinationAddress, destinationPort, sourcePort, protocol, - applicationProtocol, reason, action, commentaire + cef_version, date_alerte, agent_severity, device_event_class_id, + device_product, device_vendor, device_version, name, dst, src, + dpt, spt, msg, proto, bytesin, bytesout, reason, act ) VALUES ( - %(cef_version)s, %(date_alerte)s, %(event_gravite)s, %(device_product)s, - %(device_vendor)s, %(device_version)s, %(alerte_name)s, %(src)s, - %(dst)s, %(destinationPort)s, %(sourcePort)s, %(protocol)s, - %(applicationProtocol)s, %(reason)s, %(action)s, %(commentaire)s + %(cef_version)s, %(date_alerte)s, %(agent_severity)s, %(device_event_class_id)s, + %(device_product)s, %(device_vendor)s, %(device_version)s, %(name)s, %(dst)s, + %(src)s, %(dpt)s, %(spt)s, %(msg)s, %(proto)s, %(bytesin)s, %(bytesout)s, + %(reason)s, %(act)s ); """ @@ -97,20 +95,22 @@ def generate_alerts(conn, cursor, main_headers): params = { "cef_version": merged["CEF"], "date_alerte": datetime.now(), - "event_gravite": int(merged["agent_severity"]), + "agent_severity": int(merged["agent_severity"]), + "device_event_class_id": None, "device_product": merged["Device Product"], "device_vendor": merged["Device Vendor"], "device_version": merged["Device Version"], - "alerte_name": merged["name"], + "name": merged["name"], "src": merged["src"], "dst": merged["dst"], - "destinationPort": None, # A définir si disponible - "sourcePort": None, # A définir si disponible - "protocol": "TCP", # Par défaut, à adapter si besoin - "applicationProtocol": "N/A", # À ajuster en fonction des besoins - "reason": "Suspicious activity detected", # Exemple, à adapter - "action": "Alerted", # Exemple d'action - "commentaire": "" # Optionnel + "dpt": None, + "spt": None, + "msg": "Message", + "proto": "TCP", + "bytesin": None, + "bytesout": None, + "reason": "Activité suspecte", + "act": "Alert" } # Exécution de la requête d'insertion @@ -132,17 +132,11 @@ def main(): cursor = conn.cursor() - # En-têtes généraux - CEF_version = 1 - Device_vendor = "ArKa" - Device_product = "SIDPS" - Device_version = "vAlpha" - main_headers = { - "CEF": CEF_version, - "Device Vendor": Device_vendor, - "Device Product": Device_product, - "Device Version": Device_version + "CEF": 1, + "Device Vendor": "ArKa", + "Device Product": "SIDPS", + "Device Version": "vAlpha" } # Lancer la génération d'alertes diff --git a/sql/db-schema.sql b/sql/db-schema.sql index e33ff05..94772e1 100644 --- a/sql/db-schema.sql +++ b/sql/db-schema.sql @@ -12,18 +12,21 @@ CREATE TABLE alertes ( id SERIAL PRIMARY KEY, -- Identifiant unique pour chaque alerte cef_version VARCHAR(10) DEFAULT 'CEF:1', -- Version du format CEF utilisé date_alerte TIMESTAMP(3) NOT NULL, -- Date et heure de l'alerte avec une précision de millisecondes - event_gravite INT CHECK (event_gravite >= 0 AND event_gravite <= 10), -- Niveau de gravité de l'alerte sur une échelle de 0 à 10 + agent_severity INT CHECK (agent_severity >= 0 AND agent_severity <= 10), -- Niveau de gravité de l'alerte sur une échelle de 0 à 10 + device_event_class_id VARCHAR(1023), -- Identifiant de la signature permettant d'aider les moteurs de corrélations device_product VARCHAR(63), -- Nom du produit à l'origine de l'alerte device_vendor VARCHAR(63), -- Nom du fournisseur ou fabricant du produit device_version VARCHAR(31), -- Version du produit ou dispositif ayant généré l'alerte - alerte_name VARCHAR(512), -- Nom descriptif de l'alerte - destinationAddress VARCHAR(45), -- Adresse IP de destination impliquée dans l'alerte - sourceAddress VARCHAR(45), -- Adresse IP source impliquée dans l'alerte - destinationPort INT, -- Port de destination utilisé pour l'événement ou l'alerte - sourcePort INT, -- Port source de l'événement ou de l'alerte - protocol VARCHAR(10), -- Protocole réseau impliqué (ex : TCP, UDP) - applicationProtocol VARCHAR(20), -- Protocole applicatif impliqué (ex : HTTP, FTP) - reason TEXT, -- Description de la raison de l'alerte expliquant pourquoi elle a été générée - action VARCHAR(50), -- Action entreprise en réponse à l'alerte (ex : bloqué, alerté uniquement, ...) - commentaire TEXT -- Champ texte pour des notes ou commentaires additionnels concernant l'alerte + name VARCHAR(512), -- Nom descriptif de l'alerte + -- Champ d'extension du CEF + dst VARCHAR(45), -- Adresse IP de destination impliquée dans l'alerte + src VARCHAR(45), -- Adresse IP source impliquée dans l'alerte + dpt INT, -- Port de destination utilisé pour l'événement ou l'alerte + spt INT, -- Port source de l'événement ou de l'alerte + msg VARCHAR(1023), -- Champ texte pour des notes ou commentaires additionnels concernant l'alerte + proto VARCHAR(10), -- Protocole réseau impliqué (ex : TCP, UDP) + bytesin INT, -- Quantité de bytes (8 bits ici) entrant (cas de flood ou DOS) + bytesout INT, -- Quantité des bytes (8 bits ici) sortants + reason VARCHAR(1023), -- Description de la raison de l'alerte expliquant pourquoi elle a été générée + act VARCHAR(50) -- Action entreprise en réponse à l'alerte (ex : bloqué, alerté uniquement, ...) ); diff --git a/sql/init.sql b/sql/init.sql index c9677cf..61f7aa8 100644 --- a/sql/init.sql +++ b/sql/init.sql @@ -18,18 +18,20 @@ CREATE TABLE alertes ( id SERIAL PRIMARY KEY, -- Identifiant unique pour chaque alerte cef_version VARCHAR(10) DEFAULT 'CEF:1', -- Version du format CEF utilisé date_alerte TIMESTAMP(3) NOT NULL, -- Date et heure de l'alerte avec une précision de millisecondes - event_gravite INT CHECK (event_gravite >= 0 AND event_gravite <= 10), -- Niveau de gravité de l'alerte sur une échelle de 0 à 10 + agent_severity INT CHECK (agent_severity >= 0 AND agent_severity <= 10), -- Niveau de gravité de l'alerte sur une échelle de 0 à 10 + device_event_class_id VARCHAR(1023), -- Identifiant de la signature permettant d'aider les moteurs de corrélations device_product VARCHAR(63), -- Nom du produit à l'origine de l'alerte device_vendor VARCHAR(63), -- Nom du fournisseur ou fabricant du produit device_version VARCHAR(31), -- Version du produit ou dispositif ayant généré l'alerte - alerte_name VARCHAR(512), -- Nom descriptif de l'alerte - destinationAddress VARCHAR(45), -- Adresse IP de destination impliquée dans l'alerte - sourceAddress VARCHAR(45), -- Adresse IP source impliquée dans l'alerte - destinationPort INT, -- Port de destination utilisé pour l'événement ou l'alerte - sourcePort INT, -- Port source de l'événement ou de l'alerte - protocol VARCHAR(10), -- Protocole réseau impliqué (ex : TCP, UDP) - applicationProtocol VARCHAR(20), -- Protocole applicatif impliqué (ex : HTTP, FTP) - reason TEXT, -- Description de la raison de l'alerte expliquant pourquoi elle a été générée - action VARCHAR(50), -- Action entreprise en réponse à l'alerte (ex : bloqué, alerté uniquement, ...) - commentaire TEXT -- Champ texte pour des notes ou commentaires additionnels concernant l'alerte + name VARCHAR(512), -- Nom descriptif de l'alerte + dst VARCHAR(45), -- Adresse IP de destination impliquée dans l'alerte + src VARCHAR(45), -- Adresse IP source impliquée dans l'alerte + dpt INT, -- Port de destination utilisé pour l'événement ou l'alerte + spt INT, -- Port source de l'événement ou de l'alerte + msg VARCHAR(1023), -- Champ texte pour des notes ou commentaires additionnels concernant l'alerte + proto VARCHAR(10), -- Protocole réseau impliqué (ex : TCP, UDP) + bytesin INT, -- Quantité de bits entrant (cas de flood ou DOS) + bytesout INT, -- Quantité des bits sortants + reason VARCHAR(1023), -- Description de la raison de l'alerte expliquant pourquoi elle a été générée + act VARCHAR(50) -- Action entreprise en réponse à l'alerte (ex : bloqué, alerté uniquement, ...) ); From 3e75cb8927da928af691d16fa15051d4ee0a02eb Mon Sep 17 00:00:00 2001 From: Oxbian Date: Tue, 19 Nov 2024 16:42:08 -0500 Subject: [PATCH 08/18] feat: adding cooldown to alerts + more precise pattern matching for TCP --- idps/rules/TCP/Scan/synscan.py | 21 ++++++-- idps/rules/TCP/Scan/tcpconnectscan.py | 21 ++++++-- idps/tcp.py | 75 +++++++++++++++------------ 3 files changed, 77 insertions(+), 40 deletions(-) diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py index 2b0e729..59411c4 100644 --- a/idps/rules/TCP/Scan/synscan.py +++ b/idps/rules/TCP/Scan/synscan.py @@ -1,4 +1,6 @@ from datetime import datetime +import time + def rule(packet, tcp_packets, db): """Règle SYNScan: @@ -6,10 +8,21 @@ def rule(packet, tcp_packets, db): Si le port est ouvert alors le serveur répondra: Syn ACK, puis le client Reset la connexion Sinon le port est fermé et le serveur répondera: Reset ACK """ + if (rule.cooldown + rule.time_window > time.time()): + return - time_window = db.get_key("synscan_time", 180) - seuil = db.get_key("synscan_count", 5) + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("synscan_time", 180) + rule.seuil = db.get_key("synscan_count", 5) - if (tcp_packets.count_packet_of_type("RA", time_window) + tcp_packets.count_packet_of_type("SA", time_window)) + tcp_packets.count_packet_of_type("R", time_window) >= seuil: - db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset ACK et Syn->Reset ACK", act="Alerte") + if tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "SA", "RA"], rule.time_window, True) >= rule.seuil: + db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset ACK et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuil dépassés, risque de SynScan") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py index 7629158..e887ca3 100644 --- a/idps/rules/TCP/Scan/tcpconnectscan.py +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -1,4 +1,6 @@ from datetime import datetime +import time + def rule(packet, tcp_packets, db): """Règle TCPConnect Scan: @@ -6,9 +8,22 @@ def rule(packet, tcp_packets, db): Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset -> ACK Sinon le port est fermé et le serveur refusera la connexion SYN -> Reset ACK """ - time_window = db.get_key("tcpconnectscan_time", 180) - seuil = db.get_key("tcpconnectscan_count", 5) - if (tcp_packets.count_packet_of_type("A", time_window) + tcp_packets.count_packet_of_type("RA", time_window)) >= seuil: + if (rule.cooldown + rule.time_window > time.time()): + return + + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("tcpconnectscan_time", 180) + rule.seuil = db.get_key("tcpconnectscan_count", 5) + + if tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) >= rule.seuil: db.send_alert(datetime.now(), 5, None, "TCPConnect Scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset->ACK et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuils dépassés, risque de TCPConnectScan") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 180 +rule.seuil = 5 diff --git a/idps/tcp.py b/idps/tcp.py index 0869f13..efcfb63 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -19,74 +19,81 @@ class TCP: self.packets[ip_src] = [] if flags == "S": - self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, ["S"], timestamp]) return elif flags == "SA": - i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S", True) + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - self.packets[ip_dst][i][3].append("SA") - self.packets[ip_dst][i][4] = timestamp + print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + self.packets[ip][i][3].append("SA") + self.packets[ip][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, ["SA"], timestamp]) return elif flags == "A": - i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "SA") + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "SA") if i is None: - i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "R", True) + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "R") if i is not None: - self.packets[ip_src][i][3].append("A") - self.packets[ip_src][i][4] = timestamp + print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + self.packets[ip][i][3].append("A") + self.packets[ip][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, ["A"], timestamp]) return elif flags == "RA": - i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") if i is None: - i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - self.packets[ip_src][i][3].append("RA") - self.packets[ip_src][i][4] = timestamp + print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + self.packets[ip][i][3].append("RA") + self.packets[ip][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, ["RA"], timestamp]) return elif flags == "R": - i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") if i is None: - i = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - self.packets[ip_src][i][3].append("R") - self.packets[ip_src][i][4] = timestamp + print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + self.packets[ip][i][3].append("R") + self.packets[ip][i][4] = timestamp return else: - self.packets[ip_src].append([port_src, ip_dst, port_dst, [flags], timestamp]) + self.packets[ip_src].append([port_src, ip_dst, port_dst, ["R"], timestamp]) return - def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags, reverse=False): - """Cherche l'indice du paquet dont le flag doit être remplacé""" - if reverse is True: - ip_src, ip_dst = ip_dst, ip_src - port_src, port_dst = port_dst, port_src + def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags): + """Cherche l'indice et le port de source du paquet dont le flag doit être remplacé""" - if ip_src not in self.packets.keys(): - return None + # Recherche dans le sens src->dst + if ip_src in self.packets.keys(): + for i, [p_s, ip_d, p_d, f, stamp] in enumerate(self.packets[ip_src]): + if p_s == port_src and ip_d == ip_dst and p_d == port_dst and flags in f: + return i, ip_src - for i, [p_s, ip_d, p_d, f, stamp] in enumerate(self.packets[ip_src]): - if p_s == port_src and ip_d == ip_dst and p_d == port_dst and flags in f: - return i - return None + # Recherche dans le sens dst->src + if ip_dst in self.packets.keys(): + for i, [p_d, ip_s, p_s, f, stamp] in enumerate(self.packets[ip_dst]): + if p_s == port_src and ip_s == ip_src and p_d == port_dst and flags in f: + return i, ip_dst + + return None, None def clean_old_packets(self): """Supprime les paquets qui date de plus longtemps que le temps de clean""" @@ -108,14 +115,16 @@ class TCP: if not self.packets[ip_src]: del self.packets[ip_src] - def count_packet_of_type(self, flag, time_treshold): + def count_packet_of_type(self, flag, time_treshold, isList = False): """Compte les paquets qui ont le flag choisi et qui sont dans la fenêtre de temps""" count = 0 current_timestamp = time.time() for ip in list(self.packets.keys()): for packet in self.packets[ip]: - if flag in packet[3] and packet[4] >= current_timestamp - time_treshold: + if isList and set(flag) == set(packet[3]) and packet[4] >= current_timestamp - time_treshold: + count += 1 + elif not isList and flag in packet[3] and packet[4] >= current_timestamp - time_treshold: count += 1 return count From 09abb7e20ffedd590bee38d8f3b7f4fd39677526 Mon Sep 17 00:00:00 2001 From: Oxbian Date: Tue, 19 Nov 2024 22:15:30 -0500 Subject: [PATCH 09/18] feat: adding other TCP scan rules --- idps/rules/TCP/Scan/ackscan.py | 28 +++++++++++++++++++++++++++ idps/rules/TCP/Scan/finscan.py | 28 +++++++++++++++++++++++++++ idps/rules/TCP/Scan/nullscan.py | 28 +++++++++++++++++++++++++++ idps/rules/TCP/Scan/synscan.py | 6 +++--- idps/rules/TCP/Scan/tcpconnectscan.py | 4 ++-- idps/rules/TCP/Scan/xmasscan.py | 28 +++++++++++++++++++++++++++ idps/tcp.py | 22 +++++++++++++++++++++ 7 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 idps/rules/TCP/Scan/ackscan.py create mode 100644 idps/rules/TCP/Scan/finscan.py create mode 100644 idps/rules/TCP/Scan/nullscan.py create mode 100644 idps/rules/TCP/Scan/xmasscan.py diff --git a/idps/rules/TCP/Scan/ackscan.py b/idps/rules/TCP/Scan/ackscan.py new file mode 100644 index 0000000..c210738 --- /dev/null +++ b/idps/rules/TCP/Scan/ackscan.py @@ -0,0 +1,28 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """Règle ACK Scan: + Un ACK Scan va envoyer des requêtes TCP avec le flag ACK + Si le firewall ne bloque pas, alors il répond avec le flag Reset + Sinon il répond rien + """ + if (rule.cooldown + rule.time_window > time.time()): + return + + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("ackscan_time", 180) + rule.seuil = db.get_key("ackscan_count", 5) + + if tcp_packets.count_packet_of_type(["A", "R"], rule.time_window, True) + tcp_packets.count_packet_of_type(["A"], rule.time_window, True) >= rule.seuil: + db.send_alert(datetime.now(), 5, None, "ACK scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Ack->Reset et Ack pas de réponse", act="Alerte") + print(f"Alerte, seuil dépassés, risque d'Ack scan") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/Scan/finscan.py b/idps/rules/TCP/Scan/finscan.py new file mode 100644 index 0000000..3ecf5f5 --- /dev/null +++ b/idps/rules/TCP/Scan/finscan.py @@ -0,0 +1,28 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """Règle Fin Scan: + Un Fin Scan va envoyer des requêtes TCP avec le flag Fin + Si le port est ouvert alors le serveur répondra pas + Sinon le port est fermé et le serveur répondra: Reset ACK + """ + if (rule.cooldown + rule.time_window > time.time()): + return + + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("finscan_time", 180) + rule.seuil = db.get_key("finscan_count", 5) + + if tcp_packets.count_packet_of_type(["F", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["F"], rule.time_window, True) >= rule.seuil: + db.send_alert(datetime.now(), 5, None, "Fin scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin->Reset Ack et Fin->rien", act="Alerte") + print(f"Alerte, seuil dépassés, risque de Fin Scan") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/Scan/nullscan.py b/idps/rules/TCP/Scan/nullscan.py new file mode 100644 index 0000000..7b373e2 --- /dev/null +++ b/idps/rules/TCP/Scan/nullscan.py @@ -0,0 +1,28 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """Règle Null Scan: + Un Null Scan va envoyer des requêtes TCP avec aucun flag d'actif + Si le port est ouvert alors le serveur ne répondra pas + Sinon le port est fermé et le serveur répondra: Reset ACK + """ + if (rule.cooldown + rule.time_window > time.time()): + return + + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("nullscan_time", 180) + rule.seuil = db.get_key("nullscan_count", 5) + + if tcp_packets.count_packet_of_type([""], rule.time_window, True) + tcp_packets.count_packet_of_type(["", "RA"], rule.time_window, True) >= rule.seuil: + db.send_alert(datetime.now(), 5, None, "Null scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de None->Reset Ack et None -> rien", act="Alerte") + print(f"Alerte, seuil dépassés, risque de Null Scan") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py index 59411c4..3a6e3c4 100644 --- a/idps/rules/TCP/Scan/synscan.py +++ b/idps/rules/TCP/Scan/synscan.py @@ -6,7 +6,7 @@ def rule(packet, tcp_packets, db): """Règle SYNScan: Un SYNScan va envoyer des requêtes TCP avec le flag SYN Si le port est ouvert alors le serveur répondra: Syn ACK, puis le client Reset la connexion - Sinon le port est fermé et le serveur répondera: Reset ACK + Sinon le port est fermé et le serveur répondra: Reset ACK """ if (rule.cooldown + rule.time_window > time.time()): return @@ -16,8 +16,8 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("synscan_time", 180) rule.seuil = db.get_key("synscan_count", 5) - if tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "SA", "RA"], rule.time_window, True) >= rule.seuil: - db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset ACK et Syn->Reset ACK", act="Alerte") + if tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) >= rule.seuil: + db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuil dépassés, risque de SynScan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py index e887ca3..3451fb0 100644 --- a/idps/rules/TCP/Scan/tcpconnectscan.py +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -5,7 +5,7 @@ import time def rule(packet, tcp_packets, db): """Règle TCPConnect Scan: Un scan TCP connect va effectuer une connexion TCP en entier sur chaque port scanné. - Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset -> ACK + Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset ACK Sinon le port est fermé et le serveur refusera la connexion SYN -> Reset ACK """ @@ -18,7 +18,7 @@ def rule(packet, tcp_packets, db): rule.seuil = db.get_key("tcpconnectscan_count", 5) if tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) >= rule.seuil: - db.send_alert(datetime.now(), 5, None, "TCPConnect Scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset->ACK et Syn->Reset ACK", act="Alerte") + db.send_alert(datetime.now(), 5, None, "TCPConnect Scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuils dépassés, risque de TCPConnectScan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/xmasscan.py b/idps/rules/TCP/Scan/xmasscan.py new file mode 100644 index 0000000..4f811c5 --- /dev/null +++ b/idps/rules/TCP/Scan/xmasscan.py @@ -0,0 +1,28 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """Règle XMAS Scan: + Un XMAS Scan va envoyer des requêtes TCP avec le flag Fin, Push, Urg + Si le port est ouvert alors le serveur répondra pas + Sinon le port est fermé et le serveur répondra: Reset ACK + """ + if (rule.cooldown + rule.time_window > time.time()): + return + + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("xmasscan_time", 180) + rule.seuil = db.get_key("xmasscan_count", 5) + + if tcp_packets.count_packet_of_type(["FPU", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["FPU"], rule.time_window, True) >= rule.seuil: + db.send_alert(datetime.now(), 5, None, "XMAS scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin Push Urg -> rien et Fin Push Urg->Reset ACK", act="Alerte") + print(f"Alerte, seuil dépassés, risque de XMAS Scan") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/tcp.py b/idps/tcp.py index efcfb63..0ee21f3 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -22,6 +22,14 @@ class TCP: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["S"], timestamp]) return + elif flags is None: + self.packets[ip_src].append([port_src, ip_dst, port_dst, [""], timestamp]) + return + + elif flags == "FPU": + self.packets[ip_src].append([port_src, ip_dst, port_dst, ["FPU"], timestamp]) + return + elif flags == "SA": i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") @@ -78,6 +86,20 @@ class TCP: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["R"], timestamp]) return + elif flags == "F": + i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") + + if i is not None: + print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + self.packets[ip][i][3].append("F") + self.packets[ip][i][4] = timestamp + return + else: + self.packets[ip_src].append([port_src, ip_dst, port_dst, ["F"], timestamp]) + return + + # TODO: ajout flag fin, none, fin urg push + def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags): """Cherche l'indice et le port de source du paquet dont le flag doit être remplacé""" From 6377eae0ae03b78b0a745d71c8afe3812b51f901 Mon Sep 17 00:00:00 2001 From: Oxbian Date: Wed, 20 Nov 2024 11:33:24 -0500 Subject: [PATCH 10/18] feat: new networking partition + schema + test everything works --- Demo/Dockerfiles/Dockerfile.attaquant | 6 +++++- Demo/Dockerfiles/Dockerfile.cible | 5 ++++- Demo/Dockerfiles/Dockerfile.idps | 12 +++++++----- Demo/Dockerfiles/attaquant-entrypoint.sh | 6 ++++++ Demo/Dockerfiles/cible-entrypoint.sh | 6 ++++++ Demo/Dockerfiles/idps-entrypoint.sh | 14 +++++++++++++ Demo/deploy.sh | 6 ++++++ Demo/docker-compose.yml | 25 ++++++++++++++++++------ config.json | 14 ++++++++++--- 9 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 Demo/Dockerfiles/attaquant-entrypoint.sh create mode 100644 Demo/Dockerfiles/cible-entrypoint.sh create mode 100644 Demo/Dockerfiles/idps-entrypoint.sh create mode 100755 Demo/deploy.sh diff --git a/Demo/Dockerfiles/Dockerfile.attaquant b/Demo/Dockerfiles/Dockerfile.attaquant index aa5466f..bbdaa4a 100644 --- a/Demo/Dockerfiles/Dockerfile.attaquant +++ b/Demo/Dockerfiles/Dockerfile.attaquant @@ -2,9 +2,13 @@ FROM python:alpine3.20 # Installation des paquets nécessaires pour scapy RUN apk -U upgrade && \ - apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev nmap + apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev nmap iproute2 RUN pip install scapy +COPY Demo/Dockerfiles/attaquant-entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] + # Copier le script d'attaque #COPY attack.py /attack.py diff --git a/Demo/Dockerfiles/Dockerfile.cible b/Demo/Dockerfiles/Dockerfile.cible index c10bf58..6793bc3 100644 --- a/Demo/Dockerfiles/Dockerfile.cible +++ b/Demo/Dockerfiles/Dockerfile.cible @@ -2,9 +2,12 @@ FROM python:alpine3.20 # Installation des paquets nécessaires pour scapy RUN apk -U upgrade && \ - apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev + apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev iproute2 RUN pip install scapy +COPY Demo/Dockerfiles/cible-entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] # Copier le script de détection d'attaques #COPY cible.py /cible.py diff --git a/Demo/Dockerfiles/Dockerfile.idps b/Demo/Dockerfiles/Dockerfile.idps index 330bba4..adc6592 100644 --- a/Demo/Dockerfiles/Dockerfile.idps +++ b/Demo/Dockerfiles/Dockerfile.idps @@ -2,9 +2,13 @@ FROM python:alpine3.20 # Installation des paquets nécessaires pour scapy RUN apk -U upgrade && \ - apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev + apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev iptables iproute2 RUN pip install scapy mysql-connector-python +# Copier le script de démarrage +COPY Demo/Dockerfiles/idps-entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + # Copier le script de l'idps WORKDIR /app @@ -14,9 +18,7 @@ COPY idps /app/idps # Copie du fichier de configuration COPY config.json /app/config.json -# Autres commandes nécessaires pour ton projet -# Par exemple, pour installer des dépendances : -# RUN pip install -r /app/idps/requirements.txt (si applicable) - +# Utiliser le script comme point d'entrée +ENTRYPOINT ["/entrypoint.sh"] # Commande par défaut CMD ["python", "/app/idps/main.py"] diff --git a/Demo/Dockerfiles/attaquant-entrypoint.sh b/Demo/Dockerfiles/attaquant-entrypoint.sh new file mode 100644 index 0000000..11792c1 --- /dev/null +++ b/Demo/Dockerfiles/attaquant-entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +ip route add 172.20.2.0/24 via 172.20.1.3 dev eth0 + +# Lancer l'application IDPS +exec "$@" diff --git a/Demo/Dockerfiles/cible-entrypoint.sh b/Demo/Dockerfiles/cible-entrypoint.sh new file mode 100644 index 0000000..74b24ae --- /dev/null +++ b/Demo/Dockerfiles/cible-entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +ip route add 172.20.1.0/24 via 172.20.2.2 dev eth0 + +# Lancer l'application IDPS +exec "$@" diff --git a/Demo/Dockerfiles/idps-entrypoint.sh b/Demo/Dockerfiles/idps-entrypoint.sh new file mode 100644 index 0000000..c69f83b --- /dev/null +++ b/Demo/Dockerfiles/idps-entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Activer l'acheminement des paquets +echo 1 > /proc/sys/net/ipv4/ip_forward + +# Configurer les règles iptables +ip route add 172.20.2.0/24 via 172.20.2.2 dev eth1 +ip route add 172.20.1.0/24 via 172.20.1.3 dev eth2 + +iptables -A FORWARD -i eth1 -o eth2 -j ACCEPT +iptables -A FORWARD -i eth2 -o eth1 -j ACCEPT + +# Lancer l'application IDPS +exec "$@" diff --git a/Demo/deploy.sh b/Demo/deploy.sh new file mode 100755 index 0000000..969b744 --- /dev/null +++ b/Demo/deploy.sh @@ -0,0 +1,6 @@ +#/bin/sh +docker compose build +docker compose stop +#docker rm ids idps +docker rm attaquant1 attaquant2 ids idps cible alert_db +docker compose up -d diff --git a/Demo/docker-compose.yml b/Demo/docker-compose.yml index 596459f..9180621 100644 --- a/Demo/docker-compose.yml +++ b/Demo/docker-compose.yml @@ -7,6 +7,8 @@ services: dockerfile: Demo/Dockerfiles/Dockerfile.attaquant container_name: attaquant1 command: sleep infinity + cap_add: + - NET_ADMIN networks: net_public: ipv4_address: 172.20.1.2 @@ -27,15 +29,19 @@ services: ipv4_address: 172.20.1.3 net_private: ipv4_address: 172.20.2.2 + net_data: + ipv4_address: 172.20.3.2 restart: unless-stopped # Cible cible: build: - context: Dockerfiles/. - dockerfile: Dockerfile.cible + context: .. + dockerfile: Demo/Dockerfiles/Dockerfile.cible container_name: cible command: sleep infinity + cap_add: + - NET_ADMIN networks: net_private: ipv4_address: 172.20.2.3 @@ -44,10 +50,12 @@ services: # Attaquant 2 atk2: build: - context: Dockerfiles/. - dockerfile: Dockerfile.attaquant + context: .. + dockerfile: Demo/Dockerfiles/Dockerfile.attaquant container_name: attaquant2 command: sleep infinity + cap_add: + - NET_ADMIN networks: net_private: ipv4_address: 172.20.2.4 @@ -81,8 +89,8 @@ services: ports: - "3306:3306" networks: - net_private: - ipv4_address: 172.20.2.10 + net_data: + ipv4_address: 172.20.3.10 restart: unless-stopped networks: @@ -96,3 +104,8 @@ networks: ipam: config: - subnet: 172.20.2.0/24 + net_data: + driver: bridge + ipam: + config: + - subnet: 172.20.3.0/24 diff --git a/config.json b/config.json index 5f69321..e028151 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,7 @@ { "rules_dirpath": "/app/idps/rules", - "ifaces": ["eth0", "eth1"], - "db_host": "172.20.2.10", + "ifaces": ["eth1"], + "db_host": "172.20.3.10", "db_database": "sidps", "db_user": "sidps", "db_password": "SUPERPASSWORD", @@ -13,5 +13,13 @@ "synscan_time": 180, "synscan_count": 5, "tcpconnectscan_time": 180, - "tcpconnectscan_count": 5 + "tcpconnectscan_count": 5, + "ackscan_time": 180, + "ackscan_count": 5, + "finscan_time": 180, + "finscan_count": 5, + "nullscan_time": 180, + "nullscan_count": 5, + "xmasscan_time": 180, + "xmasscan_count": 5 } From a1dcee53a15f81118f2a250b07b7765444c19ecc Mon Sep 17 00:00:00 2001 From: Oxbian Date: Wed, 20 Nov 2024 13:10:59 -0500 Subject: [PATCH 11/18] feat: update schema architecture --- Demo/architecture.png | Bin 76180 -> 117428 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Demo/architecture.png b/Demo/architecture.png index 08bc882a5a53f9c511c43b43db63178acdae9557..96126b854713277f7ec7d1afa6514ae3fa7b8efd 100644 GIT binary patch literal 117428 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

T#p&Q5nNdgMuwW$UJk-Y_pa++`( z{($M-UPFPNmP}$sfV6zuHwliIM(ZZDSvuD6Bh93%COUGO8X*(JW?Q$iaP7J_ zuawei#(^h66e@bXwz*hkPhLLm=hONS?Gvfvy+}H~MY+vs!1|5{vhvyuolUT-8TfCg z;RUtvWLD5|3A7tMT|^v6*{BkRmmyU~fdvQPDpJX=05aeN4wprZYT|dqe05I=?$sd^JQE&u!A-ei~OH5t3h7w;TcEw10Z!e^gs6fe_RkTyRr z(~U7e%*C=Q1FqKJhmfp4q>&oGh=%}ohb6hg)TJ%E@a35-bz^fxNaU-V>8LrEif{%@ef0ZS zOpbB4fTZBG``>_Pq5e(IvR`(E=_QhlzkM8LK>mvL$Jw!TfDo7r*3d5EknR5wzIXw{ zQ9WKVaycX9#ny?bgF42zttevp)h{2{D;&0HzR&R!p6{>s*N&y$n+JgBo5e+o-4Ir8 z-xo;N@fL~^Ff>H>TFem_|O_NzlZX9n7;@Pt!e9wd19Ze~Vc%LqiECS+FMFnW~ zuz)xBzn?ffa1G<9sn|PxtS3N+;h2+vUX9PS1{hf3cTtGzp8$wm1ZZx&~aa$5vaEjY`vt9Ey$<0wt2zd{!8JhoPVb#?0?FK+0P07K>WIX=4-s9``R z5p6aYj<{GsmnNo%7+w^%yz~)$c@_{u?K>SJEEGW%@ann(w_;1yZf^V4r)lr5kh|~V zXaQWC-YRcz&-SxdBaEe(BMiT&khb9vGn%wu6oI<}4;-~@p$HE=Y|zfl&){FxRiJ}v%{8zW(i^z9XbX0J7$5}W_B z2eSBl99VREP<21b&@!M>2y^2;Gpv*v(n_8+LJEd?pg@o10~Fb6q|q|q?kx&yiu*0i zN2R$H94R3wDcNURzlaTvn!BD*FC1e4f$;FZN82U26?BxbSN0De=jX4_3L{hWi-FJS zgA%kpvk2EB%w=5d{<YVP7Gz?+&Wc(2+vr)h&& zOH5_K(QPQ}G1E~0oPyHt9QliF*^Dzd(8GVy#{Vgt%%qV_h%ZcRqrifSE(?DCZeHb? zh&E}g|3q-1THlBSA0Z*HgV0LY9PhBMsXYZ>&rUw50SGaC!!&k|_*p!K(Y<7DiOH~`;jz{x_k)qU!k z0O0-)-(DTRYDg6{Mo*ExkTUzddH0?zlr8oL?>~ReL}XP4bS)`B7v;bj`BQm3c#~sB zpO-mFp0^Ps<#Z*Zm`t1?$q89T)C;e1?r6|g3a!|>a+w8`Z;F%sLqu2%zg+MF>sF%6 z`h4!w79ZB+LGV656+)3uWPBXXJhZgshiJd?`;gRxEmkG?o(Uu9;xz&7CtD@bT zgKq_To~SbU^sE8lsNWVEZL2Cl8UF0QB>oHjvhVM&pbj~li)OkZj<(g*lcnps)#Ylw zHX|{bnyO-%Hf63;k24PGnN!b7Ure<{>mR1M{K5fS{!<*}-S9Fi5uX4n6IZBvLu;!+ zPTUVqMJ%;HXC4v!5ZrP*wgK!PO{(I8gnVFl0ZI`)4M|?RD=5j*A@Ry}FU$3v$eVO5 z>xG~WvhZ+_TI21%gG_WQhhIClXyAxkA8F?G(8$f7Ras-i!+NZ9sypwr^SV$Ir=>YK zNU(Iji%jc*pfb~>X`vD~B8w7*jyi{FO4w+8dPFPokyhKZ9E{7i&5155mO-i#j|77L zR_(ku3#r3n79AvjXd(ER$VKaZf~@-)tBFdi1q+TU-O?{+XxZqg>HoU+UnAQn%YW3p zpuQU}fnj(;U2c??<|Mpmehm2@hyuRos1$m(YKkdz_L8xf75Rx#;#B?V?oL!IQIGf& z1D5dfJe`Lm0s4?d@|EbkX&cORxEi_d^>&#e!y@h-HI>aGI*nb$ZQ(0COkrZTKoNrw zSe@P*CJlF+SF_FhI8`BQwHh5yC3!{5C^Jd1T^`P;ZS$J36dgGdgavB_?GAlK1pSu= z!bM?e${~UBi}m2~%7&8E^99e1*OkD+5bw+<{{PdtVB zPM>raYcpTCqx0Bf!^=N0Ojv*sO{TNpCA)Te3OS$oH^nn8?SukEHqdHA3K4wd@DR zB0`70$-XbWqi7__QLM?ahLeo@YiF_42I18YFZ+D+T@fH%Zz9knH`Ik5RQD^mR~blM zk7|vZh?KZWFt1tvkK(>010F#+eUzG$l5&w*WwuVRJ{0xbko;s?KM;7j)}R?4yy5ul zBFb;r1NJDr7l(Y_dO+xL*$XRnAptY;Bm6)!>1W{3{CG)%j7Z!yBQQdm+lb{j1F|w= zBRPK=y}V5c9^Ia!ImOnxWl^5tCSRZUXE1fI&84a<=VwDF?SZV1OzGlIlNZi9aK_IT zo>X=l=Y<}Gjg#mfAb%XVQWPH1GAaCdR@aq|3_|kE87*B)2SsJ}82FFdd-!y_2d!F< z*Fu8!Q^rc;q{LS~wU!y(9z2nH=#0mGXdnw4{XNf>3nV&NQJ95sg7-q z=AcBBSOk8u|A|S841}!QAW@pL)B*%{Pc6W{9Lf$D42IJ|VK6iU^Ei?g#-4!a>(RC6 z^AfF+ahtTB#ZJ=8zeo6QV|8NToxEeF-JTq=(n{ghs#V&{@6|YiSu0P};%w6%%2kG4 z4PqBsPoYR4`E^}~wu!(|mqqJW>i+u7h1NC*$RgX7bJ**GwIAOnt#90QZoRp|h_r!g z!YTX2-zVdJ42T%%IAqj#kBAMSAvQ2j_!^gm-s?)EbyUNfK__e?cO*U!NI~fJhLoUP zpfyUE`YRZ`z-UEr+weCdV3MG8iFzp~H~%MC%}&Yk4{>u9%qL&>J46ql^6D?0dL?ta zMuob(;CvHO+)M9IYkKmZ;rRZ#orP(ovK(}#+X4^`UySo*Pnkyo6XQJ`bTgUM(`X74 zr5(6Ql#G9R;4lCAnTGSk9<{7L;Yqk$`};E+zN2iph_W<88g(9np00!Hh#)y8sib)v zVu6snnH3O&Hx5~QIgCx)PQP+FgG^B&$=-f6-7sQC%u_R+!a_JpnA%WE zg4{R{Ri>FLz}3}H+})fPg?Q!p6cGqR`}`(Fv2x3bROLPeiugn${v@lz+|Hb`>DEig zgiq#A3n#hZ)_B*g(`>ix9)6c@0~JUMK^T5yq({;>f~vZp=7mqd5GVwZ3QWRY(N)y? zU`w$`O}>fb)25-9t1H|U0fB*`iP6|Bq+{Ph==rB~xJi|a zWh7==PWEF*&(+Xs73<^RWsr4|qJNNRDXg@g&W4b`A(b%{Ap{SMWl@t2lDO40`O}o$ z53nfaXS0hV#m6^%QLRnIF1xxKL#w!YHKv^y57#R%&DEe?UO{VfhmKb}ZL zRUcSp!EQRw${RV^-iZQ=D?SK6dp_c%v3{umkcSOc&@<_+Snie6lr+u6PfaK{s6+9m zf;%{LkRX4+>ogPaUv=JOLH$_gI& zZxS*@4Jc8$kxzC?X#R3d9lRLrfr3S`liG}pQysoiC(g|@(BwkY z?5s3#G^Qz7WB(w6k(EAf>y*SoUL%q43LI>b`b++=>`R33QC#*vk`Gt`108bRR<4#CG!5)8b!-o&TEr|Hy%_Xc2 zh~I3W00UeeZ{F-3qIU&?J9ePf|KXa)lla{$uJ^>5S_;!W;4aaUQbRnoFIir(nYs*H zlRi52U8MnT60UOk4q?&K3;r0acZ4d(2Cm#i^~Sq9Hea+ZbMRJfE_;zM))b%qE3-OI zRinSZG%%t2%VEF4PgA5&4_q(@!`L85ieqIl??x@hQfGM9YPd4JsvUMFmJ`_ZHivYQ z#=ofiRT3d^THY^BpT?iQcS&yw;3<_b|Eyiu{8`S5W27rSj-jeET!kI7T?Grl_~upd z)trSxs}B`xr+|GTm0;#IraV4B*_?%>&EFGrtjPnrTiapIyTi%`)uB+M^23=WsY_$= z)P|*sZZa^#daVpW5cd5+to-;o;QBnkz&8%#m7cfsfaG_@BtM#3(a(NsMB2ma{>C=r zl7$^ng#tislD={|F{`-HNp!WQO8K#*2#4MG@w}W5RZOJ3L0#mEsPxYa30S)G8_!aC3-RqN*k1_BuW(-0=tVYT z6U+-vS6Atfl4N)3n&g`wqkLPhpeXM8I(BdCzS(s>$>%7ga}Opr&Mf(99E@h%TF@J% zW_{-Wn4KP3sIEtou(jt9iejVZ*q2;$^3(@m1re_*f@h#}`uCkD!cN~X45?2Bhqd~` z(J&fsVI}jRQsO~R5jyCn^#RX^Q9aq>(+f>9nlopX#mO@x!RvLng8mpp{=qhdk# z;>4L1xQM_g;lF?=BOu4GslNfNFY*zOg2?G$l0&k@JFmG-prEbxKVS@Z2Y0GO<)&?t z_qp(E9^kJXGy_BuWS8rGUt6EAlgxAL32hl}=>SW_{LAO!a?+!W1S zMJU0y2NM(AJ%1EIo4?k3rz~kgB?vzYh@pw{6)OGdUjXEzSjy4~Je6=0?T7!b1qd>( zbp5CM`b3&{ZJ_Wcb7gabK>(jxGpGO`#b~cTmis+#5yO5$&yM-T$uE ze6ntJGtlSI(4_H~YYzo}MR25zBy91uNkip3s&FUZqGV31W*ER{#uA$!cpk^IDs_XT zWm3>v<3{0+YB(r%f(*Nqq5^5D{0o&hLW*;` z*RP=ynkaFbxs_N40{m6Y%N!!RKT1?!Zgz_ISPs zD7x&kpW{9#=i}&R2xNlrepd;bSc|yujpz&SadpWq5$of2iGc+IlHxuzX60%)x8eTc z*(!~%OEe{!#+ZKYOmBI1mkNIem#Yi!E&%m+P4<1(2Mg8r_iL+@DGW>2+hy8J=}LI# zeAe`Gq~-K_iSCr#I++$A9#2WPB`cDbtPY^*N7|ptVKT+cMB&G`8li0f)Wx4Aw>`^y zI3%j893T8kvJ;sgrD*8l6ryOZK7{*yk-~rd!5xLMWb@UM)ttst`}keH=0r$yN7zNT z^VM-+jG#;Vu_qX<;Ux`YRwspK+fgzJKE1~eSoe8RalfloCY?I6z zs7-qrHOk}fXYP0R*6j?QF73(pyYFeIs9A7Z)_}b6{Idc^Ky(53>K~5nr<0odZ&%W3 ztC!oqp~)mQgzb*>>{r1t*X!?o=kV=CD{7>IzdZd(b9B7rN1Oef!6nOLE1)Dwwez8h z&NMC~k}r4-3S^>Hzxck{Nc{o`h%&$MPey;;wLE*rw#w~hNCQ39Z*L*e5D58pbO6`U zeGu>;S88YE+qnGEV@FA$ts}!UZ^dX8a@o?h)%B^a*d3c&;o|OESdPBb_E}+-ueHMd z+F5d^@q!7#D^_8cqWdx6*HsXzTKwJ51E(eQC6s)bPJCLLIx)-;bZ|LWKwWOD5PC$U z#T5}40d}qXV`njK5AQQbTQ2~6k2qFYo8-#(61u~Jq!a?8Ps%ymxbFDT6%9*oZHJlPTn@#$$6s6BFq;NASN+^!~M8Z%LXVR_UhG*6(}EqtCW^Ya{Q+Z zYISZ{r1l^$E|ZaPGgSatd%v~zvs;`0*6Tsd-H5p(pUn87M&LQM%-aot+(8spfr5qIz!L~;}2jOHuFUkWEw~CUANK+i) zAA)tjbFomBk(QI`eKi8UsrkZAT+-33=Kz#HB3zS3Y(@B681tHhp8jE?Gz_=w-E4V2 zZ=aH)CAc}Br>h7v?af)w?%jkVZuC8^9jfyj$#z|_?4#uyxa)=TT)zSr0z4&b^n$r@ z!T-3_56W1Ik}D6b%!6pOsiH&Lewb2x*Jv)=zZT}Y5FqFBZjtkBs-(SlE@y!3ev}k^ z_Nl-x;$K4QYAI-SwgL5aTunu*0=gZEv^L}BQw8Z1+&$wWzk@c%39YUyzo+uftKJ*= ztD!b>o>*7abc)1y3orIq_1n?x@8;=xvo~$hQSo(l2O>PuXR9P-SXqBNbqx)UjXW+E z<*z!^actInq(=LbV)d&kMs`x>xLC8+wx+P1_>vbF$=tfIl$Lbe-n6_%K_Jn6IAW%d zRHIZ3##|=SgoP==XZni4g;vfr0U+GnW|+h@scX`k3yTwI)+6ygxZGJout1#q8#gU> zE`>yZV+X8s!x%89I3PuvZOB_ot@#1$0BR-k3Ts(g4jmKHz;wR@gnoTBh z2;{@GR4a*ZlEvN)p)y{^>FnYD-!a}OW(vZYJgjiR;-NQwVd=XYZKDikPuIW!1-^gg z1jaMCrcQ@wIpZ;o6@$R#T8MK$(&-%v3$o`%g1I@0V?pGWm{bym*V$q-Pic`}&$Iq) zyK})a`o9xfg!Dq?SILQ{Ks4F$eO(7s!wD%_- z8PcC4!Qy=6l;ths9vxAt)Hq2lSBPZ$Wm2Er!CXVC3j!m$9U|HIHsW5{^)&qonVT}#{} zD{XW6T{?F!JY?TbmsrTAUV#A9dVOPuka0_+mH-v6pCzHQjxbb?!!%mj5nDe1Iz=YI z$#XOyy+Bg7!FNe(*B&bNtPbMXUog#ESvy!AD%SU(NZ2?Q;M!ki)!t+ihd(xo`wKAc zirP&!mUa0+NH9y|m!2{fhEW!n=hpYNRC=uLccyC!<$<8$6-sv_wy5`T(s-DrYk<{8pkB+F7xj1(Rb z@*ax7O>CuJJLkzvnM3~!(t8N6}R0_NhjxVtuf6Dh!&x!JwK~xu0qgOO4K|n zMkeVS+#RDE>@_!HW$ja2OiM;4MR5s;kwOtgtw_d^SH4j`bR^IX%XZc$tjCz!#gz*XdfB7^F8S*a{Ig?@IO>~-}`=YWOFeyQI58v#VCG`}4}$_%COGU0@_OlokX6A&R&N?qr=1J3Rr5IPBQ$ zQSkh`hts3)07>(nqR^`;zpA^s2;?3Hy_MegUTASwhQuirn4v#)d3RIAdx*EynBrLA zG5ze~MEO~eu<3F0FZ+1mfSBu00!PBayzyHo@Io3k{z%e^xcmWzWAFQ22kHj0P@&>i zPvKbF59Vc2)}YK38ydqaV*&!7c05^58WtZ8GLxrpwAsnlIelKqBFe^pJ)34de#gg( zS?CIPi^&+Rmu5+q7BW7aQG?5Oy^Jo63pf2Hd#)6}Eo|aMb{0|*sb_R9hn`+3e;+9j zo|FOHuDV|^DUXNmFKKazXC}v|E6-0TZUssC! zO$b_KfQNI*e}`dNe-sZtHm`Rz08?ul0?;n|>P}=F%F4f1o`oN;>TNVgpB$)}|12NY za5LMC#&6Y`wuB&K5?&?WaO<71gebyuq8K`i`j^MP^`?U%55xo_V4WLC}hVkA(ngpwjv+;u@JZ>$0eaMK3mf?+|<2>oE7P z+TT!_ER%?_mm~ZQ>dDCtjf@#_{ycClDiZB51qYd5oyIAEpG)lNCL=+i9Iy^EnsftOos!)c9%UwJ*1{Ln9Y4=IoAc z1DHv>8~nztBq^z=txof|oXDn)K7x<3NHO_lYn=>*@v@u0G<;Wx?ceJ}7LWy~A}V=@ zj$b!GJoy|2n`>EK``3TAO|E)UyQAta*l2~i&UD}98rGs5VgyU1X~mg}1{sn#p6yXz zP;<$l9gj`FVzVqubzT3gyFa40^%(l<1h|y6M4U0my$QXboo3gNii6(vTkgt=8*yA* z@`zg*M|(JdxrVpBHiwR(TL7r|!(2u{j=?L>Y~P3KK9SC0zSaU&pQ};^3Oxt{mgg_& zC_);Nd^yV_HVX?jlW`B#oTt=<$1^UPVi$7EH%b3_6LltVEl^iaRpQJ$cjz%;WryhJ zthS#o)sMXp1fbDTZle5H&>IXq47QbsOjYFAJJq*V89OG>2m`i*EL-b?>Sk9aKK!o} z!GZ(Z6!;Z=v)d-fV&t2Z`f^#F2}W0esw?=kkr3L(&b@-Y_~QPH`c=h$8Hv7mT2le( zw>FhCE6P5K0wVFU>Nj~c>SL!v+Oq31LnmK(E+}aKO;lwkyKf15S42B(hrV9vPK7!; zJ@2F$8IYb?M)D;}6)NP|u@<-V>I5r5l`aAr#FDysdyvU{ZaOvQT|Tx}`q2|U50DZV zRL0<<>ncW79uSj=_yr{H{n?*Fcf&+RJx%jp2XRCbU^pM%OS|W-17=QR8BNT9B(d5L zmbS0zNKH|mJ~uS`AC?(|4QeRqrh~`ZitAF11h{hB6^=a~ z_p^_arbAu;)474aw%F;qY|7n+V;_(5PnoiUa*Y&Cy4zd6yWS=-N5{G}L~hpeHkXrh zOlaUPgYd1idZLWa?c7G{sG_EemdN)ZkH_wp^f5%+66w-%*~RYM+vi!2cS`B|<~Qe) z-PN5liaN`Cku;&w33!eEN8*}>%??g-ZV9lAb3FNwlENfwajE|-F57iK2qp7zDQ}$ zthFdez*?7Q>PW?~ZuXRVWsmPuqcmi=sLnnaaweyclH#jt5BK_L)v!B;&A`GC2rEFO zI0Au>?n&N-JUmB|#nGvV(30#5M4$v>%+eJ2|F~+!J{k=CuyHju0Jg!JRt9?Gj}Vo) zXD!nhu&F=)rNbos2)RH7{0}H{>KouiVy5_yh;ST+QoMizz0yd9YV06Ye1nvE=c2Qi z9X|K3m5LB>hS`@id-;^ny<&@T-<`cxD-q7244$skZXuFGtc9E+;Y#oB7Ow$^A z^B#^RQLp>56{X+#>YvHQUVzgq1kzt~wIsMU+uRS0<>|pFTQ;fRtDCJDUR}(|v~|9q z!}0MH9V}#_QYh1sVf@ooETFB<5sbdo5V2Ej^2>SWa_{QeU?@u>%cTFCfF#{3MDDzN zjrx3{V{zePnUhb0jzC#nl^Jm^g{ldgemC=|#T}oE_U}Y$#=7$XC$s5L^47mu6rxo& z3QAO~$~BGF5u=X!JD)Jx_5u&z^y3E83a~27k`@0kY7cK>%#-a~5#a zgeEfTG>v1^|Let(sl)NB?)=p}AmCOqs_uvTJ#>Wf3BpRntMj@Vw#C+*tcRF+k`8i)KjL@y9a7>$`CW5`aO;g&;cA|39oxFhJ z%WYoJP)(e&Q!@=}RPwnt0>X$3hge@{3h&~3CP-Spt30j}gu@Ejd^r4j^?lKkk}&pc zLYuEnw7%2neVs~&BjRb_g-TYDV!9#QL)zLJR?jtFx8N1zgJTkPpy{mDO=}Y`etyjtw_}C4yQ{aOg(@9=WUSg}O=E4S=Ipm5AZaMZ;|KUY z$}q=K#4b})c`%g4C^tt{Su)L-bM$uX1h-ym**-|~{2c$y=Hvof%+@O`Rh@{1)X?Jw zwd!E4WN5jDTtzRmFfbiI>9znf1clpk9~eFi1f!;4{Qa$fCR6p}t<Z*W7i=kkbE?s2Zx^?C_xS@YxpPO7`I(+zW<97j0I_V_&_19l>-6#AuC}3TA_ysK6 z6_F)H8Hn`R0gFy_1PC{veniSUNlWY;pvZXi(MQAWQVZ;QT#4zos-VJS!xOyLm=@Rw z3+li{9*gjgCMC&UT?tIqTH#}9X`+roS~GRjZ({1ijv5w6N`-wo*;G$`(-tpY zY)B~+FeVbzP2s|eTn5mJ2vQmq6%}f?CZfixWt)O+u1bQAh3 zQ-A6T)E;C{PdVijzpsiGHAw4NlmmD=ARo?OgfDp^lTAh&G;Z8DtJih@#?Kxt93z0+ zuB*}u^#jim=8oYE%CDGvIiPnlB?NfLSa^>B3a?(7QeH}XytS4KFJf8*PX>*6$y_|7FpG561W2doRo6$QI@2cIWKtp%Q@| z+IT%x>w03;oTY}EW>|z*1n6tXgw|7zg3CZukB~FJoJL z3RuttO;x4fcog`5r102-8p#$dT7<{N6u?zr;E40KBb(|lf~A}^LV?IpeAbr;G8I~D^(Cw+AGBA>P?)=LjBn`uVW2`{nFR2m2J9; zepFp?vq1@Ev}PTNTeQ|8mDZLj#eHapL|@;dyLL%AHKvNyFR#72;*6v>5Ms)>c!qeE zK!pkwMtV=xHi)xd9@~r98jL+>PQ@EG0E+E>0912lbC+3#I(I7rn!a8 z|JNY|e2_UnmYGwgLYnl%j+dvvv#j46u;EFuH~tov#2LM?-1NP#R3NjPAIj>#9Kbouh- zrr|T0Q)_Y*NYw4V!4`pCI?+jY(=*C}HFkvcKXpF42;D6Zc%^ni8hPxJdc!F)UxerL~~ZA^Qd-t)mc-ohFi3qU*% zIBh#XLeDdk7YTl0jk}=FgHtahe6G(*^XAP>A_2dTU_dYxBJ9zYbf-K%+k|ED;IpJ^ z8PBDT9;Li#x+1V$$*bTY_!j;X0ci7Hj3 zf=Wm|InEwZ7uW-nCrg@sa2?Zz)Uo=egrGUDw;XS?P9lthu#5BTF?~aCP?L%n)#cY1 zGbY<59MwK}dv*2pz|TL+(cQbHxMmPbb?s`#;ff^9GA4ccsnk?ig{WM2tFBfd&xNqp z)O%4vof)aI#Wj~~GKNLC@>bRl4UU%|a5B?OpqWSqiU~R)N74rB*RP+|bMEDrUpARk zR_Ky+ae}rBkWy=M6llcl{=pUj-oppfh^3@1T1Ba2s73fkfQcOhb+g`k2bj7+PW$xf zlPv&{rs>nCo4@tz*H0cP!uDU`c4v@6&z(EhTo&IsktR(%Pdz>Ga0oQX5Khm<#~*(z zPe1*1R_jBqjYV=wi!3rC;99Hg#Do&9TeU3DB6|e3?MpKq18P_F-XGW_F-_73a*t;2 zKwTv&7RMui)Cfm1np0zVgp?={>u3lQ<~$`eD_TX1s|}%3d1+Z~B~oF)fD=Lw*@KMb z>~ZSu9{IZMA+4=|93S1kUt-mW0^*CYPpW=VQGtBt-3l1fu((mgCi=F-J#BB)X_%kq%^vIJ!Hq{7b7*P<~*iPKr{Lm{-@VW^O%YeLWvp(ZBxs z%RF1OJK#&c1aQ|yarCJ!Ho5|7DFhXh5k3Q% zD1%6p4QeC z?c!P^xlbn%dv$T6vc5Ul&cSZ||NZ(UK#gbh%!vplMcX*868;J*S1qgm29VWF7hNPJ z)EKCil0fGWQ;o+ka0DoFoa}V|pUECESR+7>blm<~EOKDg3Ax`bjMxV1eA%`2 z3ZMOF001BWNklYK zFEC{6rkf1OE2lN3v8qcyqN|m-$I{CWMCpTFL%)Pw&3ULrJ*+)2>tr?*_jYbywk4}c zb~9%y73c58;^U>Z%Ik`$`xuUy7?hYAFeR}LQAGL+nPyzhLI%&zKK-fo!3V~a2^`+O zUAAb(ms(n~u+=kH!1rtBbGJ@N%4$4ZWxLMb+1E8Qxl5%IWKsb}Mm4l&ELmD=S0UQ9 za%6Lz>@COU9QlFmYJzl77j2MKbD#1HtW2`#K~{h^G1Pbr9XeE~fw3sO2+-Q4$)mqZ z@}VO#;l38qs$SW`JGniRjX(rPfClz&zy0`>BOEIQis?5v`)sgk;#lSM7BlG}2b^*<2oose6abZZ-%x;k+H zIMyPwb@t_NiJI|CrAA067*U#ScBH(CO70J+9HNdAUx+X`q9m5uQRKyp0V!|A%$5R< zdnf0El+xD~KyJy#LfRqH*{(-3j!1lw`T}ZDx9I(&C66!dVshRm78SS;3EIvDgQxre z7UbCW)1wcEXB_WRwCG$7$MAtE`e$B)kqF`Vju=Iws=j0EsX%UsppZh%m>kq6-TpH3t5|83SV?ZutSe z9KQJC3v(!BRQ5wGKcbqqV^FBya&U$j$cw!j$@OjXkC^UHOOZ8u*Gb9fcxhbWq`VC< zANCr#>}zRL;|yt1$u}wbF*zn%lXuAO)ICxmuDsMJT~&$~vt=Ina4YN~+(dwWr>-U< zl+hqHv?$mJP-Ezj(Iz@4p})38ct(J_(Gi+NaDcZ3F1&UzBCz|7>W$=rYX-Wc&i5gw zS6p#LU=o9WaR=CSbW@?0J4a1MMTv#pCS2cg9XHIigRk+Qmz zfo?eaY#|c~$#c#8aeSwx0)#D2x1+x)=1Ju>Bbc-OiZ9zDw{>LO&iEmLRdsQKdd*E* z--AOgnL%7~jXZe6hOA3veC1W%3!$a<)sRPpk@qTLMp|n!yIR9aX0oahd+JPS3qfm~ zc$JADiA5Tl4Z2T7C2D2#P3#yAIV5tMI-aGgNfHK7uB~Vws}RQW>TZiX+QDJ14c@HR zfpajVmH$svf`3?vwK;|leN1!S+f7}%7-C*aCr>3bE`j1M%|icAV+hXH`#Rc7Ha*aD z+5K~m!1kmxIpe8JVtS<#)3bderfEmgN~WxvAzSuulTtAy<1$$wkjE>XpEU;LWAXuEA!~?sfd|WxXvPn0&v3YMP;f8GPIIv6l z{`ipmyYKjWzhqRrTu}EM8PMhqLsY$i>;FdMFmCmavS!bErMSoB?1WbGSiAeAN_?f< zZ;0I@q9Slmo!&cW$;ft9&VU~3t#`{nPp$I{bfw`L7f)La7Tt}zl)q8U}EjyV){rF-;C3X;fc)WPmk zC)y(#gBV?1E3L$_g!a|ks-_9Fjd9J|LST{aLIBBDBL6L>*<~`U^lCLVpZX>RxDz8u z#`TwsYo%6bM|KSCf55TGP03<3J8+_YE)tJCoDpv_W&sQHJ(vC^xk8F4sPE zB+ZbnkCu#++W|bOC>6lV_ zJ%{9vZA)co;tDyxPCI$M(_pXT`|mGL%Crr?D-o_Gt!kX6WO$d%*f>{Cui9Kb>GoQH zcgyY`ZV?!!-;aE+0y|+Y{JVQt7sgw*Y-zkS%BwQ#5B;w5R~c6LqxS!d^aa007qjWj z>6$t8|45;;#|Jvk!ZFqX$}HY%HcMJC_Ym?=t*&b?Sd<84PkHVl1mmwjpf@|tGQ9k5bOjgLjqM!=PrzHmiD zxv9NpV!Hd_Ub*py`wXdUUA={nT|}k}F?EN;)Lqi!o7?2FMxEuMv+gpRKq4QW_MBYT ztfxG9RzLH%!^e)uO?uqqv;#8!ii}nnp3wczpkM<<6fTmbNup%3BvbE78TZmR$dP=+|du`o`HZ9PHQOW8~w4;gg3 z;Soa1KM?Nq%X{|h5tLcHpB&g)(!zTr-+%vo<2vpNdNJdA9PT)nepF6YGfDcG&UmDi zG_0E8CF2gB`A-fQfFrOwC0&|7k&!Wdu4efMvs+#DecOaA$Lhrpx?;wZ;X-W}Al%hX&Y$%8z7C=P-QBhD)P^1W0Km!$H*NdQd|y5^d3(!wo9sJxX3kL=Qhme}1aSM6y(*LG&n2`7^qnr) z|22(lG?+sCZj}wcvSo(KOoF@_ip>|dtL!X@trjS|9k}{&n%wa@8dCqB-0x4>HjA^d z$7tQ)uk#Ff=Eiv%vSu7Dyla-~JuN6ul6x%bG;O}HolBH|=Im}Wn%?E5JQ>-7UbpDb z_bM~1l`Z3%6(@eCx4G0Aq#K#k2!8lY=Jo|tfIx*?!Z8t8vt|uJ$r6FXU)_T{$3(<( zyYAh)H=X9T8H7C^5P%fGiUKB-9MC478QD4wr+iF^J?SX8p&#~A`}X9;U+5vV?O>k};u2{S2FjzJ<8o{mGiw1A zw{iLVY)!ZZ8QL%c@GxyMCA*Db1{2fA3=q@&BMn>kB>B4e(3kzPZ5MPy%Q8OPWC%^X zBU>R_U!-THQ{UwysJ4F%`r@wQ+cqpa_7lz8vw#-g{h=xkMxY0_=l2iL@J0h}D-TXc zPo&P@4WOCbU#Gq`yBD~ukM}L2uMYn}eq7G`ShL|YqR~L|aJi*`U7YvT3xB>zJFosr ze~(~aV;&=%`{Yx&bp)R~=mnQ>OavefvJa~B94onM$dSt3tnH4&m+?_{0zkm>LOU?9 zwsn?tJy0D6Q9$NOS7@uG<5}bD@NDs&P9+=qh0!-GVL1do=61;sVY!$SKCE-{9#>ML zMbIAOL}(KAoSp6P@&yyqdrCq~?GYGL?+Mm1yK?$*p=|aGi|Rmy%Ml`jRs62U%nBWNeF3BDbb4fA$Z!d5uGs1~`0U?SyXtf;~w|x*N=`JJ4S)*7?9t-$2wLht0)M8Bz9YXP$!-_5a<;~^#L+;5|&4x zpzJBMYP8;Z%dgOQD>xaJL_KC@6VrvG8q&SZOOP=&-f|pkB%HdTF9YGry`f)lS*s(I zN~9h*Kv2r{Vy~tEJ_(X27y+p6;>0H zEV}Y??;nOzw`%QaO2_Bb#y)W^eYP_z0z)i z%5D}X{tY{%NMBhNLV~c6u43*!{@IxI6KTo4bE#RSyb7lad5vGOc+;Q5SCE&het`n0 z2Oqh9g0r3b6mj!?H9gNN_6VrOqyJaJx)A^wh59Sn%@EyKC=$=39{B_^t$P=au{!iP zqt{uBDpjhezkO}mw6PliPBAgs3{Y(F1Hat2n9XQf<=d!_`TZUDH__Kc%?n7PyI&k?3_!r z%2ijH&kA073AL6LeY5jK8c_GH+dpv{L(_G zTko{!9o01{cN8Ty>%AkUU0Lg|`_e;=2h$68(Bj3b=Yd=gPw12nQ$Pv zySU}qEYx>FK+CxM(RcUFSDvL1GM zu!gx1dpS2t`OK!t$`dqyfE2a}XhdC@Od=Cn-m{##1R2~nx4%z!*XpU(^TYAAbSUCD zeR=o$%BNJlcax(DCCP{{`+dN~axaS>Emvd`y|HyzkjaBBWmca2g^6?|E$u&_>iO5Y z?RDt29kA*#f<;dL@N@TN_1_lC2Nmmxnea?@##B^!?ew?9@V0bS%IC9)-hKDo=a4v9 z`p{xQ1)hP3|OZ7LDjj)i9L^cA*kV1JE0t5(r zXrP=|J}B(_9fIs-|COVZVy&)4%ZaEn1hwA5_3zH@J=Ksn8*_mk{`nd5boHR8T90N= z&kB^pL^hPmeosfAqy6DWC_E{WW^{c;k;zGazf1c<4=N8*Sg?R(f^0%b7g<&i+#4ye zbTRIV>IFR#d4ekY2GN>9w=7sdDChmVm@>1ns1p<439Uv`wKBK7B0;1_{`|BmHD1_n z7Oy9nR-X8UeNK0)l4K|bLwUGf`C2r##Y4GbN%>y~KU7%IT#XN-(M=zurU4BpB_ow0 zlcMQt%ta=|$LI|2e-M{9k6m&?h^c-5dKlbYr%s*d3Jd8WjvP5cetv!qjE41X9ilmB z&z@DiZ>v_Vvc3ftb46&o>d~VI1q5XKKHF+QXcHc@Ag2g>70|KO`%}_&qn~@)v}w7| zkPRC)RQ>mEZh5PqN;Q zb?VUO&6_R0E?IzS5Wok+cJ8}H;ExFYxZrydj*9@u;!sw@O=eQ|8~c~$5B%JT%W6?t zTatipYDsNdN-|$@UV~EMOeXBQCBOx}KJvBKC~?CE@@C7eO57u5myyN0D%mZzOE|Pm zojiGx`mh%^qBEUv5RRRjmg+S8m+6QEl1F%S(BaLcc=7J`jLb%_EOIqCA8VaB-MAbt;V> zJ=&%=n4Wo)>c6&=Qqr?%{qrrUc~$+|Dtb$KlbAF`vbU2T|Kj?yca?;35Wq>}_3PKw zV8Ow`%3BH~Rl+_HKp7%4m7q|{y0$Y;n#a;=^%Fl4RK zwQE*RjHUO+dqk56`U~$LYt1AAYDrawKd6 z0jS>Lj|BYp5bfKyCzM=B*argLX8ud3!;@(4i25|7jcp5L*vB1_UDzW6H*VZehqDNf z1g&SzmiL-@{SYNAX-*!kpC`}m9~#_B%HJc02MXYlXjS|hv9)>;FCekdai3JM}< zXGoX_0c59l@7}E@L)k8TNuks#;g|?OeC!3CHp@ztDk&`!WK?ZE^b^y`lPU4H-=vh+ z40jmiBrropc?{zI`|npJp%T`OfUY+wJ}6L*jqgd=4+7O++D>TNf2vnidhMPX_OmhB zi6CG_2xvkySW^G~{b}C3c~-Q#TT4L}^k!Ndxm0Le==w6QZl}Z_x{znrS>$nt;Z~jG zO;1wV!Ov`>ly}{_b&3$7m+{P*Glk+H7nBZxKmPcGCQh7~+e_M{NfV{aTGEPw47MUk zX59;4e$I5VvA){UA!&cF#@|gGP+Vqh1}(;qA5XB|vgOcEOgRgb$Y$3Npa@yJ)|U5Z z6KjVAJCwIHsr(S`?FC^KV`S^QeJ~eCPe)i-m|7eRkbmWJcQG8dzI#>L71exsJEdma zr2qA(LX+>SS=!-j>h;ovVNX>nYEO(b^v+zTS9J)9yWM?lGZ;$>Bqh$ztP8e z{03HiFY$~5TOY*v^XE%UkgR%>RS$s@1@15Z;y`BBhCNR`E??72*nUcGvC zb1%mz^XVt1lO|Cj`!EVIH44r}9t1*2AURqaOkDwNr06c!xlofx4-0D9_-uGr} z45aRTk5aZxBHxGqBbNZfpA$(xKS1fHR#MsLQi+%VTYG>g!Bqh60(d^LwTOs_pd=;$ z*oUby;|Tf{>%%?j2NMJ3J4-W^F%l1&!12C<;#qh zW{stJZFFJ=MaHL5y&%IPuX>5;blZ5VO|8FO8CSRPZ0dI5Fn-a;{-)K z3G*TVwd6P1(>En0MNKR=Fy_VIlCx>VbZplUnl?a)sj2TpG@m%fuUMhVqAG~}fvMrP zn(-mnapcGmwVp$V4k=}GO9sk!Q}?_>ZVgA0_ub#-E+ymgUz|nl$-R00RAxf9qCVng zMlxlb|Bame>vJZxiTYm3mWh=5?}y|!{t7w!h8WyV;wmP*SGG}^XOk?s?IO=zuU4!!gI&4&*t`G%mJ7N0X=wzQ~f7WW1AFwty@!|4NHQT>Rn<5FNVq%N=LPL_~D0@T)2dJ5EwmrH2wMK zpK3A~aD$-Q+6S?Dkh0HN@P{-mC6gZSQkmWwSld1~X+^sV=fk*^y?e={RVxb8DNC}V zCCXAvfI!=}Z7DoFT#bBzvj%9BuvFYkjiva{nMk^qA-^$a$;nm63_c@;;ucg?CB0>z zzTI001BWNklBn@$d+OU_fU?=$vQ1rvV^*I>t;2}hcYz?1;iBL zf!?{Z@$NJJuHx^j79lL4Y z3kX@k;#_Mrz?x_wS$w#WcKS4-Z$m!9XQgB@R8;jXCZd|x%n~9*J@VGQ;`DS)+{;UV; z(#Q@$dZ*G$OmFgOSRw>n*jvo4wmguT>Sh&XT=a3^13>dU#c3t}pa!$Ytb}P0z^Oe> zDz9I^t|oxlJ9<1|=_BDd2sE0!i(-;8Xmsbw^!6b6J80@VFT~W;2wUg)t@t1U*&<(G z-#iafmRN1tk*_HE_s7Vy%X{R}_IA>hcJv#{iaA4`o!&CIyu{Uaa~5?ym7NItIm1Ld z{%d|Gl(?opWnA7u?#;(@wxm9#?w?0Dxn$Vy$xtS{zLtPT&DpVIN4msOj?P@& z2+WX;_T zS_=x<8ikk^wrTmfc@aRr>En+-PFwhmi@=E*nw^L79~%kdA^J&`x4zA;P0GN5l;cT~*vTvVcOwEkDrKdwVB}ywHq=SQ4OGfe^<0M~KXW4Ia&=TMsz;lN zxf$2^FIYX()rVDikLA8T`LAcQ*YV(A5I zXJR-DS9Z)8KIpitgiWh#*ud}a0E*{UrDzsH(hWZ*LH?}%>%>`8-6+nrrhacCvxtl? zN@#T>dFM`w;!4BH>?iMBuAEVpk;GMVz|D^{?M`fygt*+jyUK2A0U{pA)s60T`1jJt z6(2YdxWZysAiY&Nqiv{^S9imBZ=uRk^S_0_9PGF(5fR*5+G1*U#&qV8I`nWy{fRZb z8BhjgP4G~ z+V?;baXtRkzK7>4{I~W!{Hu{k5K4$4>i&!WM$fIWBhA$uZ|(yC0hK-|zH8THOPD#Mq_qEJxft;p?SK1_u2M{%yr^IFCi+5sT8 z$l5wFiNkyWbLVoYyzA}ru<|ohX;b--GK1IT%vSe>2`MQy^XAi~j0YDmO9-TNNj8f)`+$XK8KnxY!tK9Pr5?Yp%5^`kEuD(ww^gOF`YZOhfVWswAAWS_q?rqNj*DFCy(}1 zinNTBtuIsRKeJg7DN2!0MBHbU>1JZ6D*1J9{X%Y^X;$nxO8BO^>QnU_cZr<+s!-g# zGE5SNaIZ<667FDlvwiswG3qaF=6Z0~J{b(;$Fq zE%fkudFk{y7h@_|k6ar%RF&W&o9EG_2}MqxOo?0$T9r#i^OxI#3`Vl(PC*{0`KK-N zwM_6MnOI>?m-6MwovntP{ro8PzyU>0K_GPl<*d<6j5DKeiHm7JFUKuy$oe9#aW*-f zeRME?R(aN3*vlGM;Er1ld*npgd17KkMQD5%49w#3i`i zy?ayHQKKl7%bfX?LjBB%D;29Uv2*gs+gpzQPd>SzkQ`<4V%#Fbm-1nX5}9HzTc!8I z+CTYAe2X&IG8Vd;#1^3F-3M>Lfswf*Dj}VkzOh?P`yOXZACZiyxo?4a=7TJ>MxOA7 z8^>jEuc0Cz(SX`fzm8s-?&oXkWH>A+zfRuuq`V8X!ubQ0I;fP;UhqF;;gn&Lg}DCm%apWf6IJ0a5JlZUCN+|ue~=YKcF<51 z_1fr}Gbx_SYQ4F-uOhceX{7Gjpg{zCl*&vP-ExvD5MILikVW-k;U^!?^nu8xaTOb~ zlE`9~XUi1CCGNp>;iOE+nl-u0R3)#hYzrc(DG;corl~bd9Y9A$SC`Z>-4TN(Ag#i2-t}1Lk$+ z9{iF76wjf2j#$W|wtaO7dr8JC$!o61r&IH(LQG47oz1-ljm@x?(S(uEH?a;UNClKf z*xcq!ykJ=I;6xH44v6aP*^3W>n*7I0LJ$xH%#T1A9|)y#d6cNZn;&~i&WOLcD6_P* zK!=7w`svk_^b0?zvMR1yy$8s><s5t-60)3HD9f2u{W$x=s=s5;DG{T%1uVdmm99uELi06sZ!v+qdd;`w zttoJB&BxTx!o0aZ5n31peIWygtPTFfb@*5J3uVE&U-%jR--9z%`o18XWsX3}xmMb% zmHO(I{^tLg?*D85jWS{FH4v$RUI-4w@qKutLwFHChuGrCkt5aKiyO!qB73N;M>tCg zK~sq5#Bn(-NDl~NIra}O!{ciKi%5_mT_US*-lAL!VWn#<>I7m1Z&WSY2f~MpCqg$1 z8p@S`Y20rc%!gC%ItsEX+sTxKHq#MGr01c|nYwO7I@g)&i@^S)46KeER99baw$|+QwM7p)n#kW7;eyV+y?v z=yvD}=`l6+-7wSmk38~7ZtXb!h@-h*Y)$lo4_~Kuxzq!_C5QoBit#afcS#5Wf`H`^ z5MpXM>@7KS6D~1~kB?V}gIl+5wd7KA=gz#gi;{jH&HbL)UgG48@;CmxV6uvUFp^e! zi@wpsm3>(JXa;$-%Qm=28E?W;7O`O!U6)GDxvwsWvoYb^$9F)L^?KjGmRzg%R@bTw z>DBE_RL`@(Ne#-3I!XykSa^x&a&J0DsRKKgsZN>K4^#T-mE5PgNnM9hUvmfU6Ydw{ z85YQynA3A-?seGHe6WSN%;Gv)%w{p72U&oqqya(`%Gt#%zE}Ffmr0pFXCHO5a2okS zA0zr15$G$u#v+>)nLNY(M2n(ai%cmprU5LvA)G6FrSTB$Kgey^asm*>YibOTDosfQ0| zuRBNh2zHw(|NcvX{H$5j07*v4GuDO7E&6;xj5WcfqK>0`9ZGj0c!UEL1lrc1f^O~* zVrp*0tzyw1K+t*)zZ6&L-j%DB!auol8f|nTrB>n?Fjnc{-tYek33PHdz z5xCBM-bpNegZ`dMIVZf1iG*YA8sZ$sj~^%WEFL^~(0Vq{mM!V0S5f+@6_gpem$H&0 zRi@On#+~HeY#g~%$o2(P-lq$zk=LD{lUsvZO8Fq7se9g~w39#5O}y5(GQak&Y@%8A zR%H&xPu@6Il@7bs%od%=xUhkeejULN}~Ecn!s|;?Yf7wc#;fduXX>%=UXX*naQ(@lB~)ef^5bdNZa8T(=#~5A0?6p)mRoU1Td*Ue&L%~*TDM<08&{4vanb}? zVqlN#sTL@~Mk%pU2QI{x<|QV(KXMtg7C&%ix&yDzQUOvL5tl~wgYw!CZRAwuQjkd`k7@mtU&B9mEJe1w-koqXz2h@gb^(c#}HnJ3;m>2nYhDLjdg$ zPNf?n->dQ2^jS`i*9p$rlvIV(sEd-p3PfN&XPr=LihzPLl$5P9ZgFX=TweY~Arp<3 zB9uy3<3qViT+#|rONiC<;gZy%1c(zdekjvL31~sY1=c69K!LDOMUB|$433N`vZ1QP zm910oFUojzv!&YQMY$Hf)F5fdT)OeT{5aF;$32}K`etA7km%pv|fBTnqO=PxFE9$k5pZc*JN%#h~R9l@)reJC^ej3RoNZv(1&NX{4g&u$aY9uW1d)P+g9+Av2(%jw0huc#!dV>1lQXPkVR51-o0h?2 zhOy`)RA}MTnLkik8_CMJ2yZ5@ewz1zj5Cjr(X_6(uAH>==FO= zt=V|U%1DC1Ed(HV1aEExO3&J{kD!EgA^<%G*iRsE_zl%v3F9FEZ2!l~vllr_hG&)J z;GoWLc&=o<~>>@j*RB??C1C<`~?y>o%H(+E88<4^;ccv}h~ zrnYpqO0m{oxIX|!%?aH2jex4&axOUt^NEjah zWK3V?tmQ@)g3}FH$DmEi(ISRRVq?GfLiLQAGYe`loJ(+M0JU8xWJ6~LQHQ-@;WVKs zXj^PAC74)0G39z`)J;RhD|p$m5)3Ubu{H$IZwd<;WD*hZ14DB(N=NJ^pt?JVo8u30 z9XsKl1dgXP3fUP0`LApO#a1m8JC`psBJ_Mj* zKV`}kwJ`KNqD)Z2vzRa}UzK3vtxFJ`>aNLQG48rMy-UFoeJ|uFRS=X_C4G z!W|InGg*|NRL*2;v7v!+@cZkpzp52ON!eDP7ih!6med$yMbQVrs4T*eL75 zA3B_Rrn12=0-jlTK(M9I6=SH(>TwXys9LqEEp0*8YNZGan0Ju&o{yu>b<5F@Pd2sE zRoc(8VEle#!2&ABQvUGalW-gaAohYP7erB2NF4_q>)2_lR;?&1DoQQp54Q9`zo~@z z5P-V?GGb7!*5V=dzXWNu=g@pe;XCSSt@cD_yaDJnh9WisiI~@3dyU4hBD1wei>Z4k zB0f#EMWH=PU+B%4Msa;|0!xB>b?it1>{}&azX*VoBK5B+?UgB0MwR;ZXD=*k4wQXC z7F#Rb?cKXKEn+_^2|>VE2n?Kmi1wU|rH*yV(#roeGuE&r9LN6CJmFmB053OBE>R0) zu?q>uLZD^KmK4o~_c&PG&fbL*)`P%dwh_7a-h0)8%9k%s`}gm+p2a!XO5jlsf~sZ9 zAanzPOM7)3P^!F4zM*#m3rj~0RFc3^1L9bS2CM;u_kt}XViHp`sqUnmYTZ-rt4UAx zs8W1ln#o>A@Z|C044PX_u}N@*Uj#JNfAYyEdH&dK=J$X#22KgJ2NyJW!vhaJN)nEM zfcXg8kOhZmWW8lT9m~=M3LD!%a0?LJJrFdwdvMnf+}+(hxVt+94NeH|?iwUG1b5z$ zbH01;d+!%Nm_5@{-CezE)vDjA>gH&v!d3Ej}E0UtgHKKjuClsTD{ z_kz6oKmE6F|7;DN2y}l$z4b>4H?A>)1A!!5i5V4Ew$->2_Y%)Z37|e)~~ z9chK@&Hy3BMXFC6cTxHM>9c$s87^w$--sC!T+jyMgzA+oylR4;@Pks8y2Xs5`otl2 z+kn8dQt=%4ZKm*SBk;FT($iE%9!@)}9Z|_Epddplfb3IA1~GcC zimfbtEI?XbnXs5caD~(T`Y5%ZcHCW+mW~DC)09dJgg;~>owyZR)D%|jP(~`L!?7z!^y-qT(#aww6mc&49K*qJWyQ<9-L_+3YufUL0Rv8ni6D;7!7oQKUw1B*_O z)4OPA!%Rf@VbU|8j^YGR-z5**?>7X4gZZM$;L#nLuglJ_-Ut<;AB&3`i@$%A>jHET zU+*E{5fX*%|G<|?Cs?zX=wQOBp(`8lbiK28|t;pf`55SEY`~;NKHfNTHAQ*4o zK%WbPNbs2SDWSm3DR`6ZewibM2?co}sj;o0tgikR;9fUjywxmsdJUEzKVCpdI z6Vd2Hhps?`1jfaQpS~e2S2$z}Ak5ER{z^70ZH?izp+@}NXtU1ef(D2Dj@ZY?XP8mS zm#o?S1VYFReV^+^lV&KD zYTZnLOqEBzEsgO~Bil2~)G70OEK})cjyTBZr(8`_ZXhu+c!3`jOMe-2`*6CwT8^Xg z3*8&OUo;0OIq3Lw?*s$k{`+VS_UDidb1nNsx>9k^o%~)!k)pb1T{-EJt$>@cjnIe-eEALvU zH&aq^R|F1>UvDVp5dbg-i7e)akcs5V@a}2@UGq>tJkt8$6w_1t%^I2M8)8o{FZkVa zNJz*+B6Trp77!IDm*2RPNCY;6eXn{rkFT~V8+gxndm|uB*k>QB@#y$2oC_Oym9;nw zhy|6KeD?V7QMd-%RFa&cYob?B!2d$dVSJkC^Ejz%7w46T4w(?>`RKar1A4)lR=YK6Zv?mHe%KAZ|w zII=(WBv2H^v)fQ|e0oqb9tVyw0U{8UTvh?@2jdAqCFnw1u}})jpL7KP^5AjhZES4( zfBouCycKK7)b%L;Nnoda<^!OM3D{St9+O?nJALji>}r zpjv(b^V~tOs{%Z->X^Fra16RK-H?;+XJbBGVMztdH3l8R51k&Ajn?UaQX9CB<_mfT zG7AP~XA^+}dtw0VhyAI5C14SCf+4ZLpvE+K3ZSqBqmrZ>`5XCSa3}mYi#Evy8oF57qpZM8&4P*R!0#JW6K|WAK zyc9mm``*kwR;!i#2*nSm1xX|4&fuYzD+DvEJKOHz@~~V1rEP;48i zW_7-FmuIKge{q~5@&PlmQ7$3#VBZIxeGXw+-Pq8F6BBB*mIk+de`IA?#t;)UTHWs~ zJ+?I4uT>T7vgYfeT>U>T0P4iCQ%_OP@=SdbHo}8EVvs04Z7%r{4&=M*4InE+&u4VC z;NA1vQ}29#)Vv&KW@dAFuzOxL&Os|W3|UTgO2<7dg&k9lRurDH+m-nbIRNUecn3LP z!L4zJXJzHaRLv>7evFVWkPKA4*Y)KWu7nl_lo z5ez()d@Clv#60`B9hfqtB>}X+64#Gj*Hh9cg0k|X@cI$BFucRs(X<6s$)OEpBm0=~ zX?NFmsc2WgVgRULpWJF38VrczCOtkrTACBhwW(j8M&omQV)!N*Pw7@`I@e~ck#2|j z{gt)2%IA8ff8tvMBO<1fw+HUB`vnv=%zb*eDaXl0f(+pWI5G_P#Llip+ESD{?Xf~g z0bXxTs^kq2n3`kQERIk~7vlgE1%raoT)nO|?#&=Ps$Kg4<^v(r;(2$zLWGRZPTxeoHpwhK`dyMuZ>>r{#ZeB) zy+v*I7sm9+;XF<3@W-~LMv5l)t9JxSi=D46BnBzXXXP_JcSv;*GCCftMo0Vk!lWk# zrF`tus$gxEk&`R-gMym^4s3^zSIutI$J;-JxO1QN5ba+8fx;=EAVK+iR7AuOFS?aR zyM>2MmqWm99Dl;)v9hyOC{?6@q=kb_;M?kYQ#b+Ul!G8sSZ%+;W=3F6bjkQTh0)Pn z^-jO{E*R7XmseBA+U5r*H{ahq|6FwCF*?;fH=T?0?|5F?z8HjV41>V@61y4k_3QX* zR|1Wa=|~E5V>1b2)jj-krdFqSyC!6t6i4k|;pMUBS+M%%44_SsjxH7+5usFmadky; zo3rM!?xp%&^McU~DEY_=B=D?Al3=sBoM@LR7KXdw80^#)7MLhhs?{C?N`jI5N)&@B znskDsc+ut3&6pnl`c!f`<3V_;0f&1 z5qzOgdhl_OD8m3Xdnd2PbdvO7wY3Q2)Vb;A#CFVkg>#KpxW z1nLAhF{Cz359cbIJwn!*Sc=h`$cTHC*RWvG2Hv0)N0zG%CO(Pi&~MYYf1n97;Co6K z`U96ApPanHEZAj^#_7%wYp#4oPQ>^-@jU}bNJciIx;@JK`O!`ElUx>0YHP#mX$82e zmNr^!2j24bU`2PJT=|M!Zr=k?3j*JX5O?GmRlU&?H}@kX#Rm9xN|?Izi#VK_(keU@KwX=G&1^wg8R*F$;2HERDQ-kYgh)r1Vq^0S*dL(a}q zqq1gXZ_+VJ<$7v7lg`y{Wkfe>)F;!kwlMtzqjruuW483#w*Z#KHw$dUzC+Oj<(Mpp zNGGD9CPWp`s^m%+-^}Vv9Hp6^+=zg3jkWndb=>n(c zXpiDFcc-0LKQ6cNJVH$<9KvGYh9lwZkUFdlYx<{W-_;_{n#|`AOMTviVZ$*|;9YK@ zv!(U&m}#o|RWYb|BfE<6NrG6RSFi~uDYyaT^*3F z?QOGC7F8SHqyTDdp*f4^Mx`95@r)=(=JwW_SXULjbZYg zeYU@K&j*btV*~BXun#WNzwb1@U8h_O{i-Nc<`B?*B`k;u5~opI|8eO`M(Ls5qb9&J zvc>HoLG}GgJft{%TZg=PdMXDfKjky(v~c!3U)Zpak_v?hJpm=0+`I$nX=)3B^NJbO zmv@LN!*L={ty&klS5qrGFc5mS`WeVXFSR0;4)0|6%6px{U^8rBVe>Gj+hR|ah#h4u z@|31J(Td#8TSN^XwTl5t(1hKeQPQ#$XR(V#{hpd4k$emF{arF!B16}_Y%KpX6nae+O}ojlo*`w^IGKPHPEmvKrUU%zA!3XQT=SB9Mwq^M1&ty!Ig7 z0p`gDKnqMwGhr%Azdyts!axdkIf6F?X4(azre%rAmU%&Ye(9`c=*K`FgiCdG$9)-X zuS3CY7)p?!R4#FN$iYZP5+RRvezmd?>U&DiKo%cRWZW@qxd9ccSrK`=p6ddv6_J>s z?l+)>j_5?1#%?7wkO9p5>|CP(+hLUKSk6QWt2yeCm8~qm5stc9FXmKTw>Rj_GyiBm zpjs!aA>jwkX}XXCu2@;p&X4N15-<@Ef{|dmtLF!rh(U|O#X6PX>BaHtE<0;`6e&)h z&|VxhZK+ibsn*_#5mUMex2jvuO0tfU_?&*d@p%jQ<#-s%!W#FW z8}-21eJv$4UE1WoR~_J5`4&Xv^Y{&&auP(*4!8ux9gnzX#PI5GX*tFiONq7+ZLwcsmU5D^1NZF2(bUB3A-1Cq6JGIw9y-bL*D5-Wd6 zRE1v_APz9vs0QxhSj~ZRzpGj?Nszuw+lAuqpp+b|QVYBTIkTXxc*Knr>!Okgx!Ky0 z0(lrTcu(cL9*Pu{X)T36zGeGV1tyo-Q6^?&oWF^9X5pJE>|*M8&$(*lLEruBO=T&V zDOvj6TR$K-Ub#5~F7ayUBr^#W8X9t0P#?HM(_YvCYj8!h$=HwYGIF+3Yu=e%u_w`c zJiC)xr(-C|_R}M7`Bm?abu2>_po4Irhr3h^jl07Pdcm10o%FeCJ)7Bs2IBm^Rg~-aM;WwIEEqmrfcW^<4#8_Lm#157K)$GMT?=7= zCj0sJn*jQ~So=rE0b#svKk9#m(D=`K+SvPig7Eo{6_HSz$HbB~;Ca8|#i3%TVI>Qe zgpxB7T{K}dT>WTYX)n!)cM*I}qoN=ciMW)%maY`Yw%8MuD5?qV$3SI05gH_35|@on zkTJJLY7rv|Sar@NIEVEVXlBvg-rmX&JlnzB?jS@fT~W-eIK8@A{0_#tCp;m#)ygg_ z<^k0ob3#DBIY7k4_!tjM+ zqEEl2q!_UDQ&(PZou`f;BrXysPUIcx{?5$pi-O(e*h84J;E_7(-2QNx8xE78oRiHO z`{G(c&xMGh@=MVgCF$AuyrUhP=Xg&c++;`iGP5N(a6;A^HRQ(ZUG_{~$P8Rzk9J@A zkdISfLd`>@#eBk)P3q>)K_VgPckY5Gx7uz>6PQd95crT z5h$i6B>$dfObVi#OOx?YGlbO=-6%hv-@BS!JU~_cUAv${cbD9u0RXXPXHSkX4_r>nUKCJ9TR@R8)7Q^II+jW@w*lwO;|3}ZujLnb zG9Wq&{g|J!%Zg_wTh#r7&{RpXa(9Q*sHEbEPL-saFFW$p`bV2+425o^x51FE$hVqf zeFFuZ{_ib49|jRe{UN{x&^}$TwI9={Sn{}Xy@;f~cW57!UWG`n*vgW z7K~v(8vum8@IfO4a>sLkRr8BL7udVtR;{-Z8Lc?p}1`TIKS;7!u)#W?1mQ4^{#?eGpFahS&A52Q^pYC}@t z)LsJ#mAML%u{+pE;Hl^i$i|#gO4bE!9zL$e;zzljt>s^#0`TiO!i! zAQ|E=H&_%uzHN0rHlNfH|EBg`Oze*hf={3MW^cB~;NxB7_pNAdOp^9^6n_e6NDGk- zKpa!KeXPbnFek&CZK>1KbEHwb1okUFM|8A9A^|`Z*&WU1U;oTdI0Ea5Mgb-dYrfApt+5b&YOeAmVwA;+6M*K$SIkd=K%gl%AqaGNa}``EB><(nro z0q316Qdc`mR^}yrDcXMs$e+4uM{9knL`J`b69~~0yY?F!JK@hhI=^h*Ln~^z&C+Ab5a{`j*)M`gj0M zwf7Wft@CV-&52&KUg9dvVonl>Fpz_TB~u9f6qkE*A~}MG-O$SV6V^G=8>6~p6CU4x z{$SW^u*{tRq;mF&>ff!|x<7{~nNRqvnM#vXjM07m2rWPBcYsXf-Boovr&W|LA%+e8 zh8V&=oMo~7@d#s#_6i1O;4?&1-psEda@ThNtgL%gmNaN4&J6wDT{!nKtV7;2C^&c* zT_Hw+0ji7}wlC@nFDygMjvxw6hx?gdT_CZ(1(;X~NF$zExnV>0+3*Nor}@$kU-j$} z)*y#$$41zlx{R4S_w?4H7RW~Qo14CtH?_oLz@HCn;W(S;E?tW>194D_+qJBwddZZB ze=T)8NgE*r+%MIjuCFhF(+=w<7}LD*%Zjt-!0p2=K)xe;gs<-e319KO2ca|=lq3eR zIL)@=4C)=rr++LiKPb1ck|zqPrD72rsQ87*>qM<5QlvCIx98DbRFeMko4EK)9|jkQ zoHZ5Z#@@j|<`d@};)g@R)j0%Kz1W&j38tO^2%kfUpVO$x$~6r4+XpZiElMglCU8ck zjDx1N)7AV%leNP`;!oJV?DJM?R}$gL(Z$Y>EWQ806XnlQImO9Y%FAnaO9aaKdBypH z`g2c!+0d=9XuzZT$`1h=uqwEuLzW889#ONqv7_{nw%8^gW2W)g%uCP>3}Ytvm#D6c3mm+?d%HXi|wQ&^w zAVm><4>r9Q|D0=tp)4%wz%NzYglGSfJRS~u`bZ#%HlrpZ^Tw_AeKwrOPqO&%3fdv~ zKZQo>fZz! z#Wrk>`S}G|5S%c2k|0F4IFjCaA!RnZZx(`J{GL>6d1GLbPhXMkcNflds1GESt z8~2Dz@>59++kLpxLvg@WH0`Lr?c ziWoIBMNqcL5MvrQz5K;e!>3X{*%*ts5+s`DkmQ{toaz z2JZpAk?z7mAM3fIQ=(u*6mfi0$Dme%VFH&He4A#3w4chcZ=j4oQDm%W%jJS_=D;!B z#`4c-_6Y!I?rKXS>4G>I?Qzv*d#xmvc{iTl6g-k{!fsxPLS>uP)Jh;|7HNup6go~E$NMD?W#yN$_=08Y-t$S>PK>!!eI zf-v;(ed;HH|NbDM%3!ZAyR_u|_b10UQFjM#{SqvI+U%LZO^A6o_sSfcCZ8XYvR~8u ziS?0Ry;Mxq4g{YAnug$<>P|`&)z-MbgWDC0I+4i9|GqNQkm%k1?yznpvL8U4y8mp$ zIlAtd`l_Z=N83@q8IH_Fr!4kO zr?PhD{X+UR^A8?-w%DxpI=uF&>Xsk8J{>!>vRW>m&_)Q6hU(6XF)Ejd1W&5Q>OJhW z&P_VMFtE7M9IvmH?^a`Mh{|$)apz%;t@|zs`E22n<*kdg#K6qkNi zPPkpWocqY8za}U(I`HZoLA>yI2VBc^1boP_Hb?S=miREpBfx9FeisHiFr1^H293ROzGJzCdM4RH@Jpx~3qpQ%hC0+Ujbv@cjrX4S- z>4(lh91P@xaLy^*!(j4*u$t`m_R+nC29blOXCL6m2Fo62XX4J{n62=y87~nQVmANs z>9x_AVu|DDos~(1Bb$I)K8n)0R8Njs9tu#<)p}{jyreNvKb;?}!E=bZIsd%m<5{9w zmq*n;)?No-G?5{syd{KYjC=%N} zDbVWGrgy^u#TPuKQ!&8*@j^`0kwF?eaa|iSO?Cf-yMB$jcR9vCQy)&`buAIF(koo> z1|$aTLy~kiq7&jj4;6|(?ojvWb=u+%Y2#S6iqWMeIG1F~(nsL^uA)+UX@*n3nomyR zpJYvb%r$8khkL=g<$$W*e>~|hXn@6ZiOR<&*s}%vW6k>45SA0$oiX+W_INS6EF*XetWhV zvJF6@WLq>IIKY_#CnDg{)iZ~~KNospuJ{8|;r)8j7aYcdlyN??YU@>M{jql!vh*Jo z-+>s4PICF8hNmmw4$B(GwS8jwp0}o~9!h>_{LH)?GP6UgO=Ge*JEO&xb&pVSB05!U zR)3pw=`u3kuYNWVHOI4>L3_JKySd!UkN-GGa(}moJ=4;nmu1KQi%qC)f8r8(``B9D zET7dvWblvoSlV+BNFLbEN-a;!#~7u#Y`$67{nYgY=nMC8S4OXSOH!Xc6@B~CKeas= zzt3-d0ir z*nrF^Cf3j0(4xNCLue7bYu(-5ra+Vo`C*O5bc>VKlE)2)q9#g3&v**VR zLSSHKJjQe4VBKuRkdd!0ul@bYI4A-pQri*-e6-fCWh5ymA#UrBkSZMo0PR13F^v~< zI9wOvQ$Jd6s&3hCnAcT;z68p><^V-WOHTa~{9}*_c~SsvES+|BKgFN^DP({!QZGeJAh69kH7M#!PW!@>8e>I z=@NX4O_u0?9OFQU3Ig|$do>2L&5~e8n~U(ddY)D->1}))dD3j5);u+{)sL;q*_H#Y zU}Y~m{0LN)T#ozskq>)acOiRHjtEZ|eaA*lH7SDEsC-4YHYHcc))+DUyQ27So_5x2 zI1Vnn%4l-QOKwiMaKwk5LuljXeJhPSTmJn`Y^SuOlq-Fl5c(gx%aQNc-aRIoQLM-|`9u}`80F!EqO{45qUzEd#-0!!orycq8 zcW39-ozIG?$_&6ARz#=8F&CghGL5GYms2uDYbwBuope{i}13GeJ0~7ewlO-%ZSnB@bYZfHz_Y{V9Y>p(%B-2eaMs zNo%Dxz}8S(rr~CQMu|F>C|p}ZfNcABwk%szq{S9kz^UP3WK&R$zUC!VUT3@=rfJEQ1| zc;e-fr>;jcwmS(F%4) zB5_v})yZafCng4AhzR`$kd>giwA)3A`4A&_sewH=?)G?V*K%0Zx(7tyb4;?m8W-pY zIIQ1U0d6&NEoZqHtAb|a^SnQB(jr90Z2;5~g+eLOha<)Vyh%CDW_u&ee5J(z`h9@s zxepY*R!Wgv5!wKim$?|~K=iDjUESI29D8*y%?iovWRm?oF$tm1P!VB9F}=S(co|5W z0>?>AUf6&8e;A#Y<4T5Ta2-9Pzoyc-kKI zuAs}ZEUGQ+)z~tiY^`fS6~;rz1k|3v(wGTN;lgZ zjoPgk9t1<;yY?yOy&+h97o3+@jAW#or zIW@gI@5MmZ9%mo~su%ZI6<`;(Q~%+0zcj7di(}`PiYY$({2RC)4TB5OAzjT5zY|<1wVi)|2P!yXk%%%;-Sb?)dGY`?0o|5wK2u!)JQEC&aQWzE zfT?N#c{i)3M{~Ydt;e6n@8g{{wegkjJ`@{}?*r&#BgYpru;MPd8BMkK6tzxL3 zW3Do}U3TLft&k06Cp&5F5FvF8T6`;OVc*sap&QViz7y<1Lw%no5JlES;Zgqvq@azS z)J4(8C?iu2W^Ndft@)!dIgFc}k$cY#ppSw%j$qAX4QL4m*GjZXcxG+~Dy8k+nEQgsQ$g zH%O@<^Ye2d)Y_PC*GK0699+_Lp-I*PmZn&r^Uqyji%Y@UGUyaWPmE#C(7?W5V3UI z!#?HI#G5VFQrz9%t~933maEadC>i3euCA(>y>F9argE16Sm4$7>I%>4*|&Ka*xlmt zFnw%b>T_f~RtcIL|L;P~IE`!r_x|sHX^Pm*g?7xn3Od}?9H8r4eW2cg!AA8w0P1q> zSf?b8RnU>&-H{=wthaXnxs8P!3Q4bIQh(ok5>z%TJc zVA_5rfKr@mu$W&7^5u-iW0RuUBn3{onkd0k3qe0V<&s;{bd64LFC!9%egc;gX$5;k z6|Ds1t%p0Pr*dMiSB1) zQJ4>Px;$EpAIst`SA&)sp2(ZWrszj^L*pb&lV~@7Dek!I%}3fNZ2U8Y18g*_|7lpw850jQLULLvj*-DFq=P1?=&WiGRTvY`<^z+_Iup=HTMFGhD#eiOf5Bn?bEO18C}D_gR8k4R&sS*AzJoISMtnMvcLZJ5N!>20QB4Cl zwDhJr^1HJqx0UQs5ETa921=!$ z&yMqu*xQ*k+WxQgubog0^c6I4PsA!>S@0PMNspwf<*EOtd(puHTY&TQb$`l^erQ5~ ze1qWldD#2!asAJ|ng{%rvgimu!R`;~oh_Mtugf~yc(@@pu;^+Wple-yir7jyuzml~ zq$+3QUjve8^Lc+(g(KPOBmcFHf5$K<;I#!-d-75ySoAhY)>W53;6VSdvyg)X49qEK zGZSQGidWR)vyK#cbFZ1w0dmQ!)9_C#w83x5i*m`t6_>t!*`6)MfEh_QsbU-C`3umg z!+-|OG?X7^3CtO)*R=po1k=DAi$e_iU(E8g3CI$ehrSFMtf;6eTZ z3TP#d-Rw^L7B@3F#qKH$2gBPf=%hJE24!kgRM!phe?R|EE0)DK4x*GB!ccus0@9f! zWPUELu>YlxP5S#|Gc|fC8^Zl<4knZzD|53B^>zEH$=dVPfe|ngO_I)tjq4pb+SWmG6kOebSh9YAj4(WZ*YmS6IU1By( z{rOn){9q*&v^&OvUgM0hVgUgl7St*X3wk2W^2j64Nua1Z4 z3{TIJrN$$fhX0r|5YJ}>0jKs9kY6$bt14?MMqr*i+lm{|!x~>{fX-p1*fUdUEW0c! zqRI%29DAVeRmn9AQz0!z9sE>;i%K!hJ-}k!!IumzrI}3p_8(ihAgcjjH(nt1gYA!; z99zC~gOr5KXs2VU!rv|)3JDxC!_dHRB?5F>j@^;m?>3zjRC01Xm2(0M`Y=-kbY{SmRwdp%R{mTz`zm7d8qK&S5`+K^(f&( zvL?{~s#TxHyLx;3C46g5kqQN+tkEKQwn7@46pRTE=?11om$8opmIWs^NbA!|4jSUu z64{qWOGI;>Rk_g8FYPdfO~9b)(?g>#3|}fLBe0bneW@TZddCZ1(Ps$w4nTxdE-qz_ z9!(qM|7;AehQ%J;mECVMF~9`iYxlpk6fep;gk-E9vxd(94or;)w7~)s_jP%7sJ2e& zN4jnxM)P;(UjJB;o%K(e;x+7*EcL)r7L5j`EL|fx-OeuOu{Zu)XNBxK0x$eHl^l7z z!$h=TAt^HUc^C-%&#!4v7i`JH3AH?BklO7G=*-dcIzh7TGO~7XhBE({m7f6_YMnl0 zulF5AY~2Ty^``2D>SUb%X@C<+&9f~g@3RU!^XjDmT|lKm5c>3GoylOKrF9Er}OmwWwYj^vEiS3@;!#$szjO0|^W@)#O=*fU}^vXnieXl4gCs3e>*W^Xo zn(>q4d1mzX{%(Z}0c@DrfzOM=LJITt(V?^oAh9rDY^eCJ?e_~3Kh4nCBf*nU5uv5q zXS6bMV?jz$WZOJ6L-RjBBafjQYhCe>6*8cb?sdxyrTV8B-Y%~sl_R(0|Hn6uhChE5z{b4 zjOohd6_MQUj8?im)w2KZODrKFfzP@1BZs@*n>BphppYJDm&DLoh_Cp^u=7dY+dc~} zIWR^SA(e=JX$^jBrH%VaZT@dtHn3ltfKW~v{1v~r3R(Mm49{{s+R@(!Y^k9&WmbjJ z{+O}WdZCWG%a@70JJ=mI{?ED+?6Q2_{mep8l=ey#%$XrAJx^v!;}@|hG5(IcJ`%V- ztuX|^;7vtZiQRolP?apcQ`N%$w+}V^&~MO{O2~Ba*=3GffRrB~J0$sugqWKJ52V2p z=M8C^FG~gm4>A_bVZ)e~r!4xp3^N5Me3ID8w+eyV{q){0+g4wuXF@%<-#YCFe;jOt4 zzOlv6I5~2KGb@t3ek#NWOV1OSlJ@L9@aA=Ne}c)2O(s)A$<6V8S^R9Ri7KS3&=gg$ z>CBXs0RTB|T9w+Upkdm-hW?%cWG|pEhQ`zOlFaF^ z&)v`@)a!!tisZ&Ai#ngB7=Qc#y&ehw&hEl{(CL%2->!9w%oSqu8;CuqD_R=M1SS4YTR1`M$H@7~ zK0LCcW%pCTzqOL0Q~JFB!1Q|F)3`Yuia|Q;E^xBedj7l4fo<&R(aoMlEjr`rsnRX= z-%ad!ea%TgO~GnX7*Lu7Qxy1;hUS3%!$V20gVkS}ZggvIY)%(Eguj8V*B*XH5X-t_ zpn^*iF4vydIGO=fw;N;Kb0K0b69#NNHS}m+iupAWA;oX(>}7L%+Gzp zgan>lAVF16iK{*~a1KqJN>>KH@y`qV2(Tc<4bq-g9O5qe@JX$fBu=>;oM+q)yy!sT zzN8bx(0#I+j6~yu3DV+J1FK&iSWVyXO8&n--Ng@z?qU6XHBa#ngfl|jZZd)z7Ah}; z_4)-Mb?n{6B~NM-qa5-YgBYbwt$2BA(b>k${_3(8Q@F#ZVz-x_U_VG9_T{=Bei`{>Rkno}lK zkS9b=FZ0cm61tD)gWPTv4D&IHfqN-!(P;e}ca8rJo#`f+6Mecn+dB@4W8G3e^yT&o z{JPt3Y~-*{a%cw)--}&d1uG_PZjHljh=IOK-sH1|QAm$IjP`0@5~-HODFFfGTiL%>60w zR8Nm}*DO}N($ybS{+UVBT=2?6uesY!6DF6PDTmu;#p>hORBVc>^&0(P2!S!IU> zp}MZkrx|^^$dgA3hcThvVVo^FH2u9GX$X?V(D42OU?VwT>c6Ja1I}Rk9Q#8RZv!|*o}_v?{a8lq{w5FrEF*@v8<3!Uht)VBdU_D0S|g8KAr+m zCI5>}yHg0whzd}bwjj$n&5`FqCaifAw$maJAp6EWjB!svIYiXUJXX0R4(Psa#$ z>g)pWn+mTll4NMAhm5XH;d?y#8_;&?6k)lfQ-xg665$BK_abZwN{i)EH zE%$50nRLZHg)XG7a5=?p7phM!%Jk`YFPA*Ic{xq7dr)2|YiJmeb<>!UK~Y37{!!XM z;MzHGAjG}{zF;Ow#SV&oD2V?ND2e(^jZVlom@huhC#_@MLNhQui^Htv%P2FLEC@d~ zyY1gbTxtEi*5^5PCSH#H;^cZSf2yjeL$Dl5h^hiy&jKw)S7tcJ-yD~wLLYKUNSC>6 z7E!Ny4Td&qd9kEV`me&Fo{8{h*e# z(Ibu5&e2oDPD)TovmNeP_I{j_G9yk@c=E%iv(vXuqB7;@7qZ^uhzihC{j6KH!;uE& zx-7cxl6k=>HrL}|#PMyPhstl54lW%?nA+G$VJpKvi6y~nt^mI>*z;CJvXovfn-NC7 zFZ}mN?0EvFu<_PpCrg2FNU&~8Z&p8HNX3fA_0780Xly$Q+2jraLoZHj9*enm(6gkVfPH?ofX$T_J>x)&Z=mF6%|q; zVMG4y+{|V@?csD*W96{s4lV{2!p8$58rsT)c9#R{(|n{<^yv-yCJKEHf?2I9?mRVH zSSx>pwTvXnh|M1Nje-tz+_}qB^U)~j$E%kQ)GZn~YCSU@5)Lj z6u~Kz){AIZIKl=7kH~_{HrI635^=~q>>}!*-SQ&keGD3HZC0%Jn%mU1 zFH`{rrZk4UI0yfqz-_;y*{=dxc9uW}E{#U5h;rw=CkqBnRa|wl$_XTlYh_sR z+Da7UVOG;snIc49^*!1il`e6=jKAgZCDE%B$F`p8ikB9Wrh>ExPC3l8z0Adze1FMe z-8Oxn*K_&MGXJFnG<7gCRKGU!*~g(?#flfs`0Kd!SKc{tb5F=6a-%O7{tnh~bXLWP zj0@%gMJyciF}|N17;LvD}ENz@dQD&xflIfxfX9OBQiadBShd zw@ov|4~x}$2S59#4qz1iN;}&xj)OH&ffrqbu1NYrT<)BljTI_6QaX}$=NqYtg(+cD zqM!6$ONER49$PM}U0b@~v|;vpra zp!v|fbv^eku>&rf^ozF-*)I}~vfeoTG-)4ISOi_oI#28`MvYD5vJI7owwEaKsK2If z^obyxhjZ&I`5%62h)E|fW@xLIvCAL}y)@>5iwx!SGQ?nq3KgY4n)(s#sob-3>ja`T zntwRu7|%qKX2+1X`)FC5Y3^gq;lx81X&jADMPAYV?b}9yIm>!gS-mp4zQ#31+1O|DAzr_xVA2{gVtIdTgZ+iuO&3qa(bGtR&5kQVzzyxf_0!_lq_KHXc;f4S z?EH`uu4^mM*5edz%jbswP63(g1N5n`vQ0W^*8S&9p6gXj+_mET|EI09jEbY#7IuOK z4H^hK$e_Uq3{H@N!68U+m*4?{yE72n-8Hxq+#Lc03GVJb!M=HO?z!iDYu*0St5?_R zuI{d?-tz3d1)a2fewTcIjqsPpeVK9(S&nJB*{3|X(%1-NEAlYK9)Zo(U)2?+c2dVJGK^SFAs>lNsZ zY93w*h^{e4qM2aWg88Xq+3yvJ(;S{K9`b^`bZN@r{7V)b2+7^lwsb$dY}n`9g6%qi zU#vbhCK@v!FL9D82`}D5;m6iVT_wX^Pi-S51x^^ zLz8a!e#QPmfSD*1KA>Bj508qW1^5fVVnu@mQ3Q(Pr`o0OD>}0KZV!=3w?|;4Tb1>0 zHMoI?q023UX++&Kh1G8mdYwk6FHJ18y40T&aqt<%JzS!fH}kfesFqF4lhR%;BJ6+} zk!ze)aA$dDd0+XHFJiC)#>V5n)3br5?^kU+1o&xma8)K`ptf2%cZiMDTq+kIY#ock zHiCX2Lez+&WhGDYrDKsD`jf2GnaeBbY=R5o4-AN|%7Bx#U=zsTLeIFRG5(VXfbAkC z07Y6S;?J;^GAx&W(BM>6eGm(1J{vjF&E3kA_f$WIowH}E6AGZnVEkn^i%9Qj}K%-v9;3a}=BrhR$w2HsEeWOT^^|I2uz>4bTi7zC5fgTAnrP zD^1kll70B7RrI=95rP{u*HmmXi7Ovh! zm%|$1ua_BP2yuPMH0Ds7^NQe_p^T3vnosKiBA1p+RH0^fVCSjPmqdzhKW}Xq?HVGw zPsdTO?B`ZtF7UP@YJf~7QmA1Txs&KiX)4vc?>d(lc=^&@GDDJr>GF6quihdK7|`19 zo9qnq18dyV%*EX}q)q6+^^ADKa-oD}mhj@|Z9+ffA(+EXAlL!u?I!45+7NCZo<>ph zS1Y1NI5Kwa{~n(IR)U&IP=b|@L6nsufwFq?DO_mk=DzpV%2d>WBEAQQ`0c8mLdb&q zhTd|c`y0(FVSPN~-0Z>G@{TV{T$fu_e!5$!J>M^1mqe~S{ldQjJRRonr?w&V# zwSL^$yzK?ey^b-p2y%E%`fduAq=G1EyPY2`=YJn~n6+ghq!1x}6H3EQw2*wt=N-QN z^>yf8!YOl{Q(E|;pdheTUq@*E5E1O~_(D}|LpJjwLEQdtv6(G*Yjgxh<^OU64CiSz_xwtlX4H+heW4!(=k z*B-4EX^w9P_X00bc%UTD#LU0T9%KbIio+*VS5KU5_VNH3G$F6|s9lW6c^iqmHKVYC zKk`-Sf1A4v6|g0^Zd~io zmghp(QO`@weNFM#ibvX}MHVeA*DHQ23iy+&SjlwLHIg+cf}2~gYrhgL9KELhkm@KZ=pf1jQMG8^<`^BYL9GAQ<*8Wek}=LV zfD`4ZlV`LknKwU4C^u!^!&3sfq_;0+jNWYSTGOmfObAH9KC)n`x6$CGb7T?-_zZgg znWivdE?CV>I#@c)xOx%?3y*A&>{w%mjG;Qc*OK{h;Kdnko=F@4HrO%)GB; z=`o9=;*B!r*XyzH-A0xebZqXAs`#Dwpg@0a6P&jYdAcK8Kl36F|F4;W@&l5(8R1Zm z{xi)g>ypVhQ1tOuSjc24M_SBjgbP9efVoGshMpQoYLm(0wFrOjeGmx;wxL`YN;5#m zAaw=2hLyI#I13C6CDGoEk5q{64M|ycB$nQzNe}0%72MDA{+|2}LKctKp$<+rfqhCk zppnzYV;U(TzE2L}-^mSu8v6Q;M8AFl)b>kxxBN92!nMT=%b^3uHJ$ z?Lvx`ek0oaTxoWV;=jziFb`fjdqSUXOnYpxd1!L2O~3zR)O^u!t=e1Mu!$W>>xE&bOzX=Gy9!@@bRP74q%$7@_SAP#4HDm)`o&2cf9S-P^vj zNJ>yyz9LDOSB$^DyrsHEuubVT%I|^=f#aKlR5s5QKquYcS8E7Cf;!|j5|^^u%LFql zl!GKJ9Dl`$?sUTkvQ^n>Hj)XQyjZ>-4>DWERneI*wPcns(T{yx#&+D(5c(DU4uGsz z7F0)S9eJGX{#)>;1_5HOTAlaLFj-k!`mL$+f)$EYtb?@rozxo=%B->mS>$&VTix0O z;u%IK@5-C%;+*}};)b)+2A?-Det(@1(tZc!rk_3_AtAL2GE(k(yMzpTc-kx#S z!$C?oAcAtCF~Rd{CWF&8mXl${wmc~F3V}A@1DrSW7GosTA>jucmj>nN=9fC<+i_bV z;Hcu2$$lB9)U8pJ1c?Td9GQK(&)NlE30+Pb?kU(9E^FQ+8ZjhvvDY?^7DCxaVMu2w@+lsXr`kPg91d#xXH{M>}AVIt4Oo z83!=oUm_D9`P{K<`AUf6nyjp;@ZO4V;h!L@ovPpn#CEdn*hG)4=ryQS_Vy|LdL5G6 zzadkH$636lG_>yYyJCA!v>Ge(tX@Sud8vQhi+{-f+U=sZq-A(r$()9xftFI0(!%rv z=ZzU;Ii_hvwgX7&FgnYtx>BP=V1D<=MGKHfJvf;zx?PolUAGPq;9LdtPb7+GkH&;v zY5@yF1bL()0aLn}B37~;kk|(+`pRg<9WxRKk+&TK5N|WFX49w>D8;ecKk{CNxjmh_ za^bLCjm*?AM9MG?7kgYnG%d53{jdWow9VzFY2-VPXPHN3MUa*3_NMD^B(1c@55UNh6PJ90HpwM$=xuy3yBdAqw@rrt59j zkP_C`QQ45&7{)>`-P+2p`>hw&z~hqh0Ut!wBpl-F>ae*pKpHY@Yo;*@fv=sgqc6q= zgcTmIc_iljgR)-kSj2@Y=*E~@U)=wy4R_2~TEk;lu@!l*YTz*-Neo_P)WKI_5>fSi z%j~|HWU!vBMID~xj)$$KI2JB+al>RFm5-dz8$Db&qz&c(EHY8zC0K15$d{MThB+29 zn2F-%p{MwISOgGxdkCW8=|5-+CA=Xo5j)>*C*aFygM4(;E!L?!pISK3+)tb_Oqm;Q zr6a_45H~?*_aSUKS1q^nL)q63Kj^z2O0NvcUaoz6z~P8dvc?&THe|{Z%4<`lx(NBG zl0)sda$Y5PZxvvKaZ}Za&yqE2vrU#VA|q>y>p)>a-r&44R&16Qf*{Rt2O?z1#Y)!T zAabEWEh)kqyf^JCVX|(UF*-bpKX*?Vtl#4Qd2sN1fQMMkR{DWgYNcqA&t1=f{KBIr zo3)?o7T*x#eX}m2e&d8WloT1W;UR}M)mhV)guOC}iTC?Epu*2u9L`amwaEO!HqgN+4!W0!d%;g{G8C*4bJk`B?v@}iiuP;%Od1tjF5BQ z*HD?wcIqr8G>Apmvf~kS`C7U_Bl3m8v@=-cDmUm&SUBgb(QllmWeGBF4@u!?F8jw%F&XP5%hCFs_}@*teH( zAs8fKWWYs7kfIUW&| zR#-XA1B`N3Qfw*j3$rAVj-~Z}B`m0|o|AOI2EvM4c2_4_%R8J0A} zBE|9QA}3tl7`v1P(RCiNR-@lgAsU&OO2*{pCb2*{K!nLrys%iI(bQM`QWT0yH$QeK z=!S;27t+s`9?E%y^R43TC?pO6dN$ z!|y#ys|vN!td}`YM4|OqvQHj8Bv1JL)Nc7dEVZzyPUkCX)###LuKOIfzI3YCB~1E| z$q34d2qxQ1O};QqZ}$B5HX3sx7reqM*F8YZ0t^&J1W@lJ%`Q0Scux)w61gwDl{S+e zh2%mIG(3Zw-I?)vvbST9{JcbLeol?F=kII-EECnR$|DjImo=7%E;U%r%V{Mj722Lc z^aQw(Cg;4;nnhEtXM{s|)izc(47e+%g^`c~wyJP|G$f_OYHWm4ISz6cbI3E!(!QgO zMDGqRRzEc5MduCk*#!2bY^BXtb;@hwL^B!mqjxbgsfCGw$_Pm#ORH3EBE05lrP)wq+ zI>ilUsh4VkM>PW>x>j>W-q_@}MsV>uOis*$9FM!SZ%HsTjaRv8Xq~@GSas0?gAPi^ z$kv$*OyJ|TWS&uu6^reQ>>RDz7oB%1Ya=`ffc4>OY+iS=Bb2+Abq`J8y)oI*R%zZT zM0Avr6}5I-K2a1>Tf9u_s|j^O2({GkY$eVtkDjk6c9D-V$V?0KFkEK{W+dC3jD^mg zQoNnE;2PpqC_nqK;Ghw`;i($!`E$GC%ez47BDk3w6X|YY8O)H3i3Ob%*zGp zp@0adgK`g2|Ihk&02E~*qQH7@_N=R7`sdR6lh{2W=x`&zFaB6R4lxB`O8f$RU)(4- zcDf#FSg#WqbS0Emr;E+aoa3mgT`iK#>{o~mW6|Nh-sGsLF7Yx!X%$Lq2`&zbYGZYv!YA)dXW>-{B`s!%nGOLX}2 znCUo;bXLThDnHKM7`G(VB$lCqAH(U&{bN$MiB?t@c8czXenX$+-4MV+Rv+bTT5u^m zt_`L8&6a*bR&%#Wg)wF=Pa z+CHtFE=1r6@SssA*a};{0}wMFQ;ThRHkI93!~2sv#8nQ^`PBaD*Fr9bB>!wwDcw6Y zkJ5>{uGp{Mm{S4>Tenk_AayidqjS48E zA|xQS-=E1AV~o8qmhC2}^1OhE6N+boyaNlQ9(hxh{2bL za@f63KkKV@L;iBb0}3{LQ!JoU*vWzN#j$hsun_C z*t8Jcc*uzr=u6cgBPS)8rerO^-6@S)M0hkznd$GKxHE#Ky|h(zv7fn$6`TW|l5cIa zhUa+zl;%`Q!^NpnA4d$hwQu&enn?|*Dl!6g6WmyEV75&>;oH$iF~4f=u8NetXsJ4prB;Yrd3+K?hHmtnBipDUP4{(M+SW; zPM6AwR*p*2E2SN3%a-G`OD=V!JsMm8tlV>60`ZW1t?Es9yxf5Kady^x`jK0=n=eDV?)DY?HX zR+DMd4dMAoWO$nqny#cJl9G2j#fONgY}(FL-nHVuc^K8#0JK&V%QZuLcU))QTBBsP zeyc_Nl!jbT+|OZsZIX64Xcgsd(xA+5VN7cQbgS!HjnEwAE;u-%+bJK3Ggbm8iDGci zg^QZHDMri4dLpLewN=!k#dXFE{=Ssy>JME=k&j(mq>4wVxBQm=4o?x61@V(jsD`lsVj&^0yt3 zQCTsxIGm-hRZEL9cQrpM$_j9tJz$=ZftubUodz52pSJpjGU~_v77n~o!s|O0nio&t zkzKrvzm@HlO=C(JLEqx#B$~l7#erx=l71|3c}MoaS-SV)3wdb_Fd2vn{ANAVZ3Pww z*RqHft8&^Um;^{fY=r>B&{L@1l}&|T+Egjwh657(;zM!^5TGH|48|4mxYjXvXnhk* zL%{w~)2q5Il=~lkqcQo+h>02%F4`Ia(w#yeL2KdSMUQ;TW&Cmn>mY+Xx!9|kJ}ju$ zi#O0QZqdZ%3Tr2V_%$>13-$U8Nu{4(xd-uAE4c*bzojtfL~B$+LcWV$QD&i9ckf_y zsO$kJ|K)%3tqvDFsP1WMn2nw7 zzhGIeN=pC42Br|hEoh32xxk1trvm&VZ91}wgbaTbLZvB>o&K~#=LRqY1uS{?&tDF2m#hEDh>(dY3La*OGu=HgU=7j`aWNAHG+sFnb(mKP7 z+X*0p^KvfDH|}_Fhz4fJ<Kd4HiIKUA)wn4qr|-DD|6uB6P(syCkn>YZ0w zgtcia<>k4ZbqN`$OK8=X`g4hW<)Y7tQLsm21xShy*^{aHASIC}`U*uq0R7Z8N?awoJVIU3Z$qh@BSrIeBHm70)H5`QCkQWV$LGPIjR z^jRIrx?XAp$%UoaqXd@>NpR7wx~SS5%XdvjR7x4{Z`_ge4UB4zg9}ai5JOV0y?mAi z-BQ7j^`I=bh;t=@6saL1hnpK9ngK_G^q^E7%%jY51c5WNT>bNY24<`{1|0^0=1jEl zN96plKa^$NqZW0&bM4u2yydQMkx|L5mq&@(P=}dWngKeI>fRL9B(Stsoid}jym3DP z_1YmU<@UTuB~_JE{hkq z;v#FMbiu+jweIr|X zyd>CcEC*15B}w>81T@EC;xVa@ni@(io&-Hg?Jl=u(fp=Pc^hs7V%Bh+EI!b};eqtR zS_0s{bh^mEjQ9lUxt!t^v90>p2X>8k=-Vpu!#+D!jzmqAAtsN;*xrjw;xflh_g8hZ zQ)1S;Yi_zEEx|duXdaO@;32@3{$+jE27$^8ak`X*r3Xd&X2XhePlUv#SqUSH27X?ox=7h(5_7p|&9 zX=5)VT*0@WcMoRy+;l?7r8vR`Vo#1*WOW#cM8uGsjBGVCj-d(~?Z~L*nPb?^b3V3a zTGpCsaDRa0ef+37@s2e~H)g|eNE9jtUO<@;d9&p~Z9RPS>X7A5$I-Y;J*;8i3r+g0 zv2AE;@MX!kI|>N%q*Dt|eB2($BcahWV*B&#vhQF>HALt#DdWpJH;I4a+z|Ihh>RTR z%goG$8eD^}JnOC0)ZrFYO>Ql2goZOeb3nB^76gYbE11lyP=MV%my`FN)9PP*69H=U zm!D?)zlq`llXzx+SN*gdW#eZ1BV>TR@`^NC70n{g+BzDw4MFU7`vEI>?`J7#Kv;{k z(jw%fc-9?W#javIO=)o+^tFI7UX_tNC;b{+`Eh3@Hr|~nj#*VAw~i#A38i6cQb{2S ze68#As7T6H#77AekB!b$?>U5gYtC6K8Rs_hwA)4Dl+tpU$gCQSKBF->qP*Fi1p5P+~lO zb5vH1Sg*fUrx}=={>%9N1L`RvSudtJD;bBJE}`+|9tREcvUFSrByKQ{mV?_lhn{BQ zlG3nzw+67k*10q~|7v!#C(}XtR;j!M<=eIuhn8sPUp1+R_}Xy%qB!>X(LMY9pV`$V z+F8riurD96bi%Jz8{kMx4*oYch>DI-C)UBuA`dOWc&{iqlC!ULK^%Uv%0_uD%+MQO zu5jm&1AeDdmPk<}P8IFXl(St@5*sL7k(m(VQY^hU#)Pnli_n1m-VS=4xAD^qT3-DA ze~HNBH!leV-7(#AFisXHipxk=a1AowJDL#Jov#GQbooi-K`qV!K9GL3PbpT;VD4%1 zoCrC}7yH%aq%Ut=Oc%3G_GqlM`ai=5&4&P71FNFz0WxE)&&pI0;)*M%SNeak6T-+B zhd0*8iPr0Jv-|ZxB;k}aiwn8cA75MuY^Q$Ew9h6AS!&uO_qFdVaWCbO$F;Ee^~1C2 zZ~@_@i{)wMX7jGhDEC|)Jm2wd?q5d}H4YHzW2A^4Q*DjhiSyRagWwYqQOVBb(`QO} zSyPq2B-S>yfi`A_FM{e(-1lm3gd?93;U>&QBL<~(5_vf{QNk(%DhyKGmQ&X1#?^|O zvJaocqyEx!*+Dc)Y9Fc9z+k+oW=D*y5;z?B&qoJm(^7SMR}H0wn{xaqs~ITnCq$Z` zzRBO+P1EZ;YWc&Z_4LbbcMGL58%IU2*mXy4sC6Bsgo&ZJo%Mj;g%@VBFKC;-v(v1J zCL{^Jpfdz1Q(^_}`?avsLPa6=UwY&3%*#f7FM`m;6IIo5xJ7JH*umg&V5v$I9nb)} z7h)fI7`uZN=5W4v6Ge(AN>kYC>gE9FdHS^*%;b;TzIear-;d{d@{$LwVilujZpZ~)$W}{kXp;iITH228g&7-;A#kV`03}#}r zPiEt(co4xD2;(mQ9DdAU&nI<`gP!dbN`Sj`B~VKDmGbl4s6pVwc7Ncr=qx6bp?U7A>+L0ReAbC=wZ)<8c7 zD*PS1*Lc7N3Ebp}tW4s_Obfa}p$%Wlxxvp-LN~H&Qxh{X_M+%R?=MgyU67D?+kJd| z%HB#Kndchc!H~)$FGI+B+G!j2Di-D=}2^o{}MM3<%W zP1Ood^^Gr=*EZ326*7RW`XU{-qw+aZrXz6vm0x5^`-?Gy5$M@;a#=9M(B8g(WuL9M zHR0hpNmb2Wd%+{nNRKQ;h}{c(1BZpqTiqfj6pz|&{|NQZ?2@mNR=X@wQIQMGMuLs_ zpVGK%-k1NtSz4?GBzVJSEU?=BNgd7so@-!{Z>`xb9@|6HfnR5vsSDv@J(6_ulcNq_FR#)GDbqQ-i z!v{LdvsZ?wZSRi!P|iyaW`ABej*-gGh)NQPEih^AY=$<0R^tbSZm-<-w338gY_7P9 zQ@_Hty=r}kP)W&P844lWFw@%U<1^}fv3khukZ(c1P5@o?qR&}wxu@9eL~K-r-f(F= zNC9BLWl!5!si?$KIOw`~F2GhQOEw_i+i{y2czPft#Sy(50v^bf{C4IxR98D5J4Gu? zW><3Pbt`?(VcaSr(ixJ)23oK4s~g|`;o@~BYTq8LUIm{~F@URGnDPggk$oew)FJO(U-k@MyVC=8L3H9a|_1 zSIh>DND?RmZWPrtQ$A5HX}E=(kA6{AD#qkx4A)c?qNNQdy4S_YOU?~>=UC>6{6;0x z_z&zH8={!eab7cV56$B2tGq~sW2YZET`HdMyLg4@6<1_nXM#g4qUTca?;IU~#Fo&s zFTg@p5S~9+?h)7jI5HWf>gAe*-1LNiq6{JP7adN*>hmJ!LVed9W&Xz?x6Dd?VZ&l*?J!qQG={@enEAx2(*8y#BR2kX(-eZ^`5xDmxWx*do7G2`))Cg%HGdV^jrN+7~7hPs!EBQN9Vx4ceme!uxKZ}25(CnpvVo` zs% z%>RG~XC=$LYd1HbF5>LDStB}~4MzJ$cz{aS_Qc#!rhV%TjAG!}v5BGJgM-zAwrdOH zM(e9DksrZugJb}fmDXym5$!p0mq?bu*D}45$yE1>D$_A_vXje7TDwVj`z-{ z{!j)tZ=X^AyLIdrOopOEWOOrB!9E^=r(+49nh$4 zw2&;l-;5>hJ3C$u;gsfjI_q0xOqxsR`xUf36M;Op-xjmUDYem;aie0*OAa@ zsF;>%irZwcfd{jlER;laxI59^D#!3DdN25w+S4J#ew~&uhz?F_IKs&`Dwbnuww_W+tF(K zH0n~M<3-iU#ZtpVMP8Il9dcE`?Xy9tr%DMOd@c$s;xM#T} z($(ih`}BZ6E{TjuuP@w|jPJhH@RzC_&DLf-IK-X0>E5oO|6_fhX6M9gYw2k1cM*Eo zm{qwM{59dz`1vEueQm^Nt4}|}-uX|uaNudruC6D5Kf)2CJ!{qe{L%9&Tf>c9NYM*9 zi(FV-!T!vagL6Mt$dh7+aQ6~B6l8OJ@CqanymDV;(o=EB(q!=kvmNobQ|Bs*|Fq!J zLkpe?h+&`O?-KVO7lBKC+jp-#W~TUPWcehxzk#~YR=+djWcM}BG?X>8WSSR#*!YIS zNj4e&{SuS;+wQ(_`CIJ}$jCj?Y)O1s_GaA>kQzQ}X#f}+qTu8=jqaX=e$nW zj1Ing;NuD9x|b97bkNVj76SF%k#7+sMJU9#^#7?Ky@0dt8kO6Tw~n{-!Vdd;NLfjF z?jAye4lw}JRC)m~g=IY6BKsw85dp7>7TUrP%+MGYHd{dsA?(Aa=qM+^`C8e+ID&w2 zkL9PPqML)6F6-Cu3{vG{(ESE6t;)Q=QaT14poz`yE?H|q`K6v`ZI}3|@piKxeY+p; z$VBsN4ZG%tjDCBobBCH_TPx4>GArBiT7|o&zTap7c)RzJi`Nd_1Mr3J?x4iYpeM_rF0xmFrCXf z;*{+##wE;+omSeIZWmmqpf^@#k9nI)=3u@gwi$=V(WLJk*8i_w_n)XHB_s)Gi7-5& z=)dEA{wM6`pWRrPFW$6SkUm?*zjTrRI`vQcUe&Dsi8lNHcYbEz4^WHR?n;Ad5{aQ^!N{#U~@1Ft<>9r4qf8MN%a PfN#=Z1&InV1ONXA7GxP7 literal 76180 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

cgVw$_$pMTwi9tb8%mK7 zFb$uv00*wkhYpA}i%#UiITks0yu{kue0r+%;p%~n8b|@x3(=p4Wk9fX$jYm zeKiSP2_iRW05OT?<;+~QxdBV*`^&AGD6~m!qL)im*PuZB72B@8X9J#MFVlJ8RRee{ zFd#dtO67CZ3M!agqj&K_P=9M6fnbM_2(EvoXF!FI|3Y-G$2|grFE$`o63y~8dTpHW ze&lDU?j7anxhm=y)k!0+xL_enjgpT~2L*R`zODrKi}s8L#O|ZZn8sxd3EZbRB#m_H zsM26Fb3SkVtT9^;RX1h~Q?4;@NN`^ajPHIgp3c`>cCSQN_5f&noNL5OU;Mv`V;u03m3pRALjO zjMoG3b?ulP)*?GDHNS_~*^4K&$o~}$AUll=u$!q?uSh-22^v#Km}dh2{`?;&mR;?P z_2E)Wm?$~-HDdcj4`)rvx?Q0NP*wMbkbBq!yf`@8_((H0P@!2p0BA0!y#&oW#ILff^AR zOkXXV>8#>M_tMrkbo-ndr%3mpfRm4{2|ZAsOe6*Nj^*j=jsECYf<8PzP*T(+5EcFf zBv}1I2f3yo{E3IEQ$LwnzP^OLBx(t&-|44c;+Wt<{(lSv4iX?AOEs%=S3Zk%TcoJx z6TxS%lqicp?UwJtAdO@%imS>WMBU12+?bC?bv7VoPaHVJRG6@Rz(TYlFr{j%Y|eVUERo7>C1gC41%9 zXpq@kaP3*x(C5#4gE0h49}gDVy_?3Zvy_ds9%G;EK? z9EgBmHh%&GWRrcO1u+eA_>}%xe6BlrXPuEXmIjT4y3bz7ful1>*vg8QfWs;;{v+s# zHbp>B#0?52D0@%;rAisRE=w)k~WeCJq5LPf%2@Fw?ql>3cu6qFsG z$zqH|DO2XdPRHAn>w7sbcRoygNlKbu{^4*5)zHw82$89zi5vtm5Wjq*2cNaLzO(=D zq+mfp{MS?oPbDy=0$zVDtOcNwlo4*T0W8lf_oQ>~m{dOwZY4z50CLWYq4~HW!4}(S z79`wv`V!06>V-y1dWC>BITEnp=bu&JGHS743)Dsmpbnu&gp{We#{Tzv3nN{@pf6th z+V(NOH+5wzXK1!6bbOR0<$tnbZq0Sgh3u{zfE z0fnL5MT+89{g!Z4_JCDa6T!TppObb{B>|wS#m%-YJ`z4s8TQT zJFKS2y)i7+ANkPkwgc%aAMu-?YLWaBay2mRTjfVUyy036_WR z)65rdoiJQ1bDJneMr^QUPKWe;7VrrF9whiy)xmmB2b}=ut$Vy?=$li-y|-;_9(|ps8qr!SIAB5WmmS;3Fc^x%HXx*3dJ^yeRw-y!s?tJ}U#1f0z zbM~WR)3uo{###g{d*#JJ3a`}-_qt&SvmHw3;p=lebv#o{5JVUk_k&JE0!U*D z&Z_ZSMzeXb!C-0-?nW$8AbKj!dTIhL+sPRTL~#8ybd`Ri>ou3{^OaWse(IfVPYijgFj0BiG^>hvzG~m__=-;RJyrDSXPL1evQ;V%r zk3H*J-UR-0SBEFf9)HArhIk{chWnQ#qu*BFh$fvzem2(|UH6R8nn5}ItV_1_(^=T_ zekn>23LJ1db*|b>#SwcE3j*k@x5X5K=LLu3oQ}vqrmf=nQn9<_!1a$cgVQVvtEB%- z4})hSdr*hsgZt54vU-%>V=n9~HqM}Ll&M>Ve0--H8kx{c$fK(5nnv5#nS=Q*K}fND zRv6&s3e?I}yu9l}PPv^EUl)Otz`cVkatW*AEY83lwN4GfByX?h}~=6 zlNyokI);eVe9>>!*yc&{v6EmB`Q$~pw3cRP`kb8rE8IQEZ8$?tI5%7am^;y3wZyoTIsdVaUdP< z(W$8(>SrA$W{11C%5Tpq|Jf98Q5kgaJP|7MjGfYb+n_XJC_ZM)!e7DvsWCwPh(V{uiFA8fH)@Beb)s;^!-- zFZSa%?&PGrul`7g!c^bN{5U0g>kbbMqy;56ZaboGy0%6aewdTOvl)pFc=-9VgT@el zMN=mQ^uoOa;NjSu5So#1?UtFeG?2kzQr_4|l+&eNBra_9Md~bhR8WuU%QXmPX;7b# z%~3vcVBK}-#>0+VEAyilj$C+leLaCXyJ6Z;Lg#!2ZKnUa1+42FO;Qq7B$a;^)E4>F z^J4q#bKcKhQJD0P=x}&)61+GXAkpP)y3R|6!i`psmPdSDg{9wiMWq@|Jx*hy7~BCCYi!?*Zi!IloOBi4UXi@lxMLJFMaN7{MFy*CVoqy>HT0 zwHLIm2Psox4NPm_XICg%^%(G&wa*W%z2qxh-{8P!zR8j^5T+Sd?|lQUAx!G<7_(2X zf64Dk92G#G2jvM0fN@DG{jkSD6wjN2!u>(DAXNiownQghHR+nkK~pCYr$r>j9glx% zz4%@`RP%f*C@)*xo{;|CmY=|AL~;mv2C|8Vf?GjPE_k_64%;_xGurzu3 zX4)G^d{D`m+YQ-#T?qcWG+LynfVULF-CU_wx*wm#rKD8I6utfQKBtv@QVyyWVhgnf)CYStlwHA(vSul&7x=kY!1d@2D_DcTd=oMGCx3v<(Vyj&v-3lH&(T8U*`Q zb6@d6WHH!RtxV%c_|`Vt{S49aF;Z2NoI=mNKUA-(?uVc@&i(zL7NCFztMFH5Qojx2 z4~v`a%R7y#Y^}4aTOF2R0+&w0Ah~(DI%HY)U`0PWW;PwStG1&-ne}1Km`_BZQZ|~C!aN01u#;f4P%sthft#M1e?J6h-HWH;BXr&9`amUaXb4+Z8&%`yh znP?dbm@5KB8V2sfF`;El!V2$h+Me}r5p*uMW+#wSXghwud5n8PY3Fo6pBXkPEYD^) zhm?F$E|JpFqW5gJgLyse4foR(&fq_>+DGo#k6b0Bs+aAX3=nGuy^G>qP>}Vds(UKFUE7EegOr(|@a-lULmLOoI_y|lM3Ua*{9nXIJP}%%m++lb5mYa`4 zylWausb_1~QfsyZItM|FuCbr1>AwCt&m=V$bSo$JZ>999Vr&5k&f}b>5(33_%uCyk zo!lXR4-__5FV!d{4RuqBt5A0N`i3sTbI(K?$pYq#;R3yk^t zk~wb#+2X#1otecvb3IKZqfU>tZs!y8@eQUbZ1~6IfY`6MIa4UJiwRD##gYL(rh%}C zlWG!Z=u*KjrEQmH{WpcmmJnz^D;a2MhrSo?IsNzB@4rUWA|0c}sxe6l>D0G$g=PDfLrSC{-kb zh=gErfe?);0|}}C$p$s2)W`1%BJ-0pr1g44Q;tWkdwz_5N#ZOECgY*xQ>Qq(Wu+DO zQ4dn|B=j}K_!)(?J-{1={y>n?=JGmBO}p&G*z})ei?w@pNU+h(0HMm81SIJPOxS9n zV=0&4Nh&X<-mc@#UJtVYx%QDrRVR-kxf1L^SG zpWe}_7JkQqM=<>cY2pbT1$=5WX z`z!6bV5CW@t*tFHxAb>(*9;etTQnfV9&q8cAUBNS$gwF;N?d88glZ?96+JhTYLR5} z0A|)ze88z-{g+Q_xz`pwDjrL-YIW~wzqP>A-Cmn5sbPs3<@KqiZdk0Z={`vXrzlF2 zc%kh>F55pW&68;gCVUb|_61TdadH`&basNj z_4#zAqsZpo2gj5QAAN@dA*8X*vWhj4b65BzTvBh$lfy!8dG&O4v9c+9NF2~DQ{UmtpdS8R1_6P%__-J){iGQQiU+~G`b(? z{96wvvEv>=yR6B1$UYIVwMyB4=*MImUJXb8(!QTe70gH!^Xg*OpeWM$it%j`T8H7{ zbP?l+crvU0*BvSEN@}Rh zQdG&h$bLJ(sHd+Swy)Ve5ie>KLTpnq^UYJ+p}_1Nf5?18gz{byrDwxeL?d^`yB~(- z(OHve2b~J;(LM#OY><2=2G-xTwI_4JSXRU7o_Ol@l|y90bMx2 zKm@3Rk^y-po%ZH}vD3cm#Py}PFqRU8A3qS-88c2#M@Iqg=Xo0WtAP$_EVc_s0!ZQg zZlyu{0u*bGDW>vq{)p7uP5Qp%X`xM~h-yl(Sl~PZtTt1`Wq+SeQp)<5d*rM3`Jt6M zoLWX^{HRDjmCO!lT1J)3hA+Q(A+CHA=kv;eQ;?e;nYst$M22?@!;;Su)=i4PH0G^p zAJfHWRHjmhybjvOAR|CRmMmxbK{C!=9*l)U$1s|r;?ag%>7`$4AZ^lTz$Gyr!ya2C zB+K_C{u`cvt!RxR9a`6HZ{Z=GscqMB^jp0iW1!&xc(50v#VNcMhGk@AU`=foBkp4(x^g|9vl%L$ZA}+ z6o!l97^4|MSG0cg=?*Gm~@Fv8`BgoP?>sz~eOKuBR{LnAF-o8wNZ`!#N&W}M;jwL<%jBEl{wc5r zDBVr+9%sXy_!YU!d42CK%O+0H0~du<(5TL3{o#<7c~)h%VRY5T>*epIZ*C;k-?GUF zicH-SW(|%Rod0!;{Q z(WJ{2YkU%;B0pR2edgdsRY}a)A?ek8|3*r?<{C2i%3RDaAvs_?IRC|bt6;D9e&fIA z4%~Q%e4^^UV!E-bAqtj}D8FnjP`UV^Tsb|CSt&aApwdX0 znH9mfuY_{GA&GbWg4(Ti=mYyV_3rMj%$%KXv8!`bKo*4&RwEE8ziyCf6(4vm$nxGm zyFxN^dFwCMSs+w;ykzIY;^mWCS8kE9ua_&WVU-PN?I9UER59PayyBm%CKKHeybumx zn^sdS+Fk%!9`kdn%wBKz8phrFX$AJ;H84Ia4G9VHxD0Z019xh&5=v`qt8sm?78P(s zD%>McdkHA?ArSCo*K{0ng2-Z*`&2pFxG^iMM4_~jR`;~?b#U!S2JHQe5cTWb7+S3x zp4t!0QorSQ$6qN7mOcpt;gsLO>?U@bz;_tPh<0$(1weir8%X~;tAESqwfcF)05R;1 z3aC+fQC(o`Nz5m69i2>zIlZX*7gbOXUL-u@&9N~MQ)VCj)H^rm+bVT;iGX=)%WlZu zaN$eI9Z@lV3z317c_+T~#&ibaa__;6dT z=lq>2DKoPiKo!dWgDP4fvG=y4wew8Qf_o^{HJy}2k2pS7xeiUcyFP?sc^f z51FuD>Qi=OHccHnK!9O~9_W)eLSofr!1fL|q=MQ9w|7Oa0frWqhe*vaO8b|KFEE|@ zHETyTF~baphQiTvEdTFIkUAcIRDr$?EX{gs<#l$_Tpp!@PMS`(Jj;8NQT(DD%7Y)c zU)_;(j*49b`5Ye;5d4Cz=!?e$@tHpf|C$jO6J~~WX9#32!%Pa%&heSXmjzqu?m;5U z2wlLEE98EDvHb=-lrCxPpU>1FON5A*jguVS0Om^g^f@TE;eMtU5-{=^xzqhb+ucq* zXCKA)i4T*OK`L!D@;wW6r`)?+d5t!lKx)x|cB#A53;U2Gx^zPx9>>(r+ihKPjOLSH)1MQ&iIe1Yd&)%e7HMP#Agwf|IQS{ZNET? zO{0(k+7`);4WrA$LTzzPeSddi?w6k&>6GNDM9xs3!3atcbL2l__lL9%?5C_S^hFA#+C9tfxhtwj7_D;e#=RCV&)jBFfB4%SuXQJ-r_-i1 zkVL&!iggx2fXx97>WF=lh&>mNmhlN2lsF#f;zAuPQ-u(BNkY%9@5u`;xX& zIO_{CgS`QIuNpLCYaZ^Yo?<|yo^kS%1cF5C5fD;HiI0I$A3k1!`0p&t`oo^S6BqGPqiEE2BI=S~w)`mkmZKS_O&4=vbc3f4e%j zg586F2We~TGC10I9;Pd4z6#3bx%ED3*L(=myTyUZfsG(<-cm)6Chf{(b z3^vn6dj3BfW;0jVEg`au(o0dKg2tgjUaKY~o?=19W%=v#P?l)_8Ffu*7+bZ>9RID} z-d~(R3-JJMRzR=4%ge4 z8|+N@W?!J((^f_}{NGtz;@hrGBELO&QOq3eOZgvge)nkg!WD@I*mr2;jmu@eEB|Y< zypS;o8qtyhs0SM;rdfb=tSlEt9&xapFucp#4L`N@O-lJwBBQOG3L)lych`!B)tMfA zvc7+mNtf3BsiYo)^z_=`#AW7a%k6HZ&7#98Sjp{ncy-h5PH$jU6s_Bi=C0-PG3(&^ zcG#&BWe|m&3C9MDq?3O2gx$fwr@Z}gl}oUL1^==)Rz)tVRgwmhUT4@GMf2Kdbl& z2dgP*1^j*z^7$^3Pa3sT^KKjyBZ*2TOVdaFPENe#be0LGe$t+Vplm;m()$s+VB!%i zkxUX#Jx2ebwLMP#&)lDslDljEs0*Pp|FfVA`fcSuk73Q~8FidjnX47{rbM4jMo*vI zeTd0?tad;B;#>KW!E9{|iN2=3hN7c`G#J`>U1&uARx8MBN%gCKgUE%@n|FDTuuf!T zWEcU#-vWxAny7$#th^?j1zBcwg`d^tvZ6nG5}AGAS&0E;dy5aDuBCCbcYA~*?zkgt7#vp>HowI!H-5EU{qqh>T_JJa`6>iT_? zGA^e3#JG7y{whE9_j;slhZJi^T9A>tS?{nC{U*hudEaoIA?_m$UENTw_&0heK5dpy zC!e^WPK_w_GTI+e7@kE{!a6%XHVyA3!dstpOS^A!Ssgf zyg?;V02^=uw}g$jZz7(RpBqaWc$Jaa3XV~7s3KAP`APE$hh8nS%M!Z%bK{q8))QiZ z;%H1jfRG!xX@Rz=G!7y3*<6B<%a$AkYSlUq(&qYZZ;1`}vTJg^_4L3Ak((^|TUL0G zbdeGkkT>Efq1AhjMcWrVu&m_G$YApMNiLb&KJ8b`byU867G1_S7zH%@C56yu!3OsB z#w%ae@u7BeH6m4^5$L#HoV{E4+iIHm&^Z`*Bz=Lls1__s(H)Jy>WWE|qy+$@geP zH)Lc!k*>_^G&gT4yQHef`zWmN>iyf_53-m0tQ1oQr0ZXrDA)3Wvsr3iOl89np2GRX zTvWhIGU1*}41&*{*Bj3Z@yft0pviU$66>^pzStHQ>}O&EFmR! zg!qnaWV^}KAFrfE5r#{p3glFJec?n@$F_oH6|@-_l%-psKMGMi;3O0^8jK@ivzjE8 z4n$>8FHn24#Jc2KF+d?)(2c^#cvSe!7QVMnsPtv5u;~fj@y55qZ+j^ zgK4<=?OxLS5Wyv?ImTd}8<{B%r=j49RiB;C^r)n8_(TS3MUw>SP> zj+Ee?`kSR++p;v32n7$x+OTtI2mlcv5 zT>U~;3L6HKQ;Z2CpHzcRt~~(JUJ^r9b5FX6EiF=RobcA|kt~7C#22WTMhn$&p!T!f z@kH0{oTS_34CLNOnMgR~0X!7*P)sW*(N?-{$u!O8w5%Ha}^B5_*7X>u8A5HfgE` z@d+i~!0MQ}Fgqx%6R-kAf|J(bb%D)t-J9H8u# zGZq_c({^v4qoGxL(=5LO1;Z}9t5XTT$O%*3pyA~taY?v#L%rpvk9W8X^fWl`hb^$% zt|vVmoQkpUBK)XUy{mE7&*q}=Fli#&?wl3%Yb7hAuMkWVPL_dwz+#SnBjztT4q_I$ zaL+(i>eUoQmjM^}=)55)dlG2lPJ!9$XM33Z6}HKKL$L>v{V`M_<25S zkQ~#rT9qA0()VR<7SDOXdW?rbz||hy`{_OS{mg_Q!a(EJi0VBr^^W7Ogwgf!Iyj!_ z!HNM68DB7YsK9In+=>~njlf_q6MjFSPttdzttR@g(&p(5pqVVtr^r#O7FuHsi8Ua7 z*O|#Hh4zcL@j6>fq~e_Kf9&QPh$@{bq$0>QB)AmmBDcdK(r$Lj2iojeUfz!v)!5|A zaE{A{+z5-SB26Bv{B>aO+DDg35fpq3MkdvY*UZZW#?Z;l_#m!%mbrEe#aYQs3wc!W z-kP87`{4-Q4L^)La!{h5F$4)`>*mREO5G2kQJ&|@dfuJb&}ZQ2M~YWx`QKh%zAZE0 zDeRo|_F(rypYJUW8GFu*pkE7rC)LIP$WWR2aT(8#n_tzkMKIst+gcg+lY^ZETt5S5 zp4U2f{EgUFf#r45b_|zvFMTXX_*V?RgjS!5_-{%M@A@Ov#M3_Pr2BcxkFT%8LZ#89 zbmw@tIY$0X2S0?vJ5qxG>qy}&uNf$j#gs|(i8m1c$C`<**r(!>?uScsAUo1NIh#Tt z;)+~JO^vcY;pP|0lNE1tj~~ObNy$_fE!&h$!`_xgB?{CPcs@(-bL-Vgs;Ty-6{#-D zO3GtplkGF@Z8=Dg04~7r7N{j(Q-?PRz@yGSFc0=o7&JWGyh$}rNI}GaLK8q*+3bf8 z%PZ(uw7uEBOHM0%e{Lw0baZUW(dvKXJvljf08-mpcc+N0C22Csg~gJS58 zI$~c$C3OGSnAxJ1LiyA={5T$0ozZUi_xuroiebovd zpe(W(7gLfm?so7l2-ROHwpiQ3={kipXds8@w)$fE+b?+76>qcS=mfAfE z<^e*wIjGcSKyo9k0a0S8LA*|2aU5=ih49*fZS_as7#aro?lJb^5}TMq;d1_`h4C_| zIOmmME!HMW!{vC!+gY+snBI%pH=L9wRjfA97^oukY-1mU`DN>jehCKjP#psIi9Z_!s8r|zKP)l$o> zvtu_i%IF$psw8q{CPEe-O>KY4gqi;)ododn0I(h4q9kHXuUve6j=NEce+P!xKivKE zqM}1m5I3646M6Sz00nWho_Aw=^C#+#(No0B(t*A{D-zu&)hL-pG(yJ#HLJtV#>zP{ zEsuRwPu?twu+qvE$ zD_WqNhHpWnlZy(N#vB?O<1|mWQ!vg_Zk|_Je_qmE@q`l#Xe~OUMXO?5Fjhy zRXLLo?P;``p+|l3LPPH|u#5M&%{XI0S(36W_B^%zO2I#p1e^_*V7xILh08$6!J&3ij*J+E1v2-?wMdS)BO;*v(x7Vc6C%Q_ z49#fk`5P{=b1uHqNYol8kXeNEz{qm9#=GPS|6vUUcqrWTMSjF4%ZT&+jfKklCuQqX zcK9ebhQhO@^ux%FKEOW;D>GGEOzmIIB|DersabMh5zBMgSq?afRfjb+G?eggf18!t z19ECgnRR2Qb7EF#Wk%S2lw?S*`mkXO6={}+I1bHxrj6*ZvC1sm#56r}CMCLpDG%`6 za1x6WiGVLlC=9AUz@KU0D3$i`Xnx}Dxk}x%uN~1OFEr*A>${}neF{mLse#z7M?@4NN>qSP{Z3BC5%neC zqatP097<=g{W20%+|O#0rDeeP2t};R=w53{=cU#mVTdtYmPHw{jBDptA;wH6`1eWL)~+0$L&d= zW@M&v&jZ*ZtXb2|WdptyRr@{6-e!J#SOG-DNs>Jp+74aj3f0!a2j@Q8AmM)?1<0JSNpsly}9sKv&O z;4!jsq=O8SQew%c>m32WZ`Jsjx zY5wu{(^mxAvG1(Olvs|zXoR6=0PBELWBJuC9(di>AaE#VI)E1b+9JnEtBGLa+g=s> zXIpD)YwGD@fdB9UdwSlfrGBK-wq;C^ZxfoxXp*|4S#eGN&7`do>2w`{2)ms#m5*sA zt}4Tvdm*kiB0E7tDQ1!%M-WCV9(zxb7b0Jc32#VY;Ek9;XCIlJYx-5DN<-!eeo7p~ zBhdh}So0}xv?U{?#CzJ9`JRLpbzYm84^ZWaqFAGv>peEw3%Gs%R`m=rSC}q=YnEcm z{%(Rt)P&ea=}xC!DdsW|jx*qIEMUHCpo^BDe7Br>?ULn2sZr(u+Rb(u=ly{!KW{n^ zlL(UVW~kYxt>N^rDtV1b|FafAh5iXdAx?Pyrn!qkdNCIuHj+IvD@9dR1N}>0jrE(0 zq=<=cusLlO9}05Hr@7w7_c!yFNnDwcFs|1*XgN{jYu^Fhh!qq~c^MxYd-40vFK@Uc zg}ru#1Gglq`0{$@^}A(6C{W3%#_^v@?FQI|hTW30*v+x14)cMM6MtGc`fw^+NTBuX zle7fszN}7nQ?yOOMP#;P2djXR$RMHWr)5{&EV3@YMzhj@t@}HdKchWlaX7(#5(oAb zezkD!wdHm5WVpOKxxG8to-3FczXR{MVIG&5;w;6ti=ZB)@NSwUr2tsBl%s5| z?!pmd^FZt(BV%llPEi=S5(xx`jUAe6JI_KONWfigNS>SzNC`y5OxmLs;CA`Z6i}uA zc}$Wdu;Cwvl^4EJyxgEB!V2?Z*KD0lN^!|Z<4QZ#{(c?RVOh!LTR-1M`$@57s}i;J zBuhlua<1C6ny<mhR z>ineJWp5b>rKw-)yC!NsxfP3ld&tvd5U;SpjyWXui~HbnnwSx*ND!XqN&k?zSRx+GV}I`7f+8wH z{ouc^PBr8vMIq>4dorJkl;I}t$!!TB9=tqY> z2h{&z(${H`x8GhsHv;RSn0ny*+QQusd?ul--1hE&>s?tunK|YF1x=!MfKiu$-+G!> zGJw(@R93iXCWE*UkKVpAP2vgW(8R<`5Hb|M>uG}kA#Qo@*mC`6Z%=Uk?Dy?qGBAOS z{sU;;$a)MWMbmf4P@NLA>d#FPn&Vy77l@;yoS8uv`glj7me)rT1R;7Kl9Jb#O&h#rBJ25zkNZ^W6?VtVa5`x)=K-;=iFl3$}f;-Y|>i9w&wuQl|pq$b(3I zewNE95?qaSTk5f;DALitJ8JkwZob6xT_Um=H{bV0iXURz#+g#%xtB5P#(?zSOuR!P znI}|I2k=RK>@`R01M9(&+-7PMfO;W0c&nU~0T4O|FA@%kG5$Yv?j=$(7J^3adF!8*3l?wsU|V`ssK+iHb*8}q z!ExXds>?)4LIUQ^gC;7Xkg2Hh?WKG~ek%$pJ7QNhH@c{R9IP7XYe)V$)9I(?FoHi& zrJh@@Qe*q&Z|VjWr|U)6pg;$Z3p1qLim2s=u|V1h4(y7@&}QGHwyq=MI4)qXc#Y7} z)NoLUy1yWz2Yu9lp7&L$GEC5;rmtW$?koE50Bv>#DHfPfBqr22DRYDRV*VFh^6CWX ze*f8EuWV|J20Dx`m6}UTysojAHCjRz`SM=-Z-(}eSMjeQt*u zAXu9+7Z!@J;-uQ?V1=V(8(+UYZUjW2y`|o41zd#ZxE}nLj!rt=ShYvvp3+scvtMZ` zhGlQ4WC!%o6i~acn-!6S&R@qqkf&&`NO7pYVSEmAAFn+Knc`L_yEic@TE6?I@Rl`| zN_f98KGV51ht!txWh$D0?Dnbut$fcopKKDTk_c5#{+RetnDfxQ5JIB598j~u(HY?|ee$Vwj$un7 ze*o*xVRN6O>m>|rW@^~9TDlrJIMscW1r<+wJk`*n+RYR)$nEpmXlcEd+;%?~k0y#W zj>X__gd1pH9)DhI9u-U#Hc#yvQa6j3=a1??zW(BQ=aqV|c@SIZB(0mG>7`3+eAdWb zwFmSlsGvNu_QEli3@~bDSyNx~?SmaXzl*aR*tk$AZO`?8C_(WlRCS{~AIwVKX zYgf2J+suSdzM>1-{&P7DLjJfZwoWLnnN71NUa^!C!gJSlmhIKT5}nRt5tGto`735I{lLZ!M?_@S%tBah zLGF`7$4mPq+PBPL(eyE{%Tc>GQP4bhDnes5%kIi5A>n*#Mwvc^L^_)yOhPt*!tzj0 zdf=oY(zvU`Xx2PUnvA$lxr+h~LrrTzDoEUIgxqX#fmx5X0}D&yMv$nF;su6Ya}F-Y z+4#Ff1n(goGTDJVo*{?0=cm&fsk)RfA$F;a#!sFWo)XyLu?S)Lk(Zkhd4*igYJtc- zoLlICMTZOoEDm(0CeRW?<+SNzx+nrA zXHF&mA5&i)l|}c3D@Y5{D&1X5igb6EAR*ErEl78Fy>z!UNOyO4NOyO~J$!fl?z(@= za%SE+v(G-yeq#TZ#RL+Mv#L98&Siq5o;-gxTZPi#UO7h?%wMh0gS6Pg^;vGwtk-j5 z(VHC)t^k)O-1zg!9%|aXUA)Q<`=GsWm5#+pVBI1cLMtiG!XI>|Ruln)mVIZ@fO0$nMeJA1?^Kj7 z_LWp}&J`Lu8<{ZRG@=W&%U*Sw0XHWYjLUzrQ=Ljv?!GR_`q%17O<+)_ADP`fA6H7z zmPL<>^Z7v`nD1_|D5^J`>lo_~J>e@saj#x#s5(7M+yPcjc!+Q}ad0=W3Ay9Osrd8` zTMzNB-c^`B1g3J{X$7iZQ34{(JiA_viStE+>ND;BNY&Q!S#aOcW|rpU&9P@~lsO0c zEc^}A08QlXMbD$qx2tVOg%@<_sPk7Do+`F-Oju}WvF+tv$N%80Nny|{+bWQ@VU)a9 zAYD6D2tlnGmjBd%u_Op$OyF) zAddl0m>3o&NH{2=><@+OWfw1|dL`@Z>yLCB!Dh*GltH2L#NJ*w4JYYdJlbp`oXF~R zm#RWe^WG~rqGCxx$3Fas{L$?3dQ(>V-yrzo(M8z(JT$CP-n{0LGZW0|uoXe{6o30k z8T2eM$RTEmgJhUE)<_W%+;`s@;OVu^bNQj;d@zKswz@pU)i=HA9msbx~_kyckQs;s`Q)2Oq_DI;gbAbJ1+(@jWWwIiEFEMPl8@x+Tn?DH6W1oIYM z@uZX=@Gz`Fkx<0tpPEE>^z`_?xq8jvTz!wcDJPFG2xnVgj+SLkpo>cTlR#?GlUi_) zz=9Hq*lj;|@~D5sgj+im)8_zwG=>V7a?=R>Dq;JO$L|Z}hP3R}u#s7&Su~Xo*USAw zoGr%sjp7%x-;Bhu+hZiW#4Ciy^r20BJ+vz!rOmVldMsx7XfwTH)m9^HGs^x@_njW} z6%VYpsm|o^Jm&A}GTVNm|6!+YRGeb=AP>`L#3d!BXQ}eq4%rTqgpk`lxMKuZenQB@ z>3||)m+FhwV}2v9fECmdL#)(e=DA-Hln6v6#3i#k4vzl645G+ivNR>6KmoLcr9aX@~aF@j!MOF^Mvqn60bX9bbfFe0o`ES%IFDiOx_8n8^9LILEGoLI41fH@OcE?C94K^y z+aEs@K0scLONGLuqx61&<@qDJ6wW6}>cc7h{2>sH+3esj)03l8&3QNFlhq(Q&u z_jgjnp&sxE9|q1o(DO(ONs#wpy7wIXfEz}UkR%Sx6Ucv%Z?1mxgOGl|FmaQtoD7}h z(+~S#gBV_Fe|^y~ZQI;DWP@a z^NxMF`m~5+7y+TH=!$D?SQ-zJQi}dIWiuj7f95mV2tlQTTd!#pn#L9E1HmCeyeqlt zAU#Cz6VNwCx^Ws}s;~8(w<7G%lqRBh3B8BFn`iqBy_U^n6hOCv2d9GW`F)4eN#(~Z zVGA)%WGNvN+p=CL5f+EfBVWX3h|^QeO4_Eh#Bz29ebLI({j*XK@J|0?A>Fd{!L#Ug zn;{#x{}Lf|Djbj04H6R_Bo(eY6#CU=u3xl6BWk0@LR}yE+B)icjAGQsijYx^S0;ni zzlPl1Ta0k1G)HpSxX1AkY4xKXz8a*29ZbakoV||IjO;>!rO8Cfb5CLq#i$o7mYf25;jH1;FPviE$cQ=u{6thuzBhyGp?N%|V!_p{6Gxf0K`h1Ji{} zwGG{}1^24yX?twooW#jVG@S6Kq!ECE8_48UJbYZg4bqn%2W&<*??|0@&xW1J8@|S* zlsW6(oN*pfsjON|P*+5XXT|m`zV^{-^u}O+|GKDy4ge&aV50Iz2T`4RpYyHaa9l=P zvR^Ih(Dcj5>c#tK0O2B8-gwQX_a~pKf<>-44Ya)&F$!g00yggtauckhbW{DsXgSC= zhoi#Bft%w%DoKRq*{s}hcbM7Io@O4puMi0$jwp9a6bkbtr>$TAz?t-gGY7l;I(@_NN((OIqIyq5wia!h#YFB;@`_H#Tl$C?uoo715+e zL)F|NRMdR&dDH$==h^W>hP>bR_H$5g;{NRUIn5orc1!G;ct)sYWcM*-@-NMnZXag& z3@wzt0^ic8FxWy5oy8ei0u62Y=bUZjR~gVlx6;xhll|uYyLdJy zTZ*%al|>!+eV44uv{44dMrXzkgZ;5k0bqcX0v_ZHfRQIYtL?9$1|-jk8@2X42vWr1 zqB2jctm)BZ0JEwh;csDpjQC|{)0YK}6=&ukd_@4tABDFbKXhNgFdX1xA@zBzC{Lwt ze|YKq99`Itz?j zjh=CxW0b8r8Py7gh0v||VEo#zgK?Z7Un}jVhjo$DB6TxeTsDUsM^Z81mp_R$HXk%r zKMpatcOlKa9!p=*3y+2QU}Y9V#{Vgi2Tk#Z{Sb@>%nw~IG+zAxLFE^~(@Ek5cZ((l zZ<%PNjTzl9OG`I-x42EQw=(^M;XmVom4F&;#Ci*n^iweZdM0;j-x;vyc4y?U&i%W{tZF(EFTFMJ`fEqgNWvPSE z-hL_SK+cT_A^hdJj%xi~#ZUUF67$CKGV1OqA|42fVEC6ia_)w}thqwrh3vG|gy)IB z=#on+WNe`EAn;{jIQ8&f`tO}R6S!ux8!O%JNc7PRZ}N19AtsVGA+>`>0~%dhLdcgW zaLogF@CKeeSpXG+b3KGb8W9t*$d8mCrup&eTeLL;HFZQoI;1-dl#NpUSB@Ts+sR}U z&R6l9085g>@81+0UCsr}pm^r5iGD)jf#`nKuW$>@KKlXewa03__yv89d}+~x0tP<< zL&V}pvijqre+>?CATqGGlp6L2U)synEb4bDZ}$pIv%%jm10)+5o2h(%8DtWlKVDN1 z90wYRh#3A`^@fu;=s}Gzu7K{NCtB=z2!oc~gTA%X*b3lW$WjV|V zAjn4u@%*i8WDI!W19vE3*nn`1L_C{BL%=i<_JB!6Wf5PL{jy75vnw)QX~YC0DJ3;j zrDtSW{Yau31)*#h8xXBDfg9M;Xu3|l5fz<(W1J$Bf-vgMgpNw(D2oFyShC_J$GqW3 zJMSiN1G#FxFPBFI1+rfk0DPqezy~cVGE&!KP{k@+f|0N0Gr~P?Wo0D={^s|mh#F8c zalKkuM!5B0#HkN9-Udb9Yv^HY{IlI2VrjYZgx7s@;UL=D&fmde4e}* zu@PWbF+k;KVq%w!_s6*ho z7przUsnF4Y4(yzg{#q_CH3*DOaS?cKZ0H9H71P*GI;2MlgWX*laBsA;SM#Krm18Hi*>Sc_ga*DN^|p6G_)8Z{sp5U7ERc9NP)LFgm% zQk^8jKCdB^3Tr-NCFvs@N`q6lqpw=HBZJ zi+uqE&0rgns}BnJUPR5byz2r~Glo*D3`q@=567sIPSpy5^56AZ5j?R)7b{1CEWgGN z4SN{LQei`DsIwRhYEsF$aelyXBHO`4i6=ZKm-A zC7F%F#c>Oq`Eme4Ac$#0GF=(fjW~0Gvm)JX4Flp_&fr6&T}Q-b0fyY$D7eE&svku?>&>}Dk)%V zA*+wU=!;Dao$FB9md5$EsM%SEzOS5DZatW=dAv0+3f>2R7f_1~Wl3cYTyJ84wrx~j z2~duFD69c``0{TUP=>R^y!Yn2)5S?4M10!q+_jn?QBm8Y6znY|`tMg=+24Bc9u$rn zb3^y-R1JYoxZhJ5w&FB?+6V@W83m+jUdD`YFI$d|+pP#;7iN7{IB$KMUfp__Qm%9) zNE99bayq?EN?FcLEC)@$VRf)X7m=avcoY}6kYfif8U+_OXEP@38xc4~m9NAq$!=Py+-p8|+OM zZ0+j@lpyn?POmyT8oqs*1$s9ZS$!=A^Ev)6(xog*ZVhL?Xw<>o0-h7^DROX!f?uL6 z7{E`Om7SMoCZT_x8WfbZ9{P9XdYJ;1hw=7zzXF0MG?Bae#K!LX_f$_i?kh@RfR1VY zNh<{~xq}T4x zO@JJzU1hIT)P(l^nSR-yvEhIjQ8X~UK}=FIh{WXK%RyNOvVz%MMGi2cmN9IdyagpD z7Fcsi0@73tvOWWBLMHx)>2K(MikBa_`7i7R1ufZ-g0a@xqOd<*FOmVR(Z*3+K+oVZ zsW}b~&K8TW>BKMHB=-3KaRGc$Q-@=wsv@77-4L*jXGs!{o2b;m)E(g=aSw@zn#UIi zmd5mYa4~?uZT|GDRsl6bdA zng5xth#Man8DV&T3B2L^UmVQ?a3yeCfGz&drx9~@30$3EQBIwq-UK!&Mfp^1KMV;t zsiz;K`&-3^3v(xXQm~O#jZ@HXzlg7;x+p^HR+s1!z0gw5>!_ESwU|ejBec2}+NJw? z#GvKBV0%!Bj;>=9#f(}lWDX_euyQrb7s>SFYLgANgR_Ud2tdim>93cZO94L=lJ3Jd zMPicp2p+*{pyF2wC{*8BU~cT5xZ@>(5X9GJh;61;%kk*p_MA>4L1c1kIK@nx>~_Np z!~+&$Uas*tlfxeOscb%zF*SeHShN;Pxpx|b%gM=AV}M_yR~3HM@ByLHcor2(1NwB; zlCp@7wPV_6+rPk3a@Y_ECaSXF2!6!~YdIP?+HUij4(|F!zRfAeZSoyc zQ%H_v*$N6M0s4t*I|RX(8FyyM`z*@f1kMS>dL90DS~QfUKR&Ten%fh`hPo$dJv)ex z|4`F+1zF?u_X)vayK;|;Nde62*qn$16oXwdokB}}-N8v(#b+pjFXH$WmYzF~=Nr^t z>lCAQi{aM#Pkb|+=pPi+>vDAEUVh~cN8Lv|+VLS376THh6mnJvwd2( z!(D!YTQ=8dJ`1`5;hD&E6F|~?FA9EQx>Esbj?@*$;J=({2$j1{0PG$IsgZRUsQRqj zcu){N!}Z66Cf1joVe})6eY#2~t+W0zQy}g@&@HaBU@`Ini9h~$*=ywk6@*XzSTVw9 z4cMQ0|B4W=Zv`qSeI@^pQ%>)B5gdBix#={R2ySz=fPSe;N^#UKH5^Zs&P(od8|yFj ztpZWR!LQL{cuJg%{m>eVcG1GxZjP8GvZy%-2SiYo6y}5Z<%e;K6IdxH?=ts_-BAzJ z8a{A1B`GvN0k7JAkO#Y4EWcBa?FmQ1uS;t<*(_=qE7A`%9LCxUWx7I}W>uGYY&#y< zTn3GokOJ*LjeH%iFMi(`-c66g&&02@&NNf>=2Eo3`HKcONGacC5U_i)I>bi7W5I*A zQssVFHG}li>o0i)Ve6E`gk2+gnc5Hr)~VT)rMndFdFjj7} z{^JS+m#IqzQmyFva&%&=Y3f?6lr|iFnLs{9>^EPsTEeXt#kc?_KDZ-nv{NZy`i(*$ zd94J~h~%k`_L_u7&oERt)YV=m^QR9^6`-M=&jaC;W{^Z%BHLD*)7W(JW-?rk*C4NN z?d`JlJ9^Y{eqILMNa7tbE3K#ehfyn3uqNtmxKG1*cdr(5j3;u>$ONRxkvOcz^tx*| zdUK4amtLpANhQXrzCt7pf`TX9iCW)H5Aw)D_)VvqwY>P|Cfx=I$Ay@0oFDkmD^|v`#FCzj z83OIbZ|T})G)NIJrtooiGcqu|2`f(oyp!!{q3=gQ;)dyjars=cgj+Z z&V%KU!>xPOr;yU3_C0%cm6;Fk&}dIHK4HAarGpo(j$YRw@GT`fO$?%*{KfF`%>%0j z%}x4h09lyTEnCCy(;q_pz=c&=qTfyA%D*%xFHfymluf)r`0VlenaVXBSq19?Dl-G~ z`}XYX+iS@I=;4G|t>0GptIaP`gR{Ezi4gNd9X0(aL0KLZjW8n1@zEg+YKK|hL5Sy;$aq!`S^jQuSr!z=Gr4r-|wLJQC$xj z*6opW0B)9{I1VgkJm>y$ON)zFGi~!U2v-rB1ep@sI|V<_4$t^mqsJDyt1wDYYR0Vv{dMxGa=RCwgq)Z;sjwbZ)s&}-r4x1Yr#(u@0@+v+wnR5BP zeUwv%;V>!xjY+OsDU{uc|0&6m5&2@Q%4wSbu#}9sq-C~OD8MQ6CmXN4g(zHN6K^Wv zdjY5`KRgRGr0|p7520EB1+f$(F8tVo_Lu1?m5dHkP0HFNup{Cxa%l7`KKIiuJ|Y*$ zX|Qlfc9F16(Ai+exU~MdqUur_QjOT~*OXe1fjn(}o=dr893i$3OioQO>`}hcYi2mw0-54FmE~J@duPd;@Gk!y5Wr5$+UU~mhiZ-6AZoeH z2WS}8VXuR-vTv_MUYvrddSwNZmWCf6??D83h5d{*B-@sbe7i zyKRCwBuHGv;9p+d*v~e67;MeU>ZO+;NJKQ`!)iIj$=pqYT!*(4-NL)kf@l-YQ&@pt z23U{xrP=(*zRlLiX)E6YMZyUV;aRyc!FxveTq^OgaoE?q@|Fw{A;OqjB)l^zra^?3 zyt@*ZIk?RK&I)Zh=0&_t&(k@w=jC>7UJ{)>>R47%i|IcJJckjdA%e?NL>UoCFDsLO z%lBZFg<$e89d6~EUr2vx%a_@D6KgI}p(Mr}w$hmFEsxId!RSQe1vbLJbt&yAD(59K zS1#6;wwnJFKQg2!Je|Ei)jOL#%M{rq5iE48B%#!q96Ob?}r zo-mOsf!lRJ+j$6mnx4Noz!XgM7n7CyJ=8pm)>~gir}uw~+zGbp;x~Oh5`*4rz+8gG zbeiEl6Te%F>^%i?A8|S)Q+`(6NCKbS4HP0HAkJcR>#bCdXx7h5wh5|4)h#@I;Ss&` z;+lcxSD<$OWaCJYUPu2<`2(a@ReW!QcEsOn1)N&5hja^G==&~h_0zCERh3X)_*B}C z29&7vZw=w2*v^Mbf>#VQ90sM8S@L(Y}TZ56xi+t*;l117<{uUmUFiY_=QX(dHaBk<)HGidrZqxW^U>0Hb&b7(a{}Hu9kT!%}FbK7wF>9R`7^f_-EgSm~NL0%x^bJ zOltc^%)7)h)&SWZ^8h=%zK?LIfjYT~>)k~pIC9SGPloxeu?A`!FE#PJ4fms`M$8$n zTXxr}GkXCok!cyBagCv6q2mKbFs=&KSHo>F{ozFfOtB{-lr|vu=DxU(;6Uffvjb(RrNoARAP|AOsrhX;2T~@F+k+&OoUN&^*dcEsvA!< ziWS0Z^DT4_VdMEKiQGFocI9z7Xq06*0^w_u{J~Jv{|f; zZ@{;F&$;aQTQCZlsS0raE3wm}MmN-Eh{OaO)usX+acV?c|u4V_) zowHk~S&3v*%y2=qWWT=NZY3`cHa3-E!GzP>-rg5Es81_VpxI_KQ5xh>eUkw?B=t}( z=35vZ13?x~r6mmmpO*H+B|{doN!O_NNG!Z;b62!%vAMT&qsXKz-=m$-ML++|#1P6^O?n>lMa5 zjt40}9p2fkKljN7e6Oar3nxh zl>jg51xIWFdQyU%+`45~wSD~Eq^)P95zqU}{h?&e2{g7lBxdLC)W1M3GKf|M+_n>DUhq{*?k-s^ zmgBs5&V~2ZEbv)5g1&cT&v-%FZ9pobifNvgig=ALjrcA0TvQ=4gkuTq%Jx(HFqhmK zq3a~iNKv$5%3Js95QpVr{7_56&Q2=UNeQu0-9}h|f<5{&hnr#b<-w%H2?CEJ3m`q_FX>j{MbzV(hRGWA4iTrR(>Da1&_K3UJtc)o=QUA87I(*Uk z;g?OHu8?_4c5-rZe?<=viQ+1Dn04%>r{!jFJVZPgw5Q1^>h8%{u{=b2P!?(Y=v{RqK}vvtGf8vN@0;z~gpf>R{LiD*?&G%o zct0Fuqe4<`{mlm!O&|-vGCg7Pm@^Q?WEEw=!8nvY694@0b!_(n2cffX2ycJtQV|}9 zMG?6vy=CL8_8$jyhU^S*yxNT<_{^P8J`)+3>u`7qDM_8hfJ^Jr(a}YO^N4M413J~x#y&%Q@8BMpH58h4vT&i5zeu{RK=t|GrC=ZI2MgZjgZoB! zxo-i9nsPE|Ac(W!lkB|pyao2=ICZv`0kF@Eu?_D-qP?PQeCq|Y?nnyl8#w5jmdpl) z6Lt(LyZa$Xx6j|gh#1uPX(kv2Sj-?iParNf7j-K;S~d!dKOi_&FJi0^T$B~CEsC_J zBAAO6zLSax4hl-7>6i|w%_f$LdF*;`2*+!@kqxCg$u`5f9&+HmgB(vZ5j~7#I2Zp@ zZ(8O*Ql+JkYfJ)CqBzGdiH#9FmW|~}m-8wH3Y~G=U<&GVZlS1H9a4Am5y8x5u^;Ww z*&h_AMJNn5b-Et3gJ$}rzd^l$HjW=mn=}2s#C7u8UBA6+WJc`awCmXI_rK-Rwcyh8 z?Vx3~Cv)xd;v225uOEuAde%P$OLgL>+0I48(|JBMkCU)}aNXWq_lLdhvnC+j=(WEw zC1O+{d2&LpNAN5vq9?J=YUCWL%j?;vzI3k4oMh_d6Yoy3k4v7*$jf7D7~99Yn8U8X zZng_)7+rSwH#2HB5e_{Pn~1MV6$|5HI}?B5MB%vJy50O z<`fb0OWu^SwAUXWPT?T0NCn9Rf&RO$zvxtXPh;<-pN7S)5u5eOMqvepJR)m9ASn2pl0z0F;lM#&a7)uKqSi%TEOt@$H8 zi<6*nvNX>zwn^YIZWxKxQAlJ3nOV);jc2q4B*P!s%3O@+sFH7yd%m@i7-Q?RTDZzVR}7pI9r$D6X=N$PtJX%YnYnjjC$h3 z>00e?eJP^6OBcNq`xx3C&RKLio=%8Maq(Tg z?Ycc4q;7S1T2^C@#2y@^gLDoG+J+=rYs?te9TvUL785&GtSNq@_vrc$q46!*0S8@3 zS$M!Pr4oFj=Cy3S2pde0Wbj5KPTZUO=MUj2PI<@&Yfcn0yvUUg6L3OhnGVNG6*ila zLX*^I!kJrrPjOB-fI1Z7p@v?~^Ksu`1h?Zwn>7}V?Kl53)Q>CzWp{ZpFAc){(G3oT zWc}p1)f?5~CcQpSjC2&sCp6)25}zg$-$Sh7$HrPQI-!zgO?9{R&d-fMYmvDrW$)~Q zBQ1(M5@F1E*GS8mH)FAd!wkacQ^-w_;Yi3n6~;H6S4g_ztMpKdU6wCFUhg$)p8v6 zKYWxOLPg|F4~CRz!)L{#a#`aS!*y1>a}em#0GM(sFQMkq7!`;_`?9Eu0!=b=Jf zL2INnv+h$1+(om0cW*H@DtEVcpvF+){=Q0|&A)s1ge1%E$ua+gkW4>41dvUy3=u-- zfIil0X=R~-!Ny6&-&cH!jMNDic~|>&P4I{Q(@8jwW1UPryX2D&XTw8kmXNaZ?Q%qS zfqdS2Tcyg?EQsmdoheOIU^18^Bl;MTUyh~t@)2{tfeNZFpG?p)A&k|fn{QN)vS?{i z{Mw27L<)5Ig)P3prOWMAW)!`DtKFD#gN!WinyCPbO_4#=?jK6#TU29U@u>-reTI=H}Dvj{2fs1f@k<(xQH(_gzLd*^J!<^gV z*4E|dJsHU@RE2`MWcRkiRB@6P)~PHIRfu{!mzU_=-M{3= zal3ZAUZ$eZVN#Q~GeJZMP~MP2_<?$61^zf4Y4McZj+=AK^=S`n$7ZoWSE;t>4Nu zP3wGdfn27|2j&OF70%ZdIIPAIp6!P$<~h{Z;)12P&ePJZ--a#}Ga5y*cG1&YrOsTh zB_uTJUcnq<#&04EHY9Pr4m zlYd8R<1z{oGw^i;M2vnnY6^1_WP+T$bmdA3tM?&D#XF7EnY_hLy zH|4H+GPy4ZV**X7p%<7P`d64rm|e|IGs@2n%XX21g3-VJ{h1Jw@a)0aUtSy*(f2se zSAp&5=*SF&8$y$Beb&x^(=l}t`%h-M35oF=k#-=lrG{Sef62|<;8rdy7he9!VlDyZ zj&2G-G5>oT<;YD&wL7Yf* z>^-Iyp2dzEhzXd^KA+MVOjVl)BEE^>BjQuYP=L|D;BWu{pBfH%_qC(46MzTQ26h2IrZA+#)GS2H+WnTac~M9^*_2R*laQ<(zLC;_>%1_xY30m zeS5Bi^Su8J&Xa}fB4*o(XQ#`U^>Ca;9>a0Erz0mlTRu}sDCd57_=QcD!E7Qg9|0&k z9OFP?EHqB-1_nO>y?%u*E-f8nJHn&p;_CX3t^d!%-s!) zT%YRDeQCTMkjZxPv$C=2p~)bnCNsJ4qB=?GhnJhP2avsJZVe$~cxPEQ2_4vXVd_dw*;} zXiw%~l5iq)2@=+aLv)@ls^}pL`<#hrl;!{8_zaffA;P!SG&pL24I8bax8<#RQX(1Uoi~Wy2wR9S+4pDxuJ`L#Vm< zf;r@N_tsJ(?vWbX>C3yJy5_p1_r3q#q<&QT;B@lJaYcWmWGj{RtbSBWeol+B1ll!by(xPB-mspQbKIL-aJoV`dFr=;RDy3X#K~nwnfSe-eoV$ zUx#45fh#-~bZ(6ok`I=1~&ob*esIJvFO7hmJea zB$*j$>XEkA9BDA%&ug|%Eg6;pwKfqQ>KkS?4=~8QZHc{yzs;;}pr|wjE>~olPR43v z@{MM32hC@aG@i+y$Pk8R5G`ANVo|Uy;(7K(Q{mn2F?_53%+O)q#bu_yl&CDk3v8IK z!dpEZp2)#ji}`fi+u)>}mUUHTW?(+XePbaPICK)-V78Aa$4<-f%+UAH^vi)-i z1qMwC>xTpDjE??c-)LuAnd24{t9 z?O@$yylD9L?rVIznIAONjIl56)V&(f*6zU6rHa7!_OqJJrYWK%wWB?2Z%vn-?_E7` z2#rm9LXMX;HnAHC?;EM$g{!ODitLbH?v?{aQCGM7KDV`%-x;m?#nKgXE0R)vgn-TI zudt3oicl@~@gj{Q=y`Jl0GjT9H5Ll^nge7LI?giLMT64J7)x3Vjr>@x%|_YQEVi(^ z`!*vOeKho*rC*UBx?(&gfBDrfzG*}XPUxs}KIOQ25<}q8O!W z5rS`bP`*_!-@E9h9aHx`itG{aW8lvLM6Kf8TF`o6iGK-`J6!KJ(|417J81Eo1Iv%^qN%O ze;Jp=|%lL&?fHDNQD9se` z9<=2|L6qqA?yKXRhk-@McP+iTg=5>(B^HFK_jv5)5rjNW4{1&3uL90Yr%%MOMFfP) zt}V@e?dh~(iBB5$};pK53vP4m?fN5;gby(&PrU2rl1aBff3_Cu^ zKZ60T=gmy3X4@@pBkx8oTSMcL;WWPL>XF$8Ehk-u$NF=J%i?#pc#3hE#fQ4z>?{2r zYr+*5s{T#6sk*ZzjXT{f3@w$RqrHNfKohrWqolD6ugmu_?9Ocp+-X>-DohmZObuw> z$qoEi_lC-0jaT0q$1G8=Y*?MO4O08{(^(obg`2F6#(JM_;crdwgX|gu%hhU;X+0dbCze7_0`x@3&eKNe8-Oq#L zLUL4*)V(A%q22}3Hfq&y_vGT%Q34nTe|(;alAUzIzjb{Mx?KDcKdn8NS$(f|8L775t%3-Q>{cXRT0|#)6< zM4F_GdZDLNs;OfzN#9brV?;3}ML#pqhPOCI-TL&uCLn+ccfWtVtcJhFy?Ah-|fk_l^=af z;k5O`Wi!oY{E14){WT}{b5Lx8Qe0}YlW5-}w@D9&6u!ZN!hOu6lybRS39f3x^_`T) zM2^@@zVLjwiOrO*>OK|zYbZ4F576Q29I?8OYpbieoNZTo?XXB&4qqt7Ng)AAv3I9j zsTh5qy0wp%5SaTJ`kAYNKH$C4S)C zBQxtUDEj0!KhA5uR=}ay{ge4i@pQFQ$O-%HU$~NW!JWf$cDb0}>0Gq3e++HpkJo$p zIqU`mg}7RupBJNIFdQA2K~mwVfQixwVV!N1MoHKpZ$WY$a%d6S+~ctCN+GCOX`rM+k#iikR4yxV*syx===pkgF6z1Y4c+FYZ-Our<~cz` zyh&bpiaPcC$hr}c?;EliY6FlzUwhf!^_+qf%`o9vuUgY=EDH4Vjf>nE7gP+xCYV8z z*?v?$;cahi`IPno;~z>0)u<^?DO9ETC#Cn35pGqLiuY$>6thLwEy(9i@2m`IP!_lZ z7{*KFmGE3 z!E){lDtE5!FlTG|GM_m%U59@#JkD2b9Bhlpy@uX_dQTi^fe|Wk+JQ>@=l#Dm=4p_; z5@;a-Bd>^_^{w~lpX5V!3WppU28VCcY@@oh)O4-2vh5z;=0NmKdIEy7yM@yMB{o;x zl%R`rP?#o@mIk6J`t&Iq`p@wiIcZvt{@eDVXb(=9Z@#PkyPBi6f3$kzC^?+3Ti)+y zM_6g6G(9HMhJ7x=zsWItcUO|Bmm^Gxf9s>A-kBJ{UXG4^H*S?x9QpyR-3KB{iDrC3&#k94*A9mTFw41wk~z>y?w25`3hb zMQh?Tfo{&Jan1Qh;Abytnv7;m92O@L=|D-?>HLh&1mT8k5C80-Ac}3#ZW^}-g~wYQ zwQ(26n~xO5ioQqIdw&9!?FJw?uCil9F}Ahp#fd-29Z+O+YrbapJ=V%^&G^7>HaTB^ zo|xL@BN~2iJ=`yURKHKmux1t;EcbgNTwrn9D({R(EzY=hW*&|hivQ$YqFE=%af1S_ z#5P>=c?}J`AurQ+7dd=MLS?Qy$XD8K(wE&tYC=v^z0xVPoT_8!LZx!fk8VAeO(tsJ zHy)2De&s2=I}TB8nBwvD&;Pu6l=qYDYPnjMt2yE6GUZWRbL|0gyY)*3N z$&j+u)P{#;GfM(Vc~-cxna6gani3qN4LZwD1z|<2G~V(n8cN05sQ+F10}sbpW##POrD5%sDq2QFVVG-E2C;8T(0Mvwx#2vS1;ZQL+)fTzHX_ z=e62=Oumubn+-zqPLsS{Rks@=k*00x>vxvccR$wTcoiNer442{rSaQK11$vwcL?2E z>7|I#pS=vk7k&Nw{vf%Q-m+0S1Z-%L3JJ2`UF!u|q4(WGFONQQGwhs0H(#i|d8sgW zkV@3uBtEix&8wBDrP^JRd)Az9BVN6}h2(_h&E0>( zG)eWN!v;5g;HlAk%6sMK)0AzUhLSnH%NKZN`!u(?cyf<%sSmZjb%1+$={GPxabEWR z@7aJmZ*5+ZoTbu`?@+!eL#=})wn&umxWDxAEPRLGn3AlVbbHRGYu#E7rM+-Oz(0>BRz|(TV@ZK8b>#9MfYLO3+Ug*V;{ABr$4qm zHQl6AQ$l-0LOP2@dEfLe8-`-W>*={_iq~;o z{&0Ke-!1yAeNkS~jKDCI7rzc%ZYw(2K922s4dn}u3H~i3lGJranA%%!n*?suY#ZBq z3AIHnm!cYL_w$i!q-;0Karf89N(OG;rqIuWcEWGAZLUO&Y_8zG9mULP1* z^=P+$9Z%WewB|zPC~-1R->7iT-8{_h>vA-CfBXo?`=J81rT=wr6yHC!QDzEu`qsbh zYI!i&z~T)=z|q4nh%$~2z$6O$)3oYvL_u+cm`5Sm@CsdaiGWMd<{e=EeODlDr><{x zUY>XA?sskcrsJ9uWF>CN!H}Zh6CvE&nJG48!SPeFR5m4(wbC&1TeFLTRN>BtJVr@7 zneJe%`x`w;&1{5QxfEPBSu-|b9eEW7^~u2B4Sg*!y-yPr;?{0-)8tY1h4w#@j0E2C zL{ZQrd6M2OX-I~>m28WR;BnqzJU?4S(66XzHq*0kz0Hxl9PGW`meysu)v~PXp)M$k zN;RdOAgxurJV$7u{8Aa=&-uUAStCNNT+mnBi(!l?|mM9@3+>t)-3tY%sKn)-uvtyja^-_ zD$AzBrtg=BHZ}Egx#F(HL+Kq9LLwSH64ND8sN67>gxC{f_Sy1~?H+WuMauKhPt8OJ zeCHe$LN`rik|$y_Od;3E;h$5;)@#1T z#B)e$9<8pq?&TIb%g#Q5IX%{2zY$&wme}23wGb~w<;+!-Y~q?QlM@_sZHMYOI0)s- zC8lb6@pa+I8KZ;1gNS@Dy-Xc{G1n_L=fzKGnu~#~L@G4QIbCY)iwe9p6>qV&XMhg& z&NIvHqc*H{fFX3nq97Ez9Q-8O+%a{O@j8Z*-2+k}o(iLuMt=46z@#n2y3 zJKi^qvZ3)J4a?odJ3m8sc_qMr?a-s=2zS${Pc0bt9$4P$fNvb4YLRar_B)k2L zzRV}>0;Skll>qL@qp*_{DwA-b%bpe?hfP5Lox&p0PJ8&JVFiQhxddC7JzkuEy-sHV zTyZ9z6ZYKTGQ^g_@tdSj{H$G`QdAv#9hB81)xyep`K{`HhPc|eI13A^e-zmE0(rcr(*Zn8PQq#5-dzkaiBT1L;N^vykZq0@Ey}`M!*qdE1S2)~B&Qn!s4zlqp zzpI>^)3-Ue*-U#rkez|)bqopZlN6hJum}~D(Pm|{?da1a_Vfj$Cd!K|$QBe(+3rSq z&AJntX5@Q$`n>n}Bwu2Xo)$iT;T`1Jd_6}^+|ZhW3ezuEKkkS(6X*6&!n*oA=l|$u zsjQT&rvnl|vwF+D*9WdwL_gXmnvD`cIKiPWdR0?>=u`#OxHRLk4U*1LDnc%_kop`t zR}x`DSEvMM!?pTUKtznnpL1#5jm_25D^x4NlR1^U|4^=ESP>R@>3mG6&T95**A%pho{H2{A<{pdR2z2nfeD6TV5d8=}w+o>t zPO(ljDbJA7@Fr`&o#Z@s3JXhiEmSPolhl(}J=m$Tc{hl@{5(-&3|{qFT`gX~M2T-% zHO!|?GhV#&D!e~@rc#c9YR1GUDJ(Dv&ShC(_8v|oJCP$%r0Tp~q5~CNdP+(0^MxI` zr-8zo$V7r-uH!`6Ac`f4TEP@PwR-}gyaj86fw4T{Of^h4sLwM*l#0*vjp<1olkz0z zr#$3;#tf^nn$Gn!_EcRMKFOLr{lze%z7lU92bZtkZ;YT73{E7VcU{|gwJ8-^iy4E5 z9U~i&I&Fxs+Do4rOYm@dXFrwPvqph&iDDKvhHjv-s+;UX!I@#_lgls9A*JQRlcX#k zyiGhW?{zPYuH?&Ih7(FVr|uJ>;PWwaH)*~a#^!I$EmeI^nmTgs6JsTQ5G4IM$7D21 zHKzN=I!uOFgTyV_RtPmBY#6U|4i?_bD)XT?v=((4?NQ|~{!)H|$JA4v+H{}jlOjD* z^10}y_OCw%lQcrLSn4XZFL>1ej8!m?mkM11j<5SR*Tv`c?z^c?2i!IyH_G1Dbd!6F z?eVM`^O}@ud^%%3<1dfi!o{yAH_=9t?wj5~Vr#l2z)V6LeCjJM6^iwU*p&y<1te+W zxEOuec4(doB6y*mcR9F+cJjIUW_{}kmY?U4mQVYktT!Ars`JC)l2SDXn5;v|cYOw0 zvlsO&1_MgW-W9Fjsw87oFJ0s163!J64(a~SU)_)HxF+n9DVOMAi4WVIGtUK80pU>alQip2R@cY?nX7NYrj+=xfgwdGGF@fJ;mck%Mo;2hY@!X`?{^vtC4vk8y zP+nO)FTMTA#}FciyJ*8SP!H&q*Gsr_h?(WQ0|M0a|3 z3F_)k7K9a+p>YzuOTE($uE5iAGM?7UQbah0X?G@82()ONZ;EzV z`hNbGK(shQl=t0_jE0U&LmAE*aB%qZI4S6;`14fPPj@t|uUg;|jqvBPVweUBdlGk9 zu(?Asi`B(g99XlciJ!PTD-eA!dk>|?X2n@|>`9J^b$G$_aP}pJ6xYTzI zh>XV>_X3d9G}@~JW6k*CgNa0`QP+G58lSe$tc9y*YbI1W9!YsA3k}J|5{7zLEw8<9 zlNcp84)JPtvsBOY=+|al&XFdS4p{qj2&{2F;mlKW*FCc>`A)IsMIZj;T9?3mP&nH- z6OS_-X?X2ubmSmH4qiZhRN1WMyu9{FH{TXxh28syo&|@NwVvy~@U+i&Y!~j(Dh1or z)eM=Gkjg-m-N9t^(e;NSjEP@GLN~H#iW68A9X3OGTJa(pwp=dbfv<*rR%KpkeUMFb+^`bs z+f{9(E?pmT{$_4oH?y?0B(J4i?p61`w1kGQ)>=uwDaF12dQ!TGxrPxdz>tGWzZ(Uy zT0!(f9Nv=bo?}KEg};J5thv11=PJKr9pA>amQLEZiE)KGe{FUskNWc126cf`t~l(0 zZhbzS4%sPRs)CAXBi7+?-3z;^_H9I;oG4>9MQ(4N{KEjXP%Jz@3Ked-aW4z~7998Vgq;Is5cFK8k_>Q_t-wBkzdg$_L%}v5}M^HZ)~~$a?*Tn^*>ixJ|+`ia?!* zGqW}ML#hd$^btGyvp(xDQ|pD4dq!g<4M=S>(JSo`D;1e@XHTT7l^$yR(ke-&-*0;L zG-XQs-KQcxjV@Kcpv2wMF7(nUof_k9?T}wYxz?)5;;7E%iCwfrFXb~M5$n8K*XIsO zE`3C|L*sh{IC=ys(}T8%rG3=T6Bu5+o$}e;7PmOcS77*})xwG?*CgS**Xy7mcG740 zRRcTzO?l6#i)u|z%+q6;uA?oDshM~fG^+ww58szisu07tQlSN7;;2F;t%mppbBi;@ z1c}d&d*CB}Q*sBZPe~j}F-?zW3!uPW?gu(|~-zlwyJG2iAQdhbaH}bW! z=Mp$EE@Yk3)2P%Nkc}~&?JGrpGEGlb%EOe>B+AsWp+bxCzqb%vz4mU@NL@Hv7>$}o zN5_ue&A|a({P>Aryli(#aagpuq#8knuH;?Us1@h$@|osDtDu^fgK@mipzt1cc`9pP6p#vaXsNibNuZ z5nHtSD@fmUP`mIw6TJfgNk6>7uD*nIHMopX9W*Uyft`^2b(?GN((z~be6fcr28|Ah zgXO#l%PgzwAk#yx%HE_rqq0l~yZQ@HX=M(JcVs6QRK$3u(~xfZG2vy|P_!mSL%cim zyc8DE?;1Q$^^fv{cL!W6`v#*~E7cBEW3a2&xXr)er*<&kk*YMbYWbp2iC##ed|**n zM9cFovBAU`=T(EZ$Qzcadn&GbaOsJZ$v%4AS%t}Q#{Gyi&7r>jbG4Y0Ex2;1dJ0o} zan|>VISnm~%Yu%08HusC`R2NP3IZgeix^j>>DPrT+6>VQ^J!h-uW_)cRo;v6ZqN#i z-A{p5Z_$73->MNB)pT%vk174b_}Dbg4P%y1Z1%%W!5}rQ#zWbgbUm3o4EfOduhmgQ z7?TbYMsc1;XU`2h#N~7kFPs!v3$QOJJeG+~TUQ{hrYhIk_aX07S{R!;6QU;l^W{@w z6YYhd#nm<)IKP%xv_JF_xicN_b~RSbJ#SQJW&d#$bD=e(C-YT>DLFi%qw!<%)%fF= zHxA>4KR<|i(A=w`h;9f|jRzR%w<_NiqR zlIDhuGBp_Bq)t#^F3V;}c)?U@mNV0*jE2G@mO#xZw3I*aY9aj*pJxx(qaLSFvGRvU zsugv?1@!%5=8@-xO)23in%^zrqK@ow-;KH%^3R#`m3TYprx>@dI8iXW6kx- zY{bpGj`UStUQ$ocsPL3B}neLVR@W61m!u8h9~a==BB)&23}av$K>I6>k{B4QVUH-boc zZCIQgqte`)wVQ=4mAhx0BKLGEj)YRh%SVh`T|$s_L*GB&xYp8B=-dW6KGYKi*%Ie= zoh9Dj-u=uFdgF8?UxAVFX_fm(+df9he)+pyEmmmqA*cr~%?K<~AF&G%KKhY9D31S_ zz74(Z!0Bb@*o?Bzw=cH6Gi0eBxs){m@fg2g*W6QZQj^MRtFI9ZLxaE7BYLKAbP@Kj z$h8M^SL>whf%zv$uCz70HV8^-#RiLb>~m_D>SbB6(N5#~NiRcRrs+dU;uks}yQUJf z3{+uhl)Qxco49Xl5(Ig%nkjK=6p~Zv^A}dCo^b0RoI{Uq*Cm2Y1S;wnG(PYFsuyHV(`3! zut{!+@2~I`d-!wRhCa>87j%0yr%pJ>s^vswsB%KkPb}+-tdH@VNvJtG4%ilaWau?< znq{_qtY{5WY0n^&+62~GS*i{M)^cyLtj%nN3S}ST6AkeadTDU(>z|*DGbrj>b1ZhF z>~{5t*az1`(hD*02i0bEVkCvAHe3>ih&>K6DvYO2m?;Z|&S|4Ay!2stQ_klI5js8! zTs?^tG;#v?hVz6EV>n*uz?Hsx^=VLe`aN3u@KVF0 z{+cQ}G2KAi!;ZMXO39YNFClA)n{iLSvR-e(Ae>EMrD$k^QTJ>{_l0|*DGn^n!5AUK z!(JsK!NXiNx7qZ#FE`g|o~ccz6cl})R7x!owXy=}hh-W1Gtwa{batPT&z!kmSQ!w_ zVHYuIks*fiTd~Q<-1w z*>H^#Z9b{R>7nx?*es{T`TYx0zv$@(4U+>Ny-sy`9ir2Z+D<*!*Vlq`W{nWjo>a-z z+EQ^t!|Wenk;A5~F40Jnw9h`rzYcw8Grxa6d+8RN_=-X1+efOKxkblzc?O;m(}@5% z2aR^up#(UOE*gt0MMQ0$^qAw(jDp4IDT{Y8^l9uFu_3ynb%g3KJ6TZ+b77AyhD;or z6?evgW>_aTy)a=B{`}N{CE~Mje{o06aET~o+SD+SySUQRtaS!eoFsG-RDQ8{EH;J} z4~kY;5B ztLS(c&mz81K7VJKsXBs-j0m#vj}R;bVwrWhsmGXp1}k7*he$`QaTm%2&4#?UG#&M- zh6kaQh)Fgw?bxerCwZKdG|N@m8AR51HcBPi;Ic&-3Vf%JQR4kV;Mz)KEW48gqy8@S zP3>LBv;IkAGL8K+Ww{*>8kY+dx)bqmGPCPz&BzW|yzFKa!Ii{R-QWwSojw}Z`Kq-^ zbOP6JD8wOZDtL8qw5|tjq_EQW8f^G4_Z(Iq+#MK7D${V!hxSCIlRR5pROhS+Z334Z z1ndS_!&$}3$B%ua9FCg~xA+g4w)ngcVsDna5{Z1YFmP?P?3L)XY8iHlO*nFxm!rU2K-sp(?znG^8Kjza0_N;@!uYt#@c9_^T%;l9cM2H1xTAGx{cO{ggmJ`?dXNGW)vl;POZ^l zZk|Q#gb#lmIeVEExkxMK+7JdOQeeLdk}r|==9{l&DA*_O%AlcVK9BVHxTnu8L=z}i z-`AWSv_bzd*G%zkg*T#3s{TwopN6Dl@++J%M=zdN)58XQw8igYzo3GqfIA2gzIbbW zvD9d1PP>-x!pbE@atobS`tR<1%1<%N;E(@kuq0`j?1lB3*Ah=?zDju^x=i~cjY3Co zctp!qa0?iNunrpXoi~3n$4wgzb)L89%Pt{D%5&Xps^e+zQnAQpFE2TsyJArl2aP8sO}1Ce5c_tiI@xUzlz%%wFA&qmof z&ms?^isqL(7(P?{l&EUm%4%sYOzPkB!X1&iYpDbmq<0#-DX_5*7OHW0=hvkhznWJ| zE%r@5-^QNM{voJXrbEEoJ?m+pYSS=x1_Cne#~LR4Dq%?~#D zE`gu)i%u=*@^qK&g31u1RWkr-5}Uv}%k-oGDV+rBA>y|oX=eHyddhsWl7Hc*Eyz@_>W7G&~IM$AceWUNm z>2Gdms3eF(rYzzbZ0M$p1j>|3jcRdbNJy5xKAo!M_KqpfzQBmUeLM^vkSu$znvlb`jk^CEU4pqW|p>qspUw#&VqRs5a+NjUldyH{!xN+T?5b zm+34Y`;c#c}w>*KdORkjLcy;)k~8MUo0 zCG%hD9k9KqKcM$S?WP5bc4P|SO*QaH3VOdMh@P<=;+rytra2IjHT%V?Wou5$R@!CX1KDD6K5a^)tfl<*iai*+svb zBt2}{h1;{3`$KgF$tLFV7+G!L2Gy8qnPu0O1o=nuHUSOg21yMz*9qJPllk1IPQP}G z9A@f|8=h_5mb=Xn2ZNcZN8Po1o8{zwVT&h*$jM#T5LD+BcAs7)pKeN?nU4$Z+IVmlW?dK?@iT9?@s%8uwf0q+uBe*i0DthMW#LthjMG6rmBS7S49ebgK-Iq1g*qgDwJpa`)JXBAQ zj#}C|*87?dLkQuXU?z72iBif_yDwi82x0HEXlG}=(ou6W#CQWju^Ey1um#BV$ zV9?}w_PRm!zwKostP9eMO+WB=&$hs{{i~A!AzLs-)zf`LS0KF6j_@K}DtqONsq?|Q z&A!rx+~y;QZ$ttXufr}Am;N}+Ev{`Oz=bEY`>CJb9jLFUJmPqz87(O(>10H?Wz!x|lL)sY_@M)2hk@2?m{9Z%8RaRgOnY00T2Ai87wfn4vUS*425qta(V!TKp_1UChh97 z@M4IrBn!V|VtC{*%Tkx?*#4c52#C+TXC!mxu{l3Du#^}KV}5@8R`i7VuEp1pZOhT2 zk{d-y)lEC@UBe=#kJABS?L|kaS;IQ?wf?IF>U&jCS0+TnYFRR^4|+?>%P)QW6)>n? zY--|QWB*zRu~-Zy+hTXW z7`hFA;n-E2Z$9j+$fo{cE|KtFL!yY`3M~({*;IMscuHHbK8l+jCE(XsgQ0TqN@yei zpCh3_1^=Sm3rEoC38MJ%+dMZj%H8*$IzTZ4cwZmu*s+1zeTCi8lj8s5G;9D2XV_-^ zQb3#lUkOcyF8iYxZwQY>lP{^1#9w8YB5tkydiyZu1euazcmwuMgL1Yt0JjB~$)X3s z2^u?NY$mF5KECYwJ~=&M5;Xu)L3H6|DBBzQoHGaG2M}6Y;k=T($Rg&(`tzM#{0o(Q`IjvWe$aT#(^!(mw_C7!_zY*~LSX05d(L>;1Q2U~ z(M&hpVxWO+X6r0?RWbe%{NZQ# za=P%P@UCf=js)e2k|x@VeOaZh4F#TATME!Qn9rHhz@UC79 z+N=y|1R8(CBgU&H28UlUBXP*jweHOy#`~Q8WOA!Cjn9=M z{EBJ(MjRLPZo?%2R#s$ZJi7verYQ^jR~VWFCrf6k6nFQ0|J&J`v(=n3dg-$1jY$rj z&$+X60-CYt{&n!{!d1+e9cW_4Q=Mu+_p~o|U=}%<7Y#ZPpg&NjNM~=h5bE zHI>cJ^K4%wmJ0S*uKb6a&}_LMiM<`0MLl!S{sE~selq|orH{U~#dkC62qj8X@;Vv~ z#fZGmzP^&fW=k@B_x9{YEP%lH5kRm0%h|Yye zGOtg>bx^3}58~&CY6RU03xr;lSFqYNS7?=TUmb`PmETAc=sf&g-+kg2C43$tczPZ) zO+d`<%q#Zz8QQYrqOoc;)pA+0YAh=LeW4ZQSwaVotlf*od*~V$ih7@U&*XBjS*9`X zA_zfNdeWqWF^DNb%U{ifxU3Hrzz`-p&e%tYeDv!28>CFnn^cj7c6f)A<)>X$$2NI} zbDbYO(qnB9-zH9r$Y|NVZiUc_;|(xpBYRXD?^GE+P~D?+FU-=< zm59%EGK=Muc>rw-^sR%Wosyl5EeWSJyu&R$%^~xO@8w|mFn%<)GNd>Vq=wlMFs}FL zxLAJ|KP{Zd4`b6~FtbH`Bd3jJhqGaYw=6TzXodM=rXc8M^cO6ND#S9U))6*tfaP^JzEG--7ioe{!kROb%P-N zAdez4fkCANn{w+|1kt+t60*{lr3CI2D$~ahpGEj8iE!Cet=1%HnSWX75a6p*r3Iac zt1fFR{j_(pRE|U<2RB1_;#qA}C-#QgS43XCH*|s^Z;r`97FZlKjM3)JL;^k(5$6@v;CTYoT z{c?xcb^4R_rEQy+?Pl(-aJ`%Gp0ts+Q0*TVhwI{*pRCfn$-CE-A>GVl5Yx?vX68q~ z48M&`e+v!rO2~MGci>9b`*B<{ctG2=F4YOX-xW9(c)6pEfC3oB?b`3Zh3d+D=Cw}KdH z95(VpCBmEeD$mOXs{sK4j4SX1^;M@*5i@A@$$)pYGriE9a|;hSxn+pJiP+xFg&pH@f+P!s?aTWyRGmG!En^aAX#F^b3PoDbQ$N?!n}{`0?Sx&uulAY11nd5ie|s z3tTqcCHRsUV6uxq_0(GOpiN7YcH^$T>n z*zGq~^ob8y7)pw8Q~IZ#Y*{9Tlz%ys4W}gQfUkcGdRxyAoTIlnUk3pWWj4ovcD)spV3=zG?-C zo1gbi9-j2-ZU}2xuVl0ZQYEMkq72z{%I^HyyD4_9km%$)xN%y!S?&I!*p_kpZ08M( z$gk~ke1saiuJgn#J)Gl4XrnKt&%E!-4kJ@-CH9xy>iyM@xp#X|)MZR;gOjY_0rBhC zZP=Bx-?W>1&c}R$MFv2^}kvAS{qv|Exkjw8hFIpl`Tz{e$yjIJane z8I~fRFMUo`eRDBcAUFsrekwIR%~A^Eb>>!=H1+9J#^ND}K^myXIErc_FR=unDv8;(A>v_y_kP(?71|k|E z3tY(KxF}vm?jE-dDTSx$PLsj~t4NO5l(_)aRg8gg;H?Jc7v%~no zA@9Meo*s;Y=ByS{lxuhjEujQ@M-~H5#HvhMlE)LnAu%%37p2bUO3AZ!{F!Z7fa|bc zi})FT3saGhfIxKh45&)RkF$JYp}g#vkq=H4lCefDn1ruc3LS&Criy>Ql1+T;S?Adt zoU()a%+pD`-|`+6+%Wv!@@bEm^YU}3kk3)-2c%|rgc*rF6*Kmk(;Ec}2b}HLqBKto z58~Ds)=2MPt8Ci`ljg~u`a9jQmqKc(64SA@0&1#}=hSlDq$VG)Y(_QqL{9wq0FN@2xxM)}>qhQ4f!V z9a?y;!>@SI?3rS0*^PjRe9zopL6xFmzwrkSwd@1W@0!RVwP?#l8F2c})uhX3ZTiVL zUYBOnm)c|BViVWDTOEfbXg|mTgg?>Z8vqb zc=qdG3wYn3d4bv5k_jE4e`d46mA*)W5p`97-oMp5nJwSw=m4iL5PxcjKyRnX>hJ!R)SGSirQrM;87u8R>d`YcaOW^m)2 zWm&K1?$M{PBG?NB3Tw7oIbowlDE>g)sa1hx#6f<0S5FzV`yZ|>%W=Ka?M*LfPO&=P zqS2#1E~YARi5em{$Pg$*=B0)`rN21JqtYlz_OfBRgSbms4o138RG6TI8g9-s3cy&n zZxb@r&~D*R$x=I6c+1WOOY3VjABEN_KTxgH9fwdxd`)THkV~5xcZ?Z6vyiD1UJ7n{ z6}hk4A}rRD3z2p3Ye{;~NH!+__Ub4A#kow55LL+SiKVGUbw;{JR!Y|r$#h;QZeFfs zC>p+M0%JZo_(7al5YpRD)rtw#q6eu9_ydDKM&hT|x>`&+Yt?W__hjVxd(-O9;XDax z*_9Ow52CPu_RTVDH5IN+H%elW{Ial8 zFZCx92aaBI&Fxv!dhP+>+mJ%g{$RYr|%ie*t;WV%$r!)WSuZ=|a{$)%0J!XkZNzcHxHO;4e)wXgyXa-Q zpwN#7Co@^iX7BVQ?rU zm%(;o4LuVBB?*bSw#G_5W(TGW4DZRf_|c;!n#qxmn%T#JX)$HNQGtT&Jx?0$VwNlG zN(tERT=c!kw1pMxR=C{u(GD>MJ-Zb)Q4~Lr4;UOOR3aa9E`RbP8ieG7U$H5#N3GM$ zUhN-iK4p9sfQ(FO+ox3)iDy}3Cw;cqt5B|n@mS_V3P)O-v^*kW0ZqB{y6VKomuP^~ zCu>-}0QNw^bHoF`7LR)}Bt8^->;ee%cC02>NiRxBf|H1t_LeAAWRq|vc7I0&9(g5m{Rs%V|#@*22Uj%6){ z%emiLh=5QcD${nbs=`6#=#WE|@X|hQc#^?D;yCu+2c%z@{Sd)IYrd#m%$}Hjp%8DNzVFs~F|^9q6a{nKLMb8M?VZ^MJly@qpr`o`OXKWi5~jFV0Ao%}Y4Auoz+ zJz5*;;nURjtk&KLrNFN=z;_V~%G>w`v6m@tQwi~=(t`D5DLzXVF}_FHUnERz1MY2l z_kik<9`*|h+jPHT^(T4#!R7N|_YaC6rcTdasY@s{{Zg25XZqQ+pnBD0dVq!-0L0jr z1aY}8Yk#pl3fpMtZdba=bL(kYrPZFiax}vD*B-dX&92lh^+OBl97Ss22@K@9ro90z zQ>NtQ*5gkmsw{9r4T;zc@8B;a;@&FEc5?g8XIQ15YgO_eKlgmi#o&L`n-(+WJJBWd zFkfLqX}s>SyX->|Y; z&Hd|icmCNYI4n##u8$3?Tmuoze{eryKwr8@L_#B|8YykD153rls%^=&8K_IBI{9gY z!%isl>PhuFHP=9BxD{Vzk(0xM4sCy_47B4*-3V44`x?W;}?={BtJLC5qRnO zsk_C?yh~nJ>+I-hF#;z{W@rOp(0nh0Nhn;JMquK$lxMTKg8oI zp)Dk!4l*Gmfx#W0pZSzKbYP3_OSzlnsa$BMbuK1jP0m9pSa~0c0Yeu z^z^&x1_!ViAdE~ArS2_n@VODT87oJ4c~yFrJx2r`d*Zj;mGqAE362qHc36&kvrA^^ zhSNG@7E25h?Ahg#B{l6R~sTT zB^u`$)5(hA@7-8I7_>gfx3;!oSy#K*?-4?*LxBaM`ojI91FJJjq?x%6(*P)+TipR( zWUWxo?;1lotm~?Lp#7-6+ zDbZL5!GIlM-#Ihnj=JZNA(g zzztFcY0dXtVz2N1UdZp|Xv)rk(MyG3vICTxQHZn_3DHH&5Uh`ilw$1r+lS(HPOH`7 zUPiZJ(?9FCMdY#^&Q9a8ds?1C#JPfkAWf5fuR5HNbr6iGp#vG{$hUVrK*IbV@=QZ4 zf4+zD*iQKx4k_Hf3n;%J4^&ET$KF3H2kQr*ftDk=01{KYeEtY{9@JzRD7bz~p3wKt z8&lz`aEUP*`D9T(r{GN_FR!__g+aGzzH_ ze2z;pcUa4*{-P3zA8XU8|Ltu~um!0EnMncR*Y^>t#em{k?aL~pS1V9H-Ws?0>hSvB zKU=gSl0Z8Mo_>Q4v?Q8 z^yL5m7r660RG^Rt#)LlN!OledLtGR}YO;i+^No3 z>Tv3$cAdWtuM*O9xi5EAzynF^At8T^g0M+jZadAdQ)P~wA>@&G+s%^lJi|*b;!RFD)*b?A=oj z$|8yWm)ziuGuA1qF@HzT3aY?mDh!f#F)GyAuezb=@7wW3+0$k zakNS$`_~qOaD<2d;pG4b#p^e5ttt<0rFa(dh{smGJ&H8guyWVr`;I7?(QODeL#$J6 z{SZ{=`HhIbZ2U!dN=PcF#Zxc?BG9lh=Dh32j`(;;RmCubglzUT<#+wCEQLc@*4BzqaXC+1>GD)|B@ao@L2%xDEl6CRrv;z144br1_78l zZ>;NWe#dl5;x+0Y0R;s)FcEE-Xa=Ynm%T9-sP=7S0{;@TWa#1UuH)$T9_i0Wg}v$-V2q@&IGRuYpOCq1PZU1_(ywX%z#ajzm2hjd>S+=vgaie* zUcDRpn|0$w0eLKdtW>$~KGzSNRCaEIpRzxM@**Rgk#pEga3)~5ZH=+Zrt?;qSU+xn z{HrniUgMkspTk-~X0Qk|4@$vDFl)c}*6aP^# zyaaxv-lu*)%M6sjz23s5A8|xef?<&l{^55S`U#-QiwdFuMlA&`?HlV~41l-)u}MM@ ze%Bp&0Ob~7ICK}y1gzsNTOnV+dxphTkPB9UG%8NoKftDG0Io_4Ts$2PP z5B(2Qy$=(uv7I(Q+86=n{))jK8M5`(SK{aQDAF?T{tja9zqah_D~u>|eM(uXR~L&x zA}I4CmYU-f>#scnDfI4_NdVQB|0>~I#R@)ib%+aU)`${qR zxD`l*+xZwLR6FE$LZJC@k&5%iFg?H5c~zk1w?$Durv2-ScW0FXP%sOCyT)%n=gY1(_g~X=%h>iZhydS&u?NhW z)n|l(608_99ltRaHZov_HYzfI;K_UEWoMJcniKu@$p1??QBpsIyU6{ZD~^2ZaQ+J& z_$m{qjJnNSi=XrEj8JUme-cXn*+4lR0?`Lq#%A#=;5A}d6L_^6vSZn^0p*N_fl&Zp zbOpwCD)j#qGc2~umTa*AbAURFW&NG9Ee_B(2r83<{iE6Ya19&yDMS7Co}g>yUvGSl z8KF)S0MOira(|`(|J^MO{IV!gkpjSh$#&%3pw9P?!E=!kMXgcD63zhg?4@9_RP40^ zc*N}gxD33`YgjPMnA^k!7>s@g`qyuW()y8$2lZE346U91S_CdbiV=_)(Z}~fe#icS zZ{G9+*KOgHGw3$X{I5H+i1UEk`hh|QKfZsDg8||gA2d0uW&UgMZAJs{(IZ*lOmg4& zYl9}1fA+HVre$yb>w2Ha4T!4Z4%)ayTNnVZGcz&0y&XuJApC{?524DX5GkeJW&@Qa zTK;TtzJ(U6oDfku@^Q}dM)%uncd0@1%=79%ufGI){NCHge6ci2new!X>13Fgm;swP zYawD1x9$m6oG-K*NMZ?VnQjfn|JAcNr&lMlz^#FSox9!c+!q@XNg^Z*kTp5@1O$da zzVvM}LeyWsWP$_oks{__-rU2oj&!>mD*rR*;wk28hmKp$&Odd;mKjgzYw*qd~y7 z28be*z)jHk{F?pFAAJI}8x@=P-ZS<RnQNTYun4H!UPp@V^R&L}Byl!Brd1@d3rTk@Pqk$l(2Hk&X4&s+Pe_155 z?6{UJ(BlJC63{w7(7uBGy(I%$2WZ_P@Gs(jPdl0a6$ARiCrd*9%>FsNjdzi;x!XN6 z3`fbZSP^5LrklJxIx~d?fanQ5cbYf)!^HMfh(1?GgyQB`u@!J~w!&>K103stY-0b56<@Ty&Lj@V{2jI{d^=jD^lG$35>G$scbtqXaKH)5> zJ_>gkyHmNsZv;wZ@Fw*{&M!i^@@sHH_jGAx1M-ron{>#VU4gWnE%*iIN zi>Kx5OM$of7%5N$&;iL>TwWa zD+3f5i_^XN>J{Njq<z)1nkJte+s$>a!{eMbU8$^z;cBUTs_pnEiHXwu4Zgh#1f!9&Od9*Oa z|M&)ptOg*)e3c9QPt{zBpbJh)YE@FLTkkGJ3OG7od~xwk1?-v5|G0txxET(#1YotV zfhvI2zGFqpeT>Bzud-0nScd*z$EF1U7pyhxHUSs;FHZ#&7K-Hl*Hh6fd#(T?&s)cL z-Te-IOg)20T9*7z|+>ixGf(2!fwK1K!o2z(q1sFv&SEeir+HN|)(Wkn&n2@D$MdvmSoHMaUz zuW-HpXk6bBY+%GuxNIiy{ChSOkum%LtZl8^0gV^H_~W!5V=K{bs3zXNulv_N4sd)8 zIam$4F%ZdGfFNpo&`a^YxpLK*A^jhA1Q}C}1RJ=-#^P_*z15PFU~HMjFYNze@&?!4 z0&rsDf0!J4|2{knpK%bldm5Hh|HFp2jSJN>A?53TeJ?=7j<^4x!01kEK@_eO*lb%s z3!q~Wus57wTsp`#>j|2E$@}-*$>y|wM*tw7CGn=GB9gcP384!IEEc3~6+k+wdTT-Z zuK>_Gxdlw9E(T^0%bMFW$etMTKC@+evZmO2{39pGTrg;q#E)E{q5P$db)djW?1Hsm zVwIZ!%akVM!Hv)Qd@9m4tn{z5u(Y7XUp22cKXr*p{=3{qiv z5V;2Y(WIQM)u3d|pq%adlHeP|ADS4VKq4RWJq5`YkpBv(Y$FhDvAhS;l+yS_&p@yV ziU56aWm`wHxGbw8bm6$B=bGl)A|9^e_$2sSBp7Si< z=llIF!+dx?6a{_N{zJeFQ{%wx5>@xo;QTSd>k_v=d{-Lqx!y%{F7)oUdG_k2?J}SG zi;rOGGU37BMsClZ0L-5a_1MYlP(B~r(y`_O6KM;3-J*5Y8ksXCQ1%E20n{wGa@A}FY@gq4x8dK@ct6LR2Qkf?_JlGy;OH;4W8~ECpD84Nwo3iHgwM(ElB(1s)}NuaJZ)_{$CA;ez7HfkvfV z+uJw=&nNF5A*{_Av;k%E@=~ddrsLvqsi~>y=30D&1%Zko(BHX1hIR>nz^SB6{SF;Z zYKS3Bc33dqgfSPS7TfE_!lvy*J%nP2GBXtL95-ObUE|#oZTYVZC;7%}zmp5Hi)|Gp z2(6Q6D6cDm3Lp?h=u#R7fVB{RiF2B7{jqd4m@V*P{K;`V_p%TzBEoK+4!G3#WUsbB(ray_MYpa z3(6sXtBv}RJzSr~SA?-^-MlU=qB2k|z_txJ=kJG86R}8Aw8V{dF7aBpYrA+j z&=Y$h$NSC6MWIuNuc{je3+5?Y-at}*QypdmM72}mLExzteK@5ie2Hj(UQtzJ+HF{y z&&t7Y2sN=7*M{^oM1;8(GLa$`jA>iA08ypXobM%91Ptd2Io&WlC#EO*!2KsvVMgH5 zK?{lvoqQ)Mz}GDy^$r$?Xa|kE>iKjF1qBAKqAaDcezH4%A+oxyCIe1P{$GFy%t0n> zMbQLRdc%&`6(ZMYF7r)>BEGz>=wP)n=HoB5_>1H%D7uJ-1Q=__$jFGuI=*YzSv#fU zca~NL3`3v2@Np5e=iBpqN8|osI7_}F9mK9EOa#30VcaVHfc%Yma0KP*8oq!7?wJcS zw{44@4HL8cAo0rX#sUrfFmgM5^v#$dI4)aC7IqEB^srK;f9c@GuxLny+Ku}0yB<8n%NJxXHK$G+ZQ2SZ46ILfmn6$2)r-!bG!$u*PHc!yzxQw{R#XAR}ZzE**R#^dNh!ln4Y>tyu=t z+b>@RNP4~>(7%udwZ;g}(xyzF#J%e6?KNv`urGoSr4;1@_b$dIZ$1(|Sl0?C3GqOL z+KyQqDFH7ccrG8n)%j>~S>oL6ckio?3ft-LdLVm1CkB_O1L z(S~*qV1p^#l~k?S0}7J$F?@S>DAD!Jp5{BVehs3grr2aS+} zR5$4A?z>+u>i{aurp*^X(Tz#0In4>l302*dZjeH}qJ|+ZT9-TeL*Rl!?jUTAu<~Hv zi+}uvX6PzDT7no#5~m$l4%lQlizv0mAW#d>hjdJE$wpz@fSXH1B2Z3F&PPKVCkx7p zNmV4>1FN-8a9~pjh%bYjYNM6{r#8y6L+*=_OE*Tv``cCqko~KT6clLLRw+15P5Jij zC}7kO<`j#=86!RGS&4OxAdIO(KS$-u|Ki&Tp>rP1w#>+ zjp7w@PRYG{I0==X}At@=T zq`Z7Xh4b3A^H*VS=?l)_KFrQm^$UF+9LyaW8nU%fl3@_(hgYDmqZm&zIc2VNxwts& zAmEpxAi$ncR_5mEnO|~-OSg+&`3Os;?&iLKZ_?V@ zTHmJl^=|mrul}FYw=6z*G6~b4YAh-$>KhWG&f#!Mm`v5m%F4#qulENP`?PN~uNQ3deYc0KFwSFQQ^=2&XYL8X)a{z`Rqb-n=s$^cxR zST>bKUb%9`^~jO;<}acjP26N|1v7AQfk8o%GdD-3rpgVrZ6lsOUFPTK_jGcSSw?kH=CTC ztaaW+Q%%hRvibwXM0l3{#dYQK0^vH6fni}=idJ7uPk;XSaa2cV=d-r9Bp>b&ErCbu z>Fdjh`{>>?OM{(WG?xummgFlZYtSrMCbK}ew~@Ho63}pXD{p1U|pgAw~9-hODOsqzK^J@ zGup|m3QRZYr{p?yyK6$O3P+Ox+gPxhM6VJOmfq`>*??J_eJbFZE`TX?Sz9vl21L4 z$8$Y)%)-pftUj{XS_bT2_C8*XyyR?wwy_x4&`y$V^tr04YIbViH{G<(#=D(eU0wCN z?DaRb#WjU|FHK9ye#`WqoMyKaS9qyN$HK~|)=;9#aeqhu(9MQ#554vyOBjs|GShAh zyO_vk`ClNf`e@Z@-PAJHbN%IiAnv%Aj~s3&H?R(_$Do&YhkP$SHSI0-(jy%- zJXJc>%Oc&adXcGiY2Wvp_JYCLeNVjNJ~J%j$}YHl?kn)lV_>q*x(2C;P-gzd#Ic1k zf;s1RVY9779MhUD4O&jCG<1Z7jkDe~tL)WLU+F08uw{iqO5Vpha>d#~RLhwIi5?x< zcVi{Q#FEEMWp!j2dUtSckq{?rJW9T=(O>Pz*a~y)-VFDxg+WI{On94fTE(%X&yg|* zIA(IPc~0y7KDReD$&O~%noQZq6xc_MDJ1P|B~@G|aja+98QV@|a9-YFXK+rh%xyk* z-)>Ko!KJ40CUN(;Q&$XF^3+GIR~gya3xWB=XIW@2y(RyFs>VW~BXP@?LFsz3JWd>6 x`Xgn`U($R*K-`J7=0dkIa_vG!`M=(JblGN=?(TePk9Yz2vD{&8T4?M-`!B2(&OHDC From e19b197acc1ad6bc77dc5cec19e369ca03ba4a46 Mon Sep 17 00:00:00 2001 From: SofianeElNaggar Date: Wed, 20 Nov 2024 16:47:15 -0500 Subject: [PATCH 12/18] add data exfiltration detection rule --- idps/rules/TCP/Scan/dataExfiltration.py | 50 +++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 idps/rules/TCP/Scan/dataExfiltration.py diff --git a/idps/rules/TCP/Scan/dataExfiltration.py b/idps/rules/TCP/Scan/dataExfiltration.py new file mode 100644 index 0000000..cd64b1d --- /dev/null +++ b/idps/rules/TCP/Scan/dataExfiltration.py @@ -0,0 +1,50 @@ +from collections import defaultdict +from scapy.all import IP +import time + +data_transfer = defaultdict(lambda: {"current": 0, "daily": 0, "last_reset": time.time()}) + +def rule(packet, _, db): + """Règle pour détecter une exfiltration de données importantes.""" + global data_transfer + + if IP in packet: + src_ip = packet[IP].src + dst_ip = packet[IP].dst + payload_size = len(packet[IP].payload) + + # Mettre à jour le volume de données transférées + current_time = time.time() + if current_time - data_transfer[src_ip]["last_reset"] > rule.reset_time: + data_transfer[src_ip]["daily"] = 0 + data_transfer[src_ip]["last_reset"] = current_time + + data_transfer[src_ip]["current"] += payload_size + data_transfer[src_ip]["daily"] += payload_size + + # Déclencher une alerte si un seuil est atteint + if data_transfer[src_ip]["current"] > rule.seuil_session: + alert = { + "type": "Exfiltration de données détectée (instantané)", + "source_ip": src_ip, + "destination_ip": dst_ip, + "volume": data_transfer[src_ip]["current"] / (1024 ** 3), + "threshold": rule.seuil_session / (1024 ** 3), + "time": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()), + } + db.save_alert(alert) + data_transfer[src_ip]["current"] = 0 # Réinitialiser pour les prochaines sessions + + if data_transfer[src_ip]["daily"] > rule.seuil_journalier: + alert = { + "type": "Exfiltration de données détectée (journalière)", + "source_ip": src_ip, + "volume": data_transfer[src_ip]["daily"] / (1024 ** 3), + "threshold": rule.seuil_journalier / (1024 ** 3), + "time": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()), + } + db.save_alert(alert) + +rule.reset_time = 24 * 3600 # 24 heures en secondes +rule.seuil_session = 5 * 1024 * 1024 * 1024 # 5 Go en octets +rule.seuil_journalier = 50 * 1024 * 1024 * 1024 # 50 Go en octets \ No newline at end of file From 6efbe6e2e4b6dac42a0034d5fb5eba44dd349ce1 Mon Sep 17 00:00:00 2001 From: SofianeElNaggar Date: Wed, 20 Nov 2024 19:02:42 -0500 Subject: [PATCH 13/18] Update dataExfiltration.py --- idps/rules/TCP/Scan/dataExfiltration.py | 46 +++++++++++++++---------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/idps/rules/TCP/Scan/dataExfiltration.py b/idps/rules/TCP/Scan/dataExfiltration.py index cd64b1d..9eab908 100644 --- a/idps/rules/TCP/Scan/dataExfiltration.py +++ b/idps/rules/TCP/Scan/dataExfiltration.py @@ -1,6 +1,7 @@ from collections import defaultdict from scapy.all import IP import time +from datetime import datetime data_transfer = defaultdict(lambda: {"current": 0, "daily": 0, "last_reset": time.time()}) @@ -22,28 +23,37 @@ def rule(packet, _, db): data_transfer[src_ip]["current"] += payload_size data_transfer[src_ip]["daily"] += payload_size - # Déclencher une alerte si un seuil est atteint + # Exfiltration de données instantané if data_transfer[src_ip]["current"] > rule.seuil_session: - alert = { - "type": "Exfiltration de données détectée (instantané)", - "source_ip": src_ip, - "destination_ip": dst_ip, - "volume": data_transfer[src_ip]["current"] / (1024 ** 3), - "threshold": rule.seuil_session / (1024 ** 3), - "time": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()), - } - db.save_alert(alert) + db.send_alert( + datetime.now(), + 5, + None, + "Exfiltration de données détectée (instantané)", + src_ip, + dst_ip, + "TCP", + reason="Exfiltration de données détectée (instantané)", + act="Alerte" + ) data_transfer[src_ip]["current"] = 0 # Réinitialiser pour les prochaines sessions + print(f"Alerte, data transfer, transfert instantané important") + # Exfiltration de données journalière if data_transfer[src_ip]["daily"] > rule.seuil_journalier: - alert = { - "type": "Exfiltration de données détectée (journalière)", - "source_ip": src_ip, - "volume": data_transfer[src_ip]["daily"] / (1024 ** 3), - "threshold": rule.seuil_journalier / (1024 ** 3), - "time": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()), - } - db.save_alert(alert) + db.send_alert( + datetime.now(), + 5, + None, + "Exfiltration de données détectée (journalière)", + src_ip, + dst_ip, + "TCP", + reason="Exfiltration de données détectée (journalière)", + act="Alerte" + ) + print(f"Alerte, data transfer, transfert journalier important") + rule.reset_time = 24 * 3600 # 24 heures en secondes rule.seuil_session = 5 * 1024 * 1024 * 1024 # 5 Go en octets From 17a6e3def21e2dfd36d25f58e5a984f8b61f5534 Mon Sep 17 00:00:00 2001 From: SofianeElNaggar Date: Wed, 20 Nov 2024 19:41:46 -0500 Subject: [PATCH 14/18] update dataExfiltration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c'est pas encore ça mais il y a de l'idée --- idps/main.py | 4 ++-- idps/rules/TCP/Scan/dataExfiltration.py | 6 ++++-- idps/tcp.py | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/idps/main.py b/idps/main.py index 664bb47..3a8f88c 100644 --- a/idps/main.py +++ b/idps/main.py @@ -91,10 +91,10 @@ def packet_callback(packet, rules_functions, tcp_packets, db): @param db: Objet database pour envoyer des alertes à la BDD """ - #print(packet) + ##print(packet) if IP in packet and TCP in packet: tcp_packets.add_packet(packet[IP].src, packet[TCP].sport, packet[IP].dst, packet[TCP].dport, packet[TCP].flags, time.time()) - print(tcp_packets[packet[IP].src]) + #print(tcp_packets[packet[IP].src]) check_frame_w_rules(packet, rules_functions['TCP'], tcp_packets, db) tcp_packets.clean_old_packets() diff --git a/idps/rules/TCP/Scan/dataExfiltration.py b/idps/rules/TCP/Scan/dataExfiltration.py index 9eab908..db616b2 100644 --- a/idps/rules/TCP/Scan/dataExfiltration.py +++ b/idps/rules/TCP/Scan/dataExfiltration.py @@ -23,6 +23,8 @@ def rule(packet, _, db): data_transfer[src_ip]["current"] += payload_size data_transfer[src_ip]["daily"] += payload_size + print(data_transfer[src_ip]["current"]) + # Exfiltration de données instantané if data_transfer[src_ip]["current"] > rule.seuil_session: db.send_alert( @@ -32,7 +34,7 @@ def rule(packet, _, db): "Exfiltration de données détectée (instantané)", src_ip, dst_ip, - "TCP", + proto = "TCP", reason="Exfiltration de données détectée (instantané)", act="Alerte" ) @@ -48,7 +50,7 @@ def rule(packet, _, db): "Exfiltration de données détectée (journalière)", src_ip, dst_ip, - "TCP", + proto = "TCP", reason="Exfiltration de données détectée (journalière)", act="Alerte" ) diff --git a/idps/tcp.py b/idps/tcp.py index 0ee21f3..2029ffb 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -34,7 +34,7 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + #print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("SA") self.packets[ip][i][4] = timestamp return @@ -48,7 +48,7 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "R") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + #print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("A") self.packets[ip][i][4] = timestamp return @@ -63,7 +63,7 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + #print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("RA") self.packets[ip][i][4] = timestamp return @@ -78,7 +78,7 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + #print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("R") self.packets[ip][i][4] = timestamp return @@ -90,7 +90,7 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") + #print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("F") self.packets[ip][i][4] = timestamp return From d64f7283defce0fd2330851a600fd806fe344999 Mon Sep 17 00:00:00 2001 From: Oxbian Date: Wed, 20 Nov 2024 21:38:37 -0500 Subject: [PATCH 15/18] =?UTF-8?q?feat:=20syn/tcpconnect=20flood=20/=20dos?= =?UTF-8?q?=20d=C3=A9tection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.json | 8 +++++- idps/main.py | 2 +- idps/rules/TCP/DOS/syndos.py | 36 +++++++++++++++++++++++++++ idps/rules/TCP/DOS/synflood.py | 36 +++++++++++++++++++++++++++ idps/rules/TCP/DOS/tcpconnectflood.py | 34 +++++++++++++++++++++++++ idps/rules/TCP/Scan/ackscan.py | 6 ++++- idps/rules/TCP/Scan/finscan.py | 6 ++++- idps/rules/TCP/Scan/nullscan.py | 6 ++++- idps/rules/TCP/Scan/synscan.py | 8 ++++-- idps/rules/TCP/Scan/tcpconnectscan.py | 10 +++++--- idps/rules/TCP/Scan/xmasscan.py | 6 ++++- idps/tcp.py | 7 ------ 12 files changed, 147 insertions(+), 18 deletions(-) create mode 100644 idps/rules/TCP/DOS/syndos.py create mode 100644 idps/rules/TCP/DOS/synflood.py create mode 100644 idps/rules/TCP/DOS/tcpconnectflood.py diff --git a/config.json b/config.json index e028151..02f0cb8 100644 --- a/config.json +++ b/config.json @@ -21,5 +21,11 @@ "nullscan_time": 180, "nullscan_count": 5, "xmasscan_time": 180, - "xmasscan_count": 5 + "xmasscan_count": 5, + "synflood_time": 60, + "synflood_count": 100, + "tcpconnectflood_time": 60, + "tcpconnectflood_count": 100, + "syndos_time": 60, + "syndos_count": 100 } diff --git a/idps/main.py b/idps/main.py index 664bb47..08934a1 100644 --- a/idps/main.py +++ b/idps/main.py @@ -94,7 +94,7 @@ def packet_callback(packet, rules_functions, tcp_packets, db): #print(packet) if IP in packet and TCP in packet: tcp_packets.add_packet(packet[IP].src, packet[TCP].sport, packet[IP].dst, packet[TCP].dport, packet[TCP].flags, time.time()) - print(tcp_packets[packet[IP].src]) + #print(tcp_packets[packet[IP].src]) check_frame_w_rules(packet, rules_functions['TCP'], tcp_packets, db) tcp_packets.clean_old_packets() diff --git a/idps/rules/TCP/DOS/syndos.py b/idps/rules/TCP/DOS/syndos.py new file mode 100644 index 0000000..54480e9 --- /dev/null +++ b/idps/rules/TCP/DOS/syndos.py @@ -0,0 +1,36 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """ + Règle SYN Dos: + Un SYN DOS va envoyer des requêtes TCP avec le flag SYN en très grand nombre afin de surcharger le serveur ou la cible avec des grosses quantités de données + - Si le port est ouvert, le serveur répond avec: SYN-ACK, puis le client RESET la connexion. + - Si le port est fermé, le serveur répond avec: RST-ACK. + """ + + # Ne pas réagir si dans la période de cooldown + if (rule.cooldown + rule.time_window > time.time()): + return + + # Initialisation des paramètres à partir de la configuration si nécessaire + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("synsdos_time", 60) + rule.seuil = db.get_key("syndos_count", 100) + + # Comptage des paquets TCP correspondant aux motifs spécifiques + syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + + # Détection si le seuil est dépassé et que la charge utile des paquets est non nulle + if (syndeny_count + synaccept_count >= rule.seuil and len(packet['TCP'].payload) > 0): + db.send_alert(datetime.now(), 5, None, "Syn DOS", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + print("Alerte, seuil dépassé, risque de Syn DOS détecté.") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/DOS/synflood.py b/idps/rules/TCP/DOS/synflood.py new file mode 100644 index 0000000..520f9f5 --- /dev/null +++ b/idps/rules/TCP/DOS/synflood.py @@ -0,0 +1,36 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """ + Règle SYN Flood: + Un SYN Flood va envoyer des requêtes TCP avec le flag SYN en très grand nombre afin de surcharger le serveur ou la cible + - Si le port est ouvert, le serveur répond avec: SYN-ACK, puis le client RESET la connexion. + - Si le port est fermé, le serveur répond avec: RST-ACK. + """ + + # Ne pas réagir si dans la période de cooldown + if (rule.cooldown + rule.time_window > time.time()): + return + + # Initialisation des paramètres à partir de la configuration si nécessaire + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("synsflood_time", 60) + rule.seuil = db.get_key("synflood_count", 100) + + # Comptage des paquets TCP correspondant aux motifs spécifiques + syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + + # Détection si le seuil est dépassé + if (syndeny_count + synaccept_count >= rule.seuil): + db.send_alert(datetime.now(), 5, None, "Syn flood", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + print("Alerte, seuil dépassé, risque de Syn Flood détecté.") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/DOS/tcpconnectflood.py b/idps/rules/TCP/DOS/tcpconnectflood.py new file mode 100644 index 0000000..ddb34e2 --- /dev/null +++ b/idps/rules/TCP/DOS/tcpconnectflood.py @@ -0,0 +1,34 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """Règle TCPConnect Flood: + Un flood TCP connect va effectuer une connexion TCP en très grand nombre + Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset ACK + Sinon le port est fermé et le serveur refusera la connexion SYN -> Reset ACK + """ + + if (rule.cooldown + rule.time_window > time.time()): + return + + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("tcpconnectflood_time", 60) + rule.seuil = db.get_key("tcpconnectflood_count", 100) + + # Comptage du nombre de scan tcp connect acceptés et refusés + tcpconnectdeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcpconnectaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + + if (tcpconnectaccept_count + tcpconnectdeny_count >= rule.seuil): + db.send_alert(datetime.now(), 5, None, "TCPConnect Flood", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") + print(f"Alerte, seuils dépassés, risque de TCPconnect Flood") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 + diff --git a/idps/rules/TCP/Scan/ackscan.py b/idps/rules/TCP/Scan/ackscan.py index c210738..3b321f5 100644 --- a/idps/rules/TCP/Scan/ackscan.py +++ b/idps/rules/TCP/Scan/ackscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("ackscan_time", 180) rule.seuil = db.get_key("ackscan_count", 5) - if tcp_packets.count_packet_of_type(["A", "R"], rule.time_window, True) + tcp_packets.count_packet_of_type(["A"], rule.time_window, True) >= rule.seuil: + # Comptage nombre de scan ack acceptés et refusés + ackdeny_count = tcp_packets.count_packet_of_type(["A", "R"], rule.time_window, True) + ackaccept_count = tcp_packets.count_packet_of_type(["A"], rule.time_window, True) + + if (ackaccept_count + ackdeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "ACK scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Ack->Reset et Ack pas de réponse", act="Alerte") print(f"Alerte, seuil dépassés, risque d'Ack scan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/finscan.py b/idps/rules/TCP/Scan/finscan.py index 3ecf5f5..d6c4ae9 100644 --- a/idps/rules/TCP/Scan/finscan.py +++ b/idps/rules/TCP/Scan/finscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("finscan_time", 180) rule.seuil = db.get_key("finscan_count", 5) - if tcp_packets.count_packet_of_type(["F", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["F"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan fin acceptés et refusés + findeny_count = tcp_packets.count_packet_of_type(["F", "RA"], rule.time_window, True) + finaccept_count = tcp_packets.count_packet_of_type(["F"], rule.time_window, True) + + if (findeny_count + finaccept_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "Fin scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin->Reset Ack et Fin->rien", act="Alerte") print(f"Alerte, seuil dépassés, risque de Fin Scan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/nullscan.py b/idps/rules/TCP/Scan/nullscan.py index 7b373e2..6c686cb 100644 --- a/idps/rules/TCP/Scan/nullscan.py +++ b/idps/rules/TCP/Scan/nullscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("nullscan_time", 180) rule.seuil = db.get_key("nullscan_count", 5) - if tcp_packets.count_packet_of_type([""], rule.time_window, True) + tcp_packets.count_packet_of_type(["", "RA"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan null acceptés et refusés + nulldeny_count = tcp_packets.count_packet_of_type(["", "RA"], rule.time_window, True) + nullaccept_count = tcp_packets.count_packet_of_type([""], rule.time_window, True) + + if (nulldeny_count + nulldeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "Null scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de None->Reset Ack et None -> rien", act="Alerte") print(f"Alerte, seuil dépassés, risque de Null Scan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py index 3a6e3c4..9a5e5dc 100644 --- a/idps/rules/TCP/Scan/synscan.py +++ b/idps/rules/TCP/Scan/synscan.py @@ -3,7 +3,7 @@ import time def rule(packet, tcp_packets, db): - """Règle SYNScan: + """Règle SYN Scan: Un SYNScan va envoyer des requêtes TCP avec le flag SYN Si le port est ouvert alors le serveur répondra: Syn ACK, puis le client Reset la connexion Sinon le port est fermé et le serveur répondra: Reset ACK @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("synscan_time", 180) rule.seuil = db.get_key("synscan_count", 5) - if tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan syn acceptés et refusés + syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + + if (synaccept_count + syndeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuil dépassés, risque de SynScan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py index 3451fb0..69253bd 100644 --- a/idps/rules/TCP/Scan/tcpconnectscan.py +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -17,7 +17,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("tcpconnectscan_time", 180) rule.seuil = db.get_key("tcpconnectscan_count", 5) - if tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan tcp connect acceptés et refusés + tcpconnectdeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcpconnectaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + + if (tcpconnectaccept_count + tcpconnectdeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "TCPConnect Scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuils dépassés, risque de TCPConnectScan") rule.cooldown = time.time() @@ -25,5 +29,5 @@ def rule(packet, tcp_packets, db): # Variables statiques rule.cooldown = 0 -rule.time_window = 180 -rule.seuil = 5 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/Scan/xmasscan.py b/idps/rules/TCP/Scan/xmasscan.py index 4f811c5..17cd359 100644 --- a/idps/rules/TCP/Scan/xmasscan.py +++ b/idps/rules/TCP/Scan/xmasscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("xmasscan_time", 180) rule.seuil = db.get_key("xmasscan_count", 5) - if tcp_packets.count_packet_of_type(["FPU", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["FPU"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan XMAS acceptés et refusés + xmasdeny_count = tcp_packets.count_packet_of_type(["FPU", "RA"], rule.time_window, True) + xmasaccept_count = tcp_packets.count_packet_of_type(["FPU"], rule.time_window, True) + + if (xmasaccept_count + xmasdeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "XMAS scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin Push Urg -> rien et Fin Push Urg->Reset ACK", act="Alerte") print(f"Alerte, seuil dépassés, risque de XMAS Scan") rule.cooldown = time.time() diff --git a/idps/tcp.py b/idps/tcp.py index 0ee21f3..edbdf03 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -34,7 +34,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("SA") self.packets[ip][i][4] = timestamp return @@ -48,7 +47,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "R") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("A") self.packets[ip][i][4] = timestamp return @@ -63,7 +61,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("RA") self.packets[ip][i][4] = timestamp return @@ -78,7 +75,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("R") self.packets[ip][i][4] = timestamp return @@ -90,7 +86,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("F") self.packets[ip][i][4] = timestamp return @@ -98,8 +93,6 @@ class TCP: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["F"], timestamp]) return - # TODO: ajout flag fin, none, fin urg push - def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags): """Cherche l'indice et le port de source du paquet dont le flag doit être remplacé""" From dbad0e7b287b4b2148e30efa545c58cec49d975a Mon Sep 17 00:00:00 2001 From: Oxbian Date: Thu, 21 Nov 2024 11:49:21 -0500 Subject: [PATCH 16/18] feat: final working demo Dockerfiles --- Demo/Dockerfiles/Dockerfile.attaquant | 5 ++-- Demo/Dockerfiles/Dockerfile.cible | 14 +++-------- Demo/Dockerfiles/Dockerfile.idps | 2 +- Demo/Dockerfiles/Dockerfile.ids | 4 +-- Demo/config/config-idps.json | 31 +++++++++++++++++++++++ Demo/config/config-ids.json | 31 +++++++++++++++++++++++ Demo/docker-compose.yml | 3 --- README.md | 17 ++++++++++--- config.json | 8 +++++- idps/main.py | 2 +- idps/rules/TCP/DOS/syndos.py | 36 +++++++++++++++++++++++++++ idps/rules/TCP/DOS/synflood.py | 36 +++++++++++++++++++++++++++ idps/rules/TCP/DOS/tcpconnectflood.py | 34 +++++++++++++++++++++++++ idps/rules/TCP/Scan/ackscan.py | 6 ++++- idps/rules/TCP/Scan/finscan.py | 6 ++++- idps/rules/TCP/Scan/nullscan.py | 6 ++++- idps/rules/TCP/Scan/synscan.py | 8 ++++-- idps/rules/TCP/Scan/tcpconnectscan.py | 10 +++++--- idps/rules/TCP/Scan/xmasscan.py | 6 ++++- idps/tcp.py | 7 ------ 20 files changed, 232 insertions(+), 40 deletions(-) create mode 100644 Demo/config/config-idps.json create mode 100644 Demo/config/config-ids.json create mode 100644 idps/rules/TCP/DOS/syndos.py create mode 100644 idps/rules/TCP/DOS/synflood.py create mode 100644 idps/rules/TCP/DOS/tcpconnectflood.py diff --git a/Demo/Dockerfiles/Dockerfile.attaquant b/Demo/Dockerfiles/Dockerfile.attaquant index bbdaa4a..8c52ada 100644 --- a/Demo/Dockerfiles/Dockerfile.attaquant +++ b/Demo/Dockerfiles/Dockerfile.attaquant @@ -2,8 +2,9 @@ FROM python:alpine3.20 # Installation des paquets nécessaires pour scapy RUN apk -U upgrade && \ - apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev nmap iproute2 -RUN pip install scapy + apk add --no-cache nmap iproute2 +RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories +RUN apk -U add --no-cache hping3 COPY Demo/Dockerfiles/attaquant-entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh diff --git a/Demo/Dockerfiles/Dockerfile.cible b/Demo/Dockerfiles/Dockerfile.cible index 6793bc3..e951461 100644 --- a/Demo/Dockerfiles/Dockerfile.cible +++ b/Demo/Dockerfiles/Dockerfile.cible @@ -1,15 +1,9 @@ -FROM python:alpine3.20 +FROM httpd:alpine -# Installation des paquets nécessaires pour scapy -RUN apk -U upgrade && \ - apk add --no-cache libpcap libpcap-dev gcc musl-dev libffi-dev iproute2 -RUN pip install scapy +# Installation des paquets nécessaire pour le routage +RUN apk -U upgrade && apk add --no-cache iproute2 COPY Demo/Dockerfiles/cible-entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] -# Copier le script de détection d'attaques -#COPY cible.py /cible.py - -# Lancer le script de détection -#CMD ["python", "/cible.py"] +CMD ["httpd-foreground"] diff --git a/Demo/Dockerfiles/Dockerfile.idps b/Demo/Dockerfiles/Dockerfile.idps index adc6592..89f925e 100644 --- a/Demo/Dockerfiles/Dockerfile.idps +++ b/Demo/Dockerfiles/Dockerfile.idps @@ -16,7 +16,7 @@ WORKDIR /app COPY idps /app/idps # Copie du fichier de configuration -COPY config.json /app/config.json +COPY Demo/config/config-idps.json /app/config.json # Utiliser le script comme point d'entrée ENTRYPOINT ["/entrypoint.sh"] diff --git a/Demo/Dockerfiles/Dockerfile.ids b/Demo/Dockerfiles/Dockerfile.ids index 2a91158..cded915 100644 --- a/Demo/Dockerfiles/Dockerfile.ids +++ b/Demo/Dockerfiles/Dockerfile.ids @@ -12,7 +12,7 @@ WORKDIR /app COPY idps /app/ids # Copie du fichier de configuration -COPY config.json /app/config.json +COPY Demo/config/config-ids.json /app/config.json # Lancer le script de la sonde IDS -CMD ["python3", "/app/ids/ids.py"] +CMD ["python3", "/app/ids/main.py"] diff --git a/Demo/config/config-idps.json b/Demo/config/config-idps.json new file mode 100644 index 0000000..02f0cb8 --- /dev/null +++ b/Demo/config/config-idps.json @@ -0,0 +1,31 @@ +{ + "rules_dirpath": "/app/idps/rules", + "ifaces": ["eth1"], + "db_host": "172.20.3.10", + "db_database": "sidps", + "db_user": "sidps", + "db_password": "SUPERPASSWORD", + "db_port": "3306", + "cef_version": 1, + "device_product": "SIDPS", + "device_vendor": "ArKa", + "device_version": "vAlpha", + "synscan_time": 180, + "synscan_count": 5, + "tcpconnectscan_time": 180, + "tcpconnectscan_count": 5, + "ackscan_time": 180, + "ackscan_count": 5, + "finscan_time": 180, + "finscan_count": 5, + "nullscan_time": 180, + "nullscan_count": 5, + "xmasscan_time": 180, + "xmasscan_count": 5, + "synflood_time": 60, + "synflood_count": 100, + "tcpconnectflood_time": 60, + "tcpconnectflood_count": 100, + "syndos_time": 60, + "syndos_count": 100 +} diff --git a/Demo/config/config-ids.json b/Demo/config/config-ids.json new file mode 100644 index 0000000..7b203bb --- /dev/null +++ b/Demo/config/config-ids.json @@ -0,0 +1,31 @@ +{ + "rules_dirpath": "/app/ids/rules", + "ifaces": ["br-c56b595383ad"], + "db_host": "172.20.3.10", + "db_database": "sidps", + "db_user": "sidps", + "db_password": "SUPERPASSWORD", + "db_port": "3306", + "cef_version": 1, + "device_product": "Sonde IDS", + "device_vendor": "ArKa", + "device_version": "vAlpha", + "synscan_time": 180, + "synscan_count": 5, + "tcpconnectscan_time": 180, + "tcpconnectscan_count": 5, + "ackscan_time": 180, + "ackscan_count": 5, + "finscan_time": 180, + "finscan_count": 5, + "nullscan_time": 180, + "nullscan_count": 5, + "xmasscan_time": 180, + "xmasscan_count": 5, + "synflood_time": 60, + "synflood_count": 100, + "tcpconnectflood_time": 60, + "tcpconnectflood_count": 100, + "syndos_time": 60, + "syndos_count": 100 +} diff --git a/Demo/docker-compose.yml b/Demo/docker-compose.yml index 9180621..0811914 100644 --- a/Demo/docker-compose.yml +++ b/Demo/docker-compose.yml @@ -20,7 +20,6 @@ services: context: .. dockerfile: Demo/Dockerfiles/Dockerfile.idps container_name: idps - command: sleep infinity cap_add: - NET_ADMIN - NET_RAW @@ -39,7 +38,6 @@ services: context: .. dockerfile: Demo/Dockerfiles/Dockerfile.cible container_name: cible - command: sleep infinity cap_add: - NET_ADMIN networks: @@ -67,7 +65,6 @@ services: context: .. dockerfile: Demo/Dockerfiles/Dockerfile.ids container_name: ids - command: sleep infinity cap_add: - NET_ADMIN - NET_RAW diff --git a/README.md b/README.md index d8bd344..28207bb 100644 --- a/README.md +++ b/README.md @@ -55,11 +55,20 @@ Pour lancer cette démonstration, il faudra avoir `docker` & `docker compose` d' ```bash cd Demo/ -docker compose up -d +./deploy.sh ``` -## TODO +La cible (172.20.2.3) héberge un serveur web apache avec la page par défaut sur son port 80. +Les conteneurs attaquants disposent tous les deux de nmap et de hping3 pour réaliser des scan et des floods / DOS. + +Rappel des commandes pour flood avec et sans charge utile avec hping3: + +```bash +hping3 -S --flood IP +hping3 -S --flood -d TAILLE IP +``` + +## TODO: -- Noyau d'analyse de l'IDS -- Interface web pour visualiser les alertes / rechercher dedans - Moteur de corrélation des alertes (récupération + renvoi dans MySQL). +- Moteur de détection par comportement diff --git a/config.json b/config.json index e028151..02f0cb8 100644 --- a/config.json +++ b/config.json @@ -21,5 +21,11 @@ "nullscan_time": 180, "nullscan_count": 5, "xmasscan_time": 180, - "xmasscan_count": 5 + "xmasscan_count": 5, + "synflood_time": 60, + "synflood_count": 100, + "tcpconnectflood_time": 60, + "tcpconnectflood_count": 100, + "syndos_time": 60, + "syndos_count": 100 } diff --git a/idps/main.py b/idps/main.py index 664bb47..08934a1 100644 --- a/idps/main.py +++ b/idps/main.py @@ -94,7 +94,7 @@ def packet_callback(packet, rules_functions, tcp_packets, db): #print(packet) if IP in packet and TCP in packet: tcp_packets.add_packet(packet[IP].src, packet[TCP].sport, packet[IP].dst, packet[TCP].dport, packet[TCP].flags, time.time()) - print(tcp_packets[packet[IP].src]) + #print(tcp_packets[packet[IP].src]) check_frame_w_rules(packet, rules_functions['TCP'], tcp_packets, db) tcp_packets.clean_old_packets() diff --git a/idps/rules/TCP/DOS/syndos.py b/idps/rules/TCP/DOS/syndos.py new file mode 100644 index 0000000..54480e9 --- /dev/null +++ b/idps/rules/TCP/DOS/syndos.py @@ -0,0 +1,36 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """ + Règle SYN Dos: + Un SYN DOS va envoyer des requêtes TCP avec le flag SYN en très grand nombre afin de surcharger le serveur ou la cible avec des grosses quantités de données + - Si le port est ouvert, le serveur répond avec: SYN-ACK, puis le client RESET la connexion. + - Si le port est fermé, le serveur répond avec: RST-ACK. + """ + + # Ne pas réagir si dans la période de cooldown + if (rule.cooldown + rule.time_window > time.time()): + return + + # Initialisation des paramètres à partir de la configuration si nécessaire + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("synsdos_time", 60) + rule.seuil = db.get_key("syndos_count", 100) + + # Comptage des paquets TCP correspondant aux motifs spécifiques + syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + + # Détection si le seuil est dépassé et que la charge utile des paquets est non nulle + if (syndeny_count + synaccept_count >= rule.seuil and len(packet['TCP'].payload) > 0): + db.send_alert(datetime.now(), 5, None, "Syn DOS", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + print("Alerte, seuil dépassé, risque de Syn DOS détecté.") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/DOS/synflood.py b/idps/rules/TCP/DOS/synflood.py new file mode 100644 index 0000000..520f9f5 --- /dev/null +++ b/idps/rules/TCP/DOS/synflood.py @@ -0,0 +1,36 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """ + Règle SYN Flood: + Un SYN Flood va envoyer des requêtes TCP avec le flag SYN en très grand nombre afin de surcharger le serveur ou la cible + - Si le port est ouvert, le serveur répond avec: SYN-ACK, puis le client RESET la connexion. + - Si le port est fermé, le serveur répond avec: RST-ACK. + """ + + # Ne pas réagir si dans la période de cooldown + if (rule.cooldown + rule.time_window > time.time()): + return + + # Initialisation des paramètres à partir de la configuration si nécessaire + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("synsflood_time", 60) + rule.seuil = db.get_key("synflood_count", 100) + + # Comptage des paquets TCP correspondant aux motifs spécifiques + syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + + # Détection si le seuil est dépassé + if (syndeny_count + synaccept_count >= rule.seuil): + db.send_alert(datetime.now(), 5, None, "Syn flood", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + print("Alerte, seuil dépassé, risque de Syn Flood détecté.") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/DOS/tcpconnectflood.py b/idps/rules/TCP/DOS/tcpconnectflood.py new file mode 100644 index 0000000..ddb34e2 --- /dev/null +++ b/idps/rules/TCP/DOS/tcpconnectflood.py @@ -0,0 +1,34 @@ +from datetime import datetime +import time + + +def rule(packet, tcp_packets, db): + """Règle TCPConnect Flood: + Un flood TCP connect va effectuer une connexion TCP en très grand nombre + Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset ACK + Sinon le port est fermé et le serveur refusera la connexion SYN -> Reset ACK + """ + + if (rule.cooldown + rule.time_window > time.time()): + return + + # Vérification si nécessaire de récupérer les variables depuis la config + if (rule.seuil == 0 and rule.time_window == 0): + rule.time_window = db.get_key("tcpconnectflood_time", 60) + rule.seuil = db.get_key("tcpconnectflood_count", 100) + + # Comptage du nombre de scan tcp connect acceptés et refusés + tcpconnectdeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcpconnectaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + + if (tcpconnectaccept_count + tcpconnectdeny_count >= rule.seuil): + db.send_alert(datetime.now(), 5, None, "TCPConnect Flood", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") + print(f"Alerte, seuils dépassés, risque de TCPconnect Flood") + rule.cooldown = time.time() + + +# Variables statiques +rule.cooldown = 0 +rule.time_window = 0 +rule.seuil = 0 + diff --git a/idps/rules/TCP/Scan/ackscan.py b/idps/rules/TCP/Scan/ackscan.py index c210738..3b321f5 100644 --- a/idps/rules/TCP/Scan/ackscan.py +++ b/idps/rules/TCP/Scan/ackscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("ackscan_time", 180) rule.seuil = db.get_key("ackscan_count", 5) - if tcp_packets.count_packet_of_type(["A", "R"], rule.time_window, True) + tcp_packets.count_packet_of_type(["A"], rule.time_window, True) >= rule.seuil: + # Comptage nombre de scan ack acceptés et refusés + ackdeny_count = tcp_packets.count_packet_of_type(["A", "R"], rule.time_window, True) + ackaccept_count = tcp_packets.count_packet_of_type(["A"], rule.time_window, True) + + if (ackaccept_count + ackdeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "ACK scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Ack->Reset et Ack pas de réponse", act="Alerte") print(f"Alerte, seuil dépassés, risque d'Ack scan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/finscan.py b/idps/rules/TCP/Scan/finscan.py index 3ecf5f5..d6c4ae9 100644 --- a/idps/rules/TCP/Scan/finscan.py +++ b/idps/rules/TCP/Scan/finscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("finscan_time", 180) rule.seuil = db.get_key("finscan_count", 5) - if tcp_packets.count_packet_of_type(["F", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["F"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan fin acceptés et refusés + findeny_count = tcp_packets.count_packet_of_type(["F", "RA"], rule.time_window, True) + finaccept_count = tcp_packets.count_packet_of_type(["F"], rule.time_window, True) + + if (findeny_count + finaccept_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "Fin scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin->Reset Ack et Fin->rien", act="Alerte") print(f"Alerte, seuil dépassés, risque de Fin Scan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/nullscan.py b/idps/rules/TCP/Scan/nullscan.py index 7b373e2..6c686cb 100644 --- a/idps/rules/TCP/Scan/nullscan.py +++ b/idps/rules/TCP/Scan/nullscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("nullscan_time", 180) rule.seuil = db.get_key("nullscan_count", 5) - if tcp_packets.count_packet_of_type([""], rule.time_window, True) + tcp_packets.count_packet_of_type(["", "RA"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan null acceptés et refusés + nulldeny_count = tcp_packets.count_packet_of_type(["", "RA"], rule.time_window, True) + nullaccept_count = tcp_packets.count_packet_of_type([""], rule.time_window, True) + + if (nulldeny_count + nulldeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "Null scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de None->Reset Ack et None -> rien", act="Alerte") print(f"Alerte, seuil dépassés, risque de Null Scan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py index 3a6e3c4..9a5e5dc 100644 --- a/idps/rules/TCP/Scan/synscan.py +++ b/idps/rules/TCP/Scan/synscan.py @@ -3,7 +3,7 @@ import time def rule(packet, tcp_packets, db): - """Règle SYNScan: + """Règle SYN Scan: Un SYNScan va envoyer des requêtes TCP avec le flag SYN Si le port est ouvert alors le serveur répondra: Syn ACK, puis le client Reset la connexion Sinon le port est fermé et le serveur répondra: Reset ACK @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("synscan_time", 180) rule.seuil = db.get_key("synscan_count", 5) - if tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan syn acceptés et refusés + syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + + if (synaccept_count + syndeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuil dépassés, risque de SynScan") rule.cooldown = time.time() diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py index 3451fb0..69253bd 100644 --- a/idps/rules/TCP/Scan/tcpconnectscan.py +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -17,7 +17,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("tcpconnectscan_time", 180) rule.seuil = db.get_key("tcpconnectscan_count", 5) - if tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan tcp connect acceptés et refusés + tcpconnectdeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) + tcpconnectaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + + if (tcpconnectaccept_count + tcpconnectdeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "TCPConnect Scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") print(f"Alerte, seuils dépassés, risque de TCPConnectScan") rule.cooldown = time.time() @@ -25,5 +29,5 @@ def rule(packet, tcp_packets, db): # Variables statiques rule.cooldown = 0 -rule.time_window = 180 -rule.seuil = 5 +rule.time_window = 0 +rule.seuil = 0 diff --git a/idps/rules/TCP/Scan/xmasscan.py b/idps/rules/TCP/Scan/xmasscan.py index 4f811c5..17cd359 100644 --- a/idps/rules/TCP/Scan/xmasscan.py +++ b/idps/rules/TCP/Scan/xmasscan.py @@ -16,7 +16,11 @@ def rule(packet, tcp_packets, db): rule.time_window = db.get_key("xmasscan_time", 180) rule.seuil = db.get_key("xmasscan_count", 5) - if tcp_packets.count_packet_of_type(["FPU", "RA"], rule.time_window, True) + tcp_packets.count_packet_of_type(["FPU"], rule.time_window, True) >= rule.seuil: + # Comptage du nombre de scan XMAS acceptés et refusés + xmasdeny_count = tcp_packets.count_packet_of_type(["FPU", "RA"], rule.time_window, True) + xmasaccept_count = tcp_packets.count_packet_of_type(["FPU"], rule.time_window, True) + + if (xmasaccept_count + xmasdeny_count >= rule.seuil): db.send_alert(datetime.now(), 5, None, "XMAS scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin Push Urg -> rien et Fin Push Urg->Reset ACK", act="Alerte") print(f"Alerte, seuil dépassés, risque de XMAS Scan") rule.cooldown = time.time() diff --git a/idps/tcp.py b/idps/tcp.py index 0ee21f3..edbdf03 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -34,7 +34,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("SA") self.packets[ip][i][4] = timestamp return @@ -48,7 +47,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "R") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("A") self.packets[ip][i][4] = timestamp return @@ -63,7 +61,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("RA") self.packets[ip][i][4] = timestamp return @@ -78,7 +75,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("R") self.packets[ip][i][4] = timestamp return @@ -90,7 +86,6 @@ class TCP: i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") if i is not None: - print(f"i: {i}, {ip_src}:{port_src}->{ip_dst}:{port_dst}, paquets: \n{self.packets}") self.packets[ip][i][3].append("F") self.packets[ip][i][4] = timestamp return @@ -98,8 +93,6 @@ class TCP: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["F"], timestamp]) return - # TODO: ajout flag fin, none, fin urg push - def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags): """Cherche l'indice et le port de source du paquet dont le flag doit être remplacé""" From c4df869596e6ab7b1066bc6095f0034e6714d821 Mon Sep 17 00:00:00 2001 From: Oxbian Date: Sat, 23 Nov 2024 12:15:10 -0500 Subject: [PATCH 17/18] feat: protection system for the idps --- Demo/config/config-idps.json | 12 +++- Demo/config/config-ids.json | 12 +++- config.json | 11 ++- idps/database.py | 15 ++--- idps/main.py | 96 ++++++++++++++------------- idps/protection.py | 49 ++++++++++++++ idps/rules/TCP/DOS/syndos.py | 17 +++-- idps/rules/TCP/DOS/synflood.py | 17 +++-- idps/rules/TCP/DOS/tcpconnectflood.py | 20 +++--- idps/rules/TCP/Scan/ackscan.py | 19 +++--- idps/rules/TCP/Scan/finscan.py | 20 +++--- idps/rules/TCP/Scan/nullscan.py | 21 +++--- idps/rules/TCP/Scan/synscan.py | 19 +++--- idps/rules/TCP/Scan/tcpconnectscan.py | 19 +++--- idps/rules/TCP/Scan/xmasscan.py | 19 +++--- idps/tcp.py | 38 +++++++---- 16 files changed, 259 insertions(+), 145 deletions(-) create mode 100644 idps/protection.py diff --git a/Demo/config/config-idps.json b/Demo/config/config-idps.json index 02f0cb8..7e734aa 100644 --- a/Demo/config/config-idps.json +++ b/Demo/config/config-idps.json @@ -6,26 +6,36 @@ "db_user": "sidps", "db_password": "SUPERPASSWORD", "db_port": "3306", + "protection": 1, "cef_version": 1, "device_product": "SIDPS", "device_vendor": "ArKa", "device_version": "vAlpha", "synscan_time": 180, "synscan_count": 5, + "synscan_bantime": 300, "tcpconnectscan_time": 180, "tcpconnectscan_count": 5, + "tcpconnectscan_bantime": 300, "ackscan_time": 180, "ackscan_count": 5, + "ackscan_bantime": 300, "finscan_time": 180, "finscan_count": 5, + "finscan_bantime": 300, "nullscan_time": 180, "nullscan_count": 5, + "nullscan_bantime": 300, "xmasscan_time": 180, "xmasscan_count": 5, + "xmasscan_bantime": 300, "synflood_time": 60, "synflood_count": 100, + "synflood_bantime": 300, "tcpconnectflood_time": 60, "tcpconnectflood_count": 100, + "tcpconnectflood_bantime": 300, "syndos_time": 60, - "syndos_count": 100 + "syndos_count": 100, + "syndos_bantime": 300 } diff --git a/Demo/config/config-ids.json b/Demo/config/config-ids.json index 7b203bb..4e091b7 100644 --- a/Demo/config/config-ids.json +++ b/Demo/config/config-ids.json @@ -6,26 +6,36 @@ "db_user": "sidps", "db_password": "SUPERPASSWORD", "db_port": "3306", + "protection": 0, "cef_version": 1, "device_product": "Sonde IDS", "device_vendor": "ArKa", "device_version": "vAlpha", "synscan_time": 180, "synscan_count": 5, + "synscan_bantime": 300, "tcpconnectscan_time": 180, "tcpconnectscan_count": 5, + "tcpconnectscan_bantime": 300, "ackscan_time": 180, "ackscan_count": 5, + "ackscan_bantime": 300, "finscan_time": 180, "finscan_count": 5, + "finscan_bantime": 300, "nullscan_time": 180, "nullscan_count": 5, + "nullscan_bantime": 300, "xmasscan_time": 180, "xmasscan_count": 5, + "xmasscan_bantime": 300, "synflood_time": 60, "synflood_count": 100, + "synflood_bantime": 300, "tcpconnectflood_time": 60, "tcpconnectflood_count": 100, + "tcpconnectflood_bantime": 300, "syndos_time": 60, - "syndos_count": 100 + "syndos_count": 100, + "syndos_bantime": 300 } diff --git a/config.json b/config.json index 02f0cb8..d827136 100644 --- a/config.json +++ b/config.json @@ -12,20 +12,29 @@ "device_version": "vAlpha", "synscan_time": 180, "synscan_count": 5, + "synscan_bantime": 300, "tcpconnectscan_time": 180, "tcpconnectscan_count": 5, + "tcpconnectscan_bantime": 300, "ackscan_time": 180, "ackscan_count": 5, + "ackscan_bantime": 300, "finscan_time": 180, "finscan_count": 5, + "finscan_bantime": 300, "nullscan_time": 180, "nullscan_count": 5, + "nullscan_bantime": 300, "xmasscan_time": 180, "xmasscan_count": 5, + "xmasscan_bantime": 300, "synflood_time": 60, "synflood_count": 100, + "synflood_bantime": 300, "tcpconnectflood_time": 60, "tcpconnectflood_count": 100, + "tcpconnectflood_bantime": 300, "syndos_time": 60, - "syndos_count": 100 + "syndos_count": 100, + "syndos_bantime": 300 } diff --git a/idps/database.py b/idps/database.py index bba8130..efdb6f0 100644 --- a/idps/database.py +++ b/idps/database.py @@ -46,13 +46,13 @@ class Database: # Paramètres pour la requête SQL params = { - "cef_version": self.get_key("cef_version", 1), + "cef_version": self.config.get("cef_version", 1), "date_alerte": date_alert, "agent_severity": agent_severity, "device_event_class_id": device_event_class_id, - "device_product": self.get_key("device_product", "SIDPS"), - "device_vendor": self.get_key("device_vendor", "ArKa"), - "device_version": self.get_key("device_version", "vAlpha"), + "device_product": self.config.get("device_product", "SIDPS"), + "device_vendor": self.config.get("device_vendor", "ArKa"), + "device_version": self.config.get("device_version", "vAlpha"), "name": name, "src": src, "dst": dst, @@ -72,10 +72,3 @@ class Database: cursor.close() except mysql.connector.Error as err: print("Erreur lors de l'envoi de l'alerte: {}".format(err)) - - def get_key(self, key, default_val): - """Donne le contenue d'un paramètre spécifique de la config - @param key: clé du paramètre souhaité - @param default_val: valeur par défaut si la clé n'existe pas""" - - return self.config.get(key, default_val) diff --git a/idps/main.py b/idps/main.py index 08934a1..379e8fb 100644 --- a/idps/main.py +++ b/idps/main.py @@ -1,13 +1,48 @@ -from scapy.all import sniff, TCP, IP -from scapy.config import conf -conf.debug_dissector = 2 - import importlib.util import os import time import tcp import database import json +import protection + +from scapy.all import sniff, TCP, IP +from scapy.config import conf +conf.debug_dissector = 2 + + +def check_frame_w_rules(packet, rules_functions, objets): + """Appliquer chaque règle des fonctions au paquet capturé. + @param packet: Paquet actuel à analyser + @param rules_functions: liste de fonctions de règles + @param objets: Dictionnaire contenant le dictionnaire de config, la liste des paquets tcp précédents, + la db, et le gestionnaire de règles Iptables""" + + for rule_func in rules_functions: + try: + rule_func(packet, objets) + except Exception as e: + print(f"Erreur lors de l'exécution de la règle : {e}") + + +def packet_callback(packet, rules_functions, objets): + """Callback réception d'un paquet + @param packet: Paquet actuel à classer + @param rules_functions: liste des fonctions de règles + @param objets: Dictionnaire contenant le dictionnaire de config, la liste des paquets tcp précédents, + la db, et le gestionnaire de règles Iptables""" + + # Nettoyage des règles et paquets TCP dépassé + objets["iptables_manager"].del_rules() + objets["tcp_packets"].clean_old_packets() + + if IP in packet and TCP in packet: + packet_origin = objets["tcp_packets"].add_packet(packet[IP].src, packet[TCP].sport, packet[IP].dst, packet[TCP].dport, packet[TCP].flags, time.time()) + + # Stockage du paquet originel lié à ce paquet pour identifier la provenance de l'attaque + objets['pkt_origin'] = packet_origin + + check_frame_w_rules(packet, rules_functions['TCP'], objets) def load_rules(rules_dirpath = "/app/idps/rules"): @@ -68,37 +103,6 @@ def load_rules(rules_dirpath = "/app/idps/rules"): return rules_functions -def check_frame_w_rules(packet, rules_functions, packets, db): - """Appliquer chaque règle des fonctions au paquet capturé. - @param packet: Paquet actuel à analyser - @param rules_functions: liste de fonctions de règles - @param packets: liste des paquets précédents (utile pour TCP) - @param db: Objet database pour envoyer les alertes à la BDD - """ - - for rule_func in rules_functions: - try: - rule_func(packet, packets, db) - except Exception as e: - print(f"Erreur lors de l'exécution de la règle : {e}") - - -def packet_callback(packet, rules_functions, tcp_packets, db): - """Callback réception d'un paquet - @param packet: Paquet actuel à classer - @param rules_functions: liste des fonctions de règles - @param tcp_packets: Objet contenant une liste des paquets tcp précédents - @param db: Objet database pour envoyer des alertes à la BDD - """ - - #print(packet) - if IP in packet and TCP in packet: - tcp_packets.add_packet(packet[IP].src, packet[TCP].sport, packet[IP].dst, packet[TCP].dport, packet[TCP].flags, time.time()) - #print(tcp_packets[packet[IP].src]) - check_frame_w_rules(packet, rules_functions['TCP'], tcp_packets, db) - tcp_packets.clean_old_packets() - - def read_config(config_filepath='config.json'): """Charge les configurations depuis le fichier de config""" @@ -115,29 +119,29 @@ def read_config(config_filepath='config.json'): def start_idps(): """Charge les règles et démarre l'IDPS""" - print(f"Récupération des configurations") + print("Récupération des configurations") config = read_config() - print(f"Configurations chargées") + print("Configurations chargées") - print(f"Chargement des règles...") + print("Chargement des règles...") rules_functions = load_rules(config["rules_dirpath"]) - print(f"Les règles sont chargées") + print("Les règles sont chargées") - print(f"Connexion à la base de données") + print("Connexion à la base de données") db = database.Database(config) - print(f"Connexion réussite à la base de données") - - # Opti possible: charger les règles par protocole, permettant des filtrages et donc optimiser - # le nombre de fonctions vérifiant le paquet (snort s'arrête à la première corrélation par exemple) + print("Connexion réussite à la base de données") tcp_packets = tcp.TCP(300) + protection_system = protection.Protection(config["protection"]) + + objets = {"config": config, "database": db, "tcp_packets": tcp_packets, "iptables_manager": protection_system} # Lancer scapy & envoyer le paquet à chaque règle de l'IDPS - sniff(iface=config["ifaces"], prn=lambda packet: packet_callback(packet, rules_functions, tcp_packets, db), store=0) + sniff(iface=config["ifaces"], prn=lambda packet: packet_callback(packet, rules_functions, objets), store=0) def main(): - print(f"Démarrage de l'IDPS") + print("Démarrage de l'IDPS") start_idps() diff --git a/idps/protection.py b/idps/protection.py new file mode 100644 index 0000000..aef2c50 --- /dev/null +++ b/idps/protection.py @@ -0,0 +1,49 @@ +import subprocess +import time + + +class Protection: + """Classe pour activer la protection du système avec iptables""" + + def __init__(self, activate = 0): + """Initialisation de la protection avec une liste pour stockées les règles créer""" + self.rules = [] + self.activate = int(activate) + + def add_rule(self, rule, duration): + """Ajouter une règle dans iptables + @param rule: Règle à ajouter + @param duration: Durée d'execution de la règle""" + + print(f"Rule: {rule}, {duration}, {self.activate}") + if self.activate == 0: + return + + print("Rule run") + try: + subprocess.run(rule.split(' '), check=True) + print(f"[iptables] Règle ajouter {rule}") + self.rules.append([rule, time.time(), duration]) + except subprocess.CalledProcessError as e: + print(f"[iptables] Erreur suppression de la règle {rule}: {e}") + + def del_rules(self): + """Supprimer les règles obsolètes de l'iptables""" + + if self.activate is False: + return + + curr = time.time() + for i, elt in enumerate(self.rules, 0): + if elt[1] + elt[2] <= curr: + self.del_rule(self, elt[0].replace("-I", "-D"), i) + + def del_rule(self, rule, i): + """Supprimer une règle dans iptables""" + + try: + subprocess.run(rule.split(' '), check=True) + print("[iptables] Règle supprimer {rule}") + self.rules.pop(i) + except subprocess.CalledProcessError as e: + print(f"[iptables] Erreur suppression de la règle {rule}: {e}") diff --git a/idps/rules/TCP/DOS/syndos.py b/idps/rules/TCP/DOS/syndos.py index 54480e9..22ad701 100644 --- a/idps/rules/TCP/DOS/syndos.py +++ b/idps/rules/TCP/DOS/syndos.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """ Règle SYN Dos: Un SYN DOS va envoyer des requêtes TCP avec le flag SYN en très grand nombre afin de surcharger le serveur ou la cible avec des grosses quantités de données @@ -15,17 +15,19 @@ def rule(packet, tcp_packets, db): return # Initialisation des paramètres à partir de la configuration si nécessaire - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("synsdos_time", 60) - rule.seuil = db.get_key("syndos_count", 100) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("synsdos_time", 60) + rule.seuil = objets["config"].get("syndos_count", 100) + rule.ban_time = objets["config"].get("syndos_bantime", 300) # Comptage des paquets TCP correspondant aux motifs spécifiques - syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) - synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + syndeny_count = objets["tcp_packets"].count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = objets["tcp_packets"].count_packet_of_type(["S", "SA", "R"], rule.time_window, True) # Détection si le seuil est dépassé et que la charge utile des paquets est non nulle if (syndeny_count + synaccept_count >= rule.seuil and len(packet['TCP'].payload) > 0): - db.send_alert(datetime.now(), 5, None, "Syn DOS", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + objets["database"].send_alert(datetime.now(), 5, None, "Syn DOS", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) print("Alerte, seuil dépassé, risque de Syn DOS détecté.") rule.cooldown = time.time() @@ -34,3 +36,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/rules/TCP/DOS/synflood.py b/idps/rules/TCP/DOS/synflood.py index 520f9f5..8cc895b 100644 --- a/idps/rules/TCP/DOS/synflood.py +++ b/idps/rules/TCP/DOS/synflood.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """ Règle SYN Flood: Un SYN Flood va envoyer des requêtes TCP avec le flag SYN en très grand nombre afin de surcharger le serveur ou la cible @@ -15,17 +15,19 @@ def rule(packet, tcp_packets, db): return # Initialisation des paramètres à partir de la configuration si nécessaire - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("synsflood_time", 60) - rule.seuil = db.get_key("synflood_count", 100) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("synsflood_time", 60) + rule.seuil = objets["config"].get("synflood_count", 100) + rule.ban_time = objets["config"].get("synflood_bantime", 300) # Comptage des paquets TCP correspondant aux motifs spécifiques - syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) - synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + syndeny_count = objets["tcp_packets"].count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = objets["tcp_packets"].count_packet_of_type(["S", "SA", "R"], rule.time_window, True) # Détection si le seuil est dépassé if (syndeny_count + synaccept_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "Syn flood", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + objets["database"].send_alert(datetime.now(), 5, None, "Syn flood", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) print("Alerte, seuil dépassé, risque de Syn Flood détecté.") rule.cooldown = time.time() @@ -34,3 +36,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/rules/TCP/DOS/tcpconnectflood.py b/idps/rules/TCP/DOS/tcpconnectflood.py index ddb34e2..d1536da 100644 --- a/idps/rules/TCP/DOS/tcpconnectflood.py +++ b/idps/rules/TCP/DOS/tcpconnectflood.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """Règle TCPConnect Flood: Un flood TCP connect va effectuer une connexion TCP en très grand nombre Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset ACK @@ -13,17 +13,19 @@ def rule(packet, tcp_packets, db): return # Vérification si nécessaire de récupérer les variables depuis la config - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("tcpconnectflood_time", 60) - rule.seuil = db.get_key("tcpconnectflood_count", 100) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("tcpconnectflood_time", 60) + rule.seuil = objets["config"].get("tcpconnectflood_count", 100) + rule.ban_time = objets["config"].get("tcpconnectflood_bantime", 300) # Comptage du nombre de scan tcp connect acceptés et refusés - tcpconnectdeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) - tcpconnectaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + tcpconnectdeny_count = objets["tcp_packets"].count_packet_of_type(["S", "RA"], rule.time_window, True) + tcpconnectaccept_count = objets["tcp_packets"].count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) if (tcpconnectaccept_count + tcpconnectdeny_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "TCPConnect Flood", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") - print(f"Alerte, seuils dépassés, risque de TCPconnect Flood") + objets["database"].send_alert(datetime.now(), 5, None, "TCPConnect Flood", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) + print("Alerte, seuils dépassés, risque de TCPconnect Flood") rule.cooldown = time.time() @@ -31,4 +33,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 - +rule.ban_time = 0 diff --git a/idps/rules/TCP/Scan/ackscan.py b/idps/rules/TCP/Scan/ackscan.py index 3b321f5..916d2ff 100644 --- a/idps/rules/TCP/Scan/ackscan.py +++ b/idps/rules/TCP/Scan/ackscan.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """Règle ACK Scan: Un ACK Scan va envoyer des requêtes TCP avec le flag ACK Si le firewall ne bloque pas, alors il répond avec le flag Reset @@ -12,17 +12,19 @@ def rule(packet, tcp_packets, db): return # Vérification si nécessaire de récupérer les variables depuis la config - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("ackscan_time", 180) - rule.seuil = db.get_key("ackscan_count", 5) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("ackscan_time", 180) + rule.seuil = objets["config"].get("ackscan_count", 5) + rule.ban_time = objets["config"].get("ackscan_bantime", 300) # Comptage nombre de scan ack acceptés et refusés - ackdeny_count = tcp_packets.count_packet_of_type(["A", "R"], rule.time_window, True) - ackaccept_count = tcp_packets.count_packet_of_type(["A"], rule.time_window, True) + ackdeny_count = objets["tcp_packets"].count_packet_of_type(["A", "R"], rule.time_window, True) + ackaccept_count = objets["tcp_packets"].count_packet_of_type(["A"], rule.time_window, True) if (ackaccept_count + ackdeny_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "ACK scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Ack->Reset et Ack pas de réponse", act="Alerte") - print(f"Alerte, seuil dépassés, risque d'Ack scan") + objets["database"].send_alert(datetime.now(), 5, None, "ACK scan", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Ack->Reset et Ack pas de réponse", act="Alerte") + print("Alerte, seuil dépassés, risque d'Ack scan") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) rule.cooldown = time.time() @@ -30,3 +32,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/rules/TCP/Scan/finscan.py b/idps/rules/TCP/Scan/finscan.py index d6c4ae9..b3a4801 100644 --- a/idps/rules/TCP/Scan/finscan.py +++ b/idps/rules/TCP/Scan/finscan.py @@ -2,27 +2,30 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """Règle Fin Scan: Un Fin Scan va envoyer des requêtes TCP avec le flag Fin Si le port est ouvert alors le serveur répondra pas Sinon le port est fermé et le serveur répondra: Reset ACK """ + if (rule.cooldown + rule.time_window > time.time()): return # Vérification si nécessaire de récupérer les variables depuis la config - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("finscan_time", 180) - rule.seuil = db.get_key("finscan_count", 5) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("finscan_time", 180) + rule.seuil = objets["config"].get("finscan_count", 5) + rule.ban_time = objets["config"].get("finscan_bantime", 300) # Comptage du nombre de scan fin acceptés et refusés - findeny_count = tcp_packets.count_packet_of_type(["F", "RA"], rule.time_window, True) - finaccept_count = tcp_packets.count_packet_of_type(["F"], rule.time_window, True) + findeny_count = objets["tcp_packets"].count_packet_of_type(["F", "RA"], rule.time_window, True) + finaccept_count = objets["tcp_packets"].count_packet_of_type(["F"], rule.time_window, True) if (findeny_count + finaccept_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "Fin scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin->Reset Ack et Fin->rien", act="Alerte") - print(f"Alerte, seuil dépassés, risque de Fin Scan") + objets["database"].send_alert(datetime.now(), 5, None, "Fin scan", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Fin->Reset Ack et Fin->rien", act="Alerte") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) + print("Alerte, seuil dépassés, risque de Fin Scan") rule.cooldown = time.time() @@ -30,3 +33,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/rules/TCP/Scan/nullscan.py b/idps/rules/TCP/Scan/nullscan.py index 6c686cb..beb9427 100644 --- a/idps/rules/TCP/Scan/nullscan.py +++ b/idps/rules/TCP/Scan/nullscan.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """Règle Null Scan: Un Null Scan va envoyer des requêtes TCP avec aucun flag d'actif Si le port est ouvert alors le serveur ne répondra pas @@ -12,17 +12,19 @@ def rule(packet, tcp_packets, db): return # Vérification si nécessaire de récupérer les variables depuis la config - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("nullscan_time", 180) - rule.seuil = db.get_key("nullscan_count", 5) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("nullscan_time", 180) + rule.seuil = objets["config"].get("nullscan_count", 5) + rule.ban_time = objets["config"].get("nullscan_bantime", 300) # Comptage du nombre de scan null acceptés et refusés - nulldeny_count = tcp_packets.count_packet_of_type(["", "RA"], rule.time_window, True) - nullaccept_count = tcp_packets.count_packet_of_type([""], rule.time_window, True) + nulldeny_count = objets["tcp_packets"].count_packet_of_type(["", "RA"], rule.time_window, True) + nullaccept_count = objets["tcp_packets"].count_packet_of_type([""], rule.time_window, True) - if (nulldeny_count + nulldeny_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "Null scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de None->Reset Ack et None -> rien", act="Alerte") - print(f"Alerte, seuil dépassés, risque de Null Scan") + if (nullaccept_count + nulldeny_count >= rule.seuil): + objets["database"].send_alert(datetime.now(), 5, None, "Null scan", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de None->Reset Ack et None -> rien", act="Alerte") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) + print("Alerte, seuil dépassés, risque de Null Scan") rule.cooldown = time.time() @@ -30,3 +32,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/rules/TCP/Scan/synscan.py b/idps/rules/TCP/Scan/synscan.py index 9a5e5dc..2c522bc 100644 --- a/idps/rules/TCP/Scan/synscan.py +++ b/idps/rules/TCP/Scan/synscan.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """Règle SYN Scan: Un SYNScan va envoyer des requêtes TCP avec le flag SYN Si le port est ouvert alors le serveur répondra: Syn ACK, puis le client Reset la connexion @@ -12,17 +12,19 @@ def rule(packet, tcp_packets, db): return # Vérification si nécessaire de récupérer les variables depuis la config - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("synscan_time", 180) - rule.seuil = db.get_key("synscan_count", 5) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("synscan_time", 180) + rule.seuil = objets["config"].get("synscan_count", 5) + rule.ban_time = objets["config"].get("synscan_bantime", 300) # Comptage du nombre de scan syn acceptés et refusés - syndeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) - synaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "R"], rule.time_window, True) + syndeny_count = objets["tcp_packets"].count_packet_of_type(["S", "RA"], rule.time_window, True) + synaccept_count = objets["tcp_packets"].count_packet_of_type(["S", "SA", "R"], rule.time_window, True) if (synaccept_count + syndeny_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "Syn scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") - print(f"Alerte, seuil dépassés, risque de SynScan") + objets["database"].send_alert(datetime.now(), 5, None, "Syn scan", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->Reset et Syn->Reset ACK", act="Alerte") + objets["iptables_manager"].add_rule("/sbin/iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) + print("Alerte, seuil dépassés, risque de SynScan") rule.cooldown = time.time() @@ -30,3 +32,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/rules/TCP/Scan/tcpconnectscan.py b/idps/rules/TCP/Scan/tcpconnectscan.py index 69253bd..24bf1fa 100644 --- a/idps/rules/TCP/Scan/tcpconnectscan.py +++ b/idps/rules/TCP/Scan/tcpconnectscan.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """Règle TCPConnect Scan: Un scan TCP connect va effectuer une connexion TCP en entier sur chaque port scanné. Si le port est ouvert le serveur acceptera la connexion SYN -> SYN ACK -> ACK -> Reset ACK @@ -13,17 +13,19 @@ def rule(packet, tcp_packets, db): return # Vérification si nécessaire de récupérer les variables depuis la config - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("tcpconnectscan_time", 180) - rule.seuil = db.get_key("tcpconnectscan_count", 5) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("tcpconnectscan_time", 180) + rule.seuil = objets["config"].get("tcpconnectscan_count", 5) + rule.ban_time = objets["config"].get("tcpconnectscan_bantime", 300) # Comptage du nombre de scan tcp connect acceptés et refusés - tcpconnectdeny_count = tcp_packets.count_packet_of_type(["S", "RA"], rule.time_window, True) - tcpconnectaccept_count = tcp_packets.count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) + tcpconnectdeny_count = objets["tcp_packets"].count_packet_of_type(["S", "RA"], rule.time_window, True) + tcpconnectaccept_count = objets["tcp_packets"].count_packet_of_type(["S", "SA", "A", "RA"], rule.time_window, True) if (tcpconnectaccept_count + tcpconnectdeny_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "TCPConnect Scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") - print(f"Alerte, seuils dépassés, risque de TCPConnectScan") + objets["database"].send_alert(datetime.now(), 5, None, "TCPConnect Scan", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Syn->SynACK->ACK->Reset ACK et Syn->Reset ACK", act="Alerte") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) + print("Alerte, seuils dépassés, risque de TCPConnectScan") rule.cooldown = time.time() @@ -31,3 +33,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/rules/TCP/Scan/xmasscan.py b/idps/rules/TCP/Scan/xmasscan.py index 17cd359..4709e8f 100644 --- a/idps/rules/TCP/Scan/xmasscan.py +++ b/idps/rules/TCP/Scan/xmasscan.py @@ -2,7 +2,7 @@ from datetime import datetime import time -def rule(packet, tcp_packets, db): +def rule(packet, objets): """Règle XMAS Scan: Un XMAS Scan va envoyer des requêtes TCP avec le flag Fin, Push, Urg Si le port est ouvert alors le serveur répondra pas @@ -12,17 +12,19 @@ def rule(packet, tcp_packets, db): return # Vérification si nécessaire de récupérer les variables depuis la config - if (rule.seuil == 0 and rule.time_window == 0): - rule.time_window = db.get_key("xmasscan_time", 180) - rule.seuil = db.get_key("xmasscan_count", 5) + if (rule.seuil == 0 and rule.time_window == 0 and rule.ban_time == 0): + rule.time_window = objets["config"].get("xmasscan_time", 180) + rule.seuil = objets["config"].get("xmasscan_count", 5) + rule.ban_time = objets["config"].get("xmasscan_bantime", 300) # Comptage du nombre de scan XMAS acceptés et refusés - xmasdeny_count = tcp_packets.count_packet_of_type(["FPU", "RA"], rule.time_window, True) - xmasaccept_count = tcp_packets.count_packet_of_type(["FPU"], rule.time_window, True) + xmasdeny_count = objets["tcp_packets"].count_packet_of_type(["FPU", "RA"], rule.time_window, True) + xmasaccept_count = objets["tcp_packets"].count_packet_of_type(["FPU"], rule.time_window, True) if (xmasaccept_count + xmasdeny_count >= rule.seuil): - db.send_alert(datetime.now(), 5, None, "XMAS scan", packet['IP'].src, packet['IP'].dst, proto="TCP", reason="Détection de nombreux patterns de Fin Push Urg -> rien et Fin Push Urg->Reset ACK", act="Alerte") - print(f"Alerte, seuil dépassés, risque de XMAS Scan") + objets["database"].send_alert(datetime.now(), 5, None, "XMAS scan", objets["pkt_origin"][0], objets["pkt_origin"][2], proto="TCP", reason="Détection de nombreux patterns de Fin Push Urg -> rien et Fin Push Urg->Reset ACK", act="Alerte") + objets["iptables_manager"].add_rule("iptables -I FORWARD -s " + objets["pkt_origin"][0] + " -j DROP", rule.ban_time) + print("Alerte, seuil dépassés, risque de XMAS Scan") rule.cooldown = time.time() @@ -30,3 +32,4 @@ def rule(packet, tcp_packets, db): rule.cooldown = 0 rule.time_window = 0 rule.seuil = 0 +rule.ban_time = 0 diff --git a/idps/tcp.py b/idps/tcp.py index edbdf03..ca6d7ae 100644 --- a/idps/tcp.py +++ b/idps/tcp.py @@ -20,15 +20,15 @@ class TCP: if flags == "S": self.packets[ip_src].append([port_src, ip_dst, port_dst, ["S"], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) elif flags is None: self.packets[ip_src].append([port_src, ip_dst, port_dst, [""], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) elif flags == "FPU": self.packets[ip_src].append([port_src, ip_dst, port_dst, ["FPU"], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) elif flags == "SA": i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "S") @@ -36,10 +36,10 @@ class TCP: if i is not None: self.packets[ip][i][3].append("SA") self.packets[ip][i][4] = timestamp - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst, ip) else: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["SA"], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) elif flags == "A": i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "SA") @@ -49,10 +49,10 @@ class TCP: if i is not None: self.packets[ip][i][3].append("A") self.packets[ip][i][4] = timestamp - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst, ip) else: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["A"], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) elif flags == "RA": i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") @@ -63,10 +63,10 @@ class TCP: if i is not None: self.packets[ip][i][3].append("RA") self.packets[ip][i][4] = timestamp - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst, ip) else: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["RA"], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) elif flags == "R": i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") @@ -77,10 +77,10 @@ class TCP: if i is not None: self.packets[ip][i][3].append("R") self.packets[ip][i][4] = timestamp - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst, ip) else: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["R"], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) elif flags == "F": i, ip = self.find_packet_to_replace(ip_src, port_src, ip_dst, port_dst, "A") @@ -88,10 +88,10 @@ class TCP: if i is not None: self.packets[ip][i][3].append("F") self.packets[ip][i][4] = timestamp - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst, ip) else: self.packets[ip_src].append([port_src, ip_dst, port_dst, ["F"], timestamp]) - return + return self.return_origin_packet(ip_src, port_src, ip_dst, port_dst) def find_packet_to_replace(self, ip_src, port_src, ip_dst, port_dst, flags): """Cherche l'indice et le port de source du paquet dont le flag doit être remplacé""" @@ -147,3 +147,15 @@ class TCP: """Retourne la liste des paquets liés à une adresse IP, pour du déboggage""" return self.packets.get(src_ip, None) + + def return_origin_packet(self, ip_src, port_src, ip_dst, port_dst, ip = None): + """Retourne le paquet d'origine par rapport à l'ip de référence""" + + if ip is None: + return [ip_src, port_src, ip_dst, port_dst] + else: + if ip == ip_src: + return [ip_src, port_src, ip_dst, port_dst] + elif ip == ip_dst: + return [ip_dst, port_dst, ip_src, port_src] + From e9b004d2f7f58afce6ba5785c3a40135418438d8 Mon Sep 17 00:00:00 2001 From: SofianeElNaggar Date: Sun, 24 Nov 2024 15:29:00 -0500 Subject: [PATCH 18/18] add lateCommunication + update dataExfiltration --- .../TCP/{Scan => Data}/dataExfiltration.py | 9 ++-- idps/rules/TCP/Data/lateCommunication.py | 48 +++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) rename idps/rules/TCP/{Scan => Data}/dataExfiltration.py (90%) create mode 100644 idps/rules/TCP/Data/lateCommunication.py diff --git a/idps/rules/TCP/Scan/dataExfiltration.py b/idps/rules/TCP/Data/dataExfiltration.py similarity index 90% rename from idps/rules/TCP/Scan/dataExfiltration.py rename to idps/rules/TCP/Data/dataExfiltration.py index db616b2..10b285d 100644 --- a/idps/rules/TCP/Scan/dataExfiltration.py +++ b/idps/rules/TCP/Data/dataExfiltration.py @@ -6,7 +6,10 @@ from datetime import datetime data_transfer = defaultdict(lambda: {"current": 0, "daily": 0, "last_reset": time.time()}) def rule(packet, _, db): - """Règle pour détecter une exfiltration de données importantes.""" + """ + Règle pour détecter une exfiltration de données importantes. + Actuellement, ne fonctionne pas pour un débit supérieur à 4Mo + """ global data_transfer if IP in packet: @@ -23,8 +26,6 @@ def rule(packet, _, db): data_transfer[src_ip]["current"] += payload_size data_transfer[src_ip]["daily"] += payload_size - print(data_transfer[src_ip]["current"]) - # Exfiltration de données instantané if data_transfer[src_ip]["current"] > rule.seuil_session: db.send_alert( @@ -58,5 +59,5 @@ def rule(packet, _, db): rule.reset_time = 24 * 3600 # 24 heures en secondes -rule.seuil_session = 5 * 1024 * 1024 * 1024 # 5 Go en octets +rule.seuil_session = 0.5 * 1024 * 1024 * 1024 # 500 Mo en octets rule.seuil_journalier = 50 * 1024 * 1024 * 1024 # 50 Go en octets \ No newline at end of file diff --git a/idps/rules/TCP/Data/lateCommunication.py b/idps/rules/TCP/Data/lateCommunication.py new file mode 100644 index 0000000..5645449 --- /dev/null +++ b/idps/rules/TCP/Data/lateCommunication.py @@ -0,0 +1,48 @@ +from datetime import datetime, time, timedelta +from scapy.all import IP + +# Dictionnaire pour stocker les dernières alertes envoyées pour chaque IP +last_alert_time = {} + +def rule(packet, _, db): + """ + Règle pour détecter l'activité réseau entre une plage horaire donnée. + """ + global last_alert_time + + if IP in packet: + + src_ip = packet[IP].src + dst_ip = packet[IP].dst + + # Obtenir l'heure actuelle + current_time = datetime.now() + + # Vérifier si l'heure est dans la plage + if rule.start_time <= current_time.time() or current_time.time() <= rule.end_time: + # Vérifier si une alerte a déjà été envoyée récemment pour cette IP + if src_ip in last_alert_time: + time_since_last_alert = current_time - last_alert_time[src_ip] + if time_since_last_alert < timedelta(minutes=5): # 5 minutes de délai + return # Ne pas envoyer une nouvelle alerte + + # Envoyer une alerte + db.send_alert( + current_time, + 5, + None, + f"Activité réseau détectée entre {rule.start_time} et {rule.end_time}", + src_ip, + dst_ip, + proto="TCP", + reason=f"Activité réseau à {current_time.time()}", + act="Alerte" + ) + print(f"Alerte : activité réseau détectée à {current_time.time()} entre {src_ip} et {dst_ip}") + + # Mettre à jour le temps de la dernière alerte pour cette IP + last_alert_time[src_ip] = current_time + +# Définir la plage horaire +rule.start_time = time(21, 0) +rule.end_time = time(6, 0)