From RF to bytes with an RTL-SDR


I recently un-earthed my RTL-SDR after moving. I also received two RF remote controls for the garage door. It seemed like a good idea to put the two together to see if I could discover what the remotes were transmitting.

The back of one of the remote controls handily listed it’s serial number, FCC ID and the frequency on which it transmits. In this case it transmits at 318MHz. I was expecting that it encoded the transmitted data with On-Off Keying (OOK), also called Amplitude Shift Keying (ASK). OOK is quite simple to generate and decode, which helps keep costs down. The device has multiple buttons, so some bits identifying the pressed button were expected. The serial number was also expected to be present, as well as a code of some description.

I hadn’t played with GNURadio for a while so I had to install it. After reading the docs about out of date versions in repos, I went the route of installing GNURadio from source with the build-gnuradio script. It turns out that the Ubuntu repos are actually up to date so I could have simply done a

sudo apt-get install gnuradio gnuradio-dev

to get everything I required. Instead I fought with some of the packages for a while. In the end it all worked. Note to self: Next time, check the version in the repo before building from source.

What’s the Frequency, Kenneth?

I fired up gnuradio-companion and created a simple flowgraph to display 1MHz of spectrum centred at 318MHz.

Running the flowgraph and pressing a button on the remote gave a nice peak at -50kHz from center, as shown below.

The remote is certainly transmitting at 318MHz and I’m capable of seeing it. The next step is to see what is being transmitted in that peak.

Looking into the Aether

A quick modification to the flow graph enabled me to record the received samples as a WAV file. I did this by adding a Wav File Sink from the Audio catagory. At the same time I dropped the sample rate to 226kHz, as that was the minimum the RTL-SDR supported while covering the spectrum of interest.

OZ9AEC’s method of Dynamically generating filenames was used as it was expecting that data would need to be collected while using the device in different ways. A WAV file ws chosen as Audacity was available and it was the easiest way to display the amplitude of data with respect to time. After running the flow graph and mashing the buttons, the resulting file was opened in Audacity.

The waveform is definitly On-Off Keying and there appears to be a preamble and a data section, which has varying bit lengths. There are two channels in this WAV file as the complex sampled signal was converted into two floats, which were recorded as seperate channels. The upper waveform is the In-Phase signal and the lower waveform is the Quadrature signal. It’s yet to be determined if the wider sections indicate a ‘1’ bit or a ‘0’ bit. The flowgraph can be modified to either decode the AM signal, or just calculate the magnitude of the signal, as the signal is OOK. The signal is also massivly oversampled at this point, as there are approximatly 92 samples per transition. This gives a rough symbol rate of 2.5kHz, or 400us per transition.

Working out the data format

The flowgraph was modified to calculate the magnitude of the signal and record it to a WAV file, as well as a file containg raw, complex samples. The latter file was generated so that future modifications to the flowgraph didn’t require pressing a button on the remote control.

The flowgraph was run several times, recording multiple presses of a single button into one file. After going through a somewhat involved route of loading a wav file into Audactiy, taking a screen shot and processing as a new layer in GIMP, the following image was generated.

There are five distinct transmissions within the image. The green signal is an extension of the preamble clock, to show the symbol boundries. The bit positions for the code, serial number, button and re-transmission could be determined by correlating usage and the received waveforms. The relationship between ‘0’ and ‘1’ to wide and short pulses was able to be determined by knowing the serial number of the device. The data is transmitted LSB first. A wide pulse corresponds to a ‘0’ bit and a thin pulse corresponds to a ‘1’ bit.

Turning a signal into symbols

The following flowgraph was generated after some trial, error, and a lot of reading. The Rational Resampler block didn’t seem to work before the Complex to Mag block. The Clock Recovery block requires a signal with a mean of 0, hence the Add Const block. The ‘test’ file is a FIFO, which was dumped with xxd. The signal source was modified to be a pre-recorded file, so that the transmitter didn’t need to be used all the time.

The correct bits were present in the output file.

The Corrolate Acces Code block sets bit 1 of the binary stream when the code has been found. Hence, the 03 byte indicates the start of a 66-bit packet.

From symbols to bytes

The value of a transmitted bit within the data section is composed of 3 symbols. A ‘0’ bit is composed of high, high and low symbols. A ‘1’ bit is composed of high, low, and low symbols. Anything else is invalid. A simple state machine is needed to wait for the Corrolate Access Code block to find the preamble and then decode the following 198 (66*3) symbols.

A python out of tree module was created to acomplish the task. It’s available at https://github.com/nada-labs/keeloq-decode. The module is added to the flow graph after the Corrolate Access Code block. It will only output bytes once 66 bits have been decoded successfully.

The following data is generated by running the flowgraph

Success!.

Impoving the flowgraph

The flowgraph worked for one set of data, but not some of the other sets. Data was only decoded sucessfully when the remote was ~5cm from the antenna. Some form of gain compensation was required. Additionally the -0.2 constant was a kludge. The first problem was solved by inserting a Feed Forward AGC block before the Complex to Mag block. The second problem was resolved be replacing the Add Const block with a DC Blocker block. The final flowgraph is shown below.

A keypress on the remote can be decoded at a range of 2m. I’ll call that a win.

Where’d KeeLoq come from?

The schematics and functional decsription of the transmitter are available on the FCC website. The major part within the transmitter is the Microchip HCS301 [PDF Datasheet]. The datasheet helpfully lists the protocol used by the device and identified some of the previously unknown bits. It looks like its possible to recover the key through power analysis. Perhaps a future project?

Please excuse me, I now need to go open the garage door a bunch of times to invalidate the codes shown above…

, , , , , ,

  1. No comments yet.
(will not be published)