blectf

环境搭建

一个esp32 的板子跟一个支持linux平台的蓝牙适配器(我网上买了一个 CSR4.0 不到10元,板子用好点的数据线,不然只能供电,用一般牌子的手机充电线都可以)

kal虚拟机(版本不能用最新的,因为新版kali内核版本过高,导致无法正常使用一些工具,我用的2024.1版的kali,内核6.6.9-amd64)

sudo apt-get install esptool
首先得安装 esptool 用来烧录 esp32

git clone https://github.com/hackgnar/ble_ctf
cd ble_ctf
esptool -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32  write_flash --flash_mode dio --flash_size 2MB --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/ble_ctf.bin
先安装:apt-get install bluetooth
service bluetooth restart #再重启:
hciconfig #查看蓝牙设备:#查看或配置本地蓝牙适配器 hci0 的状态和参数的。即csr4.0
sudo hciconfig hci0 up #激活:
sudo hciconfig hci0 lestates #查看蓝牙信息:

扫描周围低功耗设备:sudo hcitool lescan会看到一个名为 BLECTF 的设备

另外补充一些情况:

hciconfig hci0 up``Can't init device hci0: Operation not possible due to RF-``kill` `(132)

运行 rfkill unblock allhciconfig hci0 up 即可解决

有时断开连接,右上角蓝牙开关2次重新连接

命令

查看分数

gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'

查看特征

gatttool -b 2C:BC:BB:0B:DC:82 --characteristics

比如我现在的服务端是我的烧录了 BLECTFesp32 ,它由很多 Characteristic 组成

image-20250505153855691

handle 是特征的句柄,char properties 是特征的属性,char value handle 是特征值的句柄,uuid 是特征的通用唯一标识符

挑战

flag1

教你怎么提交 flag 的,使用 --char-write-req 向句柄 44 提交 12345678901234567890 即可

第一个标志是一份礼物!您只有阅读本文档或深入研究源代码才能获得它。简而言之,这个标志是为了帮助您熟悉如何简单地写入 BLE 句柄。请按照以下步骤获取您的第一个标志。请确保将以下示例中的 MAC 地址替换为您的设备 MAC 地址!

首先,检查你的分数:
gatttool -b de:ad:be:ef:be:f1 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'

接下来,让我们提交以下标志。 gatttool -b de:ad:be:ef:be:f1 --char-write-req -a 0x002c -n $(echo -n "12345678901234567890"|xxd -ps)

最后,再次检查你的分数,看看你的标记是否被接受:
gatttool -b de:ad:be:ef:be:f1 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Score: 0/20
                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "12345678901234567890"|xxd -ps)          
Characteristic value was written successfully
                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Score:1 /20

flag2

检查句柄 0x002e 的 ASCII 值,并将其提交给标志提交句柄 0x002c。如果您使用的是 gatttool,请确保使用 xxd 将其转换为十六进制。如果您使用的是 bleah,则可以将其作为字符串值发送。

查看 0x002e 句柄的 ASCII 码值,那就是用 --char-read 了,转ascii是d205303e099ceff44835

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x2e                                                         
Characteristic value/descriptor: 64 32 30 35 33 30 33 65 30 39 39 63 65 66 66 34 34 38 33 35 
                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "d205303e099ceff44835"|xxd -ps)
Characteristic value was written successfully
                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Score:2 /20

flag3

检查句柄 0x0030 的 ASCII 值。按照提示操作,并将找到的标志提交给 0x002c。

转为ASCII值为 MD5 of Device Name之前用hcitool扫描出的结果就是设备名加MAC地址将设备名BLECTF 进行 MD5 加密后得到值取前20位就是flag

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0030|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
MD5 of Device Name
                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "5cd56d74049ae40f442e"|xxd -ps)   
Characteristic value was written successfully

flag4

蓝牙 GATT 服务提供了一些额外的设备属性。尝试查找 Generic Access -> Device Name 的值。

