Android 蓝牙抓包(2) 使用xposed框架实现蓝牙BLE抓包

插件地址 https://github.com/852172891/XposedBLE
实现之前先了解一下android BLE的数据读写流程。

android BLE的数据读写流程

首先获取BluetoothGatt

 BluetoothGatt mGatt = device.connectGatt(mContext, false, gattCallback);

写数据

boolean result = mGatt.writeCharacteristic(characteristic);

读数据

mGatt.readCharacteristic(characteristic)

从上边的代码可以看出,蓝牙的读写都是调用BluetoothGatt 中的方法。
下边分别看一下BluetoothGatt 的writeCharacteristic和readCharacteristic实现。这两个方法中参数都是BluetoothGattCharacteristic ,在BluetoothGattCharacteristic 中有两个最重要的参数 protected byte[] mValue;
protected UUID mUuid;一个是传输的内容,一个是对应的UUID,做过蓝牙开发的都知道这2 个参数的重要性。

 /**
     * Writes a given characteristic and its values to the associated remote device.
     *
     * 

Once the write operation has been completed, the * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked, * reporting the result of the operation. * *

Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param characteristic Characteristic to write on the remote device * @return true, if the write operation was initiated successfully */ public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) { if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0 && (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false; if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid()); if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false; BluetoothGattService service = characteristic.getService(); if (service == null) return false; BluetoothDevice device = service.getDevice(); if (device == null) return false; synchronized(mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } try { mService.writeCharacteristic(mClientIf, device.getAddress(), characteristic.getInstanceId(), characteristic.getWriteType(), AUTHENTICATION_NONE, characteristic.getValue()); } catch (RemoteException e) { Log.e(TAG,"",e); mDeviceBusy = false; return false; } return true; }

readCharacteristic 方法

 /**
     * Reads the requested characteristic from the associated remote device.
     *
     * 

This is an asynchronous operation. The result of the read operation * is reported by the {@link BluetoothGattCallback#onCharacteristicRead} * callback. * *

Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param characteristic Characteristic to read from the remote device * @return true, if the read operation was initiated successfully */ public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) { if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false; if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid()); if (mService == null || mClientIf == 0) return false; BluetoothGattService service = characteristic.getService(); if (service == null) return false; BluetoothDevice device = service.getDevice(); if (device == null) return false; synchronized(mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } try { mService.readCharacteristic(mClientIf, device.getAddress(), characteristic.getInstanceId(), AUTHENTICATION_NONE); } catch (RemoteException e) { Log.e(TAG,"",e); mDeviceBusy = false; return false; } return true; }

插件的实现

关键代码:首先获取 BluetoothGatt,hook readCharacteristic 和writeCharacteristic方法。

 Class bluetooth = lpparam.classLoader.loadClass("android.bluetooth.BluetoothGatt");
            try {
                if (bluetooth != null) {
                    XposedHelpers.findAndHookMethod(bluetooth, "writeCharacteristic", BluetoothGattCharacteristic.class, new XC_MethodHook() {
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            BluetoothGattCharacteristic bluetoothGattCharacteristic = (BluetoothGattCharacteristic) param.args[0];
                            byte[] mValue = bluetoothGattCharacteristic.getValue();

                            String str = "";
                            if (mValue != null) {
                                for (int i = 0; i < mValue.length; i++) {
                                    str += String.format("%x ", mValue[i]);
                                }
                            }
                            Log.e("packageName" + lpparam.packageName, "writeCharacteristic   str :" + str + " bluetoothGattCharacteristic" + bluetoothGattCharacteristic.getUuid().toString());

                        }
                    });

                    XposedHelpers.findAndHookMethod(bluetooth, "readCharacteristic", BluetoothGattCharacteristic.class, new XC_MethodHook() {
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            BluetoothGattCharacteristic bluetoothGattCharacteristic = (BluetoothGattCharacteristic) param.args[0];
                            byte[] mValue = bluetoothGattCharacteristic.getValue();

                            String str = "";
                            if (mValue != null) {
                                for (int i = 0; i < mValue.length; i++) {
                                    str += String.format("%x ", mValue[i]);
                                }
                            }
                            Log.e("packageName" + lpparam.packageName, "readCharacteristic   str :" + str + " bluetoothGattCharacteristic" + bluetoothGattCharacteristic.getUuid().toString());
                        }
                    });


                }
            } catch (Exception e) {
                Log.e("wanghaha", e.toString());
            }

效果展示:用某手环和它配套的app测试了一下
Android 蓝牙抓包(2) 使用xposed框架实现蓝牙BLE抓包_第1张图片

插件的意义

分析蓝牙传输过程,当你没有协议的时候。

我是IT小王,如果喜欢我的文章,可以扫码关注我的微信公众号
Android 蓝牙抓包(2) 使用xposed框架实现蓝牙BLE抓包_第2张图片

你可能感兴趣的:(逆向与安全)