What makes an iBeacon an iBeacon
It’s very simple, it just advertises a string which contains a few characters conforming to Apple’s iBeacon standard.
If you use a bluetooth pakket sniffer you will see the advertisement strings.
To make a beacon, all you need to do is insert a specific set of bytes into the optional Manufacturer Specific Data field of the advertising packet on your Bluetooth Low Energy device.
Inside this field, you need the following values:
ID (uint8_t) - This will always be 0x02
Data Length (uint8_t) - The number of bytes in the rest of the payload = 0x15 (21 in dec)
128-bit UUID (uint8_t) - The 128-bit ID indentifying your company/store/etc
Major (uint16_t) - The major value (to differentiate individual stores, etc.)
Minor (uint16_t) - The minor value (to differentiate nodes withing one location, etc.)
TX Power (uint8_t) - This value is used to try to estimate distance based on the RSSI value
For example, the following is a valid iBeacon payload (separators added for clarity sake):
02 | 15 | E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 | 00 00 | 00 00 | C8
The only other missing piece is that, following the Bluetooth standard, the Manufacturer Specific Data needs to be preceded by the Company Identifier, which is
0x0016 for Apple.
Here is an example captured with pakketlogger
This explanation is also very good on stackoverflow
For an iBeacon with ProximityUUID E2C56DB5-DFFB-48D2-B060-D0F5A71096E0, major 0, minor 0, and calibrated Tx Power of -59 RSSI, the transmitted BLE advertisement packet looks like this:
d6 be 89 8e 40 24 05 a2 17 6e 3d 71 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 52 ab 8d 38 a5
This packet can be broken down as follows:
d6 be 89 8e # Access address for advertising data (this is always the same fixed value) 40 # Advertising Channel PDU Header byte 0. Contains: (type = 0), (tx add = 1), (rx add = 0) 24 # Advertising Channel PDU Header byte 1. Contains: (length = total bytes of the advertising payload + 6 bytes for the BLE mac address.) 05 a2 17 6e 3d 71 # Bluetooth Mac address (note this is a spoofed address) 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 # Bluetooth advertisement 52 ab 8d 38 a5 # checksum
The key part of that packet is the Bluetooth Advertisement, which can be broken down like this:
02 01 1a 1a ff 4c 00 02 15 # Apple's fixed iBeacon advertising prefix e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon profile uuid 00 00 # major 00 00 # minor c5 # The 2's complement of the calibrated Tx Power
Any Bluetooth LE device that can be configured to send a specific advertisement can generate the above packet. I have configured a Linux computer using Bluez to send this advertisement, and iOS7 devices running Apple’s AirLocate test code pick it up as an iBeacon with the fields specified above. See: Use BlueZ Stack As A Peripheral (Advertiser)
This blog has full details about the reverse engineering process.