StickNFind update

I have seen a lot of traffic today for StickNFind posts.

They’ve banned me from their Facebook page, blocked me on Twitter (which, is totally pointless) and stopped responding to email. I am sorry if I wasted your time with the survey as I have no way of communicating hundreds of people’s views to them now.

I suggest that if you have an issue with StickNFind you:

Essentially, the more noise you make, the better.

Keep rolling, rolling, rolling

In the last post about technologies used in alarms, I discussed the use of spread spectrum. Another really common keyword seen on marketing material is “rolling code”. What is it, why is it used, and what problems are there with it?

Why?

A wireless alarm system might send a signal from a keyfob to the panel to say “disarm the system”. If the content of this packet does not change in any way from time to time, we could simply record this packet and replay it at a later time.

This is commonly called a replay attack. There are alarm systems available that are vulnerable to this attack – the older Yale Wireless Alarm systems (434MHz ones) and Friedland SL series are examples. There are “Universal cloning remotes” on eBay for less than £5 that will clone any alarm using 434MHz OOK signalling. You can also use an Arduino and cheap receiver to listen out for signals and store them for later replay.

It is desirable to have a means of stopping these replay attacks from happening.

There is nothing in the EN50131-5-3 specification that means a grade 2 alarm needs any protection against these attacks. Most newer alarms do however have some protection.

How?

The attack is possible because the signal doesn’t ever change – it is always “disarm the system”.

To protect against a pure replay attack, we just need to add something that changes each time the signal is sent. How about the time? “disarm the system 21:22:32 26/04/2013”

This works. There is now no way for me to record a packet and use it again later.

But a really malicious attacker could work out how to take a packet recorded earlier, modify the time, and replay it.

This is where rolling code comes into play – instead of appending the time, we add a code to the packet. This code changes each time a packet is sent. The receiver and transmitter have agreed how this code will change – generally using a psuedo-random number generator.

The packet now becomes “disarm the system 204389473692”, the next time it will be “disarm the system 937459384322” and so on.

The sequence of this codes is essentially random to an observer, and the code is long enough that it makes guessing the next one very difficult.

Unlike spread spectrum, this sequence is generally extremely long in small systems.

Keeloq is a proprietary implementation of a rolling code protocol, often used in car keyless entry systems. The rolling code is 32-bit, which essentially means it is impossible for someone to guess the next code.

Keeloq does have weaknesses. The major one is that it is possible to recover the key used to seed the random number generator. Once you have this, it is far easier to guess the next code. It’s still very challenging though.

What issues are there with rolling code?

Again, the devil is in the detail. Rolling code is a sound principal – but it must be implemented correctly.

Predictable codes

The whole thing falls over if someone can guess the sequence of codes you are using. There are a number of ways that this can happen.

If your code is short (say, 8bits), the an attacker has a 1/256 chance of getting the next code correct if he chooses randomly. If your code is long (say, 32 bits), then it is 1/4294967296. Whatever method you are using to guess the codes, you can clearly see that the longer the code, the harder it will be.

A good pseudo-random number generator (PRNG) can be seeded – you give it a key which determines how it will hop. It shouldn’t matter what the algorithm is or if the attacker knows the algorithm, as long as they don’t know the seed, they shouldn’t be able to predict the sequence. Unfortunately, many products either used a fixed seed across all products (this makes protocol design, especially with a one-way radio, much easier) or the algorithm is bad.

How can the algorithm be bad? Say we have a PRNG with this output when seeded with “1”:

7, 3, 4, 1, 3, 6, 1, 3, 2

If I were to seed it with “2”, the output should be completely different:

8, 3, 3, 2, 7, 1, 5, 3, 1

But some systems simply use the seed to skip some of the output i.e. with a seed of “2”:

3, 4, 1, 3, 6, 1, 3, 2, 8

Notice this is just the first sequence shifted along one digit!

If I know the entire sequence, then all I need to do is gather a few packets and I can work out where we are in the sequence. The number of packets I need varies, but with a poor PRNG or short code, it’s not very many!

Worse still, some “rolling code” systems use a code like:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Whilst this might protect against casual replay attacks, it is not hard for an attacker to guess the next number.

