changed nfc decode to handle external records and if the record happens to be estonian ekaart also ASN1 decode it

This commit is contained in:
iceman1001 2023-05-05 12:33:14 +02:00
commit 3e293b4bc8
3 changed files with 56 additions and 11 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Changed `nfc decode` - now handles EXTERNAL RECORDS better (@iceman1001)
- Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001) - Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001)
- Added new standalone mode `LF_MULTIHID` - HID26 (H1031) multi simulator (@flamebarke) - Added new standalone mode `LF_MULTIHID` - HID26 (H1031) multi simulator (@flamebarke)
- Changed `hf 14b dump --ns` - now supports `no save` of card memory (@iceman1001) - Changed `hf 14b dump --ns` - now supports `no save` of card memory (@iceman1001)

View file

@ -39,8 +39,6 @@
#define NDEF_VCARDTEXT "text/vcard" #define NDEF_VCARDTEXT "text/vcard"
#define NDEF_XVCARDTEXT "text/x-vcard" #define NDEF_XVCARDTEXT "text/x-vcard"
static const char *TypeNameFormat_s[] = { static const char *TypeNameFormat_s[] = {
"Empty Record", "Empty Record",
"Well Known Record", "Well Known Record",
@ -295,8 +293,8 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) {
bool sigURI = sig[indx] & 0x80; bool sigURI = sig[indx] & 0x80;
indx++; indx++;
PrintAndLogEx(SUCCESS, "\tSignature type... " _YELLOW_("%s"), ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); PrintAndLogEx(SUCCESS, "\tType...... " _YELLOW_("%s"), ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA]));
PrintAndLogEx(SUCCESS, "\tSignature URI.... " _YELLOW_("%s"), (sigURI ? "present" : "not present")); PrintAndLogEx(SUCCESS, "\tURI....... " _YELLOW_("%s"), (sigURI ? "present" : "not present"));
if (sigType == 0 && sigURI == false) { if (sigType == 0 && sigURI == false) {
PrintAndLogEx(INFO, "\tRecord should be considered a start marker"); PrintAndLogEx(INFO, "\tRecord should be considered a start marker");
@ -327,7 +325,7 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) {
PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(sval + 32 - slen, slen)); PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(sval + 32 - slen, slen));
} }
} else { } else {
PrintAndLogEx(SUCCESS, "\tSignature [%u]...", intsiglen); PrintAndLogEx(SUCCESS, "\tData [%u]...", intsiglen);
print_hex_noascii_break(&sig[indx], intsiglen, 32); print_hex_noascii_break(&sig[indx], intsiglen, 32);
} }
@ -817,7 +815,7 @@ static int ndefDecodeMime_bt(NDEFHeader_t *ndef) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type); PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type);
uint16_t ooblen = (ndef->Payload[1] << 8 | ndef->Payload[0]); uint16_t ooblen = MemBeToUint2byte(ndef->Payload);
PrintAndLogEx(INFO, "OOB data len.... %u", ooblen); PrintAndLogEx(INFO, "OOB data len.... %u", ooblen);
PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(ndef->Payload + 2, 6)); PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(ndef->Payload + 2, 6));
// Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit // Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit
@ -856,6 +854,38 @@ static int ndefDecodeMime_bt(NDEFHeader_t *ndef) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
// https://raw.githubusercontent.com/haldean/ndef/master/docs/NFCForum-TS-RTD_1.0.pdf
static int ndefDecodeExternal_record(NDEFHeader_t *ndef) {
if (ndef->TypeLen == 0) {
PrintAndLogEx(INFO, "no type");
return PM3_SUCCESS;
}
if (ndef->PayloadLen == 0) {
PrintAndLogEx(INFO, "no payload");
return PM3_SUCCESS;
}
PrintAndLogEx(INFO
, " URN... " _GREEN_("urn:nfc:ext:%.*s")
, (int)ndef->TypeLen
, ndef->Type
);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Payload [%u]...", ndef->PayloadLen);
print_hex_noascii_break(ndef->Payload, ndef->PayloadLen, 32);
// do a character check?
if (!strncmp((char *)ndef->Type, "pilet.ee:ekaart:2", ndef->TypeLen)) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _GREEN_("Ekaart detected") " - Trying ASN1 decode...");
asn1_print(ndef->Payload, ndef->PayloadLen, " ");
}
return PM3_SUCCESS;
}
static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) { static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) {
PrintAndLogEx(INFO, ""); PrintAndLogEx(INFO, "");
@ -863,7 +893,7 @@ static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) {
case tnfEmptyRecord: case tnfEmptyRecord:
PrintAndLogEx(INFO, "Empty Record"); PrintAndLogEx(INFO, "Empty Record");
if (ndef->TypeLen != 0 || ndef->IDLen != 0 || ndef->PayloadLen != 0) { if (ndef->TypeLen != 0 || ndef->IDLen != 0 || ndef->PayloadLen != 0) {
PrintAndLogEx(FAILED, "unexpected data in TNF_EMPTY record"); PrintAndLogEx(FAILED, "unexpected data in empty record");
break; break;
} }
break; break;
@ -959,20 +989,33 @@ static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) {
} }
case tnfAbsoluteURIRecord: case tnfAbsoluteURIRecord:
PrintAndLogEx(INFO, "Absolute URI Record"); PrintAndLogEx(INFO, "Absolute URI Record");
PrintAndLogEx(INFO, " payload : %.*s", (int)ndef->PayloadLen, ndef->Payload); PrintAndLogEx(INFO, " payload : " _YELLOW_("%.*s"), (int)ndef->PayloadLen, ndef->Payload);
break; break;
case tnfExternalRecord: case tnfExternalRecord:
PrintAndLogEx(INFO, "External Record"); PrintAndLogEx(INFO, "External Record");
PrintAndLogEx(INFO, "- decoder to be impl -"); ndefDecodeExternal_record(ndef);
break; break;
case tnfUnknownRecord: case tnfUnknownRecord:
PrintAndLogEx(INFO, "Unknown Record"); PrintAndLogEx(INFO, "Unknown Record");
PrintAndLogEx(INFO, "- decoder to be impl -"); if (ndef->TypeLen != 0) {
PrintAndLogEx(FAILED, "unexpected type field");
break;
}
break; break;
case tnfUnchangedRecord: case tnfUnchangedRecord:
PrintAndLogEx(INFO, "Unchanged Record"); PrintAndLogEx(INFO, "Unchanged Record");
PrintAndLogEx(INFO, "- decoder to be impl -"); PrintAndLogEx(INFO, "- decoder to be impl -");
break; break;
case tnfReservedRecord:
PrintAndLogEx(INFO, "Reserved Record");
if (ndef->TypeLen != 0) {
PrintAndLogEx(FAILED, "unexpected type field");
break;
}
break;
default:
PrintAndLogEx(FAILED, "unexpected tnf value... 0x%02x", ndef->TypeNameFormat);
break;
} }
PrintAndLogEx(INFO, ""); PrintAndLogEx(INFO, "");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -31,7 +31,8 @@ typedef enum {
tnfAbsoluteURIRecord = 0x03, tnfAbsoluteURIRecord = 0x03,
tnfExternalRecord = 0x04, tnfExternalRecord = 0x04,
tnfUnknownRecord = 0x05, tnfUnknownRecord = 0x05,
tnfUnchangedRecord = 0x06 tnfUnchangedRecord = 0x06,
tnfReservedRecord = 0x07,
} TypeNameFormat_t; } TypeNameFormat_t;
typedef enum { typedef enum {