The Curious Case of the Ultralight EV1

Hey everyone, back again after my regularly scheduled break to talk about cloning my Ultralight EV1 access card. I’ve been toying around with the NTAG21x from KSEC and have found some strange stuff. For reference, cloning aspects of the NTAG21x used the iceman NTAG script and hf mfu commands.

So, first of all, below are the screenshots of the Proxmark3Easy hf mfu info and hf 14a sniff of both the cloned card and original card.

Original Card hf mfu info:

Cloned Card hf mfu info:

For the most part, the two cards look very similar. There also seems to be an issue with the tearing, which is visible in the info screenshot and with the counters in the dump, as well as different “Lock” values, which I’m not sure how to change. The process for figuring out the block content was done through hf mfu rdbl -b BLOCKNUMBER of the original card and then hf mfu wrbl -b BLOCKNUMBER -d 4BYTES on the cloned card.

I then did sniffs on both, doing three separate reads and grabbing the most complete cycle from all three for each.

Original Card hf 14a sniff:

Cloned Card hf 14a sniff:

In reading the blocks from the original card, though, something interesting happened. At some point after reading one of the blocks in the sniff, the original card stopped being recognized by the reader. It would no longer unlock the door, which leads me to believe there may be some sort of protection on the card that de-registers it when someone tries to read a block as some anti-copy protection method?

The dumps for each card are identicaly up until the 15th block, since 16-19 are locked on the real card.

Original Card hf mfu dump:

{
  "Created": "proxmark3",
  "FileType": "mfu",
  "Card": {
    "UID": "042F3A127A5985",
    "Version": "0004030101000B03",
    "TBO_0": "0000",
    "TBO_1": "00",
    "Signature": "44A627874568C6373FC193846C7DAF9D815FB1D8EEB225B6A8EDC516D7512E2B",
    "Counter0": "000000",
    "Tearing0": "BD",
    "Counter1": "000000",
    "Tearing1": "BD",
    "Counter2": "000000",
    "Tearing2": "BD"
  },
  "blocks": {
    "0": "042F3A99",
    "1": "127A5985",
    "2": "B4480800",
    "3": "6A00DF07",
    "4": "060A0021",
    "5": "00000000",
    "6": "0000B222",
    "7": "33724BB1",
    "8": "00000000",
    "9": "B1B21293",
    "10": "694D30B2",
    "11": "4DB2B2B2",
    "12": "B2B2B2B2",
    "13": "B2B2B2B2",
    "14": "B2B2B200",
    "15": "95993592"
  }
}

Cloned Card hf mfu dump:

{
  "Created": "proxmark3",
  "FileType": "mfu",
  "Card": {
    "UID": "042F3A127A5985",
    "Version": "0004030101000B03",
    "TBO_0": "0000",
    "TBO_1": "00",
    "Signature": "44A627874568C6373FC193846C7DAF9D815FB1D8EEB225B6A8EDC516D7512E2B",
    "Counter0": "FFFFFF",
    "Tearing0": "00",
    "Counter1": "FFFFFF",
    "Tearing1": "00",
    "Counter2": "FFFFFF",
    "Tearing2": "00"
  },
  "blocks": {
    "0": "042F3A99",
    "1": "127A5985",
    "2": "B4480800",
    "3": "6A00DF07",
    "4": "060A0021",
    "5": "00000000",
    "6": "0000B222",
    "7": "33724BB1",
    "8": "00000000",
    "9": "B1B21293",
    "10": "694D30B2",
    "11": "4DB2B2B2",
    "12": "B2B2B2B2",
    "13": "B2B2B2B2",
    "14": "B2B2B200",
    "15": "95993592",
    "16": "CEB9F511",
    "17": "7BAE00C0",
    "18": "2AA26168",
    "19": "0000509D"
  }
}

Looking at the sniff, I can see some discrepancies, which are better illustrated with a dump of each card. So, I’m a little unsure of how to move forward. Since it seems that blocks 16 - 19 are locked on the original card, I’ll have to find them through the sniff. However, I’m seeing discrepancies in the responses to the reader. If we break down the blocks by bytes: returned by each Tag Response in the sniff, we get the following table:

| Block       | 4           | 5           | 6           | 7           | 8              | 9           | 10            | 11          | 12            | 13          | 14            | 15          | 16          | 17          | 18            | 19              |
|-------------|-------------|-------------|-------------|-------------|----------------|-------------|---------------|-------------|---------------|-------------|---------------|-------------|-------------|-------------|---------------|-----------------|
| 4 Response  | 06 0a 00 21 | 00 00 00 00 | 00 00 b2 22 | 33 72 4b b1 | e1 e2 N/A N/A  |             |               |             |               |             |               |             |             |             |               |                 |
| 6 Response  |             |             | 00 00 b2 22 | 33 72 4b b1 | 00 00 00 00    | b1 b2 12 93 | 93 3c N/A N/A |             |               |             |               |             |             |             |               |                 |
| 8 Response  |             |             |             |             | 00  00  00  00 | b1 b2 12 93 | 69 4d 30 b2   | 4d b2 b2 b2 | 76 b5 N/A N/A |             |               |             |             |             |               |                 |
| 10 Response |             |             |             |             |                |             | 69 4d 30 b2   | 4d b2 b2 b2 | b2 b2 b2 b2   | b2 b2 b2 b2 | 43 25 N/A N/A |             |             |             |               |                 |
| 14 Response |             |             |             |             |                |             |               |             |               |             | b2 b2 b2 00   | 95 99 35 92 | 04 2f 3a 99 | 12 7a 59 85 | 66 9b N/A N/A | N/A N/A N/A N/A |
| 15 Response |             |             |             |             |                |             |               |             |               |             |               | 95 99 35 92 | 04 2f 3a 99 | 12 7a 59 85 | b4 48 08 00   | 5d 46 N/A N/A   |

