👋 Introduction
Hey folks, welcome back. Today I’m showing you something that started as a small experiment, and kind of turned into its own project.
I originally wanted to play around with RFID and NFC because I thought it would be a great feature to add to my ESP32-DIV project. But as I kept tweaking and testing, it turned into something bigger, so now, we have NullTag: a DIY RFID and NFC toolkit built on the ESP32.
As of recording this, I haven’t decided whether I’ll share the source code or not. It’s super experimental right now—lots of rough edges, a few bugs—but I still think it’s worth showing you what it can do.
So today, we’ll walk through the features, talk about what works well, and also what doesn’t. Let’s dive in.
🔩 Hardware Overview
At the core, we’ve got the ESP32 — it handles all the logic and communication. That’s paired with a PN532 RFID/NFC module connected over SPI, which reads most common 13.56 MHz tags like MIFARE Classic and NTAG, with a read range of about 2 to 5 centimeters.
The display is a 0.96-inch OLED screen using I2C. It’s compact, low power, and perfect for showing tag scans, signal strength, and system status in real time.
To keep everything powered reliably, I’m using an AM1117 voltage regulator to step down battery voltage to a stable 3.3V — important if you’re running this from a Li-Po cell.
A TP4056 charging module handles battery charging and includes protection features. You just plug it in via micro USB, and it charges safely.
For programming and Serial monitoring, there’s a CP2102 USB to UART bridge. It makes flashing firmware and debugging straightforward.
I also threw in a WS2812 Neopixel RGB LED for status indication — like changing colors when a tag is detected, an error occurs, or the device is jamming.
⚠️ Trade-offs and Limitations
It’s not all sunshine, though. The PN532’s range is limited, so you have to hold the tag close, usually within 3–4 cm.
The ESP32 can draw a lot of power, and not every USB port can handle it. Sometimes I needed an external 3.3V source for stable operation.
And while the SD card slot is useful for storing dumps, it caused some crashes, especially during heavy operations like decoding access bits. I’ve disabled it by default to keep things stable. Also, pay close attention to SPI pin assignments if you wire one in.
That said, once it’s set up, the platform is surprisingly capable.
💾 Software and Features
The OLED interface shows a menu with 10 main features. You can use the physical buttons or control it via Serial. Here’s a quick overview:
🔍 1. Read Card
Reads a tag’s UID and basic info — works with MIFARE Classic, NTAG, Ultralight, and DESFire. Great for quick tag scans, but won’t read protected sectors unless you already have keys.
🧬 2. Clone Card
Copies a tag’s UID and emulates it using the PN532. Works with MIFARE Classic, but protected data needs known keys. Useful for backup and compatibility testing — but only use it ethically.
🧹 3. Erase Card
Wipes writable tags back to blank. Great for reusing test cards. Just be careful — once it’s wiped, it’s permanent. And locked tags need proper keys to be erased.
💽 4. SD Card
Manage tag dumps and stored files. Useful, but can destabilize the ESP32. Requires proper wiring and FAT32 formatting.
📥 5. Dump Card
Reads every block of a MIFARE Classic tag — keys, access bits, data — and outputs it via Serial or SD card. Slow on large tags and needs valid keys.
🧾 6. Card Info
Quickly identifies tag type, storage size, lock status, and backdoor presence. Helpful for initial tag profiling.
🛡️ 7. Decode Access
Decodes MIFARE Classic access bits to reveal read/write permissions. Requires known keys. Now outputs via Serial for stability.
🔐 9. Brute Key
Tries common default keys on Classic tags to find access. Slow and limited to simple key sets — good for auditing weak tags.
📛 10. Jam Reader
Simulates a misbehaving tag that spams readers with malformed responses. Effective on cheap readers, but legally restricted. Use in lab conditions only.
💣 Bonus: Tag Virus
This feature writes bad access bits to a tag, essentially corrupting it to crash some readers. It’s meant for testing robustness, not for trolling.
Use the writeDisruptiveData()
function to flash all 16 sectors with junk. I tested it on an RC522 module, and sure enough — instant crash.
But again, this is strictly for research. Don’t use it in real-world systems.
🛠️ Use Cases
You can:
- Test your own RFID locks
- Build NFC demo interactions
- Explore MIFARE Classic security
- Learn tag structure and protocol behavior
It’s best suited for controlled environments and learning, not for deployment in critical systems. The range and reliability are good enough for lab use, but not perfect.
🎯 Final Thoughts
Is it polished? Not really.
Is it fun and useful? Absolutely.