diff --git a/research/fragattack.py b/research/fragattack.py index e808c3b5b..886a38a3c 100755 --- a/research/fragattack.py +++ b/research/fragattack.py @@ -223,6 +223,8 @@ if __name__ == "__main__": parser.add_argument('--full-reconnect', default=False, action='store_true', help="Reconnect by deauthenticating first.") parser.add_argument('--bcast-ra', default=False, action='store_true', help="Send pings using broadcast *receiver* address (= addr1).") parser.add_argument('--bcast-dst', default=False, action='store_true', help="Send pings using broadcast *destination* when to AP ().") + # TODO: Properly test the --bad-mic option + parser.add_argument('--bad-mic', default=False, action='store_true', help="Send pings using an invalid authentication tag.") parser.add_argument('--pn-per-qos', default=False, action='store_true', help="Use separate Tx packet counter for each QoS TID.") parser.add_argument('--freebsd-cache', default=False, action='store_true', help="Sent EAP(OL) frames as (malformed) broadcast EAPOL/A-MSDUs.") parser.add_argument('--connected-delay', type=float, default=1, help="Second to wait after AfterAuth before triggering Connected event") diff --git a/research/fraginternals.py b/research/fraginternals.py index 57313cc1a..0a47e6ac7 100644 --- a/research/fraginternals.py +++ b/research/fraginternals.py @@ -159,7 +159,7 @@ class Action(): # Drop: when fragmenting frames, skip the next fragment number. Used in PingTest. MetaDrop = range(0) - def __init__(self, trigger=Connected, action=Inject, meta_action=None, func=None, enc=False, frame=None, inc_pn=1, delay=None, wait=None, key=None): + def __init__(self, trigger=Connected, action=Inject, meta_action=None, func=None, enc=False, frame=None, inc_pn=1, bad_mic=False, delay=None, wait=None, key=None): self.trigger = trigger self.action = action @@ -182,6 +182,7 @@ class Action(): # Specific to fragment injection self.encrypted = enc self.inc_pn = inc_pn + self.bad_mic = bad_mic self.delay = delay self.frame = frame self.key = key @@ -433,6 +434,8 @@ class Station(): return header def encrypt(self, frame, inc_pn=1, force_key=None): + # TODO: Add argument to force a bad authenticity check + idx = dot11_get_priority(frame) if self.options.pn_per_qos else 0 self.pn[idx] += inc_pn @@ -441,7 +444,10 @@ class Station(): log(STATUS, "Encrypting with all-zero key") key = b"\x00" * len(key) - if len(key) == 16: + if len(key) == 32: + # TODO: Implement and test this function + encrypted = encrypt_tkip(frame, key, self.pn[idx], keyid) + elif len(key) == 16: encrypted = encrypt_ccmp(frame, key, self.pn[idx], keyid) else: encrypted = encrypt_wep(frame, key, self.pn[idx], keyid) diff --git a/research/tests_common.py b/research/tests_common.py index 5c1bf8827..1afaaf2da 100644 --- a/research/tests_common.py +++ b/research/tests_common.py @@ -13,6 +13,7 @@ class PingTest(Test): self.icmp_size = None if opt == None else opt.icmp_size self.padding = None if opt == None else opt.padding self.to_self = False if opt == None else opt.to_self + self.bad_mic = False if opt == None else opt.bad_mic self.parse_meta_actions() @@ -59,9 +60,11 @@ class PingTest(Test): # Assign fragment numbers according to MetaDrop rules frame.SC = (frame.SC & 0xfff0) | self.fragnums.pop(0) - frag.frame = frame + # Take into account encryption options + frag.bad_mic = self.bad_mic + # Put the separator after each fragment if requested. if self.separate_with != None: for i in range(len(self.actions) - 1, 0, -1): @@ -109,7 +112,7 @@ class ForwardTest(Test): else: request = LLC()/SNAP()/IP()/Raw(self.magic) - # Wether to send large requests + # Wether to send large requests --- TODO FIXME ath9k_htc cannot reliably send large frames... if self.large: request = request/Raw(b"A" * 1500) diff --git a/research/tests_qca.py b/research/tests_qca.py index 58013fb96..4e2ffff29 100644 --- a/research/tests_qca.py +++ b/research/tests_qca.py @@ -62,7 +62,9 @@ class QcaTestSplit(Test): controller that will perform the actual defragmentation. Essential remarks: - Sending [Encrypted, Plaintext] and [Plaintext, Encrypted] failed. It is - not clear why this is the case. + not clear why this is the case. It could be that the second Plaintext fragment + might be overwriting the first Encrypted fragment. And it depends on whether + the controller rejects plaintext fragments. - You must send [Plaintext, Encrypted2] and [Encrypted1, Plaintext]. Note that we first inject Encrypted2, which has a *higher* packet number than Encrypted1.