It appears that the last two values in every response don’t match up to the corresponding first two values of their respective block. Is it possible these two values arent actually supposed to be the first two from a block, but some response code from the tag?

Any help with any of this would be greatly appreciated. The end goal here is to hopefully grab a FlexMN and clone the card onto their, but I want to get this sorted before even thinking about an order.

1 Like

I’m guessing you mean FlexMN ???

Great write up by the way :+1:

Ah yep, I’ll edit now, thanks for the catch!

Don’t dismiss some physical problem due to the Proxmark3 itself.

Last year, I cloned an Indala 224 onto my xEM (my work badge) and it went silent after I was done. I’m 99.9% certain the reading I did to clone it killed it: the lady in charge of the badges I returned the tag to told me they’d been recycling and rotating the original set of badges for decades as employees get hired and leave the company (yeah, not too smart) and she told me she was amazed and she’d never seen one going tits up. It seemed like an extraordinary coincidence that the only time it should happen was exactly after yours truly Proxmark3-read it.

As far as I know, Indala tags don’t have in-built suicide read counters for sensitive blocks, and there’s no way the PM3 could overpower and fry it. Yet… there ya go. Don’t ask me how, but somehow the PM3 killed that LF tag. I assume it jogged the tag’s circuitry in some odd way that wasn’t expected by the designer and that bricked it.

The same sort of unfortunate command sequence pattern could have weirded out your Mifare too. Highly unlikely, but it’s possible I guess.

I dont have a ton of experience with EV1 specifically so take what I say with some salt.

Your dumps looks partially complete as an MF0UL11 should have 20 pages but one of your dumps only has 15 pages. The last 4 pages shouldnt really be an issue from my understanding. Pages 16-19 are for configuration which shouldnt play too much of a role for a PAC system.
This is also a reason why you are observing different responses in your trace on the last few pages which can be expected given their function.

The EV1 does have a feature that can prevent brute-force attempts if the number of negative attempts has been set. Exceeding said value permanently locks the card. Your page 17 isnt included in your dump to determine how AUTHLIM is set on the card.

Image of the default config EV1

Notice the default values in pages 16 and 17, of which are not present in your cloned dump

Have you tried to use the cloned card with the real reader? I would be interested to know what sort of response you got.
If the reader does not respond with anything (ie no lights change/no sound;almost ignoring the card), you could get a trace of the reader - card comms.

I wouldnt mind learning more about these cards in a real world scenario and already have some Mifare/Proxmark experience.

@Jirvin Interesting, I wonder if they’re locked off. Do you think that the blocks 17-20 matter? In addition, in the sniff, what do you make of blocks 8,10 12 14, and 18 being different for the based on the different responses to the reader? For instance, block 4 response has the first symbols of block 8 being “e1 e2”, while it’s “0,0” for block 6 and 8 response. Any idea as for what is stopping the door from opening then? I have the screenshot of the cloned card and real reader above, but it seems identical in response except for blocks 17-20.

Sorry for the delay in getting back to you.
Again, take what I say with some salt as MFU isnt something I have much experience with.

Pages 16-19 do matter for card operation since they are the card’s configuration blocks.
Page 20 (which isnt really page 20) is for the counter which can only be accessed with the counter commands for the card (READ_CNT & INCR_CNT).
The configuration pages of the card are usually used to set memory restrictions on the card and/or how the card should respond to some of the Virtual card commands (VCSL).

In terms of the trace(s), if you could save them (as .trace) and share them here so I can have a play around with them on the PM3 myself. As for looking at the screenshots of the trace, Im not too sure what explanation could be given to shed light on why various blocks are getting a different response.

Overall, probably not what you want to hear, but I dont have any definitive conclusions as to why the door isnt opening.
The only (basic) idea I can gather is that the counter is being checked on the card and compared to what the door last got for your card. To clarify, say the counter on your real card is 10, the door knows this and expects when it asks for the counter it should get 10 back thus if it doesnt, it knows there is some mismatch and denies access. If it does get 10 back, then itll increment the counter by 1 and store the new value of 11 so the next time it sees your card, it should get a value of 11 otherwise deny access.
This idea is very basic and my knowledge of MFU is not extensive by any means therefor this could be very inaccurate so more investigation is needed regardless.