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