这句话的意思是:在蓝牙设备的 GATT 服务中,有一个叫做 “Generic Access” 的服务,它包含了设备的一些基本属性,比如设备名称。你可以尝试查找其中的 “Device Name” 特征来查看设备的名字。

百度到Generic Access 服务(UUID: 0x1800

  • 是每个 BLE 设备通常都会包含的一个标准服务。

  • 提供描述设备本身的一些基本信息。

  • 它包含的典型特征:

特征名称 UUID 用途
Device Name 0x2A00 设备名称(如 "BLE_Sensor")
Appearance 0x2A01 设备外观类型(如心率带)

先使用 --primary 指令来发现所有的 GATT 主服务,从输出可以看到第二个服务的uuid就是 00001800-0000-1000-8000-00805f9b34fb ,所以第二个服务就是 Generic Access ,根据它提供的句柄范围再去查看特征与句柄发现uuid=0x2A00的是第一个,

读value转为ASCII值为 2b00042f7481c7b056c4b410d28f33cf 取前20位

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --primary
attr handle = 0x0001, end grp handle = 0x0005 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle = 0x0014, end grp handle = 0x001c uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle = 0x0028, end grp handle = 0xffff uuid: 000000ff-0000-1000-8000-00805f9b34fb                                                                                                                       
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --characteristics --start=0x14 --end=0x1c
handle = 0x0015, char properties = 0x02, char value handle = 0x0016, uuid = 00002a00-0000-1000-8000-00805f9b34fb
handle = 0x0017, char properties = 0x02, char value handle = 0x0018, uuid = 00002a01-0000-1000-8000-00805f9b34fb
handle = 0x0019, char properties = 0x02, char value handle = 0x001a, uuid = 00002aa6-0000-1000-8000-00805f9b34fb                                                                                                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x16
Characteristic value/descriptor: 32 62 30 30 30 34 32 66 37 34 38 31 63 37 62 30 35 36 63 34 62 34 31 30 64 32 38 66 33 33 63 66                                                                                                                              
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "2b00042f7481c7b056c4"|xxd -ps)
Characteristic value was written successfully                                                                                                                            
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'  
Score:4 /20

flag5

读取句柄 0032 并按照它所说的去做。请注意,它并没有像以前那样告诉你写入标志句柄。找到标志后,请继续将其写入您在过去标志中使用的标志句柄。

我们只需要往这个句柄里随便写点东西,这个特征的值就会变成flag

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0032|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Write anything here

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x0032 -n $(echo -n "1"|xxd -ps)  
Characteristic value was written successfully

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0032|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
3873c0270763568cf7aa                                                                                                                     
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "3873c0270763568cf7aa"|xxd -ps)   
Characteristic value was written successfully

flag6

按照读取 handle 0x0034 中的说明进行作。请记住,有些工具只写入十六进制值,而其他工具提供写入十六进制或 ASCII 的方法
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0034|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Write the ascii value "yo" here
                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x0034 -n $(echo -n "yo"|xxd -ps) 
Characteristic value was written successfully


┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0034|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
c55c6314b3db0a6128af

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "c55c6314b3db0a6128af"|xxd -ps)
Characteristic value was written successfully                                                                                                                       
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x002a|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Score:6 /20

flag7

按照读取 handle 0x0036 中的说明进行作。请记住,有些工具只写入十六进制值,而其他工具提供写入十六进制或 ASCII 的方法

我们之前写入的数据的格式都是字符串,现在需要的是整数类型,所以只需要 -n 直接接上对应的值就行了

┌──(kali㉿kali)-[~/Desktop]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0036|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Write the hex value 0x07 here

┌──(kali㉿kali)-[~/Desktop]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x0036 -n 07
Characteristic value was written successfully

┌──(kali㉿kali)-[~/Desktop]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0036|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
1179080b29f8da16ad66
                                                                                                                                                           
┌──(kali㉿kali)-[~/Desktop]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "1179080b29f8da16ad66"|xxd -ps)
Characteristic value was written successfully

flag8

