Hacking cheap RFID readers

RFID readers on prototype supply places are expensive. There are many cool applications for the technology, but cheap readers that include documentation and a standard interface are impossible to find.

I decided to confront this problem. I found and ordered a cheap 125kHz reader off  eBay for around ten bucks.

The interface of the reader was usb. You’d plug it into your computer, it’d identify itself as a USB keyboard, and scanned tags would be typed out into a text editor.  my hope was to locate the IC doing the initial decoding, and tap into it. Simple enough right?

When the reader arrived I verified that it indeed worked via usb (it did), then I promptly disassembled it.

IMG_20110924_140104

 

readerlayout

I Googled the specs on the components, but unsurprisingly I was unable  to find the datasheet for the chip doing the actual reading.  There were, however, some breakout pins. I was hopeful the hard work was already done, and this was just a generic board. Testing with a volt meter revealed that two were for power (5v, gnd).

IMG_20110927_194836

Now, I knew what I was looking for, a 10 digit numeric code. What I didn’t know was the protocol being used, and it what variation. I located what I believed was the TX pin (assuming it was UART) by poking around with the RX of an FTDI serial adapter and RealTerm (best serial debugging program imho) to try and get some data.

 

nope

I didn’t seem to be getting anything usable, but at least each tag was consistent. I assumed the issue was with the settings, however after messing with it for quite a while, I still hadn’t made much progress. I decided this was the perfect excuse for ordering in something I had been wanting to get; the Open Logic Sniffer from dangerous prototypes.  It’s kind of like an oscilloscope but records the data as well.

After it finally arrived, I connected it up, downloaded the software, and started collecting data. cropped

This is the output signal of the RFID reader. at this point I was confused, as there didn’t seem to be near enough data to match up what was being read in RealTerm.  As I’m a very visual person I decided to open a screenshot of the data up in Photoshop and make some visual aids to simplify analyzing the signal. If the protocol was indeed serial, then I should find some common patterns.

With the way serial works, there is a start bit (low) and a stop bit (high)  to help provide reference for reading the data. I created another layer in Photoshop with “bytes”, to see if I’d find the appropriate start and stop bits, and indeed I do.

visualaid1

This brought up a couple problems though, the bytes decoded didn’t match up to anything in ascii (or anything else really), and there were only 9 bytes, while the tags were supposedly 10 characters long. Perhaps the leading char was inserted by the usb chip? This is a possibility as it was labeled as zero on all of the tags.

visualaid

In an attempt to determine what common bytes might be, I scanned a different tag, screenshot the output, then put it as another layer with 50% opacity over the first. I was extremely confused by the result:same

As you can see, it’s exactly the same. I did this many times to make sure I’ wasn’t accidentally reading the same tag twice.

I recalled that I was getting more data out in RealTerm, so out of curiosity I lowered the frequency read rate of the logic sniffer from 1MHz to 100 kHz…

Bingo.

bingo

After manually decoding the output, I checked to see if the hand decoded bytes were consistent with the automatic logic analyzer.

almost

At this point I decided to take a different approach. I knew what the code on the tag was, so I decided to check for similarities. I  realized that there was a difference of 39 between the desired number, and the decimal value of the byte, but there were some values that wouldn’t produce a valid result.

I knew I could make it work in software, I connected the reader up to a teensy and wrote a quick test sketch.

woot

(note: I manually inserted newlines for legibility)

This is good! all I needed to do was fix an issue with zeros, as they would actually end up as tens.

woot1

And it works!

I know I went about this the long, roundabout way, but I’m still happy; I learned quite a bit, and it was a fun challenge.

Download the demo code here.

Comments are closed.