Limitations with one-way radios

If your keyfob can transmit but not receive, there is a small problem. Each time it transmits, the code rolls forward. There is no guarantee that the receiver will hear the transmission.

This means that the transmitter’s code can be further ahead in the sequence than the receiver. This needs to be taken account of – what happens if you are idly pressing the disarm button in your pocket whilst waiting for the bus?

Most systems deal with this by checking for a valid code over a “window” of acceptable values. This could, say, be the next 256 codes. This has an interesting effect on guessing. If I have a 16 bit code, there are 65,536 possibilities. If the window was only 1 long, I would have a 1/65,536 chance of randomly guessing the code. If the window is 256 long, we reduce this by a factor of 256 – to 1/256. That’s a big difference.

Message substitution

A very simple rolling code implementation just appends the pseudo-random code onto the message i.e. “disarm the system 878463098273”

There is no link between the message (“disarm the system”) and the code (“878463098273”).

This means we can change the message and use the same code, providing that the receiver hasn’t received the code.

How could this be done? I’ll give one possible attack.

When you press “arm the system” on the keyfob, it will actually send more than one packet, to ensure that the receiver gets the message. We have something like:

arm the system 736474747363

arm the system 093219457437

arm the system 384838738383

arm the system 732878476655

If I am in the position to jam the receiver, but still receive the genuine packet, I can do the following:

1. Record all 4 packets.

2. Immediately replay the first two to arm the alarm so the user does not see an issue:

arm the system 736474747363

arm the system 093219457437

3. Hold onto the last two packets.

4. Change the messages on the second two packets to:

disarm the system 384838738383

disarm the system 732878476655

And bang, we have disarmed the system.

Replay attacks still work

As long as the packet never reaches the receiver, we can still grab a transmission from a keyfob and use it later. This means someone could press the disarm button on your keyfob whilst you are away from the house (say, when you pass your keys to the checkout assistant to scan your loyalty card), and then replay it later.

Conclusion

Rolling code, again, is a good idea, and if implemented well, can protect against a lot of attacks. Many systems do not implement it well though – the above vulnerabilities can be found in real world alarm systems.

A much more robust solution is to use timestamps in the messages and then use encryption and a message authentication code.

If anyone is interested, Atmel have a really good app note on implementing a secure algorithm with one-way radios.

Social media and representing your employer

I had a recent exchange on twitter with @zacwolf about the StickNFind stickers.

He stated that he thought that StickNFind not responding to customer queries for 10 days was acceptable service. I couldn’t fathom why anyone would think this was acceptable – I assumed he either worked for them, knew them, or worked for another company that has a poor customer service ethos.

I looked at his twitter profile, which directly linked to his about.me page (this has since been edited to remove the employer, but is still visible on the mobile page).

This stated he worked for Cisco. A company which I have had more than a few dealings with and I think their customer service stinks, especially for smaller businesses and consumers. It seems endemic across multiple business units. To me, it provides an explanation as to why he thought this kind of service was acceptable.

If you list your employer openly on a social media profile, you fly their flag, especially when that employer is a huge multi-national that a lot of people will have dealings with. It doesn’t matter what you think or what the companies social media policy is – you are associated with the employer.

He then decided to call me a “punk ass bitch”. This is massively unprofessional.

Someone who works for Cisco has just called me, a customer, a “punk ass bitch”, after I have questioned poor customer service. This reinforces my previous opinion of Cisco – their employees don’t seem to care what customers think.

I included @ciscosystems on the reply to this tweet.

@zacwolf continued to tell me that he didn’t represent Cisco, despite having it clearly shown on his profile.

@zacwolf seems to have received a disciplinary warning as a result.

Did I want this to happen? No.

Is it bullying? No.

Cisco’s social media policy is clear on this. If you make it clear you work for Cisco, you need to follow it.

Would it be acceptable to call someone a “punk ass bitch” at work? Would you expect to walk down the street wearing a company T-shirt, insulting people, and them not form a negative opinion of your company?

I know the answers to those questions.

A review of Audiovox Insite BLE tracking tags – a competitor to StickNFind