按照读取 handle 0x0038 中的说明进行作。请注意此处的句柄。请记住,句柄可以由整数或十六进制引用。大多数工具(如 gatttool 和 bleah)都允许您以两种方式指定句柄。

转为ASCII值为 Write 0xC9 to handle 58,跟上一题差不多

flag9

看handle 0x003c 并按照它所说的去做。您应该为此编写一个解决方案。另请记住,某些工具的写入速度比其他工具快。

转为ASCII值为 Brute force my value 00 to ff就是让我们写个脚本来往这个0x003c句柄的特征里写数据

from time import sleep
import os

num=0
for i in range(255):
    pa="gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x003c -n "+f"{num:02x}"
    os.system(pa)
    os.system("gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x003c")
    print(pa)
    num+=1
    sleep(0.5)

最后
┌──(kali㉿kali)-[~/Desktop/ble_ctf]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x003c|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
933c1fcfa8ed52d2ec05

flag10

看看 Handle 0x003e 并按照它所说的去做。请记住,某些工具在执行读取和写入时比其他工具具有更好的连接速度。这与该工具提供的功能或它如何在主机 OS 上使用缓存的 BT 连接有关。尝试针对此标志测试不同的工具。找到最快的一个后,启动脚本或 bash 1 liner 以完成任务。仅供参考,一旦运行,如果作得当,此任务大约需要 90 秒才能完成。
import subprocess, time

for i in range(1000):
    out = subprocess.getoutput("gatttool -b 2c:bc:bb:0B:dc:82 --char-read --handle=0x3e")
    print(f"[{i+1}] {out}")
    time.sleep(0.1)

读1000次

┌──(kali㉿kali)-[~/Desktop/ble_ctf]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x003e|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Read me 1000 times

┌──(kali㉿kali)-[~/Desktop/ble_ctf]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x003e|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
6ffcd214ffebdc0d069e

┌──(kali㉿kali)-[~/Desktop/ble_ctf]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x002c -n $(echo -n "6ffcd214ffebdc0d069e"|xxd -ps)
Characteristic value was written successfully

flag11

查看 handle 0x0040 和 google search gatt 通知。一些工具(如 gatttool)能够订阅 gatt 通知

Listen to me for a single notification ,这个是让我们监听该句柄的一次通知,服务端可主动向主客户端Notify 通知数据。

这里的命令分为两步,首先需要 char-write-req -a 0x0040 -n 00 ,往该句柄随便写入数据

