unknown 2 месяцев назад
Родитель
Сommit
ecd6810d06

+ 140 - 0
books/python_black/scanner.py

@@ -0,0 +1,140 @@
+import ipaddress
+import os
+import socket
+import struct
+import sys
+import threading
+import time
+
+
+# сканируем подсеть
+SUBNET = '192.168.31.0/24'
+# волшебная строка, которую мы будем искать в ICMP-ответах
+MESSAGE = 'PYTHONRULES!'
+
+class IP:
+    def __init__(self, buff):
+        header = struct.unpack('<BBHHHBBH4s4s', buff)
+        self.ver = header[0] >> 4
+        self.ihl = header[0] & 0xF
+
+        self.tos = header[1]
+        self.len = header[2]
+        self.id = header[3]
+        self.offset = header[4]
+        self.ttl = header[5]
+        self.protocol_num = header[6]
+        self.sum = header[7]
+        self.src = header[8]
+        self.dst = header[9]
+
+        # IP-адруса, понятные человек
+        self.src_address = ipaddress.ip_address(self.src)
+        self.dst_address = ipaddress.ip_address(self.dst)
+
+        # сопоставляем константы протоколов с их назначением
+        self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}
+        try:
+            self.protocol = self.protocol_map[self.protocol_num]
+        except Exception as e:
+            print('%s No protocol for %s' % (e, self.protocol_num))
+            self.protocol = str(self.protocol_num)
+
+
+class ICMP:
+    def __init__(self, buff):
+        header = struct.unpack('<BBHHH', buff)
+        self.type = header[0]
+        self.code = header[1]
+        self.sum = header[2]
+        self.id = header[3]
+        self.seq = header[4]
+
+
+# Добавляет в UDP-датаграммы наше волшебное сообщение
+def udp_sender():
+    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sender:
+        for i in range(10):
+            # sender.sendto(bytes(MESSAGE, 'utf8'), ('192.168.31.100', 65212))
+            sender.sendto(bytes(MESSAGE, 'utf8'), ('8.8.8.8', 65212))
+            time.sleep(0.3)
+        # for ip in ipaddress.ip_network(SUBNET).hosts():
+            # print(bytes(MESSAGE, 'utf8'), (str(ip), 65212))
+            # sender.sendto(bytes(MESSAGE, 'utf8'), (str(ip), 65212))
+
+
+class Scanner:
+    def __init__(self, host):
+        self.host = host
+        if os.name == 'nt':
+            socket_protocol = socket.IPPROTO_IP
+        else:
+            socket_protocol = socket.IPPROTO_ICMP
+        
+        self.socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
+        self.socket.bind((host, 0))
+        self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
+
+        if os.name == 'nt':
+            self.socket.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
+
+
+
+    def sniff(self):
+        hosts_up = set([f'{str(self.host)} *'])
+        try:
+            while True:
+                # читаем пакет
+                raw_buffer = self.socket.recvfrom(65535)[0]
+                # создаем IP-заголовок из первых 20 байт
+                ip_header = IP(raw_buffer[0:20])
+                # нас интересует ICMP
+                print(raw_buffer)
+                print(ip_header.src_address, ip_header.dst_address)
+                if ip_header.protocol == 'ICMP':
+                    print('ICMP')
+                    offset = ip_header.ihl * 4
+                    buf = raw_buffer[offset:offset + 8]
+                    # print(raw_buffer)
+                    icmp_header = ICMP(buf)
+                    # ищем тип и код 3
+                    print(icmp_header.code, icmp_header.type)
+                    if icmp_header.code == 3 and icmp_header.type == 3:
+                        print('!')
+                        if ipaddress.ip_address(ip_header.src_address) in ipaddress.IPv4Network(SUBNET):
+                            # проверяем содержит ли буфер наше волшебное сообщение
+                            print(raw_buffer[len(raw_buffer) - len(MESSAGE):])
+                            if raw_buffer[len(raw_buffer) - len(MESSAGE):] == bytes(MESSAGE, 'utf8'):
+                                tgt = str(ip_header.src_address)
+                                print(ip_header.src_address, ip_header.dst_address)
+                                if tgt != self.host and tgt not in hosts_up:
+                                    hosts_up.add(str(ip_header.dst_address))
+                                    print(f'Host Up: {tgt}')
+        # обрабатываем Ctrl+C
+        except KeyboardInterrupt:
+            # если мы в Windows, выключаем неизбирательный режим
+            if os.name == 'nt':
+                self.socket.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
+            
+            print('\nUser interrupted')
+            
+            if hosts_up:
+                print(f'\n\nSummary: Hosts up on {SUBNET}')
+                for host in sorted(hosts_up):
+                    print(f'{host}')
+                print('')
+                sys.exit()
+
+
+
+if __name__ == '__main__':
+    if len(sys.argv) == 2:
+        host = sys.argv[1]
+        s = Scanner(host)
+        # time.sleep(1)
+        t = threading.Thread(target=udp_sender)
+        t.start()
+        s.sniff()
+            
+
+

