🎬 Intro #
This post will be about how you can easily clone MIFARE Classic cards with a Proxmark3 device. I have long been interested in how RFID works and the security behind it and the Proxmark3 is a great tool for this.
My apartment block uses MIFARE Classic cards for access control and they charge an unreasonable amount of money to get replacements/extras, so I decided to do this myself. Unfortunately it was not as simple as I initially anticipated but at the end of the day once I understood what protections were in place and how to bypass them, it was a breeze.
This post will be a somewhat technical dive into everything I learned during this process, as well as a guide on how to clone MIFARE Classic cards with a Proxmark3 device. If you’re just here to clone your cards, you can skip the technical stuff and just follow the steps below although I would advise reading the entire post to understand what’s going on and how exactly these things function.
📡 What is MIFARE Classic? #
MIFARE Classic 1K uses NXP’s proprietary CRYPTO-11 cipher for authentication, which has been thoroughly broken since 2008. The cards have 16 sectors, each protected by two 6-byte keys (Key A and Key B), and the entire security model is considered insecure by modern standards, despite this they are one of the most widely deployed contactless smart card types in the world used in access control, public transit, and plenty of other systems.
Modern replacements like MIFARE DESFire and MIFARE Plus use proper AES encryption, but Classic cards are still everywhere.
🔧 The Proxmark3 #
The Proxmark3 is a full RFID research platform. Compared to tools like the Chameleon Ultra or phone-based NFC apps, it can run the full attack chain (dictionary, darkside, nested, and hardnested) using your computer’s processing power. Phone apps and the Chameleon Ultra are generally limited to dictionary attacks and lack the computational muscle for the heavier cryptographic attacks.
The Proxmark3 was originally designed by Jonathan Westhues back in 2007 as an open-source RFID research tool. The hardware schematics and firmware were released publicly, which is how it eventually became the community-driven tool it is today. The RRG (RFID Research Group) took the design forward and produced what became the RDV4, the “official” revision from the folks who maintain the Iceman firmware. If you want a more detailed history, the Proxmark3 wiki covers it well enough.
The “proper” device is the Proxmark3 RDV4, sold by RRG for around $300. Swappable antennas, solid build quality, and it’s what the firmware is primarily developed against. If you’re doing RFID research professionally, sure, get that. For the rest of us there are clones all over AliExpress for £20–60 that do the same job. This is what I use and as a hobbyist it does everything I need. I would like to support the RRG and buy the RDV4 but I do find the cost steep just for supporting a project, personally.
The main things to know about the clones is that quality control varies and the firmware that ships on them is universally outdated and needs replacing immediately. More on that below. I have purchased several due to the micro usb ports on them being very easy to break (and in trying to repair them made things a lot worse). What I have done with my latest one is to put a generous amount of glue on the micro usb port and the port itself to try and prevent it from breaking again.
Iceman Firmware & Setup #
If you’re buying a Proxmark3 (especially a clone/generic unit), the first thing you should do is flash the Iceman firmware. The stock firmware on most units is usually a relic. Iceman (maintained by the RRG / RFID Research Group) is the actively developed community firmware that adds the advanced attack methods, better hardware support, and ongoing bug fixes.
On macOS, the easiest way to install both the client and flash the firmware is via Homebrew:
# Add the RRG tap
brew tap rfidresearchgroup/proxmark3
# Install (use --with-generic for clone/non-RDV4 devices, --with-flash to enable flashing)
brew install --with-generic --with-flash rfidresearchgroup/proxmark3/proxmark3
# Flash the firmware (device must be connected)
pm3-flash-all
For other platforms, the RRG wiki has setup guides for Linux and Windows. From what I have found, the clones require the use of the --with-generic flag when installing the firmware.
After flashing, verify with:
pm3 -c "hw version"
You should see Iceman/master/v4.xxxxx in both the Client and ARM sections, and the bootrom and OS versions should match. If they don’t match, re-flash.
The USB device shows up as /dev/tty.usbmodemiceman1 on macOS, the pm3 wrapper script auto-detects this, so you generally just run pm3 without specifying a port.
🔓 Cracking the Card #
The Quick Way #
If you already know it’s a MIFARE Classic, one command does everything: detect, attack, dump:
pm3 -c "hf mf autopwn"
If you want to check things first, hw status confirms the Proxmark is communicating, auto will detect the card type, and hf mf info gives a detailed overview (PRNG type, magic card detection, key info). Once you know what you’re dealing with, just run autopwn.
The output files are named by UID automatically:
hf-mf-[UID]-key.bin: all recovered keyshf-mf-[UID]-dump.bin: full memory dumphf-mf-[UID]-dump.json: human-readable JSON
How the Attacks Work #
autopwn runs these in order, fastest first:
1. Dictionary Attack #
Tries a list of known/common keys against each sector. Catches anything using factory defaults immediately.
2. Darkside Attack #
Used when the dictionary fails and the card has a weak PRNG2. Exploits NACK (negative acknowledgment) responses to recover a key without needing any valid key first.
3. Nested Attack #
Once any single key is found, this exploits MIFARE Classic’s weak PRNG2 to mathematically predict the RNG state and recover the remaining keys. Most genuine MIFARE Classic cards and Chinese clones have a weak PRNG, so they fall here, and it’s fast.
4. Hardnested Attack #
For cards with a hard PRNG2 (shown as Prng detection..... hard in hf mf info). These are resistant to darkside and nested, so hardnested collects ~2000 nonces3, applies cryptographic analysis to narrow the key space, then brute forces the rest. On my Mac this ran at ~1,593 million keys/second and cracked keys in about 23 seconds.
Once any key is found, autopwn also checks whether it works across other sectors. A lot of systems reuse the same key everywhere, marked with R in the output. Hotel keys in particular are often like this.
Manual Commands (if autopwn fails) #
# Dictionary attack
pm3 -c "hf mf chk --1k"
# Nested attack (needs at least one known key)
pm3 -c "hf mf nested --1k"
# Hardnested (specify source block/key and target block)
pm3 -c "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 19 --ta"
# Dump card once all keys recovered
pm3 -c "hf mf dump --1k"
🔍 Example: Standard MIFARE Classic 1K #
Card had default keys on sectors 0–3 and 15 (FFFFFFFFFFFF), and custom keys on sectors 4–14. Hard PRNG2 detected.
hf mf info output:
[=] --- ISO14443-a Information -----------------------------
[+] UID: 04 25 2F 6A
[+] ATQA: 00 04
[+] SAK: 08 [1]
[=] --- Fingerprint
[+] MIFARE Classic 1K
[=] --- PRNG Information
[+] Prng....... hard
autopwn key recovery table:
[+] -----+-----+--------------+---+--------------+----
[+] Sec | Blk | key A |res| key B |res
[+] -----+-----+--------------+---+--------------+----
[+] 000 | 003 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 001 | 007 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 002 | 011 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 003 | 015 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 004 | 019 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | H
[+] 005 | 023 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 006 | 027 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 007 | 031 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 008 | 035 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 009 | 039 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 010 | 043 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 011 | 047 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 012 | 051 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 013 | 055 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 014 | 059 | FFFFFFFFFFFF | D | A1B2C3D4E5F6 | R
[+] 015 | 063 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] -----+-----+--------------+---+--------------+----
[=] ( D:Dictionary / S:darkSide / U:User / R:Reused / N:Nested / H:Hardnested / C:statiCnested / A:keyA )
Dictionary found the default keys instantly, then hardnested cracked the custom Key B in ~23 seconds. Key reuse (R) across sectors 5–14 saved a lot of time.
Total time: ~30 seconds for a full dump.
🔍 Example: Fudan FM11RF08 Clone #
Fudan FM11RF08 is a common Chinese MIFARE Classic 1K clone. These have a manufacturer backdoor key accessible via hf mf info, and typically have weak PRNG.
hf mf info output:
[=] --- ISO14443-a Information -----------------------------
[+] UID: E6 C8 70 2B
[+] ATQA: 00 04
[+] SAK: 08 [1]
[=] --- Keys Information
[+] loaded 2 user keys
[+] loaded 61 hardcoded keys
[+] Backdoor key..... A396EFA2B2C1
[+] Block 0.......... E6C8702BA8080400015C01F5703EC81D | .\..p>..
[=] --- Fingerprint
[+] Fudan FM11RF08
[=] --- Magic Tag Information
[=]
[=] --- PRNG Information
[+] Prng....... weak
autopwn attack flow, dictionary failed (no defaults), then darkside found Key A by analyzing NACK patterns, then nested used that to crack Key B and all remaining sectors:
[=] Running darkside .
[+] found 13 candidate keys
[+] Found valid key [ 4D5946414345 ]
[+] Target sector 0 key type A -- found valid key [ 4D5946414345 ]
[+] Found 1 key candidate
[+] Target block 0 key type B -- found valid key [ 4B4559313233 ]
[+] Target sector 0 key type B -- found valid key [ 4B4559313233 ]
[+] Target sector 1 key type B -- found valid key [ 4B4559313233 ]
...
[+] Target sector 15 key type B -- found valid key [ 4B4559313233 ]
Full key recovery table:
[+] -----+-----+--------------+---+--------------+----
[+] Sec | Blk | key A |res| key B |res
[+] -----+-----+--------------+---+--------------+----
[+] 000 | 003 | 4D5946414345 | S | 4B4559313233 | N
[+] 001 | 007 | 4D5946414345 | N | 4B4559313233 | R
[+] 002 | 011 | 4D5946414345 | R | 4B4559313233 | R
[+] 003 | 015 | 4D5946414345 | R | 4B4559313233 | R
[+] 004 | 019 | 4D5946414345 | R | 4B4559313233 | R
[+] 005 | 023 | 4D5946414345 | R | 4B4559313233 | R
[+] 006 | 027 | 4D5946414345 | R | 4B4559313233 | R
[+] 007 | 031 | 4D5946414345 | R | 4B4559313233 | R
[+] 008 | 035 | 4D5946414345 | R | 4B4559313233 | R
[+] 009 | 039 | 4D5946414345 | R | 4B4559313233 | R
[+] 010 | 043 | 4D5946414345 | R | 4B4559313233 | R
[+] 011 | 047 | 4D5946414345 | R | 4B4559313233 | R
[+] 012 | 051 | 4D5946414345 | R | 4B4559313233 | R
[+] 013 | 055 | 4D5946414345 | R | 4B4559313233 | R
[+] 014 | 059 | 4D5946414345 | R | 4B4559313233 | R
[+] 015 | 063 | 4D5946414345 | R | 4B4559313233 | R
[+] -----+-----+--------------+---+--------------+----
[=] ( D:Dictionary / S:darkSide / U:User / R:Reused / N:Nested / H:Hardnested / C:statiCnested / A:keyA )
[=] Autopwn execution time: 22 seconds
Notice the res column: S = darkSide found it, N = nested cracked it, R = reused key detected. Both keys were reused across all 16 sectors.
These keys decoded to ASCII: 4D5946414345 = “MYFACE”, 4B4559313233 = “KEY123”, a pattern common in commercial access systems where readable strings are used for easier key management.
Total time: ~22 seconds.
🔑 Key Formats #
MIFARE keys are 6 bytes (48 bits). You’ll see them in different formats:
- Default keys:
FFFFFFFFFFFF,000000000000 - Random hex:
A1B2C3D4E5F6 - ASCII-encoded:
4D5946414345= “MYFACE” in ASCII, common in commercial systems - Backdoor keys: manufacturer-specific, hardcoded into clone chips
🪄 Cloning: Magic Cards & Block 0 #
After dumping a card, you can write it to a blank MIFARE Classic, but standard cards have Block 0 (containing the UID) as read-only. Since many systems verify the UID, you need a “magic” card with a writable Block 0. This is where I initially had issues when I was first trying to clone my cards.
Once I had cloned my fob and verified they had the correct data, I was unable to use them in my apartment block’s reader. When trying to use them the reader would lock out for a period of time and at the time I had no idea why. After some research, I used the Proxmark3 to sniff the traffic between the reader and the fob. The reader was querying for block 0, and when it detected that block 0 was writable, it would lock out. This makes complete sense and is an easy way to detect a clone.
After about a year of this sitting on the back burner, I came across a new type of fob starting to appear on the market. These would let you write Block 0 normally, but once written, Block 0 locks permanently and the fob becomes indistinguishable from one acquired through official channels.
How the Detection Works #
Gen1a magic cards respond to a special “backdoor” command sequence that NXP MIFARE Classic chips ignore. Readers exploit this by sending the backdoor commands during every card interaction. If the card responds, it’s flagged immediately.
The Gen1a backdoor sequence is two commands:
| Step | Command | Bit Length | Description |
|---|---|---|---|
| 1 | 0x40 |
7 bits | Magic wakeup part 1 |
| 2 | 0x43 |
8 bits | Magic wakeup part 2 |
0x40 is sent as a 7-bit frame. In ISO 14443A4, 7-bit frames are only used for REQA/WUPA5 commands (0x26/0x52). A genuine MIFARE Classic has no handler for a 7-bit 0x40 and silently ignores it. A Gen1a magic card recognises it as the backdoor entry and responds with an ACK (0x0A), which is a dead giveaway.
What the Sniffed Traffic Looks Like #
Sniffing the traffic between the reader and the card is very interesting and a great way to understand what’s going on. The decoded trace (using trace list -t mf) shows something like this:
# Normal ISO 14443A anti-collision:
Reader -> Tag: 26 # REQA
Tag -> Reader: 04 00 # ATQA
Reader -> Tag: 93 20 # ANTICOLL CL1
Tag -> Reader: AA BB CC DD EE # UID + BCC
Reader -> Tag: 93 70 AA BB CC DD EE [CRC] # SELECT
Tag -> Reader: 08 [CRC] # SAK
# --- Magic card detection probe ---
Reader -> Tag: 40 # 7-bit! Gen1a backdoor wakeup
Tag -> Reader: 0A # ACK - CLONE DETECTED
Reader -> Tag: 50 00 [CRC] # HLTA (halt) - rejected
You can reproduce this probe yourself with raw Proxmark3 commands:
# Send the Gen1a backdoor probe manually
pm3 -c "hf 14a raw -a -k -b 7 40" # 0x40 at 7 bits
pm3 -c "hf 14a raw -k 43" # 0x43 at 8 bits
# If the card ACKs (0x0A) → it's a magic card
CUID / Gen2 Detection #
CUID cards don’t respond to the backdoor commands, so they pass the 0x40 probe. But some readers have further hardening: they attempt to write to Block 0. On a genuine MIFARE Classic, Block 0 is permanently read-only (factory-programmed UID). A CUID card accepts writes to Block 0 using standard write commands, so if the reader authenticates to sector 0 and issues a write to Block 0, and the card ACKs instead of NACKing, the reader knows it’s a CUID clone.
Some readers do a “probe write” with the card’s own existing Block 0 data, so even if the write succeeds, the data doesn’t actually change on the card.
Rolling Counters: When No Static Clone Works #
Some access control systems go beyond magic card detection entirely. Using a rolling counter, each time a card is presented, the reader writes an incremented value to a specific sector. On the next tap, the reader checks if the counter matches what it expects.
A static clone has a stale counter value, so it fails after the original card has been used. This defeats all clone types regardless of how good the card hardware is. A workaround is dynamic emulation used in some hardware cloners.
Magic Card Types #
| Type | Block 0 | Detection Risk | Notes |
|---|---|---|---|
| UID (Gen 1a) | Writable via backdoor commands | High (hf search flags Chinese magic backdoor commands (GEN 1a) detected) |
Original Chinese magic card. Most security readers will probe for backdoor responses. |
| CUID (Gen 2) | Writable like any block | Medium (detectable via Block 0 write test) | No backdoor commands. Better Android NFC app compatibility. |
| FUID | Write once, self-locks permanently | None after locking | Best for permanent clones. Ships with factory UID AA55C396. Locks the moment you write a non-default UID. |
| UFUID | Writable via Gen1a backdoor, requires explicit lock command to seal | None after sealing | Rewritable until you seal it. Some sophisticated readers may detect protocol deviations after locking. |
⚙️ FUID Cloning Workflow #
Step 1: Verify the FUID is Blank/Unlocked #
pm3 -c "hf mf info"
You want to see:
[+] Magic capabilities... Gen 2 / CUID
[+] Magic capabilities... Write Once / FUID
Factory UID will be AA 55 C3 96 which means it’s blank and unlocked. If you also see a GDM / USCUID line, it’s the older revision.
Step 2: Dump the Target Card #
Swap to the original card:
pm3 -c "hf mf autopwn"
Step 3: Verify the Dump #
Open the .json dump and check:
- Block 0 has a valid UID + correct BCC (byte 4 =
UID[0] XOR UID[1] XOR UID[2] XOR UID[3]) - All 64 blocks present (0–63 for 1K)
- All 16 sector trailers6 have keys populated
- No unexpectedly empty blocks
Step 4: Write the Dump to the FUID #
Swap to the FUID:
pm3 -c "hf mf restore --1k -f /path/to/hf-mf-AABBCCDD-dump.bin -k /path/to/hf-mf-AABBCCDD-key.bin"
All 64 blocks should show ( ok ). Block 0 writing here is what triggers the permanent lock.
--ka flag. That tells Proxmark to authenticate using the keys from the key file, but the blank FUID only knows FFFFFFFFFFFF. Without --ka, it authenticates with the default key and writes everything correctly.
hf mf csetuid or hf mf cload on FUID cards. Those use Gen1a wakeup commands (40(7), 43) which FUID doesn’t support. They’ll fail silently or with wupc1 error.
Step 5: Verify the Clone #
pm3 -c "hf mf info"
You want to see:
- UID matches the original card.
- No magic tag lines at all. The lock worked, the card is ‘undetectable’.
- SAK and ATQA7 match the original card.
Quick data verification:
pm3 -c "hf mf dump --ns --1k"
--ns skips key recovery and uses known keys, this is a fast verification that the data is intact.
📖 Proxmark3 Command Reference #
# Card identification
pm3 -c "hf search" # Detect card type + magic capabilities
pm3 -c "hf mf info" # Detailed MIFARE info
# Cracking & dumping
pm3 -c "hf mf autopwn" # Full automated attack chain
pm3 -c "hf mf chk --1k" # Dictionary attack only
pm3 -c "hf mf nested --1k" # Nested attack
pm3 -c "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 19 --ta"
pm3 -c "hf mf dump --1k" # Dump with recovered keys
# Writing / cloning
pm3 -c "hf mf restore --1k -f dump.bin -k keys.bin" # Full restore
pm3 -c "hf mf csetuid AABBCCDD" # Set UID (Gen1a only)
pm3 -c "hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d [hex] --force" # Write Block 0
# Verification
pm3 -c "hf mf dump --ns --1k" # Read without key recovery
Thanks for reading! ✌️

