【发布时间】:2020-12-24 22:24:40
【问题描述】:
一位朋友有一个带有蓝牙乐的身体秤。为了保存他的体重测量值,他必须在手机上打开 Manufactures 应用程序。所以我们尝试使用他的树莓派来完成工作。我们发现,秤通过广告发送数据。秤永远无法连接,您可以同时使用不同的手机接收数据。在测量过程中,应用程序显示的值与秤的显示相同。你知道,如果你站在秤上,数值会上下波动,直到测量完成。这种“上下移动”也可以在手机上看到,如果您同时使用多个手机,也可以在手机上看到。所以我认为这是一个事实,数据是通过 BLe 广告传输的。它们只能在制造商数据中,例如如下所示:
starts always with:
0f ff ac a0 db 58 e2 53 91 a0
and then:
88,30kg
20 c9 f8 42 0d b0
20 c9 f8 78 0d a6
88,35kg
20 c9 f9 b4 0d a3
20 c9 f9 88 0d b7
88,40kg
20 c9 f9 e6 0d b5
20 c9 f9 e6 0d b5
2,15kg
a0 c8 ab 40 0d a0
0,00kg
a0 c8 a0 a0 0d b5
但无论我如何尝试,我都无法将这些数据计算到给定的重量。我在大端、小端、其他单位(如磅、盎司甚至石头)中进行了尝试。我找不到一个公式来计算每个已知重量的数据。有趣的是,零是“a0 c8 a0 a0 0d b5”。测量时第一个字节为20,完成后,秤会发送多个第一个字节为a0的广告包。我认为这会说“最终价值”。无论如何,第五个字节总是 0d。第二个字节在权重较高时从 c8 变为 c9。我认为是 50 或 60 公斤。 因为我找不到解决方案,所以我尝试了其他方法。我反编译了 android 应用程序以查找解析广告包的部分。不幸的是,该应用程序加载了一个本地库来执行此操作。看来制造商真的很想保密。我试图将他们的图书馆用于我的一个目的。但看起来我需要一个头文件才能在我自己的 Java 应用程序中使用该库。所以我最后的机会是拆解图书馆,我做了什么。我使用了objdump。我从 Java 代码中知道,我需要的功能是
private native List<Map<String, Object>> decode(byte[] bArr, int i, int i2, Object obj);
我可以在转储文件中找到这个函数/子程序。但我不明白如何使用它。我观看了汇编程序的视频教程系列,这真的很有趣,但它并没有真正帮助我。我假设您可以以某种方式查看数据的来源(解码参数),如何处理和返回它们(例如保存到内存中)。我还发现了一个“BleBroadcastScaleProtocol16decodeWeightData”-Function,但仍然存在同样的问题。我现在的问题是:是否有真正的机会,可以通过这种方式完成?转储文件有 10MB 的文本。有人知道怎么做,或者以前做过类似的事情吗?我为此工作了几个月,每向前迈出一步就会让我后退两步。
我把转储文件放在我的云盘上,也许有人会看看。
编辑: 我使用我的 Raspberry Pi 向 Manufactures App 发送广告。我使用来自 bluez 的示例广告脚本。 如果我在制造商数据的前两个字节上发送带有 Service-ID FFB0 和“aca0”的广告,应用程序会将 pi 识别为“Insmart”规模。 我还可以将体重数据发送到应用程序。如果我发送“(ac a0 db 58 e2 53 91 a0) a0 c8 a0 a0 0d b5" 应用程序显示 0。 我玩了一下,发现最后四位是校验和,通过将所有十六进制值加在一起计算得出,并取摘要的最后四位。 重量数据必须在 2. 到 4. 位(c8 - 秒 a0)中的某个位置。我编写了一个脚本来从偏移量中获取 16 位并打印出十六进制值。作为输入数据,我使用 c8a0a0 (=0)。偏移量为 1(取 16 位,从位 2 开始)打印出“0x9141”。 在第二个脚本中,我可以输入一个十六进制值,它将与默认值“c8a0a0”合并。所以我可以输入 9142 并将其放在一起作为制造商数据发送的数据。 9142 是 c8a120,除了 9143 什么都不做的是 c8a1a0。该值为 0.25 公斤。当我将第一个值 (9143) 增加 2 时,它将在应用程序中添加 0,25kg。有时它会增加 0.3 公斤。这适用于 917f / c8bfa0 / 7,95kg。如果我去 9181 / c8c0a0 它会跳到 24,55kg。 i 可以继续以 0,25 公斤的步长达到 9195 / c8caa0 / 27,15 公斤。在 9197 / c8cba0 上,它更改单位并显示 4:4.4st:lb。 如果我按 1 计数,则应用程序大部分时间都会因其他值(9144、9146、9148...)而崩溃 有人认出其中的模式吗? 我也开始尝试不同的偏移量,但看起来不太有希望。
编辑2: 4:4.4st:lb 等于 27.397kg。下一步是 4:5.0st:lb 27,67kg。所以在这一点上它是线性的。但是缺少 8 - 24 公斤的范围
【问题讨论】:
-
我假设这与您使用非常相似的广告数据提出的另一个问题有关。该广告似乎确实具有 UUID 为“FFB0”的 GATT 服务。我还找到了秤的说明,上面写着“秤一次只能连接一台设备,请不要同时在其他设备上打开应用程序”。我想知道您将其视为不可连接的原因是否是因为它已在其他地方连接?
-
我发现nRF Connect App的通用工具非常擅长分析设备nordicsemi.com/Software-and-tools/Development-Tools/…在树莓派上,使用chromium浏览器可以使用URL
chrome://bluetooth-internals/#devices来扫描和分析设备。您可能还对以下文章感兴趣,他们讨论了对协议进行逆向工程medium.com/@urish/… -
是的,这个问题与我的另一个问题有关。该规模确实可以同时与多个设备一起使用。在 Android-Sourcecode 中是一个文件“BleHandle.java”,可以导入“ICBleProtocol.java”。在这个文件中有一个名为“onDiscoverPeripheral”的函数。当我手动使用此功能时,使用我的广告数据我得到“ICDeviceCommunicationTypeBroadcast;”。 CommunicationTypeConnected 也存在,但似乎适用于其他设备。我们还尝试关闭所有手机(不仅仅是禁用蓝牙),但电子秤始终无法连接。
-
在我看来,制造商使用 UUID“FFB0”来识别设备类型,或者他们可能为不同的设备使用相同的固件,只是稍微定制一下。 Android-App 的源代码也很连贯,函数名称和 if/else 语句中存在拼写错误,什么都不做。而且看起来制造商确实没有使用任何标准。但我会看看你的链接,试图找出更多的东西。到目前为止谢谢你
-
我现在确定,体重数据是通过广告传输的。我能够在应用程序中将我的树莓派注册为比例并向应用程序发送虚假测量值。看起来最后一个字节是校验和。如果我将 1 添加到 mac 地址之后的任何字节,我也必须将 1 添加到最后一个字节。应该不难弄清楚校验和是如何计算的。
标签: android bluetooth-lowenergy reverse-engineering disassembly