Zigfrid is the end result of my RFID tinkering. Since I will most definitely forget most things described here in the (very) near future, I share this for those few who might find it interesting. Please be warned: This is not a toy. It is completely unreliable, untested, malicious tool, which can and will cause elevators to stop or even shut down immediately, locks to jam, hackers get jailed, and other weird RFID phenomenons. Ok, you get the idea, lets move on.
I guess I watched too many movies as a kid, and craved myself one of those futuristic-looking RFID “master keys” which opens all doors [with a few flashing leds for a more attractive effect], but as I grew older and learned there isn’t one I decided to try and build one for myself. I ended up with a tiny passive device consisting an ATtiny85 AVR, an antenna (coil), and 1 capacitor, with no need for external power. It’s so tiny, it can fit in a common chewing gum and glued next to any RF reader to fuzz away.
My RFID adventures began with a cheap 20$ Handheld RFID Reader/Copier – a simple battery-powered device with 2 buttons controlling the read & write functions of it’s PCB, which uses an obscure chip labeled with the mysterious “F300 ET94 242+” which later found to be based on a more popular chip C8051F300. I hacked the PCB and connected it via it’s pins to my Arduino and later to my BusPirate in the hope of getting something on it’s serial line via the RX & TX pins – (and maybe later to alter it?) for vain – only a random bits every a few reads was letting me know I’m looking at it all wrong. And I was.
I continued looking at other directions and stumbled upon this Magspoof (by SamyK) article (Hebrew only) and among it’s comments I found my answer – AVRFID, a project originated way back in 2008 by the media artist/hacker Micah Elizabeth Scott who published this project – an AVR with hardcoded EM4102 tag id, using the RF frequency for it’s power supply, thus making the AVR completely passive with no need for external battery. Some upgrades & forks has been made since, so I decided to try my luck with this approach, and check if I can adjust the project to my requirements and build a simple RFID fuzzer.
* This is a very weak power source, and the AVR typically gets little * over a volt of Vcc. As a result, most of the AVR's oscillators won't * start. We can, however, use the carrier wave itself as a clock as well. * This also makes the software easy, since the instruction clock is also * the RF clock. We're already clamping the coil voltage into something * resembles a square wave, so this makes a good external clock source.
This looked promising.
After flashing the AVR and setting lfuse to 0xC0 to use an external clock, I’ve put it against the RF reader expecting to see any result – but nothing happened. I will save you the time & frustration I had for over a few (!!) weeks – I tried different combinations of capacitors & antennas, but nothing worked, I simply didn’t get any response from my RF reader (actually, RF readers – I tried several different types of 125khz RFID readers, including proxmark3, all ended with same poor results), and during those weeks I found at least two other successful attempts of other individuals who were able to accomplish a working AVRFID without any problem, which only contributed tremendously to my frustration. I finally bought a small nano-scope to assist me with my debugging, and boy, did that help. I finally was able to visually see in real-time what was happening on the AVR with different antennas & capacitors combo, and with some little tweaks (and initially adding a battery source just to boost successful readings) I was able to finally have my own passive AVRFID working to my amusement.
Some notes regarding the capacitors:
- The capacitor is dependent on your antenna (coil). You will have to do some calculations or use trial & error approach with different capacitors combo to get best results with your antenna.
- Using a curtain capacitors combo might initiate a DoS attack on the reader which will prevent legitimate tags from being read correctly after placing it against a reader only once. A hard reset to the reader will be required to resume work. Just FYI.
Same as the original AVRFID, I started with a simple 1mH inductor to act as antenna which works better than most antennas I have tried later on, albeit with one big caveat – you must place it in a curtain angle over the RF reader antenna, which is a major drawback. Among my endless trials to extend the RF range I even tried scraping the antenna out of an RFID tag but the wires are so delicate and that failed miserably. I settled with removing the antenna out of a 125khz RFID module and soldered it to the AVR; If you plan to wire your own antenna DIY style, remember it requires calculations of the coil thickness, tolerance, rounds, etc. – all the useless headache I wanted to avoid. As Micah & others had mentioned, it is essential to add a small capacitor to improve stability & AVR performance. Your results will vary depending on the RF reader & your antennas (both the RF reader and the AVR) and the capacitors should be changed accordingly (eg, trial & error style).
The software part took me much more than I planned nor wanted, but it was a fun journey never the less. Everything was new to me, from AVR assembly language to RFID/em41xx format, so I had to take it step by step. I began with learning the original macro assembly code Micah had written so I kept the “AVR Instruction set” manual opened. After understanding her code logic (she writes beautiful code thus making it much easier and enjoyable read) I immediately jumped into the water and began coding my own version of the EM41xx part in pure AVR assembly. All went fine until I reached the last 10% of the code, at which that point I’ve decided my logic is at false and I have to start over. I did it over a few times, and by the 3rd iteration I was confident enough at my AVR assembly skills to conclude this is completely the wrong approach. I then went with a C program with some inline assembly, expecting it to work like a charm, but it didn’t ofcourse, no matter what I tried. I used the nano-scope to check what was going on and I quickly learned nothing is being sent. Oh my.
Took me a while and lots of banging my head against the wall to figure out what was wrong (debugging AVR with external clock is not an easy task as one might think) and eventually I figured out all those tiny bugs and even better – how to fix them. Hooray, I had a working C program able to send a list of known IDs using a simple state machine. I now wanted something better, and ofcourse, I decided to write a new version, this time using interrupts, only because I thought it’s more ‘appropriate’ to this kind of project. My final design is a C program which does all the boring work of setting up a buffer to be sent, increment a 32bit number with 8 bit registers, and leaves only the time-critical parts to assembly – sending Manchester encoded zeros & ones in nice & clean cycles. The code is also highly optimized (less than 500 code bytes) but won’t fit ATtiny10 because of the data buffer (64 bytes long, twice as what ATtiny10 provides) and I was too lazy to optimize any further, so only ATtiny85 and above are supported atm.
While I was doing all the debugging, I had to reflash the AVR every time. Since we are disabling the internal AVR clock, we must supply the AVR with an external clock signal when programming – luckily BusPirate supports this and latest avrdude (6.3) also supports this in binary mode (was ASCII-mode-only pre 6.3) so everything should be painless. To flash the AVR we’re using the “-x cpufreq=125” parameter to simulate the external clock while reflashing it, otherwise you have to provide your own external clock when you’ll try to reprogram your AVR. The pinout connections is same from Trammell Hudson, I just corrected the Gnd wire:
+-------+ White/white Reset |1 v 8| Vcc Red Blue/Blue Xtal1 |2 7| SCK Purple/green Xtal2 |3 6| MISO Black/Black Brown Gnd |4 5| MOSI Gray/Yellow +-------+
And there you go. You should end up with a nice, tiny, passive fuzzer which fits in the palm of your hand. You can now hide it in a chewing gum and glue it to the reader.
I’m releasing Zigfrid as a POC only – it can/should be enhanced to try some (possible) overflows in RFID readers, and of-course fuzz some “Administrator” tags by filling tag-ID with 0xFF, Nulls, etc. As for this public release, I decided to keep with the KISS approach and only use 32bit incremental, but why not increment all 40bit of the EM41xx tag ID? or fuzz HID readers? Let your imagination run free. The final code supports a led on PIN5 for debugging purposes and to provide the “flashing led effect” (a red led is recommended since it requires less amperage). If you prefer to keep it in stealth mode, simply don’t connect a led. One major drawback with my current design is other tags or interruptions may interfere with our fuzzer while it’s working, thus making it highly likely for the AVR to restart itself which will cause the entire fuzzing process to start from the beginning. Maybe a future version should save the numbers in the EEPROM every xx increments to fix this. Also, adding Manchester reading support (something like this) will turn Zigfrid into a passive sniffer – might be worth the hassle.
Finally, a demo of Zigfrid in action:
Some coding notes:
- Using PROGMEM attribute on your variables requires changing the assembly instructions used to access those variables (eg, from “LD” to “LPM”) or use pgm_read_byte() when in C. You can also modify PROGMEM area, but this is discouraged.
- “-nostdlib” flag shaves off all the gcc extra wrappers, including the part which copies the data section, thus make all your array values play hide & seek with you (spoiler: they’re not there unless you copy them manually __do_copy_data() style).
- “-nostdlib” flag will cause your main() function to travel to a random space instead of zero (which is where the AVR loads the initial code from). You can instruct the linker to set it’s loading address to zero using all kinda tricks, my chosen one is “__attribute__((section(“.vectors”)))” which places the function in the “vectors” section (which begins at zero).
- “-nostdlib” flag also removes the “interrupt jump table” so you will have to provide one yourself using a linker script or in the code.
For more RFID hacks check this site which seems to archive most of them.