The CEO of PhoneHalo, Chris Herbert, noticed some of my tweets about the problems I have been having with the StickNFind Bluetooth tracking tags, and offered to send me a sample of his competing product to review. This was very promptly shipped from the US and dropped onto my doormat on Monday morning.

The tag by itself

The tag by itself

The Audiovox Insite Ultrathin Bluetooth Proximity alarm, on the whole, is a much more functional product than the StickNFind. Let me go into some detail.

Firstly, the tag is very small. It isn’t as small as the StickNFind, but it is small enough to be used for the same applications.

inSite tag vs StickNFind

inSite tag vs StickNFind

The construction quality and plastic used are excellent and it has an integrated loop for attaching to keys. The battery fits on a small tray at one end. I can see that people might be confused which way the battery goes in, but the design protects against the battery being fully inserted incorrectly.

The app is readily available in the iTunes store for free.

Pairing the device worked easily – just insert the battery, and follow the instructions in the app.

The app only has a very small number of core features. I really believe this is why the Audiovox Insite tag works much better than the StickNFind tags.

The app

The app

There are two buttons:

  • Ring Device – this immediately causes the tag to beep and light up
  • Locate Device – this shows the last GPS location that the phone was in when the tag was in range.

That is all it has. No radar, no temperature. Very simple, but it works.

Two icons at the top of the screen show range (Close, Mid, Far) and battery level.   Generally the range is sensible, but it does jiggle around from time to time. It isn’t really that important, as none of the features rely on this.

As soon as the tag and phone are out of range from one another, the alert is triggered on both. There is no way of setting range – it is just in or out of range. It seems to me that they have admitted that any kind of range estimates will be poor, and have worked within this limitation.

So, what do I think?

  • The range is quoted as 30-60ft. This is very much what I am experiencing – it is in range anywhere in my house. StickNFind doesn’t even get to the other side of the room.
  • The connection does sometimes drop, causing false alarms. The tag automatically reconnects though. I have had a couple of disconnects a day when out and about. My cooker extractor fan seems to cause a problem – possibly it is electrically noisy.
  • The tag rings immediately when I press the button on the phone, every time, as long as the tag is in range. StickNFind only sometimes works, and with delay.
  • The beeping is far louder and more shrill than StickNFind. It makes it far easier to find the tag.
  • The app is stable and phone battery life doesn’t seem to be impacted.
  • Use of Wifi nearby doesn’t seem to impact range.

So, totally useless for tracking my cat, but it doesn’t claim to be able to do so.

I popped the tag open to see how it was constructed. The plastic is glued together and it was not possible to get the PCB out without wrecking the case.

The PCBs of the two products

The PCBs of the two products

The board is small and well constructed. Very thin PCB material. It would be possible to redesign it to be no larger than the StickNFind.

So, thanks to Chris for the sample. The Audiovox Insite tags don’t do what StickNFind claims to – but neither does the StickNFind. If you want to make sure you don’t lose your keys, camera, or phone, they do the job well.

Reverse engineering a wireless burglar alarm, part 8

Last time we worked out that we could drive the CC1150 daughterboard using the Seeeduino Mega Arduino board easily.

The Seeeduino Mega uses a ATmega2560 microcontroller, which has a number of features which will help us do this:

  • Hardware SPI interface – this makes high speed SPI connections almost effortless. No nasty bit-banging here.
  • Pin change interrupts – this means we can quickly and efficiently respond to the clock signal coming into the microcontroller. 6.25kHz isn’t so fast that it precludes the use of a polling technique, but polling is wasteful and limits what we can do with the rest of our time.
  • Lots of memory – we don’t need to care about creating wasteful buffers. The 8KB in the 2560 is far more flexible that 2KB in the 328.

Connecting the hardware is easy – we need to use PB0 (CS), PB1 (CLK), PB2 (MOSI) and PB3 (MISO). These map through to pins 53, 52, 51 and 50. We are going to use the adjacent PL0 port (pin 49) to clock out the data to GDO0. VCC is supplied from the 3.3V supply on the Seeeduino Mega (it is switchable from 3.3 to 5V operation – a valuable addition).

