esp32_bluetooth_classic_sni.../libs/scapy/contrib/ibeacon.py

102 lines
3.2 KiB
Python
Raw Normal View History

# -*- mode: python3; indent-tabs-mode: nil; tab-width: 4 -*-
# ibeacon.py - protocol handlers for iBeacons and other Apple devices
#
# This file is part of Scapy
# See http://www.secdev.org/projects/scapy for more information
# Copyright (C) Michael Farrell <micolous+git@gmail.com>
# This program is published under a GPLv2 (or later) license
#
# scapy.contrib.description = iBeacon BLE proximity beacon
# scapy.contrib.status = loads
"""
scapy.contrib.ibeacon - Apple iBeacon Bluetooth LE proximity beacons.
Packet format documentation can be found at at:
* https://en.wikipedia.org/wiki/IBeacon#Packet_Structure_Byte_Map (public)
* https://developer.apple.com/ibeacon/ (official, requires license)
"""
from scapy.fields import ByteEnumField, LenField, PacketListField, \
ShortField, SignedByteField, UUIDField
from scapy.layers.bluetooth import EIR_Hdr, EIR_Manufacturer_Specific_Data, \
LowEnergyBeaconHelper
from scapy.packet import bind_layers, Packet
APPLE_MFG = 0x004c
class Apple_BLE_Submessage(Packet, LowEnergyBeaconHelper):
"""
A basic Apple submessage.
"""
name = "Apple BLE submessage"
fields_desc = [
ByteEnumField("subtype", None, {
0x02: "ibeacon",
0x05: "airdrop",
0x07: "airpods",
0x09: "airplay_sink",
0x0a: "airplay_src",
0x0c: "handoff",
0x10: "nearby",
}),
LenField("len", None, fmt="B")
]
def extract_padding(self, s):
# Needed to end each EIR_Element packet and make PacketListField work.
return s[:self.len], s[self.len:]
# These methods are here in case you only want to send 1 submessage.
# It creates an Apple_BLE_Frame to wrap your (single) Apple_BLE_Submessage.
def build_frame(self):
"""Wraps this submessage in a Apple_BLE_Frame."""
return Apple_BLE_Frame(plist=[self])
def build_eir(self):
"""See Apple_BLE_Frame.build_eir."""
return self.build_frame().build_eir()
class Apple_BLE_Frame(Packet, LowEnergyBeaconHelper):
"""
The wrapper for a BLE manufacturer-specific data advertisement from Apple
devices.
Each advertisement is composed of one or multiple submessages.
The length of this field comes from the EIR_Hdr.
"""
name = "Apple BLE broadcast frame"
fields_desc = [
PacketListField("plist", None, Apple_BLE_Submessage)
]
def build_eir(self):
"""Builds a list of EIR messages to wrap this frame."""
return LowEnergyBeaconHelper.base_eir + [
EIR_Hdr() / EIR_Manufacturer_Specific_Data() / self
]
class IBeacon_Data(Packet):
"""
iBeacon broadcast data frame. Composed on top of an Apple_BLE_Submessage.
"""
name = "iBeacon data"
fields_desc = [
UUIDField("uuid", None, uuid_fmt=UUIDField.FORMAT_BE),
ShortField("major", None),
ShortField("minor", None),
SignedByteField("tx_power", None),
]
bind_layers(EIR_Manufacturer_Specific_Data, Apple_BLE_Frame,
company_id=APPLE_MFG)
bind_layers(Apple_BLE_Submessage, IBeacon_Data, subtype=2)