Reverse-engineering COTAG and COTAG tag simulation implementation

published:

tags: [ #RFID, #COTAG, #reverse-engineering, #RFID simulation ]

COTAG is an old RFID tech, but it's a very interesting and a bit unusual RFID tech and it just keeps intriguing me.

There has been some limited research done by Proxmark community in the past, but surprisingly, up to this date, there has been no in-depth analysis and reverse-engineering work on COTAG yet, at least I cannot find it, and especially no support for COTAG simulation.

After my more elaborate analysis of reading of COTAG tags, identifying COTAG "preambles" and implementing improved working COTAG demodulation I wanted to see if I could simulate a COTAG tag as well.

This took me quite some time and experiments and analysis, but I finally got it working.

Summary:

  • My first naive attempts to simulate an active COTAG tag were simply to do on/off keying at 66 kHz manchester encoding the 128 bits I would read from a tag with my implementation of lf cotag reader, with as much as precise timing as possible. I.e. don't try to detect COTAG reader activation sequence, just start encoding bits with on/off keying. Maybe it could work, why wouldn't it? Well it didn't.
  • Then it occurred to me: Oh, maybe I need to sync to the reader activation sequence and start sending data bits at just the right moment. So I went on and implemented that. It still did not work, the reader was still rejecting my simulated tag.
  • Then I finally decided to do some elaborate sniffing and analysis of a COTAG tag to a COTAG reader communication. With that, I found out the tags always first send 2 leading zero bits, only then they send (possibly repeating) tag data. When I started sending those 2 leading zero bits just right after detecting reader activation sequence my Proxmark COTAG tag simulation code started to work.
  • Another finding is that while the full repeating sequence of COTAG tags (obtained the way we do it with Proxmark lf cotag reader where we just keep the field on for way longer than a real COTAG reader would) is 128 bits, the readers seem to only care about the first 64 bits we send (i.e. 8 LSB bytes of the full 128 repeating sequence).

Analysis details:

Sniffing COTAG reader activation sequence with Proxmark

I know people have sniffed COTAG reader activation sequence in the past, e.g. info from the old Proxmark forum:

"4 pulses at 132 Khz. The first burst is 800 microseconds, a gap of 2.2msecs, a burst of 3.6 mSecs, a gap of 2.2 mSecs, a burst of 800uSecs, a gap of 2.2 mSecs, and then a pulse of 3.6mSecs. If no response the reader waits 17mSecs, and the resend the wake up sequence."

So even in the proxmark code at the moment we have:

READER START SEQUENCE "v1":

burst 800 us  gap 2.2 ms
burst 3.6 ms  gap 2.2 ms
burst 800 us  gap 2.2 ms
pulse 3.6 ms

Out of curiosity I wanted to confirm that with my COTAG reader.

Sniffing my COTAG reader activation sequence (aka no tag present) with proxmark5, here are my results of the lf sniff at divisor 90.

lf sniff of COTAG reader activation sequence, no tag present

Applying data dirthreshold -u 3 -d -1 :

COTAG reader activation sequence after data dirthreshold
My results:

READER START SEQUENCE "v2":

- ON: 104 samples == 787 us
- OFF: 284  samples == 2151 us
- ON:  774 samples ==  5863 us
- PAUSE: 2175  samples == 16475  us

Total repeating sequence: 3337 samples == 25278 us

These results are thus somewhat a bit different, but still very similar.

  • The second burst+gap: 3600+2200 == 5800 -- which is of similar length as the last ON in my sniff (5863) before reader's pause .

Is it possible that there is another version of activation sequence? Or maybe it just boils down to a common denominator ON(800),OFF(2200),then reader field ON for some time in which the tag is expected to respond?

So the activation sequence could be simply ON 800, OFF 2000, then ON for either 3600 or 5800 (or in general enough time where the tag should start responding).

  • To simplify detecting activation sequence in proxmark I thus used detecting timing between 2 rising edges:
    • a rising edge where ON 800 starts
    • then a rising edge where either ON 5800 or ON 3600 starts (when the tag is expected to start sending data)
    • delta between those rising edges is around 3000 us -- so I used that delta between 2 rising edges plus minus some tolerance: and it works

Sniffing COTAG tag responding to COTAG reader with Proxmark

Then I went on to sniff a COTAG tag responding to a real COTAG reader (lf sniff). (experimented with both active and passive tags)

  • I did this sniffing with a pm3-rdv4 with my custom-made antenna (LCR circuit), carefully tuned to 66 kHz, and not responding well to 132 kHz, so that I was sniffing tag's response only.
    • capacitor, 10.77 nF, coil ~500 uH, 10 ohm resistor. I initially tuned the LC series circuit first with my nanoVNA with a different capacitor set, to exactly 66 kHz, but then actually the best "hw tune" result (highest voltage) for divisor 181 with proxmark was when I lowered the capacitor a bit (freq 1 or 2 kHz up).

Sniff tag's 66 kHz response setup: pm3-rdv4 with custom LCR antenna tuned to 66 kHz for sniffing the tag response

hw tune
[=] -------- LF Antenna ----------
[+] 125,00 kHz ...........  5,85 V
[+] 134,83 kHz ...........  5,48 V
[+] 66,30 kHz ........... 32,64 V
[+] 63,49 kHz optimal.... 45,09 V
[+]
[+] Approx. Q factor measurement
[+] Frequency bandwidth... 6,3
[+] Peak voltage.......... 7,9
[+] LF antenna............ ok

Here is one data plot of such a sniff with such a setup of a COTAG tag to a COTAG reader response: lf sniff at divisor 90 + data grid -x 768 lf sniff of a COTAG tag responding to a COTAG reader, grid 768 (Yes, I set the divisor to 90 although I was sniffing 66 kHz. It was simply to get better resolution.)

Interesting points we can notice:

  • A couple of reads from the tag with gaps in between (reader pause (dropping field) + new activation sequence).
  • The reader always dropping field way earlier than we would send 128 bits (sometimes at 52 bits, or at 26 bits, or even at 20 bits or less, etc, but sometimes at 66), it seems that max time it gives for the tag is for 66 bits.
  • The gap seems to be ~2528 samples at divisor 90 == 19152 us.
    • So the math adds up: act sequence ON 104 samples (787 us) + OFF 284 samples (2151 us) + reader pause 2175 samples (16475 us) == 2563 samples (19413 us) is approx the gap we are seeing aka ~2528 samples --> so it must be that the tag is supposed to start responding in that time window of approx 5800 us (which probably not a coincidence is just about enough time for 1 manchester encoded bit, aka clock for 2 half bits).
    • Applying that to the "v1 reader start sequence", where the tag would be given 3600 us to respond: 3600 = 2900 + 700; so half_bit time + some more: Not enough time for full manchester-encoded bit, but I guess enough for the reader to see if the card responded with manchester transition.

Data plot of a sniff when 66 bits were captured (between yellow and purple): lf sniff of a COTAG tag response with 66 bits captured

cut/trim, apply dirthreshold, decimate, normalize, and rawdemod manchester:

data dirthresh -u 18 -d -6
data decimate -n 12
data norm
data rawdemod --am -c 64
[+] ASK/Manchester - clock 64 - decoded bitstream
[=] -----------------------------------------------
[+] DemodBuffer:
[+] 00101010000110000000000000000000
[+] 00011100010010000011011110010000
[+] 0
Trimmed and decimated sniff demodulated with data rawdemod --am

Expected (reversed) bits for the COTAG card I used in this sniff would be: (expected as we would obtain them with e.g "lf cotag reader") 10101000011000000000000000000000011100010010000011011110010000010100000000000000000000000000000000000000000000000000000000000000

And what we got with rawdemod above from the sniff:

00101010000110000000000000000000000111000100100000110111100100000

Quick analysis:

  • 2 zero leading bits: 00
  • then expected tag data: 101010000110000000000000000000000111000100100000110111100100000 -- matching the expected first-to-be-seen 64 bits we get with "lf cotag reader" from that real COTAG tag.

I then did numerous sniffs of other COTAG cards (active and passive) and analysed, "hand-demod", compared the traces:

  • It seems tags always first send 2 zero sync/leading bits.
  • I was thinking one of them might be a parity bit of some sort , but I sniffed a lot of cards (active, passive), where I would clearly expect different parity, and both leading bits always came up as zero.

Now, with lf cotag reader we never noticed those two 0 sync/leading bits:

  • Well, the way the current lf cotag reader implementation works, from the time we pass the activation sequence and by the time we then switch to the reading mode, those 2 bits (along with a couple of first bits) are already missed.
  • Thus it seems the cards if the reader would not drop the field, would keep repeating the full 128 bits of card data (which is what happens with lf cotag reader), but leading 00 bits are sent always just at the beginning.

Further, sniffing real COTAG reader to card communication, the reader basically turns out to not care about 128 bits at all, only up to 64 bits + 2 leading 00 bits which need to be sent.

  • At the point I had simulation working, if I did not send the leading 00 bits, or if I sent just 1 bit, or one of them as 1, the reader would not accept the tag, thus those 2 leading sync zero bits are crucial for COTAG tag response (and thus COTAG simulation).

  • And it turns out it is always enough to send just 64 bits of tag data.

    • And even more: After seeing max 64 bits of tag data, a COTAG reader would drop the field and pause.
      • If the tag was invalid (not expected bits encoded), it would pause just for 16.5 ms, then repeat activation sequence.
        • And for such tags the reader would often drop the field before seeing all the 64 bits (I guess with the bits it sees it already confirms the tags as invalid -- not programmed for the reader.).
      • If the tag was valid (expected bits encoded), the reader would pause for approx 1.5 seconds before repeating activation sequence.

As a result of this analysis and reverse engineering work I thus in parallel implemented Proxmark support for simulating a COTAG tag (lf cotag sim) (most but not all text/info from this article duplicates on that pull request).

I tested the implementation with proxmark5 and proxmark3-rdv4, both with their original antennas. Both work well. I have yet to try proxmark-easy.

Sniffing COTAG tag and COTAG reader with an SDR

In parallel to sniffing COTAG tag/reader with Proxmark I was doing sniffing with an SDR as well. It helps to visualize things in a different way and to back-confirm analysis results.

Simple SDR kHz-range RFID sniff setup: a coil (~500 uH) directly connected to the input of the: Ham It Up HF upconverter, its output connected to an RTL-SDR, display with gqrx: SDR kHz-range sniff setup: coil, Ham It Up upconverter, RTL-SDR

  • So simple coil, no LC resonant circuit and no impedance matching, but it works pretty well for close distances. Probably even better that it's not a resonant LC circuit; I guess then the input voltage might possibly get too dangerously high for the upconverter and/or RTL-SDR.
  • The Ham It Up upconverter converts up plus 125 Mhz, so 66 kHz signal would be seen at 125,066 Mhz and 132 KHz signal would be seen at 125,133 Mhz. gqrx allows setting a frequency offset, thus setting LNB LO to −125,000000 MHz, and then the displayed signals are seemingly at the actual frequencies.

Here is an SDR sniff of a COTAG reader with proxmark-simulated invalid tag (a tag with encoded bits the reader is not programmed for): sending 64 bits: SDR sniff of a COTAG reader with a proxmark simulated invalid tag

  • Time domain flows from bottom up: We see: First, the COTAG reader is sending its activation sequence at 132 kHz, no (simulated or real) tag in the field yet.
  • When (a simulated or real) tag is brought into the COTAG reader field, and when it responds to the activation sequence, we see the tag response at 66 kHz (exactly half the reader field frequency), and during that time COTAG reader switching from activation sequence to constant field carrier on at 132 kHz.
  • What we can also see: reader, after having the field constant on at 132 kHz for enough time to see enough of tag's data, the reader is then dropping field and continues almost immediately after a short pause of 16.5 ms (new activation sequence, everything repeats).
  • Note: I get basically the same SDR sniff results with a real COTAG tag, that is invalid (not programmed for the reader).

And here is an SDR sniff of a COTAG reader with proxmark-simulated tag where that tag had correct bits encoded (programmed for the reader), and the reader accepts it (green light on): sending 64 bits:

  • The difference here is that the simulated tag sends correct bits sequence that is accepted as valid by that COTAG reader.
  • In that case, after the reader reading 64 bits, it drops the field (pauses) for much longer (about 1.5 seconds), and only then repeats sending activation sequence again.
SDR sniff of a COTAG reader with a proxmark simulated valid tag sending 64 bits

Finally, here is an SDR sniff of a COTAG reader with proxmark-simulated tag where that tag was programmed for the reader, and it accepts it (green light on): this time, as an experiment, sending 128 bits:

  • What we notice: we just keep sending those 128 bits (proxmark has only one LF antenna, it cannot sense reader dropping field in the middle of its own transmission), but the reader has long ago dropped the field (after accepting our bits as valid), i.e. it only cares about the first 64 bits of data we send.
SDR sniff of a COTAG reader with a proxmark simulated valid tag sending 128 bits