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.
     *
     * <p>Once the write operation has been completed, the
     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
     * reporting the result of the operation.
     *
     * <p>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.
     *
     * <p>This is an asynchronous operation. The result of the read operation
     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
     * callback.
     *
     * <p>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測試了一下
在這裏插入圖片描述

插件的意義

分析藍牙傳輸過程,當你沒有協議的時候。

我是IT小王,如果喜歡我的文章,可以掃碼關注我的微信公衆號
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章