It was at this time I found out that if you connect the CC1150 incorrectly it gets very hot and starts letting out the magic smoke. It also still works after this..

Now, as for the software – I’m not really sure where to begin. It’s quite hard to explain bit-by-bit. I hope it is self-explanatory, to a large extent.

The code is available on github. There isn’t really much fancy going on here – I am using some CC11xx headers from previous projects to help identify the settings registers. All this aims to do is take the 48 bit (6 bytes) of data we have sniffed from a door contact, and replay this signal. It configures the CC1150 exactly as per the sniffed traffic, and then we use a pin change interrupt to clock the data out.

Oooo 2-FSK!

Oooo 2-FSK!

Once all of this is wired up, I can immediately see that my spectrum analyser is showing bursts of 2-FSK. That must mean things are approximately correct. I used to hate working with RF – I could never tell if it was the transmitter, receiver or just idiocy that was preventing things from working. A spectrum analyser gives you reassurance that you are doing at least something right.

So now I need to see if the bell box can learn the door contact from this signal. I connect up the bellbox, press and hold learn, and… nothing. I try the door contact, and it is learnt immediately. I must be doing something wrong.

(when working with alarm sirens, you need to be careful. If you leave the siren connected, they can be loud enough to actually damage your hearing. I never trust the soft setting to turn off the siren for testing, so always disconnect it physically. This then presents another danger – siren drivers can produce large voltages when the siren is open circuit – sometimes hundreds of volts, enough to give you a fair belt.)

The trusty Saleae Logic Analyser comes out again, and I connect it up to my cloned alarm sensor. It’s apparent that the signal isn’t quite right – a few extra bits here and there. A really quick and easy debug method is to use extra IO ports – PL1 and PL2 in this case – to  observe timing and code flow. Serial is just too slow for this kind of stuff – it might help me, but normally it slows down execution enough to cause problems. ATmega chips do have on-chip debug, but it is always more trouble than it is worth – these are very simple microcontrollers!

He's learning, we're learning.

He’s learning, we’re learning.

It turns out it is a simple bug – I’d used an incorrect comparison to signify the end of a packet. The code is fixed, and I try again. This time the panel learns the remote!

So where to from here? I need to start experimenting with the data in the packet, and seeing what the panel will and won’t accept. Next time.

Bitwise operations or how I learned to stop worrying and love my compiler

Whilst writing up some of the forthcoming posts on the alarm system, I found myself trying to write a simple method of setting, clearing, and getting bits in a byte buffer. I wanted this to be as transparent as possible so that the code was easy to understand.

The AVR microcontrollers are 8-bit. This means that registers, memory, and addresses are all 8-bits wide. It surprises many Arduino users when they find out that the type “boolean” is simply an entire unsigned, 8-bit integer (uint8_t). Boolean is just not a native concept to C and embedded systems. It’s incredibly wasteful to use a whole 8 bits to represent a single boolean value.

Bitwise operations

This isn’t to say that you don’t need to set individual bits in a byte though – this is actually a very common operation. Normally to do this, you use a couple of simple constructs.

To set the 6th bit in a register (0 is the first bit):

This means “Shift 0b00000001 along 5 to 0b00010000, and perform a logical OR with whatever is in the register already”. This has the effect of setting bit 5 to 1, and leaving all the other bits as are.

To clear the 5th bit in a register:

This means “Shift 0b00000001 along 4 to 0b00001000, invert it to 0b11110111, and perform a logical AND with whatever is in the register already”. This has the effect of clearing bit 4, and leaving all the other bits as are.

Bytewise operations

The above is all fine if you just want to look at a single bit in a byte. What happens if I want to deal with more than 8-bits? I need more bytes!

By far the easiest way to do this is to use an array:

Which just means “create an array of 32 unsigned 8-bit integers”.

I can access the first byte using:

And the tenth by using:

Really simple! I can combine this with the bitwise operations:

Now I have an easy way of accessing any bit in an array of bytes.

Bringing it together

The problem comes if I decide I want to set the bit 27 in the array. How do I work out which byte this is in?

