Sending GetDFNames (0x6D) inside an authenticated session destroys DESFire EV1
silicon. When the response chains, the card answers the first 0xAF continuation
frame with 0xC1 PICC_INTEGRITY_ERROR, "PICC will be disabled", and from that
moment every command returns 0xCD PICC_DISABLED_ERROR. The ATS historical byte
changes 0x80 -> 0x90. Three cards were destroyed establishing this.
It is reached by `hf mfdes dump`, `hf mfdes lsapp` and `hf mfdes info --files`,
all of which authenticate and then call DesfireFillAppList.
HOW IT WAS ISOLATED
One variable at a time, on a card that survived all of it. Unauthenticated, the
identical frames are answered normally:
- 0x6D on a blank card
- 0x6D with an application that has no DF name (empty, per 9.4.4)
- 0x6D with one DF name, single frame, no chaining
- 0x6D chained over two and then three DF names, sent by hand
- the chain abandoned mid-way with the field dropped
- a stray 0xAF with no chain open, answered 91 1C
- the client's own chaining code with splitbysize
Authenticated, the same card died on the first continuation frame. The client
appends no MAC to 0x6D -- it is not in EV1D40TransmitMAC -- so the bytes on the
wire are `90 6D 00 00 00` then `90 AF 00 00 00` either way, byte for byte
identical to the probes that passed. Only the card's session state differs.
Ruled out along the way:
- Failed or wrong-algorithm authentication. `hf mfdes chk` has fired hundreds
of failed auths per card for years without harm.
- Abandoned authentication chains. DesfireCheckAuthCmd sends only the first
frame of an auth and then drops the field, six times per `hf mfdes info`
run; 30 of them left the test card healthy.
- Malformed commands. The only out-of-spec command in the original sequence
(UpdateRecord, 18 bytes into a 16 byte record) was refused client-side and
never reached the card.
- Chaining itself, DF names themselves, and the record count.
THE FIX
Drop the PICC session around the call and restore it afterwards.
It is the card's session that has to go, not the context. Clearing
DesfireContext_t alone would leave the card authenticated and change nothing, so
SelectApplication is used: "each SelectApplication command invalidates the
current authentication status" (M134034 9.4.5).
The session is then re-established on whatever AID was selected when we were
called, not on 000000. The issuer info path enters DesfireFillAppList with an
application already selected, and re-authenticating the PICC with that
application's key would silently fail. A context selected by DF name has no AID
to return to, so the DF name list is skipped rather than guessed at.
No configuration forces the unsafe order. Key settings bit 1 governs whether the
directory commands need authentication, and its "needs auth" branch names only
GetApplicationIDs and GetKeySettings, not GetDFNames (M134034 p.39). A card that
refuses the plain command costs the DF name column; sending it authenticated
costs the card.
WHAT THE DATASHEETS SAY
EV1 never specifies how secure messaging applies across 0xAF frames. EV3 had to
write the rule down later, ev3.pdf 7.3.2.2: "the secure messaging is applied as
if the command or response would have been sent in a single large frame. The
0xAF command and response codes are ignored for these calculations." The exact
interaction that destroys these cards is the one EV1 left unwritten.
EV2 and EV3 then deleted the whole self-disable family: ev3.pdf contains zero
occurrences of PICC_DISABLED or PICC_INTEGRITY, which M134034 defines. EV3
renames 0xEE to MEMORY_ERROR and says the part may execute a reset rather than
disable itself.
Whether the disabled state is recoverable is SILENT in every direction. The five
codes appear once each, in one status table, with no prose anywhere, and there is
no lifecycle command in DESFire to rehabilitate a PICC. Measured on a dead card,
nothing works: FormatPICC cannot authenticate (0x1A -> 91 CD) and is refused raw
(90 FC -> 91 CD); SelectApplication is refused (91 CD) even though it needs no
authentication and no bit can gate it; every ISO 7816 command including ACTIVATE
FILE and TERMINATE DF answers 65 81 "Memory failure". A malformed GetVersion
still answers 91 7E LENGTH_ERROR, so anticollision, RATS, the command parser and
length validation all still run -- only the application layer underneath is gone.
Note M075031 is the D40 datasheet, not EV1; the EV1 document is M134034.
ALSO IN THIS CHANGE, because without them the cause was invisible
Every card error collapsed to PM3_EAPDU_FAIL before reaching a caller, and both
send paths only printed the status when -a was given. That is why the first two
cards told us nothing about how they died.
- The five codes M134034 Table 11 footnotes as "not expected to appear during
normal operation" (0xC1, 0xCD, 0xA1, 0xF1, 0xEE) are now reported from both
DESFIRESendRaw and DESFIRESendApduEx whether or not -a is given. Ordinary
refusals stay at debug level, so chk and the ISO file id probes stay quiet.
- A chained 0xAF is attributed to the command it is continuing, so a failure
reads "command 0x6D frame 0xAF -> 0xC1" rather than a bare 0xAF.
- DesfireContext_t keeps lastRespCode, set where both exchange paths meet.
A command error also ends the authentication on the PICC, so the client now
drops its side of the session rather than continuing to MAC into a session the
card has thrown away. The tree already did this at one call site
(DesfireGetFileISOIDList); it is now done at the choke point every native
command passes through, plus the paths that bypass it: DesfireReadSignature,
DesfireCreateDelegatedApplication, DesfireISOSelectEx, the ISO data plane
(ReadBinary, UpdateBinary, ReadRecords, AppendRecord) and GetDelegateInfo. The
three ISO authentication wrappers are deliberately left alone, since they run
before a session exists and clearing would wipe the handshake's own state.
`hf mfdes pc` checked only the transport result and treated a card error as
success: DesfireExchangeEx returns PM3_SUCCESS with the card's status in
respcode, so PreparePC, the proximity check rounds and VerifyPC went on to parse
error responses as data. They now check respcode.
DesfireFillFileList discarded the result of DesfireFileSettingsStruct, so a file
whose settings could not be read became a zeroed entry indistinguishable from a
valid 0 byte standard data file. FileListElm_t now carries fileSettingsRead and
five consumers honour it: the ISO id mapping loop (positional, an unread file
would shift every id after it onto the wrong file), `hf mfdes chk`'s used-key
set, lsfiles, the application walk print, and `hf mfdes dump`, where settings_ok
was being set true unconditionally.
DesfireFillAppList tested a stale `res` after DesfireGetKeySettings, whose return
value was discarded; only an incidental buflen guard kept it from consuming
garbage key settings.
`hf mfdes sim` now runs through the shared ISO14443-A simulation loop as tag
type 3 rather than a duplicate 14a loop, which had got the ATQA wrong. The
DESFire logic stays in armsrc/desfiresim.c behind a small hook API.
KNOWN, NOT FIXED HERE
DesfireFillAppList reads the DF name list into uint8_t buf[250] while
DesfireCommandEx copies records * 24 bytes. The EV1 limit of 28 applications
would write 672 bytes into it. Harmless at the record counts seen here, but a
stack overflow waiting for a full card.
VERIFICATION
On a fourth card from the same lot (batch B9 0C 17 49 70, week 27 / 2017, EV1 8K,
HW 04010101001A05, SW 04010101041A05): the sequence that killed the third card
now completes, the chained 0xAF is answered 91 00, and the card is healthy
afterwards. The APDU log shows GetDFNames and its continuation carrying no MAC
while the commands either side of them do, confirming the session is dropped and
restored. A full `hf mfdes dump` of three applications (AES, 2TDEA, 3TDEA) and
all five EV1 file types completes and round-trips through the dump format.
Scope: all four cards are from one production lot. This is not established as an
EV1-wide erratum.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Iceman Fork - Proxmark
The Proxmark is the swiss-army tool of RFID, allowing for interactions with the vast majority of RFID tags on a global scale. Originally built by Jonathan Westhues, the device is now the goto tool for RFID Analysis for the enthusiast.
Iceman repository is considered to be the pinnacle of features and functionality, enabling a huge range of extremely useful and convenient commands and Python/LUA scripts to automate chip identification, penetration testing, and programming.
| Latest Release | Coverity | Contributors |
|---|---|---|
| Actions OSX CI | Actions Ubuntu CI | Actions Windows CI |
|---|---|---|
Table of Contents
- Iceman Fork - Proxmark
- Table of Contents
- PROXMARK3 INSTALLATION AND OVERVIEW
- How to build?
- What has changed?
- Development
PROXMARK3 INSTALLATION AND OVERVIEW
Notes / helpful documents
How to build?
Proxmark5
The last hardware generation is called Proxmark5. It has
- MCU: AT32F435, a 288 MHz Artery Cortex-M4
- Gowin FPGA
- TypeC Extended Port (CEP)
- BLE / Wifi / Battery Addon, via a ESp32c2
- Swappable antennas (LF, HF, UHF)
- 125, 134, 250, 375, 500 KHz Low Frequency Antenna (LF)
- 13.56 MHz High Frequency Antenna (HF)
- as a addon: 860-960 MHz Ultra High Frequency Antenna (UHF), ** not developed yet **
At the moment, Proxmark5-specific instructions are all grouped in a single Getting Started guide. Read it to build, flash and run your Proxmark5 device. See the instruction links in the tables above to get the compilation environment.
- ⚠ The firmware is not stable at the moment and is actively being developed at.
- ⚠ Don't install the BWM addon board for now.
Proxmark3 RDV4
See the instruction links in the tables above to build, flash and run for your Proxmark3 RDV4 device.
Generic Proxmark3 platforms
In order to build this repo for generic Proxmark3 platforms we urge you to read Advanced compilation parameters
We define generic Proxmark3 platforms as following devices.
Supported
- RDV1, RDV2, RDV3 easy
- Ryscorp green PCB version
- Radiowar black PCB version
- numerous Chinese adapted versions of the RDV3 easy (kkmoon, PiSwords etc)
- Proxmark3 SE (Special Edition) (BLE enabled)
- Proxmark3 X
- Note: Community tested
- Note: unknown device hw
- iCopy-X
- Note: Compatible ONLY after installation of iCopy-X Open Source firmware
- Factory firmware is not compatible (Client Commands are different / Factory UI closed source / Factory Firmware enforces tag DRM)
Not supported
- ⚠ Proxmark Evolution (EVO)
- Note: unknown pin assignments.
- ⚠ Ryscorp Proxmark3 Pro
- Note: device has different fpga and unknown pin assignments.
- Note: Company have disappeared, leaving their customers in the dark.
Experimental support
- ⚠ Proxmark3 Ultimate
- Note: unknown device hw
- Note: FPGA images is building for it. Use on your own risk.
Unknown support status
- ⚠ VX
- Note: unknown device hw
When it comes to these new unknown models we are depending on the community to report in if this repo works and what they did to make it work.
256KB flash memory size of generic Proxmark3 platforms
⚠ Note: You need to keep a eye on how large your ARM chip built-in flash memory is. With 512KB you are fine but if its 256KB you need to compile this repo with even less functionality. When running the
./pm3-flash-allyou can see which size your device have if you have the bootloader from this repo installed. Otherwise you will find the size reported in the start message when running the Proxmark3 client./pm3.
What has changed?
See the Changelog file which we try to keep updated.
Development
⚠ Note: This is a bleeding edge repository. The maintainers actively is working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so DO expect significant changes to code layout on a regular basis.
👉 Remember! If you intend to contribute to the code, please read the coding style notes first. We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards.
The public roadmap is an excellent start to read if you are interesting in contributing.
Supported operating systems
This repo compiles nicely on
- WSL1 on Windows 10
- WSL2 on Windows 10/11
- Proxspace environment release v3.xx
- Windows/MinGW environment
- Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian
- Android / Termux
- macOS / Homebrew (or MacPorts, experimental) / Apple Silicon M1
- iOS (Jailbroken, rootful)
- Docker container
Precompiled binaries
See Proxmark3 precompiled builds
Proxmark3 GUI
Most community driven GUI for Proxmark tends to be quite old and out-of-date. Here is a list of a few:
- Proxmark3 Universal GUI will work more or less.
- Proxmark3 GUI cross-compiled which is recently updated and claims to support latest source of this repo.
- Proxmark3_GUI simple gui in vb.net
Official channels
Where do you find the community?
Maintainers
To all distro, package maintainers, we tried to make your life easier.
make install is now available and if you want to know more.
This document will be helpful for you
Citation
Use this bibtex to cite this repository globally:
@misc{proxmark3,
author = {C. {Herrmann} and P. {Teuwen} and O. {Moiseenko} and M. {Walker} and others},
title = {{Proxmark3 -- Iceman repo}},
howpublished = {\url{https://github.com/RfidResearchGroup/proxmark3}},
keywords = {rfid nfc iceman proxmark3 125khz 134khz 13.56mhz},
}
If you need to refer to a specific state of the repository, use a commit number or a date of access, e.g.:
note = {Accessed: commit 12327f71a27da23831901847886aaf20e8ad3ca0}
note = {Accessed: 2021-01-01}
Copyright and licensing terms
Each contribution is under the copyright of its author. See AUTHORS.
The Proxmark3 source code is covered by the following licensing terms, usually referred as GPLv3 or later.
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 3 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.
A copy of the GPLv3 is available in LICENSE.
Some dependencies may be under other free licensing terms compatible with the Proxmark3 licensing terms, see their respective description.