在寻找IOT设备的攻击面之路的时候,发现蓝牙这块的知识很薄弱,这次借着esp32+BLE_CTF这个组合来认识一下蓝牙的协议栈以及蓝牙之类的知识
蓝牙简介
在蓝牙诞生之前是通过一些复杂的电缆线或者是红外线,来实现设备与设备之间的通信的,蓝牙的前生今世看下面的链接就差不多了,这里简单介绍一下目前蓝牙的现状,目前的蓝牙是由三部分所组成的,分别是BLE(低功耗蓝牙),BT(经典蓝牙),高速蓝牙,他们三者都有各自的应用场景,同时还有Mesh网状网络技术支持成千个设备进行互联互通,这不就是正好赶上IOT的大时代趋势了吗?
- 「硬核无线技术」系列视频 蓝牙篇(上)
- 「硬核无线技术」系列视频 蓝牙篇(下)
- 一文读懂蓝牙技术从 1.0 到 5.0 的前世今生
- 经典蓝牙介绍
服务发现协议 (SDP/GAP)
SDP/GAP 是在所有蓝牙设备上发现服务的基础,这对于所有蓝牙模型都是必不可少的,因为可以通过 SDP/GAP 设备信息、服务和服务的特性来查询,然后可以在两个或多个蓝牙设备之间建立连接
射频通信(RFCOMM/GATT&&ATT)
RFCOMM 协议用于蓝牙中的电缆更换选项。它是一种简单的传输协议,具有额外的规定,用于通过蓝牙协议栈的 L2CAP 部分模拟 RS232 串行端口的九个电路。它支持使用串行通信的应用程序的大型基础。它提供可靠的数据流、多重连接、流量控制和串行电缆线路设置
逻辑链路控制和适配 – 层 (L2CAP)
蓝牙逻辑链路控制和适配层支持更高级别的多路复用、分段和数据包重组以及服务质量通信和组。该层不负责可靠性并使用 ARQ 来确保它
主机制器接口 (HCI)
HCI 为基带控制器、链路管理器以及对硬件状态和控制寄存器的访问提供命令接口。该接口提供了访问蓝牙基带功能的统一方法。主机控制传输层去除了传输依赖并提供了一个通用的驱动程序接口。核心规范中定义了三个接口:USB、RS-232 和 UART。
再往下就是硬件相关的信息处理,在此就不做过多介绍了,下面的BLE_CTF研究的是BLE中的GATT层,attribute是此层中最重要的信息,它包括包括service, characteristic,descriptor,每一个attribute都有handle、UUID、data、properties,在后面的bleah探测当中可以发现这几个属性,例如对于某个characteristic来说,他有个独一无二的handle代表server里面的attribute table里面序号,有attribute properties代表这个characteristic的类型,之后是attribute value,后面是可以通过某些方法修改这些属性的,这样属性映射到真实的设备上面就是一个个功能模块!
ESP32环境搭建
配置的环境按照芯片文档上面的就成功把环境拉起来,一定要看到下面的输出才算配置完成
- 配置步骤
.Hello world!Restarting in 10 seconds...This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision 1, 2MB external flashMinimum free heap size: 298968 bytesRestarting in 9 seconds...Restarting in 8 seconds...Restarting in 7 seconds...Restarting in 6 seconds...Restarting in 5 seconds...
搭建踩坑
- 设备管理器无法找到此设备:
- 可能一:USB线没有数据传输功能
- 原因:有些比较便宜的USB线只能进行供电,不能进行数据传输,剪开看可以发现它只有地线和±5V
- 解决办法:换条可以传输数据的线即可
- 可能二:供电不正常
- 原因:可能排线有点问题,供电不上
- 检查办法:用万用表测试一下VCC和GND是否正常
- 可能三:芯片供电不正常
- 原因:可能排线有点问题,供电不上
- 检查方法:用USB转TTL的设备通过杜邦线连接ESP32,需要连接VCC,GUN,TX(转换设备连接RX),再用串口连接工具看看有无输出,下面为输出样例:
ets Jun 8 2016 00:22:57 rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)ets Jun 8 2016 00:22:57 rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)configsip: 0, SPIWP:0x00clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00mode:DIO, clock div:2load:0x3fff0008,len:8load:0x3fff0010,len:3464load:0x40078000,len:7828load:0x40080000,len:252entry 0x40080034I (44) boot: ESP-IDF v2.0-rc1-401-gf9fba35 2nd stage bootloaderI (45) boot: compile time 18:48:10 ...
- 识别不到COM口:
- CP210X驱动安装链接
- 可能一:未安装驱动
- 解决办法:安装CP210X驱动
我踩的坑就是上面这些....
BLE_CTF环境搭建
刷入固件
在识别到COM之后,ESP-IDF 4.3 Powershell输入下面的命令,记得替换port,就可以直接将BLE_CTF的固件刷入ESP32里面
esptool.py --chip esp32 --port (yours port) \--baud 115200 --before default_reset --after hard_reset write_flash \-z --flash_mode dio --flash_freq 40m --flash_size detect \0x1000 build/bootloader/bootloader.bin \0x10000 build/gatt_server_service_table_demo.bin \0x8000 build/partitions_singleapp.bin
刷入之后,就能在蓝牙识别中看见BLECTF这个设备,此时已经成功刷入固件了!
寻找MAC地址
在拉起来BLE_CTF之后,还需要知道它的MAC地址才能与它进行通信,笔者是用树莓派来寻找它的MAC地址的,在kali和ubuntu都不太行,允许搜索附近的BLE设备的时候,报一个I/O设备的错误,解决不了,然后想到了树莓派,最后成功得到ESP32的MAC地址
链接:
- Linux下蓝牙工具:hcitool使用教程
- 树莓派通过蓝牙进行串口通讯
- 低功耗蓝牙(BLE)的简要学习分析
- 树莓派进阶之路 (022) - 串口篇 - 通过串口连接控制树莓派
- 使用串口线连接树莓派
- 树莓派三种连接电脑的方式
下面是找到BLECTF的MAC地址:
➜ ~ sudo hcitool lescan LE Scan...44:17:93:5e:46:06 BLECTF...
开启BLE_CTF之路
要想实现蓝牙的收发包,有几种方法来实现,下图展示了具体是哪几种方法:
gatttool介绍
链接:
- gatttool命令详解
- BlueZ gatttool操作
bleah介绍
Traceback (most recent call last): File "/usr/local/bin/bleah", line 4, in <module> __import__('pkg_resources').run_script('bleah==1.0.0', 'bleah') File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 666, in run_script self.require(requires)[0].run_script(script_name, ns) File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 1446, in run_script exec(code, namespace, namespace) File "/usr/local/lib/python2.7/dist-packages/bleah-1.0.0-py2.7.egg/EGG-INFO/scripts/bleah", line 119, in <module> main() File "/usr/local/lib/python2.7/dist-packages/bleah-1.0.0-py2.7.egg/EGG-INFO/scripts/bleah", line 113, in main bleah = Bleah(args) File "/usr/local/lib/python2.7/dist-packages/bleah-1.0.0-py2.7.egg/bleah/scan.py", line 277, in __init__ self.start_scan() File "/usr/local/lib/python2.7/dist-packages/bleah-1.0.0-py2.7.egg/bleah/scan.py", line 344, in start_scan self.devices += self.scanner.scan(self.args.timeout) File "/usr/local/lib/python2.7/dist-packages/bluepy-1.3.0-py2.7.egg/bluepy/btle.py", line 881, in scan self.start(passive=passive) File "/usr/local/lib/python2.7/dist-packages/bluepy-1.3.0-py2.7.egg/bluepy/btle.py", line 818, in start self._startHelper(iface=self.iface) File "/usr/local/lib/python2.7/dist-packages/bluepy-1.3.0-py2.7.egg/bluepy/btle.py", line 281, in _startHelper self._lineq = Queue()TypeError: 'module' object is not callable
flag1
第一个flag目的在说明如何提交flag,执行下面的命令即可得到一个flag:
gatttool -b 44:17:93:5e:46:06 --char-write-req -a 0x002c -n $(echo -n "12345678901234567890"|xxd -ps)
参数介绍:
-b #指明设备的mac地址--char-write-req #写入句柄并接受ack-a #指明设备的句柄
执行下面的命令可以得知目前的socre为多少:
gatttool -b 44:17:93:5e:46:06 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf ''
flag2
开始我们的夺旗之旅,hint告诉我们要去查看句柄0x002e的ascii值,有两种方法可以查看:
第一种是bleah,它可以将此设备的所有属性给列出来,所以相对来说它的速度要慢一些:
sudo bleah -b "44:17:93:5e:46:06" -e
第二种就是gatttool,它可以选择输出指定句柄的data:
➜ ~ gatttool -b 44:17:93:5e:46:06 --char-read -a 0x002e Characteristic value/descriptor: 64 32 30 35 33 30 33 65 30 39 39 63 65 66 66 34 34 38 33 35
将输出的ascii转换成字符串就可以了:
import binascii str = "64 32 30 35 33 30 33 65 30 39 39 63 65 66 66 34 34 38 33 35" list_str = list(str)while ' ' in list_str: list_str.remove(' ') print(binascii.unhexlify(''.join(list_str)))
也可以用命令行来转换:
➜ ~ echo "64 32 30 35 33 30 33 65 30 39 39 63 65 66 66 34 34 38 33 35"|tr -d ' '|xxd -r -p;printf ''
其实就是linux命令,参考下面的链接
- Linux tr命令
- xxd命令功能
最后交上获得的flag就能得分!!
sudo bleah -b "A4:C1:38:21:2C:E2" -e
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "d205303e099ceff44835"
flag3
此题要md5设备的名称,这个名称有点坑,一直以为是下图的值的md5,导致直接卡死....
最后才知道是要将BLECTF进行md5...,md5的方法有很多就不介绍了:
➜ ~ echo -n "BLECTF"|md5sum 5cd56d74049ae40f442ece036c6f4f06 -
最后取20位作为flag:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "5cd56d74049ae40f442e"
flag4
此题才是上面找错的值,Generic Access -> Device Name的data为2b00042f7481c7b056c4b410d28f33cf,同样取20位提交:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "2b00042f7481c7b056c4"
flag5
此处提示"Write anything here",尝试写入"zyen"在这个句柄里面:
gatttool -b 44:17:93:5e:46:06 --char-write-req -a 0x0032 -n $(echo -n "zyen"|xxd -ps)
或者
sudo bleah -b "44:17:93:5e:46:06" -n 0x0032 -d "hello"
提交flag:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "3873c0270763568cf7aa"
flag6
和上题大差不差:
sudo bleah -b "44:17:93:5e:46:06" -n 0x0034 -d "yo"
最后查看答案:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "c55c6314b3db0a6128af"
flag7
还是一模一样,只是将写入的字符串改成了十六进制的数字:
sudo bleah -b "44:17:93:5e:46:06" -n 0x0036 -d "0x07"
提交得分:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "1179080b29f8da16ad66"
flag8
这题虽然没有看到有58这个句柄,但是还是可以往这个句柄里面写值的,猜测应该是隐藏了:
sudo bleah -b "44:17:93:5e:46:06" -n 0x003a -d '0xc9'
提交得分:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "f8b136d937fad6a2be9f"
flag9
这题就有点不一样了,hint说要写入一个值,但是没有告诉你这个值具体的值是多少,只说这是一个00到ff的值,所以我们爆破这个值就好啦
import os for i in range(0,256): bash = 'sudo bleah -b "44:17:93:5e:46:06" -n 0x003c -d \"' + '0x{0:02x}'.format(i) + '\"' print(bash) os.system(bash)
爆破完回去看就发现,那里已经出现flag了
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "933c1fcfa8ed52d2ec05"
flag10
这题hint说要读此句柄1000次:
import os for i in range(0,1000): bash = 'gatttool -b 44:17:93:5e:46:06 --char-read -a 0x003e' os.system(bash)
脚本读完目标句柄1000之后就会出现flag,提交
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "6ffcd214ffebdc0d069e"
flag11
题目提示:Listen to me for a single notification
- 通知和指示有什么不同?
- 低功耗蓝牙:在 linux 中监听通知/指示
- GATT 服务器和客户端角色
notification只是通知,在某一个句柄是不断发送一个value
indicate和notification一样,只不过多了一个ACK的模式
gatttool -b 44:17:93:5e:46:06 --char-write-req --handle=0x0040 --value=0100 --listen
接收到:35 65 63 33 37 37 32 62 63 64 30 30 63 66 30 36 64 38 65 62
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "5ec3772bcd00cf06d8eb"
小tips:
0100 是获取 notifications
0200 是获取 indications
0300 两个都获取
0000 全部关闭
flag12
题目提示:Listen to handle 0x0044 for a single indication
刚刚讲到indication是需要多发一个ACK的:
gatttool -b 44:17:93:5e:46:06 --char-write-req --handle=0x0040 --value=0200 --listen
出现flag,提交即可:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "c7b86dd121848c77c113"
flag13
监听之后出现两个两个flag:
Notification handle = 0x0046 value: 55 20 6e 6f 20 77 61 6e 74 20 74 68 69 73 20 6d 73 67 00 00 Notification handle = 0x0046 value: 63 39 34 35 37 64 65 35 66 64 38 63 61 66 65 33 34 39 66 64
第一个拿去解码之后为:"U no want this msg\x00\x00",很明显不是flag,第二个解码就为flag:c9457de5fd8cafe349fd,提交得分:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "c9457de5fd8cafe349fd"
flag14
同12题:
gatttool -b 44:17:93:5e:46:06 --char-write-req --handle=0x004a --value=0200 --listen
提交flag:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "b6f3a47f207d38e16ffa"
flag15
此题是需要修改MAC,但是修改的有点问题,暂时还没解决
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "aca16920583e42bdcf5f"
flag16
用交互模式修改MTU为444就行:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "b1e409e5a4eaf9fe5158"
flag17
用--char-write-req参数指定数据即可:
gatttool -b 44:17:93:5e:46:06 --char-write-req -a 0x0050 -n $(echo -n "hello"|xxd -ps)
提交flag:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "d41d8cd98f00b204e980"
flag18
No notifications here! really?一样去监听notifications就行:
gatttool -b 44:17:93:5e:46:06 --char-write-req --handle=0x0052 --value=0200 --listen
提交flag:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "fc920c68b6006169477b"
flag19
此GATT属性有NOTIFY BROADCAST READ WRITE EXTENDED PROPERTIES,前半段是写句柄,后半段是监听
gatttool -b 44:17:93:5e:46:06 --char-write-req --handle=0x0054 --value=0200 --listen
提交flag:
sudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "fbb966958f07e4a0cc48"
flag20
最后以md5作者的推特账号提交,
echo -n "@hackgnar" | md5sumsudo bleah -b "44:17:93:5e:46:06" -n 0x002c -d "d953bfb9846acc2e15ee"
至此,已经完成所有BLECTF的内容!!!不过后面的题目耦合性有点大了...
总结
完成此CTF挑战是为了更好地了解蓝牙这个协议,为后面的研究打下一定的基础,从GATT层面来看,某些蓝牙设备也是存在一些问题的,可以通过这个来进行切入。
参考链接
BLECTF Capture_flag
BLUETOOTH LOW ENERGY CTF - WRITE UP
Bluetooth Protocol (Part 2): Types, Data Exchange, Security
BLUETOOTH FRAMEWORK AND RFCOMM PROTOCOL
Bluetooth: ATT and GATT
Bluetooth Protocol Stack
GATT Server and Client Roles