然后 --listen 开启监听就能接收到该句柄发送的通知(Notify)和指示(indicate

转为ASCII值为 5ec3772bcd00cf06d8eb

┌──(kali㉿kali)-[~/Desktop/ble_ctf]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0040|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Listen to me for a single notification

┌──(kali㉿kali)-[~/Desktop/ble_ctf]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x0040 -n 10 --listen
Characteristic value was written successfull
Notification handle = 0x0040 value: 35 65 63 33 37 37 32 62 63 64 30 30 63 66 30 36 64 38 65 62 

flag12

查看 handle 0x0042 和 google search gatt 指示。对于单个响应指示消息,例如此挑战,gatttool 等工具将正常工作。

与上题一样

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0042|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'                  
Listen to handle 0x0044 for a single indication
                                                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x0044 -n 10 --listen              Characteristic value was written successfully
Indication   handle = 0x0044 value: 63 37 62 38 36 64 64 31 32 31 38 34 38 63 37 37 63 31 31 33 

flag13

查看句柄 0x0046 并按照指示操作。请注意,这个通知挑战需要您接收多个响应才能完成。

就是接收多个通知,没啥区别,因为我们的监听功能是持续的,能一直接收

转为ASCII值为 c9457de5fd8cafe349fdU no want this msg

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0046|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Listen to me for multi notifications                                                                                                                                                           
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x0046 -n 11 --listen              Characteristic value was written successfully
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 
Notification handle = 0x0046 value: 63 39 34 35 37 64 65 35 66 64 38 63 61 66 65 33 34 39 66 64 

flag14

查看句柄 0x0048 并在谷歌搜索 gatt 指示。请注意,这个挑战需要您解析多个指示响应才能

Listen to handle 0x004a for multi indications ,与上题同理

flag15

查看句柄 0x004c 并执行其指示的内容。就像以太网或 wifi 设备一样,您也可以更改蓝牙设备的 MAC 地址。

改bd address,没成功

└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x004c|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Connect with BT MAC address 11:22:33:44:55:66

└─$ sudo hciconfig hci0       #查看或配置本地蓝牙适配器 hci0 的状态和参数的。即csr4.0
[sudo] password for kali: 
hci0:   Type: Primary  Bus: USB
        BD Address: 00:1A:7D:DA:71:13  ACL MTU: 679:8  SCO MTU: 48:16
        UP RUNNING 
        RX bytes:12727 acl:114 sco:0 events:720 errors:0
        TX bytes:12926 acl:96 sco:0 commands:506 errors:0

flag16

读取句柄 0x004e 并执行其指示的内容。设置 MTU 可能是一件棘手的事情。一些工具可能提供 mtu 标志,但它们似乎并没有真正触发服务器上的 MTU 协商。尝试使用 gatttool 的交互模式来完成此任务。默认情况下,BLECTF 服务器设置为强制 MTU 大小为 20。服务器将监听 MTU 协商,并查看它们,但我们实际上并没有在代码中更改 MTU。我们只是在你触发一个由句柄 0x0048 指定值的 MTU 事件时触发标志代码。GLHF!
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x004e|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Set your connection MTU to 444
                                                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 -I     #交互模式                                                                     
[2C:BC:BB:0B:DC:82][LE]> connect
Attempting to connect to 2C:BC:BB:0B:DC:82
Connection successful
[2C:BC:BB:0B:DC:82][LE]> mtu 444
MTU was exchanged successfully: 444

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x004e|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'

b1e409e5a4eaf9fe5158

flag17

查看句柄 0x0050 并执行其指示的内容。这个挑战与其他写入挑战不同,因为你的写入工具需要正确实现写入响应确认消息。这个标志也很棘手,因为即使没有“NOTIFY”属性,标志也会作为通知响应数据返回。

只需要注意只能使用--char-write-req ,而不能使用 --char-write 就行了

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0050|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
Write+resp 'hello'                                                                                                                                                               
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-write-req -a 0x0050 -n $(echo -n "hello"|xxd -ps)
Characteristic value was written successfully                                                                                                                                                           
┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0050|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
d41d8cd98f00b204e980

flag18

查看句柄 0x0052。注意它没有通知属性。在这里进行写入并监听通知!事情并不总是如表面所见!

0x0052 句柄说:No notifications here! really?

说是没有,实际还是可以监听得到,asscii:fc920c68b6006169477b,和flag11一样

flag19

查看 0x0054 的所有句柄属性!用它们都试一试,找到你的 flag 片段。
handle = 0x0053, char properties = 0x9b, char value handle = 0x0054, uuid = 0000ff16-0000-1000-8000-00805f9b34fb

特征属性 0x9b 分析(二进制 10011011):

  • 0x80 = Auth signed writes
  • 0x10 = Notify(可发送通知)
  • 0x08 = Write
  • 0x02 = Read
  • 0x01 = Broadcast

写入跟监听分别得到部分flag,转为ASCII值为 fbb966958f07e4a0cc48

Untitled

flag20

确定作者的推特用户名,然后按照 0x0056 的指示去做!

作者的推特名在项目那里有:@hackgnar,将其md5加密后取前20位得到 d953bfb9846acc2e15ee

┌──(kali㉿kali)-[~]
└─$ gatttool -b 2C:BC:BB:0B:DC:82 --char-read -a 0x0056|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'
md5 of author's twitter handle

参考资料

https://bbs.kanxue.com/thread-281313.htm#msg_header_h3_2

https://bbs.kanxue.com/thread-271543.htm#msg_header_h1_3

posted @ 2025-05-10 14:27  Ma&0xFly  阅读(15)  评论(0)    收藏  举报