This is just some simple maths. To work out the byte, integer divide 27 by 8 – we get 3. This means it will be in the 4th byte i.e.

Then take the remainder of 27 by 8 (the modulus) – we get 3 again. We need to set the 4th bit.

So now we have a method to set an individual bit in an array of bytes.

Making it easier

Rather than remember all of this maths and shifting each time I want to set a bit, why not use a macro?

This is just want we have said above. % is the modulus operator in C. This looks very clean and efficient.

That is until I use it in a project and find it is incredibly slow to set each bit in a buffer one by one. Why could this be? (I’ll go into benchmarking code another time)

If you look through the ATmega328P or ATmega2560 datasheets, you can see two key things:

  1. There is no hardware division unit on the microcontroller – division is expensive!
  2. There is only a single bit shift in either direction. Shifts of more than one need to be made up of multiple single bit shifts.

There’s something clever we could try here though. Division by 8 is exactly the same as shifting right by 3 bits:

So now we can change our macro a bit:

We can take this further though… modulus 8 is the same as only keeping the first 3 bits of a number i.e. masking.

So the macro can be changed even further:

And now we recompile and try again…

And get exactly the same result as before.

It turns out avrgcc is clever enough to spot that the divide by 8 and modulus 8 can be implemented by simple shifts and masks.

What is the moral of this story? Generally these days you will not make many gains in micro-optimisation. The compiler handles all of this, and normally much better than you can. Think about the big picture to make gains!

Reverse engineering a wireless burglar alarm, part 7

So, where were we? We’ve worked out how several components of the alarm use the CC1150 to send out signals, and now I want to emulate the signal and then play with it.

By far the easiest way to do this is to use the same CC1150 chip as in the authentic transmitters. I can be absolutely sure the 2-FSK modulation with ~50kHz deviation will be reproduced exactly. There are many other RF transmitter chips out there that can do this, but we know that these work and we already have the correct settings.

So, the first challenge is – where do I get a board with a CC1150 on it? Well, we have plenty of alarm sensors with neat little CC1150 daughterboards on them!

Door contact RF board

Door contact RF board

I chose a door contact as my victim – they are the cheapest and simplest sensors.

The daughterboard has an 8-pin interface, with a 0.1″ pitch pin header connecting the two. I need to desolder the board to use it. Desoldering pin headers is always a pain – you can’t desolder all 8 pins at a time. My technique now is:

  1. Chop the pin header along it’s length, separating the two boards. I have a nice pair of snips for this, but a Dremel with cut-off wheel can do it if they don’t fit.
  2. Chop the plastic spacer away from the pins, leaving you with just half the pins stuck in the board.
  3. Desolder the pins one at a time.
DSCF7845

The daughterboard

Now I have a small CC1150 board. I soldered a new pin header onto it, and a pin socket onto the rest of the door contact. This allows me to easily reconnect it to the door contact if I need to.

You’ll notice in the picture above that there is a small bridge wire. I desoldered and resoldered the CC1150 QLP package (just to see if I could) and burned a track in the process.

DSCF7846

Testing testing 1-2

Now we need to drive this board using something. There are a plethora of options available to me:

  • An Arduino board
  • A mbed board
  • A Bus Pirate
  • A GoodFET
  • A CC1110 development board (this would skip using the CC1150 board, as it has a built-in transceiver)
  • One of the Ciseco CC11xx boards (again, this would skip the CC1150 board)
  • Any of the other development boards I have lying around…

I decided I would use an Arduino board – specifically the Seeeduino Mega.

Why the Arduino? In reality, I’ve stopped using the Arduino environment and now use AVRGCC, so this is really just a nice little AVR development platform.

It won out over the mbed as I have had SPI issues with the mbed before.

The Bus Pirate and GoodFET are very similar, but require a host PC. I would like this standalone.

It seemed silly to implement this on a CC1110 chip, and I have had problems in implementing proprietary encoding schemes on it before.

Why the Mega? I find myself often using the extra pins and RAM as compared to the ATmega328p used in the Uno

So, now I have a RF board and something to control it. Next, I need to connect the two and write some code!

Reverse engineering a wireless burglar alarm, part 6

