Created
October 11, 2019 12:32
-
-
Save silviot/e5360836fdf88f451630384759fa8d91 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
"""Monitor signal strength of wifi deauthentication packets | |
""" | |
from ascii_graph import Pyasciigraph | |
from ascii_graph.colordata import hcolor | |
from ascii_graph.colordata import vcolor | |
from ascii_graph.colors import Blu, Red, Yel, Gre | |
from scapy.all import Dot11, sniff | |
from datetime import datetime | |
from itertools import groupby | |
import os | |
import sys | |
RETAIN_PERIOD = 100 # In REFRESH_INTERVALs | |
REFRESH_INTERVAL = 0.1 # In seconds | |
THRESHOLDS = {-80: Red, -70: Blu, -60: Yel, 0: Gre} | |
# Packet subtype constants | |
ASSOREQ = 0 | |
ASSORESPO = 1 | |
REASSOREQ = 2 | |
REASSORESP = 3 | |
PROBEREQ = 4 | |
PROBERESP = 5 | |
BEACON = 8 | |
ATIM = 9 | |
DISAS = 10 | |
AUTH = 11 | |
DEAUTH = 12 # The one we're actually interested in | |
ACK = 13 | |
def PacketHandler(packet): | |
if packet.haslayer(Dot11): | |
if packet.type == 0 and packet.subtype == DEAUTH: | |
handle_packet(packet) | |
# if packet.type == 0 and packet.subtype == BEACON and packet.info == b'Shielded': | |
# handle_packet(packet) | |
SSIDS = [] | |
ATTACKS_PERIODS = {} | |
LAST_DISPLAYED = dict(tstamp=0) # last timestamp disaplayed on screen | |
def handle_packet(packet): | |
dest = packet.addr2 | |
ATTACKS_PERIODS.setdefault(LAST_DISPLAYED["tstamp"], []).append(packet) | |
this_display = (datetime.now().timestamp() // REFRESH_INTERVAL) * REFRESH_INTERVAL | |
if this_display != LAST_DISPLAYED["tstamp"]: | |
LAST_DISPLAYED["tstamp"] = this_display | |
print_attacks() | |
cleanup_attacks() | |
def print_attacks(): | |
print("\033c", end="") | |
to_print = [] | |
interfaces = [] | |
to_print.append(f"{LAST_DISPLAYED['tstamp']} {' - '.join(interfaces)}") | |
to_print.append( | |
f"Attacks in the past {int(RETAIN_PERIOD * REFRESH_INTERVAL)} seconds: {sum(map(len, ATTACKS_PERIODS.values()))}" | |
) | |
graph = [] | |
for _, packets in sorted(ATTACKS_PERIODS.items(), reverse=True): | |
for channel, powers in groupby( | |
sorted([(el.ChannelFrequency, el.dBm_AntSignal) for el in packets]), | |
key=lambda x: x[0], | |
): | |
graph.append((channel, average(el[1] for el in powers))) | |
rows, columns = os.popen("stty size", "r").read().split() | |
graph_height = int(rows) - 5 | |
data = hcolor(graph[:graph_height], THRESHOLDS) | |
#data = graph[:graph_height] | |
for line in Pyasciigraph( | |
min_graph_length=10, | |
multivalue=False, | |
line_length=int(columns) - 20, | |
).graph("Signal strengths", data): | |
to_print.append(line) | |
print("\n".join(to_print)) | |
def average(values): | |
if not isinstance(values, (list, tuple)): | |
values = list(values) | |
return sum(values) / len(values) | |
def cleanup_attacks(): | |
threshold = datetime.now().timestamp() - (RETAIN_PERIOD * REFRESH_INTERVAL) | |
for tstamp in list(ATTACKS_PERIODS): | |
if tstamp < threshold: | |
del ATTACKS_PERIODS[tstamp] | |
def main(): | |
if len(sys.argv) < 2: | |
print(f"Provide an interface name, like this:\n{sys.argv[0]} wlan0") | |
sys.exit(1) | |
sniff(iface=sys.argv[1], prn=PacketHandler) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment