实战分析某租房App实现一键解锁个人蓝牙门锁
字数 1324 2025-08-29 08:30:36

某租房App蓝牙门锁一键解锁实战分析

测试环境准备

  • 设备: Pixel 3
  • Android版本: 12
  • Root工具: Magisk Delta 26.4-kitsune (26400)

分析流程

一、获取安装包

首先需要提取目标App的安装包(APK文件),可以通过以下方式获取:

  • 使用ADB命令从已安装设备提取
  • 从应用商店下载
  • 使用第三方APK提取工具

二、反编译APK获取DEX

使用在线反编译网站或本地工具将APK转换为可分析的DEX/JAR文件:

  • jadx-gui
  • Apktool
  • dex2jar等工具

三、使用jadx-gui分析源码

  1. 定位应用入口

    • 确定App主包位置:com.xxxx.xxxxxxxxxxxx.application.MyApplication
  2. 搜索关键字符串

    • 全局搜索"开锁成功"字符串
    • 通过提示词定位到蓝牙开锁相关代码区域
  3. 分析蓝牙模块

    • 右键查看onScanSuccess的查找用例
    • 选择可分析的代码路径(第二个用例)
    • unLockResultSuccess函数使用Frida进行hook验证
  4. 深入分析解锁流程

    • 查看unLockResultSuccess接口实现
    • 定位到75行左右的函数调用处
    • 分析调用蓝牙解锁的核心代码

四、获取蓝牙密钥

  1. 定位AES解密代码

    • 找到AESUtil.Decrypt函数
    • 使用Frida hook该函数并打印参数
  2. 获取密钥

    • 从hook结果中提取str2参数(蓝牙密钥)

五、分析蓝牙通信流程

  1. 数据发送分析

    • 定位AESUtil.Encrypt()函数
    • 使用Frida hook加密函数
    • 分析hook结果发现App发送两次数据
  2. 通信流程解析

    App发送: 初始字符串"A" → AES加密 → 发送给门锁
    门锁返回: 加密数据"B"
    App处理: 解密"B" → 截取第7-14位(8位) → 构造新字符串 → AES加密 → 发送给门锁 → 开锁成功
    
  3. 数据格式细节

    • 初始字符串: "01010100000000000000000000000000"
    • 返回数据处理: 截取解密后字符串的第7-14位(共8位)
    • 第二次发送数据格式: 02010501[8位数据]0000000000000000

六、蓝牙调试验证

  1. 使用蓝牙调试助手

    • 发送第一个固定加密数据
    • 验证是否能收到门锁返回数据
  2. 验证结果

    • 成功接收门锁返回数据,证明分析方向正确

七、实现自动化解锁

  1. 选择开发工具

    • 使用AutoJS(需修改其AndroidManifest.xml添加蓝牙权限)
    • GitHub地址: https://github.com/SuperMonster003/AutoJs6
  2. 修改AutoJS权限

    <!-- 添加以下权限到AndroidManifest.xml -->
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    
  3. 编写解锁脚本

// 1. 获取蓝牙适配器
let bluetoothAdapter = android.bluetooth.BluetoothAdapter.getDefaultAdapter();

// 2. 定义GATT回调
let gattCallback = new android.bluetooth.BluetoothGattCallback({
    onCharacteristicChanged: function(gatt, characteristic) {
        // 接收到特征数据变化时调用的回调
        let receivedData = characteristic.getValue();
        // 处理接收到的数据...
    }
});

// 3. 辅助函数
function createJavaByteArray(hexString) {
    // 将十六进制字符串转换为Java字节数组
}

function bytesToHexString(bytes) {
    // 将字节数组转换为十六进制字符串
}

function writeCharacteristic(device, serviceUuid, charUuid, data) {
    // 向设备的特征写入数据
}