Last time, we looked at the data the door contact was sending out over the airwaves. We arrived at a simple encoding system where 0 = 100 and 1 = 110. This might not be entirely correct, but we are finding 48 bit long packets containing the same data each time.

Now we need to try and work out what these bits represent.

As we worked out in part 4, all of the automated packet control in the CC1150 has been bypassed. This means that the microprocessor must deal with everything. What is everything? What does a normal packet look like in a simple RF system?

There can be a number of components sent. In approximate order, from start to finish:

  • Pre-amble – generally a series of 10101010. The purpose of this is to make the receiver aware that a transmission is happening, adjust the gain as required, and synchronise clocks. The average value of this signal is partway between 1 and 0, which will mean the gain is appropriately set to receive both 1s and 0s.
  • Sync-word – sometimes a sync word is sent immediately after the pre-amble. This is similar to an address or ID, but often it is system wide.
  • Packet length – if the packet length is variable, then the receiving system needs to know how long the packet should be. Even if packet length appears fixed, the protocol may accommodate for variable length packets.
  • ID – each device must be uniquely identifiable. We already know this is 20 bits long i.e. just over 1 million unique IDs. Sometimes other data is encoded in the ID, such as sensor type or manufacturer. This effectively reduces the keyspace, and makes guessing IDs easier.
  • Data – this is the data such as triggered/not-triggered, sensor type, battery state, tamper state and so on.
  • Checksum – often a checksum is calculated on the other other bits, so that the receiver can detect errors (and sometimes even correct them). On simple uni-directional RF systems used for safety that retransmit huge numbers of times, checksums become less useful.

Working out which piece of the data is which involves careful prodding of multiple components and observation of changes. Let’s get going!

It’s quite time consuming running a logic trace, exporting the data, running it through my parser, and interpreting the results. I should really learn to write analyser plugins for the Saleae Logic software, but my last attempt never quite worked right.

all_of_the_things

First thing I notice – there is no variation from packet to packet. There is no rolling code used here.

Door contact 1

The contact only transmits RF when the button is released (tamper) or the magnet removed (door open). There is therefore no indication to the rest of the system that a fault condition has been removed or a door closed. There appears to be no low-battery signal sent either.

These are the two transmissions

Notice only a couple of bits vary (shown in red)

Door contact 2

Again, only a couple of bits vary – the same bits as with door contact 1.

Let’s compare door contact 1 and 2:

The first 4 bits are the same between the two sensors. Is this the pre-amble and sync?

We then have a few bits that differ. This could be part of the ID.

The last bit also differs (green). Notice how 10 bits are high in the first packet, and only 9 in the second. This could mean that the last bit is a parity bit, a very simple checksum.

PIR 1

14 bits are high in the PIR packet, supporting the last bit being a parity bit.

Let’s compare this with the door contacts

It now looks like the pre-amble is shorter and the ID a bit more certain.

PIR 2

Let’s compare this to the other PIR

Wow – only a couple of bits differ. They are almost sequential!

Panel

This component is much more complex, so let’s just look at the simplest trigger – the tamper switch.

Notice how 6 bits are high, and the last bit is 0. It really does look like parity.

Let’s compare with the others:

Now we have a lot more information. The pre-amble has got shorter. Somewhere in the middle it looks like we have data indicating the sensor type.

Summary

A typical packet:

We have :

  • Packet start (not shown). The encoded bits 111000 are sent. This is on the short side for a pre-amble.
  • Yellow – this could be a continuation of the pre-amble, which would now be 111000100100 – still really quite short!
  • Red – 18 bits of ID. Not sure which end the other two bits are at. Or are they using the 2 bits of sensor type to make it up to 20 bits?
  • Blue – likely sensor type; 00 – PIR, 01 – door contact, 11 – panel.
  • Purple – status of various switches and alarms.
  • Green – a simple odd-parity checksum bit

I’ve now run out of components to test. We’ve gleaned a fair bit of information about the format of the packet, most importantly that no rolling code is in use.

Where next? I know the format of genuine packets, so I should be able to build a system to transmit these sniffed packets. We’ll test to see if the receiver can pick these packets up. Then we can start modifying the packets bit-by-bit to see how the receiver responds.


