crackle 是研究蓝牙安全的 mikeryan 大佬写的一款能够解密 BLE 传统配对(legacy pairing)后的流量包的工具,本文将通过 crackle 源码的阅读,学习 SMP 协议、学习如何解密传统配对的流量
通过 TK 计算 STK 这里用到了几个函数,copy_reverse 是用来逆序的
1 2 3 4 5 void copy_reverse (const u_char *bytes, uint8_t *dest, size_t len) { unsigned i; for (i = 0 ; i < len; ++i) dest[i] = bytes[len - 1 - i]; }
计算 iv 1 2 3 4 5 6 void calc_iv (connection_state_t *state) { assert(state != NULL ); copy_reverse(state->ivm, state->iv + 0 , 4 ); copy_reverse(state->ivs, state->iv + 4 , 4 ); }
iv 是在数据包中直接能找到的,在 LL_ENC_REQ 报文中是 ivm,意思是 master 的 iv
image.png
在 LL_ENC_RSP 报文中是 ivs,意思是 slave 的 iv
image.png
计算 iv 这里只需要把他们反转一下即可,因为在内存里放着的是逆序的,看一下 GDB 调试的 GDB 调试的方法,gdb crackle
然后 b 源码第几行
,比如b 608
下个断点,set args -i Legacy_pairing.pcapng
,然后点击运行即可
1 2 3 4 5 6 7 8 9 10 11 12 gdb-peda$ p &state->ivm $1 = (uint8_t (*)[4 ]) 0x55555555f7c0 gdb-peda$ x/gx 0x55555555f7c0 0x55555555f7c0 : 0x816400f1fda34aa8 gdb-peda$ p &state->ivs $2 = (uint8_t (*)[4 ]) 0x55555555f7cc gdb-peda$ x/gx 0x55555555f7cc 0x55555555f7cc : 0x00000000483dea50 gdb-peda$ p &state->iv $3 = (uint8_t (*)[8 ]) 0x55555555f800 gdb-peda$ x/gx 0x55555555f800 0x55555555f800 : 0x0000000000000000
等执行完两个反转就得到了真实的 iv 值
1 2 gdb-peda$ x/gx 0x55555555f800 0x55555555f800 : 0x50ea3d48a84aa3fd
计算 STK STK 的生成方式在蓝牙的规范中用的是一个叫做 s1 的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void calc_stk (connection_state_t *state, uint32_t numeric_key) { uint8_t rand[16 ]; assert(state != NULL ); numeric_key = htobe32(numeric_key); memcpy (&state->tk[12 ], &numeric_key, 4 ); memcpy (rand + 0 , state->srand + 8 , 8 ); memcpy (rand + 8 , state->mrand + 8 , 8 ); aes_block(state->tk, rand, state->stk); }
s1 这个函数需要 TK 的值和两个 random 的值,TK 需要转成小端序放在内存里,用 htobe32(numeric_key) 即可
image.png
两个 random 分别取高 8 字节拼接起来
image.png
image.png
看一下标准里咋说:For example if the 128-bit value r1 is 0x000F0E0D0C0B0A091122334455667788 then r1’is 0x1122334455667788. If the 128-bit value r2 is 0x010203040506070899AABBCCDDEEFF00 then r2’is 0x99AABBCCDDEEFF00。这明显是拿低位拼起来的啊,为啥这里是拿高位拼起来?还是说 wireshark 显示的是小端序?我理解不了了
1 2 3 4 5 6 7 8 9 10 11 gdb-peda$ p &state->mrand $5 = (uint8_t (*)[16 ]) 0x55555555f76e gdb-peda$ p &state->srand $6 = (uint8_t (*)[16 ]) 0x55555555f77e gdb-peda$ x/4 gx 0x55555555f76e 0x55555555f76e : 0xec977c9fe63591dc 0x1a10975ba476bc02 0x55555555f77e : 0xa20ea327c9897c01 0x575852f181e9db17 gdb-peda$ p &rand $7 = (uint8_t (*)[16 ]) 0x7fffffffe160 gdb-peda$ x/2 gx 0x7fffffffe160 0x7fffffffe160 : 0x575852f181e9db17 0x1a10975ba476bc02
最后更新时间:2022-10-03 21:52:43