+ 73 - 0
books/python_black/sniffer_draft.py

@@ -0,0 +1,73 @@
+import socket
+import os
+import ipaddress
+import struct
+
+
+class IP:
+    def __init__(self, buff):
+        header = struct.unpack('<BBHHHBBH4s4s', buff)
+        self.ver = header[0] >> 4
+        self.ihl = header[0] & 0xF
+
+        self.tos = header[1]
+        self.len = header[2]
+        self.id = header[3]
+        self.offset = header[4]
+        self.ttl = header[5]
+        self.protocol_num = header[6]
+        self.sum = header[7]
+        self.src = header[8]
+        self.dst = header[9]
+
+        # IP-адруса, понятные человек
+        self.src_address = ipaddress.ip_address(self.src)
+        self.dst_address = ipaddress.ip_address(self.dst)
+
+        # сопоставляем константы протоколов с их назначением
+        self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}
+
+
+class ICMP:
+    def __init__(self, buff):
+        header = struct.unpack('<BBHHH', buff)
+        self.type = header[0]
+        self.code = header[1]
+        self.sum = header[2]
+        self.id = header[3]
+        self.seq = header[4]
+
+
+        
+
+def sniffer():
+    HOST = '192.168.31.181'
+
+    # создаем сырой сокет и привязываем к общедоступному интерфейсу
+    if os.name == 'nt':
+        socket_protocol = socket.IPPROTO_IP
+    else:
+        socket_protokol = socket.IPPROTO_ICMP
+
+    sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
+    sniffer.bind((HOST, 0))
+    # делаем так, чтобы захватывался IP-заголовок
+    sniffer.setsockopt(socket.IPPROTO_IP, socket.RCVALL_ON, 1)
+    
+    if os.name == 'nt':
+        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
+
+    # читаем один пакет
+    print(sniffer.recvfrom(65565))
+
+    if os.name == 'nt':
+        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
+
+        
+
+def main():
+    sniffer()
+
+
+if __name__ == '__main__':
+    main()

+ 74 - 0
books/python_black/sniffer_ip_header_decode.py

@@ -0,0 +1,74 @@
+import ipaddress
+import os
+import socket
+import struct
+import sys
+
+
+class IP:
+    def __init__(self, buff):
+        header = struct.unpack('<BBHHHBBH4s4s', buff)
+        self.ver = header[0] >> 4
+        self.ihl = header[0] & 0xF
+
+        self.tos = header[1]
+        self.len = header[2]
+        self.id = header[3]
+        self.offset = header[4]
+        self.ttl = header[5]
+        self.protocol_num = header[6]
+        self.sum = header[7]
+        self.src = header[8]
+        self.dst = header[9]
+
+        # IP-адруса, понятные человек
+        self.src_address = ipaddress.ip_address(self.src)
+        self.dst_address = ipaddress.ip_address(self.dst)
+
+        # сопоставляем константы протоколов с их назначением
+        self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}
+        try:
+            self.protocol = self.protocol_map[self.protocol_num]
+        except Exception as e:
+            print('%s No protocol for %s' % (e, self.protocol_num))
+            self.protocol = str(self.protocol_num)
+
+
+def sniff(host):
+    # создаем сырой сокет и привязываем к общедоступному интерфейсу
+    if os.name == 'nt':
+        socket_protocol = socket.IPPROTO_IP
+    else:
+        socket_protokol = socket.IPPROTO_ICMP
+
+    sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
+    sniffer.bind((host, 0))
+    # делаем так, чтобы захватывался IP-заголовок
+    sniffer.setsockopt(socket.IPPROTO_IP, socket.RCVALL_ON, 1)
+    
+    if os.name == 'nt':
+        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
+
+    try:
+        while True:
+            # читаем пакет
+            raw_buffer = sniffer.recvfrom(65535)[0]
+            # создаем IP-заголовок из первый 20 байтов
+            ip_header = IP(raw_buffer[0:20])
+            # выводим обнаруженный протокол и адреса
+            print("Protocol: %s %s -> %s" % (ip_header.protocol,
+                                                   ip_header.src_address,
+                                                   ip_header.dst_address))
+            
+    except KeyboardInterrupt:
+        # если мы в Windows, выключаем неизбирательный режим
+        if os.name == 'nt':
+            sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
+        sys.exit()
+
+
+if __name__ == '__main__':
+    if len(sys.argv) == 2:
+        host = sys.argv[1]
+        sniff(host)
+