Pixel 9 Pro + Rear Camera @ 6.9mm, f/1.7, 1/640s, ISO 22
🦶 Footnotes #
-
A proprietary 48-bit stream cipher NXP developed for MIFARE Classic in the 1990s. Kept secret for years, it was fully reverse-engineered and broken in 2008 by researchers at Radboud University among others. The attacks
autopwnruns today are a direct result of that work. ↩︎ -
PRNG stands for Pseudo-Random Number Generator. MIFARE Classic uses one during authentication. A weak PRNG produces predictable output that makes the darkside and nested attacks possible. A hard PRNG is more resistant and requires the hardnested approach. ↩︎ ↩︎ ↩︎ ↩︎
-
A nonce (Number Used Once) is a random value generated during each authentication challenge. Hardnested collects ~2000 of them and applies statistical analysis to narrow down possible cipher states before brute-forcing. ↩︎
-
The international standard for contactless smart cards at 13.56 MHz. It defines the physical layer, anti-collision protocol, and command framing. MIFARE Classic is an NXP-proprietary implementation built on top of it, with CRYPTO-1 handling the authentication layer. ↩︎
-
REQA (Request Type A,
0x26) and WUPA (Wake Up Type A,0x52) are the ISO 14443A commands a reader sends to initialise a card. Both use 7-bit frames, which is why a 7-bit0x40is immediately suspicious. Standard card commands don’t use that framing, so a genuine MIFARE Classic has no handler for it. ↩︎ -
Each MIFARE Classic 1K sector contains 4 blocks of 16 bytes. The last block in every sector is the sector trailer, which stores Key A (6 bytes), access condition bits (3 bytes), and Key B (6 bytes). The access bits control what each key can do (read, write, increment, etc.) for the other 3 data blocks in that sector. Without valid keys in all 16 sector trailers, authentication fails and the clone won’t work. ↩︎
-
SAK (Select Acknowledge) is a single byte returned during card selection that identifies card type:
0x08= MIFARE Classic 1K,0x20= ISO 14443-4 compliant (DESFire, etc.). ATQA (Answer To Request type A) is a 2-byte response indicating the card family. Both are normal parts of ISO 14443A anti-collision. Checking they match on your clone confirms it’s presenting itself identically to the original. ↩︎