#NDEF

2024-02-11

Yesterday I was playing around with my #NFC tag.
The tag written by the Android version of "NFC Tools" couldn't be read by the desktop version.
Also, some Python tooling for reading #NDEF messages couldn't parse the message - apparently it was invalid / malformed?
Still, I learned that these NTAGs are basically Mifare Ultralight tags - when it comes to libnfc tooling.

Tod Kurt (todbot)todbot
2023-03-10

This new "Dynamic NFC Tag" board from looks pretty neat. Acts like a programmable NDEF NFC for use w/ iPhone & Android and has chainable Qwiic / StemmaQT I2C connectors sparkfun.com/products/21274

2023-01-16

@alan

Not any new app I've written, but both #MiFare classic and #NTAG formats can carry an #NDEF payload; there are many different payloads two of which are WiFi connections and contact cards. NTAG is usually the better choice as it is almost universally readable whereas only certain Android phones can read MiFare tags.

Easiest way to do this is score some writable NTAG cards/chips and use NFC Tools (app) on your phone to write the payload. Read and emulate the tag you write on Flipper :)

Terence Eden’s Blogblog@shkspr.mobi
2019-01-29

Hidden Data in NFC Tags

shkspr.mobi/blog/2019/01/hidde

I've just got a set of wearable NFC tags, and I've discovered something interesting about the way data is stored on them.

tl;dr Overwriting a tag can leave old data intact, and still readable.

Here's the decoded memory layout of a tag with data written to it. In this case, a (failed) experiment at storing a JavaScript pop-up.

# NDEF message:
[00] D1 01 7D 55 00 64 61 74 61 3A 74 65 78 74 2F 68 |.␁}U␀data:text/h|
[10] 74 6D 6C 3B 63 68 61 72 73 65 74 3D 75 74 66 2D |tml;charset=utf-|
[20] 38 2C 25 33 43 25 32 31 44 4F 43 54 59 50 45 25 |8,%3C%21DOCTYPE%|
[30] 32 30 68 74 6D 6C 25 33 45 25 33 43 62 6F 64 79 |20html%3E%3Cbody|
[40] 25 33 45 25 33 43 73 63 72 69 70 74 25 33 45 61 |%3E%3Cscript%3Ea|
[50] 6C 65 72 74 25 32 38 25 32 32 68 69 25 32 32 25 |lert%28%22hi%22%|
[60] 32 39 25 33 42 25 33 43 25 32 46 73 63 72 69 70 |29%3B%3C%2Fscrip|
[70] 74 25 33 45 25 33 43 25 32 46 62 6F 64 79 25 33 |t%3E%3C%2Fbody%3|
[80] 45                                              |E               |

As the experiment didn't work, I decided to rewrite the tag with some much shorter data. Here's the new message.

# NDEF message:
[00] D1 02 36 53 70 91 01 12 55 00 68 74 74 70 73 3A |.␂6Sp.␁␒U␀https:|
[10] 2F 2F 65 64 65 6E 74 2E 74 65 6C 51 01 1C 54 02 |//edent.telQ␁␜T␂|
[20] 65 6E 54 65 72 65 6E 63 65 27 73 20 63 6F 6E 74 |enTerence's␠cont|
[30] 61 63 74 20 64 65 74 61 69 6C 73                |act␠details     |

But that's not the whole story! The above is the NDEF (NFC Data Exchange Format) message which has been decoded. Let's look at the full memory layout:

# Memory content:
[00] *  04:01:2A A7 (UID0-UID2, BCC0)
[01] *  62:F4:48:81 (UID3-UID6)
[02] .  5F 48 00 00 (BCC1, INT, LOCK0-LOCK1)
[03] .  E1:10:12:00 (OTP0-OTP3)
[04] .  03 3B D1 02 |␃;.␂|
[05] .  36 53 70 91 |6Sp.|
[06] .  01 12 55 00 |␁␒U␀|
[07] .  68 74 74 70 |http|
[08] .  73 3A 2F 2F |s://|
[09] .  65 64 65 6E |eden|
[0A] .  74 2E 74 65 |t.te|
[0B] .  6C 51 01 1C |lQ␁␜|
[0C] .  54 02 65 6E |T␂en|
[0D] .  54 65 72 65 |Tere|
[0E] .  6E 63 65 27 |nce'|
[0F] .  73 20 63 6F |s␠co|
[10] .  6E 74 61 63 |ntac|
[11] .  74 20 64 65 |t␠de|
[12] .  74 61 69 6C |tail|
[13] .  73 FE 00 00 |s.␀␀|
[14] .  64 79 25 33 |dy%3|
[15] .  45 25 33 43 |E%3C|
[16] .  73 63 72 69 |scri|
[17] .  70 74 25 33 |pt%3|
[18] .  45 61 6C 65 |Eale|
[19] .  72 74 25 32 |rt%2|
[1A] .  38 25 32 32 |8%22|
[1B] .  68 69 25 32 |hi%2|
[1C] .  32 25 32 39 |2%29|
[1D] .  25 33 42 25 |%3B%|
[1E] .  33 43 25 32 |3C%2|
[1F] .  46 73 63 72 |Fscr|
[20] .  69 70 74 25 |ipt%|
[21] .  33 45 25 33 |3E%3|
[22] .  43 25 32 46 |C%2F|
[23] .  62 6F 64 79 |body|
[24] .  25 33 45 FE |%3E.|
[25] .  00 00 00 00 |␀␀␀␀|
[26] .  00 00 00 00 |␀␀␀␀|
[27] .  00 00 00 00 |␀␀␀␀|
[28] .  00 00 00 BD (LOCK2-LOCK4, CHK)
[29] .  04 00 00 FF (CFG, MIRROR, AUTH0)
[2A] .  00 05 -- -- (ACCESS)
[2B] +P FF FF FF FF (PWD0-PWD3)
[2C] +P 00 00 -- -- (PACK0-PACK1)

You can see the new data is at the start, then there is a gap, and then the remainder of the old data is present!

This is due to this line:

[05] .  36 53 70 91 |6Sp.|

The 36 is the Payload Length - in this case 0x36 bytes of data. In other words, the header says "This data is 54 bytes in length".

Most phones' built-in NFC readers grab the first part and correctly interpret it and stop there.

But using a reader like NXP Tag Info will allow you to see all of the data hidden in the tag.

So, go around scanning NFC tags (if you can find any), and see what leftover data is still present.

To ensure this doesn't happen to you, make sure to erase and format any tags before rewriting them.

#ndef #nfc #rfid #security

Client Info

Server: https://mastodon.social
Version: 2025.04
Repository: https://github.com/cyevgeniy/lmst