+ 93 - 0
books/python_black/sniffer_with_icmp.py

@@ -0,0 +1,93 @@
+import ipaddress
+import os
+import socket
+import struct
+import sys
+
+
+class IP:
+    def __init__(self, buff):
+        header = struct.unpack('<BBHHHBBH4s4s', buff)
+        self.ver = header[0] >> 4
+        self.ihl = header[0] & 0xF
+
+        self.tos = header[1]
+        self.len = header[2]
+        self.id = header[3]
+        self.offset = header[4]
+        self.ttl = header[5]
+        self.protocol_num = header[6]
+        self.sum = header[7]
+        self.src = header[8]
+        self.dst = header[9]
+
+        # IP-адруса, понятные человек
+        self.src_address = ipaddress.ip_address(self.src)
+        self.dst_address = ipaddress.ip_address(self.dst)
+
+        # сопоставляем константы протоколов с их назначением
+        self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}
+        try:
+            self.protocol = self.protocol_map[self.protocol_num]
+        except Exception as e:
+            print('%s No protocol for %s' % (e, self.protocol_num))
+            self.protocol = str(self.protocol_num)
+
+
+class ICMP:
+    def __init__(self, buff):
+        header = struct.unpack('<BBHHH', buff)
+        self.type = header[0]
+        self.code = header[1]
+        self.sum = header[2]
+        self.id = header[3]
+        self.seq = header[4]
+
+    
+def sniff(host):
+    # создаем сырой сокет и привязываем к общедоступному интерфейсу
+    if os.name == 'nt':
+        socket_protocol = socket.IPPROTO_IP
+    else:
+        socket_protokol = socket.IPPROTO_ICMP
+
+    sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
+    sniffer.bind((host, 0))
+    # делаем так, чтобы захватывался IP-заголовок
+    sniffer.setsockopt(socket.IPPROTO_IP, socket.RCVALL_ON, 1)
+    
+    if os.name == 'nt':
+        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
+
+    try:
+        while True:
+            # читаем пакет
+            raw_buffer = sniffer.recvfrom(65535)[0]
+            # создаем IP-заголовок из первый 20 байтов
+            ip_header = IP(raw_buffer[0:20])
+            # нас интересует ICMP
+            if ip_header.protocol == 'ICMP':
+                print("Protocol: %s %s -> %s" % (ip_header.protocol,
+                                                ip_header.src_address,
+                                                ip_header.dst_address))
+            print(f'Version: {ip_header.ver}')
+            print(f'Header Length: {ip_header.ihl} TTL: {ip_header.ttl}')
+
+            # определяем где начинается ICMP-пакет
+            offset = ip_header.ihl * 4
+            buf = raw_buffer[offset:offset + 8]
+            # создаем структуру ICMP
+            icmp_header = ICMP(buf)
+            print('ICMP -> Type: %s Code: %s\n' % (icmp_header.type, icmp_header.code))
+
+    except KeyboardInterrupt:
+        # если мы в Windows, выключаем неизбирательный режим
+        if os.name == 'nt':
+            sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
+        sys.exit()
+
+
+if __name__ == '__main__':
+    if len(sys.argv) == 2:
+        host = sys.argv[1]
+        sniff(host)