Back in June last year—at WWDC—Apple quietly announced iBeacon. It didn’t even get a mention in the keynote, appearing in just a single slide about “…some other features in the SDK.” But for hardware people it was actually one of the most prominent features of Apple’s latest OS release, and my Twitter feed exploded. People are always looking for new levers to enable them to do new things.
I’m not really going to talk here about the—interesting and somewhat telling—split between Google, which initially relied on NFC technology and only recently have grudgingly added Bluetooth LE support to Android, and Apple, which avoided NFC and concentrated on finding alternatives utilizing both Wi-Fi and Bluetooth LE—for instance by rolling out AirDrop as an alternative to Google’s now shuttered Bump file-sharing service. While I think the choice of those competing technologies actually tells us a lot about the two companies—that’s another post entirely.
In what could easily be a commodity market—after all iBeacon isn’t their technology—Estimote is viewed as the market leader, and is being promoted fairly heavily as one of the handful of partner companies on the Nordic booth at CES next week.
What is iBeacon?
iBeacon is a technology that allows you to add real world context to smart phone applications. Based around Bluetooth LE, part of the new Bluetooth 4.0 standard, it’s a way to provide basic indoor navigation and iBeacon has been integrated into iOS 7 both inside the Core Location and the Passkit frameworks to enable indoor micro-location and geofencing.
However iBeacon isn’t about location, it’s about proximity. Your iPhone—or now even your Android phone—can now alert applications when you are approaching or leaving a location with an iBeacon. It can also report an estimate of your proximity to the iBeacon, but you should be aware that the closer you are to the beacon, the more accurate the estimate of proximity becomes. The two factors here are signal strength and radio interference. Whilst signal strength is fairly dependable, interference is not—and can change radically with time—so while you can generally depend on the beacon to alert your app that you’re in its general proximity, I’d be wary of relying on the ranging to much.
Building your own iBeacon
It’s fairly simple to build your own iBeacon—either using a Raspberry Pi or using a Bluetooth LE board like the Red Bear Labs BLE Mini board—and there are some people taking advantage of that to turn a quick profit.
For instance Radius Networks is selling a “iBeacon Development Kit” which consists of a Raspberry Pi, a Bluetooth USB dongle, and an 8GB SD Card. Costing around $45 when bought separately at full retail price, they’re selling it bundled together for $100. That’s quite a markup, especially since they won’t be buying the components at retail, with very little added value over buying the parts separately and following fairly simple instructions to build your own.
To be fair, I think Radius is just selling the kit as a sideline to promote their software offering, and they’ve published their work on reverse engineering the iBeacon Bluetooth profile, and maximising iBeacon responsiveness amongst other things.
The Estimote
The way I’ve heard it, Estimote struck it lucky. There they were, playing around with Bluetooth LE “beacons” that could be used by smart phones for indoor location fixes, without people showing that much interest, and then there was Apple—and the iBeacon, and they ended up with a couple of months head start on the competition. Of course this could be the urban legend edition—or at least a revisionist version—of their company history, told in bars, conference lobbies, and other places where developer gather. But it does have a certain ring of authenticity to it.
Despite that—and whatever the true story—when the iBeacon is discussed, most times you’ll hear the phrase “…like the Estimote.” It’s a bit unfair on their competition, and there are competitors Roximity, TwoCanoes, Sonic Notify, Radius Networks, and few others, but I guess those are the breaks.
It’s actually still fairly hard to get your hands on an Estimote developer preview kit—as it’s still shipping in limited numbers—but I managed to get one of the early developer kits back in November last year and, predictably, I took one of the beacons apart.
The first thing you notice is that there is no on/off button, the device is broadcasting all the time, even before getting out of its packaging. It’s shipped live, which could get interesting.
The case is made of soft silicon with a rubberized feel and it is entirely closed so that it’s waterproof. I more-or-less had to destroy the enclosure to extract the PCB from it, which also means that changing the batteries—at least on the models in the preview kit—isn’t going to be possible. However it does mean that you can install it outdoors, which is a big plus point for some use cases.
The Estimote is built around the Nordic Semiconductor nRF51822, which explains their presence on the Nordic booth at CES. It’s a nice chip, basically a 32-bit ARM Cortex M0 CPU with 256KB of flash and 16KB of RAM with a built-in 2.4GHz radio supporting both Bluetooth LE as well as 2.4GHz operation—where the 2.4GHz mode is on air compatible with the nRF24L series products from Nordic.
The beacons are marketed as including both a temperature sensor and an accelerometer—although as we’ll see later on neither of these are advertised as part of the GATT, and aren’t accessible data packets, at least at the moment.
I’m assuming—for now—that the temperature sensor they’re talking about is the one built-in to the Nordic ARM itself, and that the accelerometer is the smaller chip (on the left of the picture) labelled “8237 C3H DEA3H” although I’m going to have to admit I haven’t tracked down the data sheet for this chip so I don’t know for certain.
Estimote are advertising a range of around 230 feet (about 70 meters) for their beacons. However testing puts the range much less, at somewhere around 130 feet (about 40 meters) out of the box, with highly variable precision. As far as I can tell you also shouldn’t rely on the proximity measurements at all as, at least from my own testing, these proximity measurements vary rapidly—presumably due to radio interference.
They’re also predicting a battery life of up to 2 years. However our beacon arrived at 55 percent charge, and it is now at 33 percent after just a month, so that seems somewhat of an optimistic prediction—and makes that sealed enclosure more of a liability than an asset.
Interestingly all of the Estimote beacons in all of their developer preview kits are shipping with identical UUIDs—the UUID for every beacon is fixed—and they’re not planning to add the ability to change the UUID any time soon. That means you can’t use them in a production environment the way Apple intended, or at least, not without some modification.
You’re also effectively locked into using their closed source iOS SDK if you’re using their hardware, as other iBeacon hardware won’t work with their SDK, and if you use the lowest common denominator—Apple’s own Core Location and Passkit frameworks—to talk to a heterogeneous collection of iBeacon hardware, you’re stuck in read-only mode with the Estimote beacons themselves. That could be a real problem in the future, both for end users, and Estimote themselves.
Estimote have now also shipping a closed source Android SDK. However, there doesn’t seem to me to be much advantage in locking yourself into their proprietary SDK on Android as—unlike their iOS SDK—the beacons can’t be configured using it, so you’re stuck with read-only mode in any case. You may as well use one of the generic libraries built for iBeacons on Android, and be able to talk to everyone’s hardware, not just Estimote’s.
The beacons themselves then must be configured by a closed source iOS SDK, and at least at the moment the Bluetooth LE GATT services and characteristics of the beacons remain—at least officially—undocumented.
To be fair to Estimote, Apple haven’t—at least officially—publicly documented the iBeacon specification yet either, although unofficial documentation based around Apple’s own example code has started to appear. As well as the hardware then, we should take a closer look at the developer preview beacon’s software and see if we can figure out how they work.
What does the Estimote Beacon advertise?
Using Sandeep‘s noble package for node.js we can look at what’s advertised by one of the beacons, using the advertisement discovery script included with the package.
An Estimote beacon—picked at random from our developer preview kit—with a Bluetooth Address of E7:44:89:31:ED:4E advertises a local name of “Estimote”, along with some service and manufacturer data. However it doesn’t seem to be advertise any service UUIDs.
Taking a closer look at the manufacture data then, the data advertised by the beacon was,
4C00 02 15 B9407F30F5F8466EAFF925556B57FE6D ED4E 8931 B6
Breaking this down,
- First two bytes are the Apple Company Identifier (Little Endian) 0x0042.
- The third byte—at least most likely—specifies the data type, which is 2.
- The fourth byte specifies the remaining data length, 21 bytes.
- Estimote Beacons have a fixed iBeacon UUID of B9407F30-F5F8-466E-AFF9-25556B57FE6D.
- The next two bytes after the iBeacon UUID are the iBeacon Major (Big Endian), i.e. 0xED4E, 60750.
- The next two bytes after the iBeacon Major are the iBeacon Minor (Big Endian), i.e. 0x8931, 35121.
- The final byte is the measured RSSI at 1 meter away, i.e. 0xB6, -74.
Effectively the Estimote isn’t doing anything special here, this is just standard iBeacon data. Three of the properties create the beacon’s identity. These are:
- UUID — This is a property which is unique to each company, n most use cases the same UUID would be given to all beacons deployed by a company (or group). Estimote is unusual in that they’ve fixed the UUID for all “their” beacons to be the same.
- Major — The property that you use to specify a related set of beacons, e.g. all the beacons in one store would share the same Major value.
- Minor — The property that you useto specify a particular beacon in a location.
We need to look at the service data advertised by the beacon,
0A18 4EED318944E7 B6 4EED 3189
to see anything Estimote specific,
- The first two bytes specify this service data is for a service with UUID 0x180A.
- The next 6 bytes are the Bluetooth Address but in reverse order, E7:44:89:31:ED:4E.
- The next byte, 0xB6 matches the measured RSSI at 1 m away.
- The next 2 bytes, match the iBeacon Major but this time it’s Little Endian.
- The final 2 bytes, match the iBeacon Minor again in Little Endian format.
According to the Bluetooth core specification service data must be prefixed with the 16-bit UUID of the service the data is for—and here for the Estimote—the service data is for for a service with UUID of 0x180a, which is interesting because as we’ll see later when we look at the GATT, that service doesn’t exist on the device.
GATT services and characteristics
In contrast with “classic” Bluetooth—where there are a whole range of protocols—with Bluetooth LE there is only one protocol at the top and it is GATT (Generic Attribute). The actual functionality of a Bluetooth LE device is implemented by means of attributes which can be read, written, or enabled for notification/indication, depending on the attribute type.
We can use the Linux gatttool command line program—part of the BlueZ package—to manipulate these attributes. Connecting to the beacon with gatttool we get a list of both the services and characteristics.
Putting the output from gatttool into tabular form—where readable characteristics were read using the “char-read-hnd <handle>” gatttool command—we can compare the values we got from the gatttool to what’s shown the Estimote iOS application,
and we’re a lot further forward. Interestingly if, at this point, you try using gatttool‘s “char-write-req <handle> <new value>” command to write to any of the Estimote’s characteristics—UUID, Minor, Major, Power Level and Advertising Interval—the writes return as successful. However subsequently the iBeacon’s broadcasted data does not update accordingly.
Despite this the Estimote SDK lets you update the iBeacon Minor and Major—although not as previously mentioned the UUID of the beacon—something is going on here that we need to understand more fully. The SDK is obviously doing something devious under the hood that gatttool isn’t.
Using the SDK
Yoann Gini has built a simple tool using the Estimote SDK allowing you to read and edit the Minor and Major numbers for the beacon, called EstimoteEditor.
We’ve forked the project—and made some changes we’ll talk about later—so if you go ahead and clone the repo,
git clone https://github.com/sandeepmistry/EstimoteEditor.git cd EstimoteEditor git submodule init git submodule update
and initialize and update the submodules, then open the project in Xcode, you can build and deploy to an Bluetooth LE enabled iPhone—unfortunately it’s not going to work in the iOS Simulator, it needs to be run on a device.
After you select the discovered beacon the Power Level, Major, Minor and Advertising Interval are all configurable—and the edited values stick, unlike the changes we made from gatttool. So, what’s the SDK doing differently?
Method Swizzling CoreBluetooth
Since Objective-C is a runtime language it is possible to inspect methods, properties, and variables of classes and objects at runtime, even though they are private and hidden by the SDK, even if you don’t have the source code and only have access to a binary blob.
To do this we use something called method swizzling—it allows you to replace the existing implementation of a method with your own at runtime. Predictably if used properly, can be a powerful tool. However, used incorrectly, it can cause devastation on a biblical scale.
Sandeep used this technique to see how CoreBluetooth works under the hood on OS X, and then used the results to communicate with the blued—the Bluetooth daemon on OS X—without using CoreBluetooth in noble, his node.js BLE library. Perhaps more scarily Alasdair has used it in production code to intercept various network calls and introduce analytics to collect network performance data “in the wild” on the iPhone.
Let’s use a similar technique on iOS to intercept the communication between the Estimote SDK and CoreBluetooth. After taking a look at the iOS runtime headers for CoreBluetooth, the CBXpcConnection class stands out. Here an XPC connection is used by CoreBluetooth to communicate with the Bluetooth daemon.
Let’s swizzle the following methods,
- (void)handleMsg:(int)arg1 args:(id)arg2; - (void)sendMsg:(int)arg1 args:(id)arg2;
which will allow us to see how the Estimote SDK is using CoreBluetooth—with some interpretation, we see that there isn’t anything special going on here,
- start scanning for devices
- devices discovered
- stop scanning
- connect to the device
- discover devices services and characteristics
- read/write some of the devices characteristics
Things look similar to what we were doing with gatttool, except for the read/writes to the characteristics at handles 45 and 47. We should probably go back to Xcode and set breakpoints during characteristic writes and see what the call stacks shows,
This gives us two more methods to swizzle, this time inside the ESTBeacon class,
- (void)pairSensorFirstPart; - (void)pairSensorSecondPart;
Looking at the output it definitely looks like there is a special pairing process going on, so setting break points in the new swizzled methods—letting us set into the original methods—doesn’t help all that much. What’s next?
Running class-dump on the build provides some interesting output. The ETBluetoothMath class looks especially interesting.
@interface ETBluetoothMath : NSObject { } + (id)stringFromHexString:(id)arg1; + (id)hexStringToBytes:(id)arg1; + (int)giveSignToUnsigned:(unsigned int)arg1; + (unsigned long)Secunit_ModExpWithBase:(unsigned long)arg1 Exp:(unsigned long)arg2 andMod:(unsigned long)arg3; + (unsigned long)randomUInt32; + (unsigned short)randomUInt16; + (id)randomDataWithBytes:(unsigned int)arg1; + (const char *)CBUUIDToString:(id)arg1; + (int)compareCBUUID:(id)arg1 UUID2:(id)arg2; + (id)IntToCBUUID:(unsigned short)arg1; + (unsigned short)CBUUIDToInt:(id)arg1; + (unsigned short)swap:(unsigned short)arg1; + (const char *)UUIDToString:(struct __CFUUID *)arg1; @end
Let’s swizzle the Secunit_ModExpWithBase:Exp:andMod: method and add some logging on the inputs and return values. That will tell us how the characteristic handle 45 is used,
- Generate a random 32-bit unsigned integer.
- Write the following to characteristic at handle 45: 5^(random 32) mod 0xfffffffb (little endian)
- Read characteristic at handle 45 (little endian): (characteristic 45 value)^(random 32) mod 0xfffffffb
Let’s put a breakpoint in swizzled pairSensorSecondPart method in ESTBeacon, and step into the original. After stepping over a few instructions we see something interesting.
Is that TI—as in Texas Instruments? Going to Google we find not only that it is, but the source code for TI_aes.c is available online. We can grab it, and add it to our project. That’ll let us try adding breakpoints to aes_encrypt and aes_decrypt inside TI_aes.c. Surprisingly, these breakpoints actually get hit, which means that we can inspect the data passed into both the encryption and decryption methods.
The AES-128 encryption key is always 0xff8af261013625c2d810097f20d3050f. Whilst the encryption state is based on the Bluetooth Address (E7:44:89:31:ED:4E) and is 0x4eed318944e731ed4ee74489443189ed.
The AES-128 decryption key is based on the last secunit calculated (0x8e450d08) and is 0x080d458e8e450d08088e0d458e08450d. Whilst the decryption state is the result of the encrypt, 0x419a05a457dcceebeed5129e88a81c4e.
The result of the decrypt is written to the characteristic at handle 47, wrapping up the pairing process.
Putting things together
Now we’ve figure out the pairing sequence and a rough specification of the characteristics. We can create a node.js script that uses noble to discover and connect to the Estimote Beacon. Then we can try—again—after pairing to write to the Major and Minor characteristics. This time with success.
Interesting. The SDK doesn’t allow us to update the UUID, can we do it using this method? It turns out we can. Writing the same value to both the UUID characteristics works, and the iBeacon UUID is updated. We can set the iBeacon UUID to something the Estimote does not expose.
Conclusion
The Estimote iOS SDK is closed source, but by using method swizzling and the class-dump utility on it and the CoreBluetooth framework we were able to find out how it interacts with the beacon.
The information contained in the SDK is probably more revealing than the authors expected it to be, and unfortunately for them, there’s very little they can do about that.
Whilst the Estimote developer preview kit and SDK are still in their early stages if Estimote sticks with their currently security model—although there are signs that they might not do that—anyone who creates an application using their SDK will be able to reconfigure any Estimote Beacon in the wild.
The implications of that are fairly far reaching. If someone maliciously changes the iBeacon Major or Minor characteristic of a beacon, any consumer application configured to use that particular beacon will stop working—the beacons must be configured with a pre-defined identity to trigger the correct behaviour inside the consumer’s own application when their smart phone comes into proximity of the beacon.
Beyond that you could configure a “fake” beacon to act as an impostor of another beacon belonging to a retail chain, potentially gaining access to promotions, gift cards and other location dependant goodies tied to the beacon you’re impersonating.
Other manufacturers use different—and possibly more secure—methods to set the UUID, Minor, and Major values of the beacon. Personally, I’d want to take a serious look at those alternatives before deploying this technology in production environments. Especially if there was real money involved.
Whilst it’s not trivial to reverse engineer the software and hardware used in devices like the Estimote, it’s entirely doable and—after understanding how the beacons work—we were able to easily modify the beacon configuration.
Update: We talked about both of the ability to configure “fake” beacons, and the ability to disable beacons in the field, however we didn’t think we’d see something like this quite this soon. This year’s Consumer Electronics Show (CES) featured a promotional scavenger hunt based around Apple’s iBeacon technology—and it turned out that you could win the hunt, without ever having to go to CES.
ADVERTISEMENT