new: exposing enumerated BLE services for each device via api.rest module

This commit is contained in:
evilsocket 2019-03-16 20:45:50 +01:00
commit 8115490d3a
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
2 changed files with 116 additions and 73 deletions

View file

@ -10,6 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/gatt" "github.com/bettercap/gatt"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
@ -276,7 +277,17 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
wantsToWrite := mod.writeUUID != nil wantsToWrite := mod.writeUUID != nil
foundToWrite := false foundToWrite := false
mod.currDevice.Services = make([]network.BLEService, 0)
for _, svc := range services { for _, svc := range services {
service := network.BLEService{
UUID: svc.UUID().String(),
Name: svc.Name(),
Handle: svc.Handle(),
EndHandle: svc.EndHandle(),
Characteristics: make([]network.BLECharacteristic, 0),
}
mod.Session.Events.Add("ble.device.service.discovered", svc) mod.Session.Events.Add("ble.device.service.discovered", svc)
name := svc.Name() name := svc.Name()
@ -298,10 +309,17 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
chars, err := p.DiscoverCharacteristics(nil, svc) chars, err := p.DiscoverCharacteristics(nil, svc)
if err != nil { if err != nil {
mod.Error("error while enumerating chars for service %s: %s", svc.UUID(), err) mod.Error("error while enumerating chars for service %s: %s", svc.UUID(), err)
continue } else {
for _, ch := range chars {
props, isReadable, isWritable, withResponse := parseProperties(ch)
char := network.BLECharacteristic{
UUID: ch.UUID().String(),
Name: ch.Name(),
Handle: ch.VHandle(),
Properties: props,
} }
for _, ch := range chars {
mod.Session.Events.Add("ble.device.characteristic.discovered", ch) mod.Session.Events.Add("ble.device.characteristic.discovered", ch)
name = ch.Name() name = ch.Name()
@ -311,8 +329,6 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
name = fmt.Sprintf(" %s (%s)", tui.Green(name), tui.Dim(ch.UUID().String())) name = fmt.Sprintf(" %s (%s)", tui.Green(name), tui.Dim(ch.UUID().String()))
} }
props, isReadable, isWritable, withResponse := parseProperties(ch)
if wantsToWrite && mod.writeUUID.Equal(ch.UUID()) { if wantsToWrite && mod.writeUUID.Equal(ch.UUID()) {
foundToWrite = true foundToWrite = true
if isWritable { if isWritable {
@ -352,6 +368,7 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
} }
if multi == nil { if multi == nil {
char.Data = data
rows = append(rows, []string{ rows = append(rows, []string{
fmt.Sprintf("%04x", ch.VHandle()), fmt.Sprintf("%04x", ch.VHandle()),
name, name,
@ -359,6 +376,7 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
data, data,
}) })
} else { } else {
char.Data = multi
for i, m := range multi { for i, m := range multi {
if i == 0 { if i == 0 {
rows = append(rows, []string{ rows = append(rows, []string{
@ -372,11 +390,16 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
} }
} }
} }
service.Characteristics = append(service.Characteristics, char)
} }
// blank row after every service, bleah style // blank row after every service, bleah style
rows = append(rows, []string{"", "", "", ""}) rows = append(rows, []string{"", "", "", ""})
} }
mod.currDevice.Services = append(mod.currDevice.Services, service)
}
if wantsToWrite && !foundToWrite { if wantsToWrite && !foundToWrite {
mod.Error("writable characteristics %s not found.", mod.writeUUID) mod.Error("writable characteristics %s not found.", mod.writeUUID)
} else { } else {

View file

@ -10,12 +10,29 @@ import (
"github.com/bettercap/gatt" "github.com/bettercap/gatt"
) )
type BLECharacteristic struct {
UUID string `json:"uuid"`
Name string `json:"name"`
Handle uint16 `json:"handle"`
Properties []string `json:"properties"`
Data interface{} `json:"data"`
}
type BLEService struct {
UUID string `json:"uuid"`
Name string `json:"name"`
Handle uint16 `json:"handle"`
EndHandle uint16 `json:"end_handle"`
Characteristics []BLECharacteristic `json:"characteristics"`
}
type BLEDevice struct { type BLEDevice struct {
LastSeen time.Time LastSeen time.Time
Vendor string Vendor string
RSSI int RSSI int
Device gatt.Peripheral Device gatt.Peripheral
Advertisement *gatt.Advertisement Advertisement *gatt.Advertisement
Services []BLEService
} }
type bleDeviceJSON struct { type bleDeviceJSON struct {
@ -26,6 +43,7 @@ type bleDeviceJSON struct {
RSSI int `json:"rssi"` RSSI int `json:"rssi"`
Connectable bool `json:"connectable"` Connectable bool `json:"connectable"`
Flags string `json:"flags"` Flags string `json:"flags"`
Services []BLEService `json:"services"`
} }
func NewBLEDevice(p gatt.Peripheral, a *gatt.Advertisement, rssi int) *BLEDevice { func NewBLEDevice(p gatt.Peripheral, a *gatt.Advertisement, rssi int) *BLEDevice {
@ -39,6 +57,7 @@ func NewBLEDevice(p gatt.Peripheral, a *gatt.Advertisement, rssi int) *BLEDevice
Vendor: vendor, Vendor: vendor,
Advertisement: a, Advertisement: a,
RSSI: rssi, RSSI: rssi,
Services: make([]BLEService, 0),
} }
} }
@ -59,6 +78,7 @@ func (d *BLEDevice) MarshalJSON() ([]byte, error) {
RSSI: d.RSSI, RSSI: d.RSSI,
Connectable: d.Advertisement.Connectable, Connectable: d.Advertisement.Connectable,
Flags: d.Advertisement.Flags.String(), Flags: d.Advertisement.Flags.String(),
Services: d.Services,
} }
return json.Marshal(doc) return json.Marshal(doc)
} }