mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2025-02-07 12:44:03 -05:00
fragattack: add separate connected event
This commit is contained in:
parent
16fa93c888
commit
22f603ceac
@ -60,7 +60,11 @@ class TestOptions():
|
||||
|
||||
class MetaFrag():
|
||||
# StartingAuth, AfterAuthRace
|
||||
BeforeAuth, BeforeAuthDone, AfterAuth = range(3)
|
||||
# StartAuth: when starting the handshake
|
||||
# BeforeAuth: right before last message of the handshake
|
||||
# AfterAuth: right after last message of the handshake
|
||||
# Connected: 1 second after handshake completed (allows peer to install keys)
|
||||
StartAuth, BeforeAuth, AfterAuth, Connected = range(4)
|
||||
|
||||
def __init__(self, frag, trigger, encrypted, inc_pn=1):
|
||||
self.frag = frag
|
||||
@ -113,6 +117,8 @@ class Station():
|
||||
self.othermac = None
|
||||
self.otherip = None
|
||||
|
||||
self.time_connected = None
|
||||
|
||||
def reset_keys(self):
|
||||
self.tk = None
|
||||
# TODO: Get the current PN from the kernel, increment by 0x99,
|
||||
@ -404,13 +410,13 @@ class Station():
|
||||
|
||||
# Inject any fragments before authenticating
|
||||
if not self.txed_before_auth:
|
||||
log(STATUS, "MetaFrag.BeforeAuth", color="green")
|
||||
self.inject_next_frags(MetaFrag.BeforeAuth)
|
||||
log(STATUS, "MetaFrag.StartAuth", color="green")
|
||||
self.inject_next_frags(MetaFrag.StartAuth)
|
||||
self.txed_before_auth = True
|
||||
# Inject any fragments when almost done authenticating
|
||||
elif is_msg3_or_4 and not self.txed_before_auth_done:
|
||||
log(STATUS, "MetaFrag.BeforeAuthDone", color="green")
|
||||
self.inject_next_frags(MetaFrag.BeforeAuthDone)
|
||||
log(STATUS, "MetaFrag.BeforeAuth", color="green")
|
||||
self.inject_next_frags(MetaFrag.BeforeAuth)
|
||||
self.txed_before_auth_done = True
|
||||
|
||||
def handle_eapol_tx(self, eapol):
|
||||
@ -428,23 +434,36 @@ class Station():
|
||||
|
||||
def handle_authenticated(self):
|
||||
"""Called after completion of the 4-way handshake or similar"""
|
||||
if not self.obtained_ip: return
|
||||
|
||||
log(STATUS, "MetaFrag.AfterAuth", color="green")
|
||||
self.tk = self.daemon.get_tk(self)
|
||||
self.gtk, self.gtk_idx = self.daemon.get_gtk()
|
||||
|
||||
time.sleep(1)
|
||||
if not self.obtained_ip: return
|
||||
|
||||
log(STATUS, "MetaFrag.AfterAuth", color="green")
|
||||
self.inject_next_frags(MetaFrag.AfterAuth)
|
||||
|
||||
self.time_connected = time.time() + 1
|
||||
|
||||
def handle_connected(self):
|
||||
"""This is called ~1 second after completing the handshake"""
|
||||
log(STATUS, "MetaFrag.Connected", color="green")
|
||||
self.inject_next_frags(MetaFrag.Connected)
|
||||
|
||||
def set_ip_addresses(self, ip, peerip):
|
||||
self.ip = ip
|
||||
self.peerip = peerip
|
||||
self.obtained_ip = True
|
||||
|
||||
# We can generate tests once we have an IP
|
||||
# We can generate tests once we know the IP addresses
|
||||
self.generate_tests()
|
||||
|
||||
def time_tick(self):
|
||||
# XXX extra check on self.obtained_ip so when the only test is on Connected event,
|
||||
# this test can be run without requiring a reconnect.
|
||||
if self.time_connected != None and time.time() > self.time_connected and self.obtained_ip:
|
||||
self.handle_connected()
|
||||
self.time_connected = None
|
||||
|
||||
class Daemon():
|
||||
def __init__(self, options):
|
||||
self.options = options
|
||||
@ -470,6 +489,10 @@ class Daemon():
|
||||
def handle_eth(self, p):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def time_tick(self, station):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_tk(self, station):
|
||||
pass
|
||||
@ -535,7 +558,7 @@ class Daemon():
|
||||
|
||||
# Monitor the virtual monitor interface of the client and perform the needed actions
|
||||
while True:
|
||||
sel = select.select([self.sock_mon, self.sock_eth, self.wpaspy_ctrl.s], [], [], 1)
|
||||
sel = select.select([self.sock_mon, self.sock_eth, self.wpaspy_ctrl.s], [], [], 0.5)
|
||||
if self.sock_mon in sel[0]:
|
||||
p = self.sock_mon.recv()
|
||||
if p != None: self.handle_mon(p)
|
||||
@ -548,6 +571,8 @@ class Daemon():
|
||||
msg = self.wpaspy_ctrl.recv()
|
||||
self.handle_wpaspy(msg)
|
||||
|
||||
self.time_tick()
|
||||
|
||||
def stop(self):
|
||||
log(STATUS, "Closing Hostap daemon and cleaning up ...")
|
||||
if self.process:
|
||||
@ -572,6 +597,10 @@ class Authenticator(Daemon):
|
||||
tk = wpaspy_command(self.wpaspy_ctrl, "GET_TK " + station.peermac)
|
||||
return bytes.fromhex(tk)
|
||||
|
||||
def time_tick(self):
|
||||
for station in self.stations.items():
|
||||
station.time_tick()
|
||||
|
||||
def force_reconnect(self, station):
|
||||
# Confirmed to *instantly* reconnect: Arch Linux, Windows 10 with Intel WiFi chip, iPad Pro 13.3.1
|
||||
# Reconnects only after a few seconds: MacOS (same with other reasons and with deauthentication)
|
||||
@ -675,6 +704,7 @@ class Supplicant(Daemon):
|
||||
super().__init__(options)
|
||||
self.station = None
|
||||
self.arp_sock = None
|
||||
self.time_dhcp_discover = None
|
||||
|
||||
def get_tk(self, station):
|
||||
tk = wpaspy_command(self.wpaspy_ctrl, "GET tk")
|
||||
@ -683,6 +713,14 @@ class Supplicant(Daemon):
|
||||
else:
|
||||
return bytes.fromhex(tk)
|
||||
|
||||
def time_tick(self):
|
||||
self.station.time_tick()
|
||||
|
||||
if self.time_dhcp_discover != None and time.time() > self.time_dhcp_discover:
|
||||
# TODO: Create a timer in case retransmissions are needed
|
||||
self.send_dhcp_discover()
|
||||
self.time_dhcp_discover = None
|
||||
|
||||
def send_dhcp_discover(self):
|
||||
rawmac = bytes.fromhex(self.station.mac.replace(':', ''))
|
||||
req = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.station.mac)/IP(src="0.0.0.0", dst="255.255.255.255")
|
||||
@ -742,15 +780,11 @@ class Supplicant(Daemon):
|
||||
log(STATUS, "daemon: " + msg)
|
||||
|
||||
if "CTRL-EVENT-CONNECTED" in msg:
|
||||
if not self.station.obtained_ip:
|
||||
# TODO: Create a timer in case retransmissions are needed
|
||||
# This get's the current keys
|
||||
self.station.handle_authenticated()
|
||||
|
||||
# Sleep to make sure the AP installed the key
|
||||
time.sleep(1)
|
||||
self.send_dhcp_discover()
|
||||
self.send_dhcp_discover()
|
||||
else:
|
||||
self.station.handle_authenticated()
|
||||
if not self.station.obtained_ip:
|
||||
self.time_dhcp_discover = time.time() + 0.5
|
||||
|
||||
# Trying to authenticate with 38:2c:4a:c1:69:bc (SSID='backupnetwork2' freq=2462 MHz)
|
||||
elif "Trying to authenticate with" in msg:
|
||||
|
Loading…
Reference in New Issue
Block a user