mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
fragattack: make injection selftest work on ath9k_htc
This commit is contained in:
parent
e4ac2d88ed
commit
3331b80fb7
@ -10,35 +10,6 @@ from scapy.arch.common import get_if_raw_hwaddr
|
|||||||
|
|
||||||
from tests_qca import *
|
from tests_qca import *
|
||||||
|
|
||||||
# Ath9k_htc dongle notes:
|
|
||||||
# - The ath9k_htc devices by default overwrite the injected sequence number.
|
|
||||||
# However, this number is not incremented when the MoreFragments flag is set,
|
|
||||||
# meaning we can inject fragmented frames (albeit with a different sequence
|
|
||||||
# number than then one we use for injection this this script).
|
|
||||||
# - The above trick does not work when we want to inject other frames between
|
|
||||||
# two fragmented frames (the chip will assign them difference sequence numbers).
|
|
||||||
# Even when the fragments use a unique QoS TID, sending frames between them
|
|
||||||
# will make the chip assign difference sequence numbers to both fragments.
|
|
||||||
# - Overwriting the sequence can be avoided by patching `ath_tgt_tx_seqno_normal`
|
|
||||||
# and commenting out the two lines that modify `i_seq`.
|
|
||||||
# - See also the comment in Station.perform_actions to avoid other bugs with
|
|
||||||
# ath9k_htc when injecting frames with the MF flag and while being in AP mode.
|
|
||||||
# - The at9k_htc dongle, and likely other Wi-Fi devices, will reorder frames with
|
|
||||||
# different QoS priorities. This means injected frames with differen priorities
|
|
||||||
# may get reordered by the driver/chip. We avoided this by modifying the ath9k_htc
|
|
||||||
# driver to send all frames using the transmission queue of priority zero,
|
|
||||||
# independent of the actual QoS priority value used in the frame.
|
|
||||||
|
|
||||||
# Intel 8265 / 8275 (rev 78)
|
|
||||||
# - Had to patch driver to prevent sequence number and QoS TID to be overwritten.
|
|
||||||
# - Unable to transmit any frames from a different transmitter address. This is
|
|
||||||
# because in ieee80211_monitor_start_xmit it cannot find a channel to transmit
|
|
||||||
# on (finding a valid chandef fails).
|
|
||||||
# - Cannot inject frames using a TID that is used for the first time. There's no
|
|
||||||
# queue in the driver allocated for it yet it seems, and this causes issues.
|
|
||||||
# To prevent this, and prevent frame reordering, we inject all frames on the
|
|
||||||
# same queue in the driver.
|
|
||||||
|
|
||||||
# ----------------------------------- Utility Commands -----------------------------------
|
# ----------------------------------- Utility Commands -----------------------------------
|
||||||
|
|
||||||
def wpaspy_clear_messages(ctrl):
|
def wpaspy_clear_messages(ctrl):
|
||||||
@ -47,6 +18,7 @@ def wpaspy_clear_messages(ctrl):
|
|||||||
while ctrl.pending():
|
while ctrl.pending():
|
||||||
ctrl.recv()
|
ctrl.recv()
|
||||||
|
|
||||||
|
#TODO: Modify so we can ignore other messages over the command interface
|
||||||
def wpaspy_command(ctrl, cmd):
|
def wpaspy_command(ctrl, cmd):
|
||||||
wpaspy_clear_messages(ctrl)
|
wpaspy_clear_messages(ctrl)
|
||||||
rval = ctrl.request(cmd)
|
rval = ctrl.request(cmd)
|
||||||
@ -144,10 +116,14 @@ def set_monitor_mode(iface):
|
|||||||
# ----------------------------------- Injection Tests -----------------------------------
|
# ----------------------------------- Injection Tests -----------------------------------
|
||||||
|
|
||||||
def test_packet_injection(sout, sin, p, test_func):
|
def test_packet_injection(sout, sin, p, test_func):
|
||||||
|
log(WARNING, "Testing injection")
|
||||||
|
|
||||||
# Append unique label to recognize frame & inject it
|
# Append unique label to recognize frame & inject it
|
||||||
label = b"AAAA" + struct.pack(">II", random.randint(0, 2**32), random.randint(0, 2**32))
|
label = b"AAAA" + struct.pack(">II", random.randint(0, 2**32), random.randint(0, 2**32))
|
||||||
sout.send(RadioTap()/p/Raw(label))
|
sout.send(RadioTap()/p/Raw(label))
|
||||||
|
|
||||||
|
#TODO: Should we prevent ath9k_htc injection bug after injecting a fragment?
|
||||||
|
|
||||||
# 1. When using a 2nd interface: capture the actual packet that was injected in the air.
|
# 1. When using a 2nd interface: capture the actual packet that was injected in the air.
|
||||||
# 2. Not using 2nd interface: capture the "reflected" frame sent back by the kernel. This allows
|
# 2. Not using 2nd interface: capture the "reflected" frame sent back by the kernel. This allows
|
||||||
# us to at least detect if the kernel (and perhaps driver) is overwriting fields. It generally
|
# us to at least detect if the kernel (and perhaps driver) is overwriting fields. It generally
|
||||||
@ -167,15 +143,15 @@ def test_injection(iface_out, iface_in=None):
|
|||||||
else:
|
else:
|
||||||
sin = L2Socket(type=ETH_P_ALL, iface=iface_in)
|
sin = L2Socket(type=ETH_P_ALL, iface=iface_in)
|
||||||
|
|
||||||
p = Dot11(addr1="00:11:11:11:11:11", addr2="00:22:22:22:22:22", type=2, SC=33<<4)
|
p = Dot11(addr1="00:11:00:00:00:01", addr2="00:22:00:00:00:01", type=2, SC=33<<4)
|
||||||
if not test_packet_injection(sout, sin, p, lambda cap: cap.SC == p.SC):
|
if not test_packet_injection(sout, sin, p, lambda cap: cap.SC == p.SC):
|
||||||
raise IOError("Sequence number of injected frames is being overwritten!")
|
raise IOError("Sequence number of injected frames is being overwritten!")
|
||||||
|
|
||||||
p = Dot11(addr1="00:11:11:11:11:11", addr2="00:22:22:22:22:22", type=2, SC=(33<<4)|1)
|
p = Dot11(addr1="00:11:00:00:00:02", addr2="00:22:00:00:00:02", type=2, SC=(33<<4)|1)
|
||||||
if not test_packet_injection(sout, sin, p, lambda cap: (cap.SC & 0xf) == 1):
|
if not test_packet_injection(sout, sin, p, lambda cap: (cap.SC & 0xf) == 1):
|
||||||
raise IOError("Fragment number of injected frames is being overwritten!")
|
raise IOError("Fragment number of injected frames is being overwritten!")
|
||||||
|
|
||||||
p = Dot11(addr1="00:11:11:11:11:11", addr2="00:22:22:22:22:22", type=2, subtype=8, SC=33)/Dot11QoS(TID=2)
|
p = Dot11(addr1="00:11:00:00:00:03", addr2="00:22:00:00:00:03", type=2, subtype=8, SC=33)/Dot11QoS(TID=2)
|
||||||
if not test_packet_injection(sout, sin, p, lambda cap: cap.TID == p.TID):
|
if not test_packet_injection(sout, sin, p, lambda cap: cap.TID == p.TID):
|
||||||
raise IOError("QoS TID of injected frames is being overwritten!")
|
raise IOError("QoS TID of injected frames is being overwritten!")
|
||||||
|
|
||||||
@ -702,8 +678,8 @@ class Station():
|
|||||||
p = p/payload
|
p = p/payload
|
||||||
if self.tk: p = self.encrypt(p)
|
if self.tk: p = self.encrypt(p)
|
||||||
|
|
||||||
log(STATUS, "[Injecting] " + repr(p))
|
|
||||||
daemon.inject_mon(p)
|
daemon.inject_mon(p)
|
||||||
|
log(STATUS, "[Injected] " + repr(p))
|
||||||
|
|
||||||
def set_header(self, p, prior=None):
|
def set_header(self, p, prior=None):
|
||||||
"""Set addresses to send frame to the peer or the 3rd party station."""
|
"""Set addresses to send frame to the peer or the 3rd party station."""
|
||||||
@ -1064,7 +1040,7 @@ class Daemon(metaclass=abc.ABCMeta):
|
|||||||
# must be executed once we are trying to connect so the channel is "stable".
|
# must be executed once we are trying to connect so the channel is "stable".
|
||||||
try: test_injection(self.nic_mon)
|
try: test_injection(self.nic_mon)
|
||||||
except IOError as ex:
|
except IOError as ex:
|
||||||
log(WARNING, "IOError: " + ex.args[0])
|
log(WARNING, ex.args[0])
|
||||||
log(ERROR, "Injection self-test failed. Are you using the correct kernel/driver/device for injection?")
|
log(ERROR, "Injection self-test failed. Are you using the correct kernel/driver/device for injection?")
|
||||||
quit(1)
|
quit(1)
|
||||||
|
|
||||||
@ -1429,12 +1405,16 @@ class Supplicant(Daemon):
|
|||||||
log(STATUS, f"{self.nic_mon}: setting to channel {channel}")
|
log(STATUS, f"{self.nic_mon}: setting to channel {channel}")
|
||||||
log(STATUS, f"{self.nic_hwsim}: setting to channel {channel}")
|
log(STATUS, f"{self.nic_hwsim}: setting to channel {channel}")
|
||||||
|
|
||||||
self.injection_selftest()
|
|
||||||
|
|
||||||
p = re.compile("Trying to authenticate with (.*) \(SSID")
|
p = re.compile("Trying to authenticate with (.*) \(SSID")
|
||||||
bss = p.search(msg).group(1)
|
bss = p.search(msg).group(1)
|
||||||
self.station.handle_connecting(bss)
|
self.station.handle_connecting(bss)
|
||||||
|
|
||||||
|
elif "Trying to associate with" in msg:
|
||||||
|
# With the ath9k_htc, injection in mixed managed/monitor only works after
|
||||||
|
# sending the association request. So only perform injection test now.
|
||||||
|
# TODO: Only do a self-test when in mixed managed/monitor mode?
|
||||||
|
self.injection_selftest()
|
||||||
|
|
||||||
elif "EAPOL-TX" in msg:
|
elif "EAPOL-TX" in msg:
|
||||||
cmd, srcaddr, payload = msg.split()
|
cmd, srcaddr, payload = msg.split()
|
||||||
self.station.handle_eapol_tx(bytes.fromhex(payload))
|
self.station.handle_eapol_tx(bytes.fromhex(payload))
|
||||||
|
Loading…
Reference in New Issue
Block a user