// 4. 实现解锁流程
function unlockProcess() {
    // 连接蓝牙设备
    // 发送第一个加密数据
    // 接收并处理返回数据
    // 构造并发送第二个加密数据
    // 完成解锁
}
  1. 脚本部署
    • 在AutoJS中创建快捷方式
    • 点击即可执行蓝牙解锁

技术要点总结

  1. 关键发现

    • 成功提取蓝牙门锁的AES密钥
    • 解析出蓝牙通信的双向数据流程
    • 确定了数据加密前后的格式转换规则
  2. 安全漏洞

    • 使用固定密钥,缺乏动态更新机制
    • 通信流程可被逆向重现
    • 无有效的防重放攻击措施
  3. 防御建议

    • 实现动态密钥交换机制
    • 增加时间戳或随机数防重放
    • 加强通信数据加密强度
    • 加入设备身份双向认证

免责声明

本技术分析仅用于安全研究目的,请勿用于非法用途。任何不当使用造成的后果由使用者自行承担。实际测试应在合法授权范围内进行。

某租房App蓝牙门锁一键解锁实战分析 测试环境准备 设备 : Pixel 3 Android版本 : 12 Root工具 : Magisk Delta 26.4-kitsune (26400) 分析流程 一、获取安装包 首先需要提取目标App的安装包(APK文件),可以通过以下方式获取: 使用ADB命令从已安装设备提取 从应用商店下载 使用第三方APK提取工具 二、反编译APK获取DEX 使用在线反编译网站或本地工具将APK转换为可分析的DEX/JAR文件: jadx-gui Apktool dex2jar等工具 三、使用jadx-gui分析源码 定位应用入口 : 确定App主包位置: com.xxxx.xxxxxxxxxxxx.application.MyApplication 搜索关键字符串 : 全局搜索"开锁成功"字符串 通过提示词定位到蓝牙开锁相关代码区域 分析蓝牙模块 : 右键查看 onScanSuccess 的查找用例 选择可分析的代码路径(第二个用例) 对 unLockResultSuccess 函数使用Frida进行hook验证 深入分析解锁流程 : 查看 unLockResultSuccess 接口实现 定位到75行左右的函数调用处 分析调用蓝牙解锁的核心代码 四、获取蓝牙密钥 定位AES解密代码 : 找到 AESUtil.Decrypt 函数 使用Frida hook该函数并打印参数 获取密钥 : 从hook结果中提取 str2 参数(蓝牙密钥) 五、分析蓝牙通信流程 数据发送分析 : 定位 AESUtil.Encrypt() 函数 使用Frida hook加密函数 分析hook结果发现App发送两次数据 通信流程解析 : 数据格式细节 : 初始字符串: "01010100000000000000000000000000" 返回数据处理: 截取解密后字符串的第7-14位(共8位) 第二次发送数据格式: 02010501[8位数据]0000000000000000 六、蓝牙调试验证 使用蓝牙调试助手 : 发送第一个固定加密数据 验证是否能收到门锁返回数据 验证结果 : 成功接收门锁返回数据,证明分析方向正确 七、实现自动化解锁 选择开发工具 : 使用AutoJS(需修改其AndroidManifest.xml添加蓝牙权限) GitHub地址: https://github.com/SuperMonster003/AutoJs6 修改AutoJS权限 : 编写解锁脚本 : 脚本部署 : 在AutoJS中创建快捷方式 点击即可执行蓝牙解锁 技术要点总结 关键发现 : 成功提取蓝牙门锁的AES密钥 解析出蓝牙通信的双向数据流程 确定了数据加密前后的格式转换规则 安全漏洞 : 使用固定密钥,缺乏动态更新机制 通信流程可被逆向重现 无有效的防重放攻击措施 防御建议 : 实现动态密钥交换机制 增加时间戳或随机数防重放 加强通信数据加密强度 加入设备身份双向认证 免责声明 本技术分析仅用于安全研究目的,请勿用于非法用途。任何不当使用造成的后果由使用者自行承担。实际测试应在合法授权范围内进行。