flipperzero-firmware icon indicating copy to clipboard operation
flipperzero-firmware copied to clipboard

MIFARE Classic Anti-Copy Detection

Open quantum-x opened this issue 2 years ago • 19 comments

Background In France, almost every apartment building uses RFID Access Control based on MIFARE Classic 1K badges. The keys to decode these badges are well known (and in Flipper's library), and the badges can be easily cloned / emulated.

However, in France many Access Control Manufacturers now include anti-copy algorithms in the badge contents.

While the implementation differs between manufacturers, the overall technique remains the same. Each time a badge is scanned on the building, a counter in the badge contents is updated. The next time the badge is scanned, the Access Control Reader checks the contents of the counter. If the counter is not at the expected value, the badge is rejected.

The problem When badges with anti-copy are cloned - the contents between original badge and the new clone (or emulation) become desynchronised. When de-synchronisation is detected, the copy will work, but the original badge will no longer work.

If the badge was emulated the original will no longer work, and the emulation will no longer work either (because its contents weren't updated during the emulation).

Depending on the brand of the badge, typically only one badge is de-activated. However some brands (such as Immotec) will deactivate all badges associated with an apartment when cloned badges are detected.

Although this problem is concentrated in France, it is also present in Belgium, UK, Germany and Australia.

As more and more people in Europe will be getting their hands on Flippers, I feel it's important to discuss the issue, to prevent people unintentionally breaking their residential badges / locking themselves out..

Suggestions for a solution The anti-copy algorithms for each brand and model have a unique fingerprint, and can be detected. I am unsure the best way to implement (if at all) some type of detection / protection.

  • It could be an additional script that can be run against a saved Mifare Classic dump that checks for Anti-Copy
  • It could be implemented into the Emulation function, to prevent (or at least warn) of anti-copy presence
  • It could be implemented into the Write function (not yet implemented, but on the to-do list) to prevent (or at least warn) of anti-copy presence.

I have the full list of signatures for all brands and models with anti-copy for all of Europe, and will happily contribute this information.

quantum-x avatar Jun 27 '22 08:06 quantum-x

@gornekich Let me know your thoughts on how to implement for the entire community, and next steps so I can provide the anti-copy detection rules.

quantum-x avatar Jun 27 '22 09:06 quantum-x

Hello @quantum-x . Thanks for information!

For now we ignore counter related commands during emulation. I can see that this can cause problems, and we try to add working with counters soon. I guess it will solve the issue, when user just copy the card to flipper and no longer use the original card.

Further we will add users possibility to synchronize both variants of card. It will come after we add write functionality. Flipper can detect if the data was updated during emulation, and I think it's a good point to notify user about it. I will talk with our UX designers and come back with solution.

I'm not sure I understood you correctly about additional script that can be run against a saved Mifare Classic dump that checks for Anti-Copy Could you explain the solution in more details?

gornekich avatar Jun 27 '22 17:06 gornekich

Hi @gornekich Thanks for the reply.

To be clear, the anti-copy algorithms in are not simply consecutive counters (0x01, 0x02, 0x03 etc), it's heavily obfuscated data that is written 'randomly' over the badge.

Regarding 'Additional Script that can be run against a Mifare Classic Dump':

  • When a user saves a dump to the Flipper, in the 'Actions' menu (Currently has "Emulate", "Edit UID and Name", "Delete", "Info", etc - it could be interesting to add a "Detect Anti-Copy" function.
  • Users could run this script against a dump to check if the badge has anti-copy signatures
  • This script could also be automatically run before a user emulates or writes a dump, to prevent (or warn) users that the badge contains anti-copy.

In France, ~20% of badges on the market have anti-copy. Currently if I emulate a badge with anti-copy, both the original badge and the emulation will be de-activated.

As EU customers are starting to receive their Flipper devices, there is a very high risk that customers will de-activate their building badges by mistake, with no warning, and no way to repair the badge except to buy a new one (~50EU - 100EU) from the building manager.

Detection is reliable and "easy" to implement, perhaps we should try to implement this quickly.

quantum-x avatar Jun 28 '22 06:06 quantum-x

Hello @quantum-x

We discussed with our team this issue and our priority is to support all commands during Classic emulation.

Regarding anti-copy algorithms, we need at least badges dumps. It would be nice if you send a few dumps with anti-copy signatures and provide an algorithm to detect the signature.

Further, it would be perfect to get these badges and may be readers on hands for tests. Is it possible for you to send them to us?

gornekich avatar Jun 28 '22 10:06 gornekich

Hi @gornekich Thanks for the internal discussion. I understand your team's priorities - and if Mifare Classic Emulation and writing can't be integrated, then integrating anti-copy detection is moot.

Regarding detection and rules, I have full rule-sets for detecting all types of known anti-copy on the market. It should be mentioned that this comes from the development team at Parklink Development Limited (a company for which I am director).

We are happy to open-source this code, as it's important for the community. If possible, we'd appreciate acknowledgement for the hard work of the dev team Contributors are myself (@quantum-x) @danielebruneo and @triplesprawl from Parklink Development Limited.

There are five brands using anti-copy:

  • Intratone (COGELEC Brand)
  • Hexact (COGELEC Brand)
  • Comelit
  • Noralsy
  • Urmet

Each brand has different generations of algorithms.

The match function ingests an ASCII HEX representation of the binary dump of a badge. Code is as follows :

Common method

        function hex_substring($hexDump,$startByte,$endByte){
            if($endByte<$startByte){
                return "";
            }
            return substr($hexDump,$startByte*2,($endByte-$startByte)*2+2);
        }

COGELEC Brands

Generic detection for COGELEC Brands

    public function match()
    {
        return
            $this->hex_substring($this->hex_dump, 0x03c0, 0x3c5) == "484558414354" && // 3c0-3c5 == HEXACT
            $this->hex_substring($this->hex_dump, 0x03c9, 0x3cf) == "434f47454c4543" && // 3c9-3cf == COGELEC
            $this->hex_substring($this->hex_dump, 0x02c0, 0x2cf) != "00000000000000000000000000000000" && // 2c* rolling counter block not empty
            $this->hex_substring($this->hex_dump, 0x02d0, 0x2df) != "00000000000000000000000000000000" && // 2d* rolling counter block not empty
            $this->hex_substring($this->hex_dump, 0x02e0, 0x2ef) != "00000000000000000000000000000000" && // 2e* rolling counter block not empty
            $this->hex_substring($this->hex_dump, 0x02c0, 0x2cf) != "ffffffffffffffffffffffffffffffff" && // 2c* rolling counter block not ff
            $this->hex_substring($this->hex_dump, 0x02d0, 0x2df) != "ffffffffffffffffffffffffffffffff" && // 2d* rolling counter block not ff
            $this->hex_substring($this->hex_dump, 0x02e0, 0x2ef) != "ffffffffffffffffffffffffffffffff"    // 2e* rolling counter block not ff
        ;
    }

Intratone

    public $regexp = '^[0-9A-F]{1412}(?:(?!00|FF)[0-9A-F]{2}).+?684578616374202D20434F47454C4543';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Hexact

Hexact A

    public $regexp = '484558414354787788008FA1D601D0A2(?!0000000000000000000000000000000000000000000000000000000000000000).+?000000000000000000000000000000004845584143547877880089347350BD36';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Hexact B


    public $regexp = '^[0-9A-F]{1376}484558414354787788008FA1D601D0A204D26';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Hexact C

    public $regexp = '^[0-9A-F]{1376}484558414354787788008FA1D601D0A2^[0-9A-F]{4}6';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Comelit

Comelit A

    public $regexp = '[0-9A-F]{2}0000014A6352684677';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Comelit B

    public $regexp = '^[0-9A-F]{216}(?:(?!0000)[0-9A-F]{4})*?[0-9A-F]{4}4A63526846777877';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Comelit C

    public $regexp = '[^00]{3}[0-9]{2}00[0-9]{2}4A6352684677';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Noralsy

Noralsy A

    public $regexp = '675A3241377078778800395244733978';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Urmet

Urmet A

    public $regexp = '^[0-9A-F]{1888}8829DA9DAF767F[0-9A-F]{109}[5|A]';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

Generic


    public $regexp = '^[0-9A-F]{1888}050908080008FF078069FFFFFFFFFFFF[0-9A-F]{8}20202020';

    public function match()
    {
        return
            preg_match('`' . $this->regexp . '`mis', $this->hex_dump);
    }

We can provide dumps to test against if required.

Please note, there are some badges that match A/C rules that do not have anti-copy enabled, but this false positive rate is ~2% maximum.

Hopefully these methods should remove some workload from your dev-team. Please let me know if I can provide any further assistance.

quantum-x avatar Jun 28 '22 20:06 quantum-x

got one dump made some times ago from a Cogelec/Intratone badge with all keys.. could help ? Intratone.zip

Foul avatar Aug 16 '22 17:08 Foul

got one dump made some times ago from a Cogelec/Intratone badge with all keys.. could help ? Intratone.zip

This one should indeed trigger the A/C Intratone ("COGELEC") algo.

quantum-x avatar Aug 16 '22 21:08 quantum-x

Hello @quantum-x, to see if a badge is really protected, the data should change if dumped before then after a badge is used to enter ? I have a spare Urmet badge with the pattern matching, but the content doesn't seems to be updated when used.

LoganMcClay avatar Aug 18 '22 15:08 LoganMcClay

@LoganMcClay The content doesn't necessarily update on each scan. Depending on the brand, either the badge contents contains the counter, or the access control system contains the counter.

With that said there is a 'before and after' difference between badges that don't have anti-copy enabled, and badges that do have anti-copy enabled - this is what the above algorithms detect.

quantum-x avatar Aug 18 '22 16:08 quantum-x

Ok so my badge is from immotec and first thing I did when I received my flipper was trying to copy it (obviously I didn't read this thread before). It seems it didn't work as I was unable to open my door with my flipper, I will go and test if my badge still work. Should I just stop everything for now about it, should I delete the saved nfc ? This sure is a huge problem and need to be told to EU users

LilianHori avatar Aug 27 '22 23:08 LilianHori

how does it work when there are several users/badges for the same building to synchronize everything?

Foul avatar Aug 28 '22 14:08 Foul

If your badge contents matches the IMMOTEC anti-copy rules above, do not attempt to emulate the badge.

IMMOTEC anti-copy will block the copy and the original badge. Depending on the configuration of the system, it can also erase the badges assigned to your apartment.

If your badge does not match the anti-copy rules, you should be OK to emulate it.

orign Sun, Aug 28, 2022, 01:08 LilianHori @.***> wrote:

Ok so my badge is from immotec and first thing I did when I received my flipper was trying to copy it (obviously I didn't read this thread before). It seems it didn't work as I was unable to open my door with my flipper, I will go and test if my badge still work. Should I just stop everything for now about it, should I delete the saved nfc ? This sure is a huge problem and need to be told to EU users

— Reply to this email directly, view it on GitHub https://github.com/flipperdevices/flipperzero-firmware/issues/1345#issuecomment-1229298237, or unsubscribe https://github.com/notifications/unsubscribe-auth/AATF43BGI6SKRYBKXXRBYI3V3KNYNANCNFSM5Z5TIVYA . You are receiving this because you were mentioned.Message ID: @.***>

quantum-x avatar Aug 28 '22 15:08 quantum-x

another user posted :

I know this remote, and talked to the vendor of it. It is not transmitting a usual signal like other remotes do. This one sends only 3 little bursts of the signal, like Horman BiSecur, which are hard to catch. And it is AES encoded. There will be no way to handle this remote with Flipper or any other cloning device or solution!

😥

Foul avatar Sep 02 '22 22:09 Foul

The one with permanent access could be interesting ;)

Foul avatar Mar 28 '23 21:03 Foul

Did you test it successfully ?

Foul avatar Mar 28 '23 21:03 Foul

Link to Pastbin.

Foul avatar Mar 28 '23 22:03 Foul

HI here, If somebody it's interested, i have two badge intratone with anty-copy , i'll can make a completly dump And I have an old card of a packet distributor who is desactived but she had a permanent acces during a certains day before. I dumped it too. I'm curious to know more about that card and how work the badge of emergency service. I'll can make test with my two badge and try to modify card and test it.

This is a thread about providing detection of anti-copy algorithms put in place by French Access Control manufacturers to prevent Flipper Zero owners for inadvertently erasing their original cards when they make private copies, or when they make in-scope penetration tests.

@Foul @Yomi2023 @Sweedn You are discussing the VIGIK Service cards, which is out of scope of this thread. Furthermore, duplication of these cards is illegal and has lead to multiple arrests. I'd suggest removing these posts, or moving the discussion into another forums.

quantum-x avatar Apr 02 '23 14:04 quantum-x

I want to propose another anti-copy situation: the original card is a Mifare Classic 1K card, SAK:08, KeyA/B are FFFFFFFFFFFFF, so it can be copied and stored by F0, but when F0 simulates, systems like the elevator system and access control system cannot read the content normally (no response at all). Later, I found information on the Internet saying that these systems "may" have a firewall, and need to use a card type called "CUID" (probably the so-called magic card) to work normally. In practice, a copied card using CUID can pass through the above systems normally.

Is it possible for F0 to update the firmware to read data normally through the above systems? Thank you.

chinlung avatar Aug 06 '23 13:08 chinlung

Hi!

got one dump made some times ago from a Cogelec/Intratone badge with all keys.. could help ? Intratone.zip

Thanks for providing the dump and thanks a lot to contributors such as @quantum-x for the hard work.

A first interesting thing to note about this dump is what we see at 0x03c0 -> 0x03cf:

xxd Intratone.dmp
...
000003c0: 6845 7861 6374 202d 0143 4f47 454c 4543  hExact -.COGELEC
...

hExact is different from HEXACT string so this should not match with:

$this->hex_substring($this->hex_dump, 0x03c0, 0x3c5) == "484558414354" && // 3c0-3c5 == HEXACT

Hope this help

jerome-jutteau avatar Oct 20 '23 18:10 jerome-jutteau