Reverse engineering a wireless burglar alarm, part 5

Last time we worked out that data was being transferred from the microprocessor to the CC1150 chip using synchronous serial mode at 6.5kBaud. This time, we are going to look at that data using the logic analyser and try to interpret it.

This is what our data looks like – channel 1 is data, channel 3 is a clock. The Saleae Logic software can help to interpret this as plain synchronous serial.

DC_data6_5k

You might notice that the software doesn’t have an option for synchronous serial – only asynchronous. It does however have “Simple Parallel”. This takes a number of channels and a clock. Serial is just parallel with a single channel, so that is what we will  use.

Another plus of the Saleae software is that you can use multiple analysers against the same channels i.e. on our MISO/GDO1 line we can have an SPI and simple parallel decoder running.

Now we have successfully decoded a series of pulses, and the software has conveniently added little dots to show the data bits:

syncdata

You might quickly notice that the pulses are either 1, 2 or 3 bits long. Never 4 or more. This is the case along the entire stream of data. 1 and 2 bit pulses are common, and 3 bit pulses are at the beginning, end and at regular intervals. We could guess that 1 bit = 0, 2 bits = 1, and 3 bits signifies the start and end of a packet? Seems sensible to me.

As an aside, it is fairly common for RF systems to encode data so that there are frequent transitions between 1 and 0. This is for a few reasons:

  • To try and keep the average value of the signal midway between 1 and 0, allowing automatic gain controls and DC filters to work correctly.
  • To make sure any clock recovery or synchronisation has frequent edges to work on.
  • Representing 1 bit of data as multiple bits can provide redundancy and error checking.

Manchester encoding is very common, but there are a lot of proprietary and ad-hoc schemes in use. I have seen infrared protocols used on AM OOK systems before now – they kind of meet the requirements and allow the use of existing chips and code.

The entire data burst lasts about 1.20s. At a data rate of 6.5kBaud, that is 7.8k symbols. I don’t fancy manually transcribing or interpreting that much data. There is a high probability that the data repeats to a certain extent, but it can be hard to see the boundaries on a logic trace. Automating this process makes more sense.

Looking back at the data, and my initial observations, I can see:

  • 111 is always followed by 000, and I can see this happens relatively infrequently but regularly
  • 1 is always followed by 00
  • 11 is always followed by 0

So, let’s make some arbitrary choices:

  • 111000 is the start/end of a packet
  • 100 is a 0
  • 110 is a 1

Where to from here then? Python! Let’s read the data in, and try to process it using these simple rules.

Why am I using Python? In recent years I have found it is by far the quickest way to get simple data processing tasks like this done. It seems naturally suited to arrays of data and is tolerant of idiocy. I use Pycharm as a cross-platform IDE – it’s really useful.

I’ve knocked up a very simple program to read in a Saleae logic file, and then interpret the data as above.

python

It’s getting like a Daily Mail article on hacking in here.

With the input from my trace, I get the following repeating pattern:

No change at all from packet to packet, 48 bits long. This encodes to 150 bits long, and re-transmits about 50 times in the 1.2s burst (retransmission is a common technique to ensure the receiver hears the transmission, even in noisy environments).

We know from the documentation the system uses 20 bit IDs. Just a gut feeling, but I would expect the address to have a lot of entropy, so might assume that the first 20 bits are the address – 001100011101111101 – and the rest is data. There may be a pre-amble and sync word before the ID, meaning it might be shifted a bit further on. To confirm this, I will need to put the sensor into different states (triggered/not triggered,tamper/safe,battery low etc.) and compare to other sensors.

Is the system rolling code? We can’t really say at this stage – we need to grab more traffic. I’d expect the code to roll in 50 retransmits though. It’s not looking good.

What is interesting is that to see this data, I didn’t actually need to look at any RF at all. In fact, I don’t even need the comparatively expensive Saleae Logic – a Bus Pirate acting as a logic analyser would be able to do this.

Where to from here? Let’s start sniffing data from the other door contact and start changing their states. For next time 🙂