SYS: FANTASI WIKI PAGE: RFID_
← HOME

RFID

Fantasi supports RFID on every device it runs on. A capable RFID frontend is one of the criteria for a board becoming a Fantasi target. Proxmark3, Proxmark5, Flipper Zero, Kiisu, and Chameleon Ultra use the same commands and dump formats, so supported operations can move between devices.

Devices and frontends

Each platform carries its own driver in platforms/*/rfid.c. They meet at a logical HAL (hal/hal_rfid.h): HF is only a framed transceive, LF is a raw acquire plus modulate. Everything above that line (anticollision, EM4100 decode, CRC, Crypto1) is written once in core/rfid/ and shared. Platforms advertise their abilities through capability bits.

DeviceRFID frontend
Proxmark3Xilinx Spartan-II XC2S30 FPGA driven by AT91SAM7S512
Proxmark5GOWIN GW1N-4B FPGA driven by AT32F435
Flipper / KiisuST25R3916 in transparent mode
Chameleon UltranRF52840 NFCT, MFRC522

NB: On the Proxmark3, FPGA bitstreams are stored compressed under /fpga to conserve internal flash. They stream from the host the first time a band is used. The Proxmark5's GW1N-4B is different: its gateware lives in the FPGA's own internal config flash and autoboots at power-on (LF and HF logic are both resident), so there is no host-streamed bitstream and no /fpga store. The AT32F435 reaches the frontend over a bit-banged command channel plus an SPI4/SSC sample bus; capability bits currently advertise LF and HF read (hal_rfid_caps() = LF_READ | HF_READ).

Quickstart

rfid is a command inside the Fantasi host CLI. Running it launches the on-device app and drops you into an interactive rfid> prompt with history and TAB completion:

fantasi> rfid
rfid> read mfc
rfid> read t5577
rfid> exit

The command requires a protobuf connection: use fantasi --usb or fantasi --ble. It is not available over the legacy --serial transport. The web Launcher exposes the same inline terminal, including command history, completion, selectable output, stop keys, and the device's live status output.

For scripting, pass a single command with -c and it runs once and exits:

fantasi --usb -c "rfid read mfc"
fantasi --usb -c "rfid emulate lf-t55xx-1A2B3C4D-dump.json"

Only one application can run at a time. If an earlier RFID session did not exit cleanly, return to the main prompt and run kill before launching it again.

Example:

read mfc reads a MIFARE Classic card end to end: it profiles the PRNG, tries known keys from the dictionaries, then authenticates and dumps every block. read t5577 gives you a complete dump of an LF T5577; it decodes the config block to learn how many data blocks to expect. A bare read <proto> reads all blocks, and read <proto> -b <n> reads one. Type list any time to see the protocol tree, or help for the verbs.

Commands

Type help for the command list, help <command> for its options and examples, or use -h / --help after a command. TAB completion covers commands, protocols, and applicable subcommands.

CommandDescription
search [band]Scan for nearby tags; bare search scans every band
read <protocol> [-b <block>] [-k <key>] [-s [file]]Read one block or dump a whole tag
write <protocol> -b <block> -d <hex> [-k <key>]Write one tag block
emulate <dump.json>Emulate a card from a saved dump
sniff <protocol>Passively capture a reader-to-card exchange
trace [clear]Show or clear the captured frame trace
collect <protocol> <card/reader/sniff> [-u <UID>] [-k <key>]Capture nonces or sniffed keys
raw <protocol> [-c] [-k] [-s] <hex>Send a raw protocol frame
field on/off/statusControl or inspect the reader carrier
list [band/subcategory]List protocols and available operations
help [command]Show general or command-specific help
exitLeave the RFID app

read, write, emulate, collect, list, and help are host-side abstractions. The remaining commands dispatch to the on-device RFID app.

Protocols

list

list presents a band > technology > protocol tree and shows which operations are available for the connected target. Pass a band or subcategory to filter it, such as list lf, list hf, or list nfca.

rfid> list
LF
  125-500 kHz
    t5577  T5577                    read write
HF · 13.56 MHz
  NFC A · ISO14443-A
    nfca   generic                  sniff raw
    mfc    MIFARE Classic           read sniff raw emulate collect
    mfp    MIFARE Plus              sniff raw
    ul     Ultralight               read sniff raw
    ulc    Ultralight C             read sniff raw
    ulaes  Ultralight AES           sniff raw
    mfdes  DESFire                  sniff raw
  NFC B · ISO14443-B
    (none yet)
  NFC F · FeliCa
    (none yet)
  NFC V · ISO15693
    (none yet)
UHF
  860-960 MHz
    (none yet)

The client colours built operations green and adds * to operations whose module was not built for the connected target architecture. Hardware without a required frontend capability reports that when the command is run.

search [band] looks for nearby tags and prints each result. Bare search checks every implemented band in order; search hf or search lf limits the scan.

read

read <protocol> dumps an entire tag. Add -b <block> to read one block, -k <key> to provide an authentication key or password, and -s [file] to save the result as JSON. When no filename follows -s, the client generates one.

rfid> read mfc
rfid> read mfc -b 4 -k FFFFFFFFFFFF
rfid> read t5577 -b 4
rfid> read mfc -s dump.json

read t5577 first decodes the configuration block, then reads the complete tag. read mfc profiles the card's PRNG, tries the bundled and card-specific key dictionaries, authenticates each sector, and reads all 64 blocks. Long reads show live phase and block/sector status in place instead of appearing to hang.

write

write <protocol> -b <block> -d <hex> [-k <key>] writes one block. The data width is validated for the selected protocol.

rfid> write t5577 -b 4 -d 1A2B3C4D

raw

raw <protocol> [-c] [-k] [-s] <hex> sends a raw frame and prints the decoded response and trace.

FlagEffect
-cAppend the protocol CRC
-kKeep the field on for a follow-up exchange
-sSelect the tag before sending the frame
rfid> raw mfc -s -c 3000

field

field on enables the reader carrier and leaves it on, field off disables it, and field status reports its current state.

trace

trace prints the raw frames accumulated during the current session. trace clear empties the trace.

The protocol tree reserves three bands - LF, HF, and UHF - even when a band does not yet contain an implemented protocol.

Sniffing

sniff <protocol> passively watches a live reader-to-card exchange with the device's own field off. Traffic scrolls as it arrives. Press any key to finish the capture, or ^C (Control-C) to abort the app.

rfid> sniff mfc

Each captured frame is annotated. The host recognises the protocol you named and labels the commands inline (SELECT, ANTICOLL, READ blk 4, AUTH-A blk 7, WRITE page 6, and so on), turning a hex trace into something readable. Bad CRCs and parity errors are flagged in place. For MIFARE Classic, mfkey64 runs inline against the trace: a captured authentication is enough to recover the sector key, with no separate cracking step.

Where the frontend can measure it, a capture opens with a coupling reading that grades the sniff quality as strong, fair or weak (green, yellow, red). On the Flipper this comes from the ST25R3916's External Field Detector.

That same measurement feeds an adaptive first-stage gain, so a reader stays in range as its distance drifts; without it the signal would degrade up close and fade out further away. A device that cannot sense field strength reports the coupling as unknown.

While a capture is running, the terminal deliberately withholds the next rfid> prompt. It prints the module's stopped/completion message first, then shows the prompt when the command is actually ready for more input.

Emulation

emulate <dump.json> plays a saved card back on targets whose list output marks emulation available. The current implementation supports MIFARE Classic 1K, including reader authentication and block reads, and runs until you press a key or ^C.

rfid> emulate hf-mfc-A1B2C3D4-dump.json

The client parses the JSON dump, uploads the 1 KiB card image, and reports its UID, populated block count, and PRNG profile before starting. Its frame delay time is close to that of a physical card. For background on the timing, see the Chameleon Ultra technical whitepaper.

Key collection

collect mfc card gathers a Hardnested nonce set from a presented MIFARE Classic card and saves it as mfc.log for the host-side solver. -u <UID> can target a 4- or 7-byte UID, while -k <key> seeds a known six-byte key.

collect mfc sniff watches live reader/card authentications, runs mfkey64 as they arrive, and stores recovered keys in /nfc/mfc.dict for later read mfc commands. Press a key to stop the capture and finalize the dictionary.

rfid> collect mfc card
rfid> collect mfc sniff

The reader collection mode is reserved for card impersonation and is not yet implemented.

Dump files

read -s writes dump files when you read a card. It stays close enough to Proxmark3's own JSON format that dumps interchange for common card types. With no explicit filename the client names the dump from its band, protocol, and UID. MIFARE Classic dumps include all block data, recovered trailer keys, and the detected PRNG class; emulate reads that JSON back.

Modularity

The resident RFID app is a small loader. Readers, writers, sniffers, collectors, and emulators are separate ELF modules loaded only when their command needs them. The app first looks for installed modules on external storage and under /modules; when the host or web Launcher supplies one on demand, it is uploaded to /ramfs, run, and removed afterward. Only the active feature module occupies RAM.

FPGA resources are different. Only the Proxmark3 requests compressed bitstreams from the host and caches them under /fpga. Proxmark5 gateware is already in the FPGA's configuration flash and is never uploaded by the RFID client.

★ DREAM // HACK ★