diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 4dad816af..2a1c3dfb2 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -18,9 +18,9 @@ #include "cmdhf14a.h" #include #include -#include "cmdparser.h" // command_t -#include "commonutil.h" // ARRAYLEN -#include "comms.h" // clearCommandBuffer +#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "comms.h" // clearCommandBuffer #include "cmdtrace.h" #include "cliparser.h" #include "cmdhfmf.h" @@ -29,16 +29,18 @@ #include "emv/emvcore.h" #include "ui.h" #include "crc16.h" -#include "util_posix.h" // msclock +#include "util_posix.h" // msclock #include "aidsearch.h" -#include "cmdhf.h" // handle HF plot +#include "cmdhf.h" // handle HF plot #include "cliparser.h" -#include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A -#include "iso7816/apduinfo.h" // GetAPDUCodeDescription -#include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint -#include "cmdnfc.h" // print_type4_cc_info -#include "fileutils.h" // saveFile -#include "atrs.h" // getATRinfo +#include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A +#include "iso7816/apduinfo.h" // GetAPDUCodeDescription +#include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint +#include "cmdnfc.h" // print_type4_cc_info +#include "fileutils.h" // saveFile +#include "atrs.h" // getATRinfo +#include "desfire.h" // desfire enums +#include "mifare/desfirecore.h" // desfire context static bool APDUInFramingEnable = true; @@ -2692,7 +2694,6 @@ int CmdHF14ANdefRead(const char *Cmd) { keep_field_on = true; // --------------- CC file reading ---------------- - uint8_t aSELECT_FILE_CC[30]; int aSELECT_FILE_CC_n = 0; if (backward_compatibility_v1) { @@ -2733,7 +2734,10 @@ int CmdHF14ANdefRead(const char *Cmd) { memcpy(cc_data, response, sizeof(cc_data)); uint8_t file_id[2] = {cc_data[9], cc_data[10]}; - print_type4_cc_info(cc_data, sizeof(cc_data)); + if (verbose) { + print_type4_cc_info(cc_data, sizeof(cc_data)); + } + uint16_t max_rapdu_size = (cc_data[3] << 8 | cc_data[4]) - 2; max_rapdu_size = max_rapdu_size < sizeof(response) - 2 ? max_rapdu_size : sizeof(response) - 2; @@ -2760,7 +2764,6 @@ int CmdHF14ANdefRead(const char *Cmd) { } // read first 2 bytes to get NDEF length - uint8_t aREAD_NDEF[30]; int aREAD_NDEF_n = 0; param_gethex_to_eol("00b0000002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n); @@ -2836,21 +2839,442 @@ int CmdHF14ANdefRead(const char *Cmd) { return PM3_SUCCESS; } +int CmdHF14ANdefFormat(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a ndefformat", + "Format ISO14443-a Tag as a NFC tag with Data Exchange Format (NDEF)", + "hf 14a ndefformat\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_litn("v", "verbose", 0, 2, "show technical data"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool verbose = arg_get_lit(ctx, 1); + CLIParserFree(ctx); + + if (g_session.pm3_present == false) + return PM3_ENOTTY; + + bool activate_field = true; + bool keep_field_on = false; + uint8_t response[PM3_CMD_DATA_SIZE]; + int resplen = 0; + + SetAPDULogging(false); + + // step 1 - Select NDEF Tag application + uint8_t aSELECT_AID[80]; + int aSELECT_AID_n = 0; + param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n); + int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen); + + if (res != PM3_SUCCESS) { + return res; + } + + if (resplen < 2) { + return PM3_ESOFT; + } + + bool have_application = true; + uint16_t sw = get_sw(response, resplen); + if (sw != 0x9000) { + have_application = false; + PrintAndLogEx(INFO, "no NDEF application found"); + } else { + PrintAndLogEx(INFO, "found ndef application"); + } + + + // setup desfire authentication context + uint8_t empty_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + DesfireContext_t dctx; + dctx.secureChannel = DACNone; + DesfireSetKey(&dctx, 0, T_DES, empty_key); + DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0); + DesfireSetCommandSet(&dctx, DCCNativeISO); + DesfireSetCommMode(&dctx, DCMPlain); + + // step 1 - create application + if (have_application == false) { + // "hf mfdes createapp --aid 000001 --fid E110 --ks1 0B --ks2 A1 --dfhex D2760000850101 -t des -n 0 -k 0000000000000000" + PrintAndLogEx(INFO, "creating NDEF application..."); + + // authenticae first to AID 00 00 00 + res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000000, false, verbose); + if (res != PM3_SUCCESS) { + DropField(); + PrintAndLogEx(INFO, "failed empty auth.."); + return res; + } + + // create application + uint8_t dfname[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}; + uint8_t ks1 = 0x0B; + uint8_t ks2 = 0xA1; // bit FileID in ks2 + uint32_t appid = 0x0000001; + uint16_t fileid = 0xE110; + uint8_t data[250] = {0}; + size_t datalen = 0; + + DesfireAIDUintToByte(appid, &data[0]); + data[3] = ks1; + data[4] = ks2; + Uint2byteToMemLe(&data[5], fileid); + memcpy(&data[7], dfname, sizeof(dfname)); + datalen = 14; + + if (verbose) { + PrintAndLogEx(INFO, "---------------------------"); + PrintAndLogEx(INFO, _CYAN_("Creating Application using:")); + PrintAndLogEx(INFO, "AID........... 0x%02X%02X%02X", data[2], data[1], data[0]); + PrintAndLogEx(INFO, "Key Set 1..... 0x%02X", data[3]); + PrintAndLogEx(INFO, "Key Set 2..... 0x%02X", data[4]); + PrintAndLogEx(INFO, "ISO file ID... %s", (data[4] & 0x20) ? "enabled" : "disabled"); + if ((data[4] & 0x20)) { + PrintAndLogEx(INFO, "ISO file ID... 0x%04X", MemLeToUint2byte(&data[5])); + PrintAndLogEx(INFO, "DF Name[%02d] %s | %s\n", 7, sprint_ascii(dfname, sizeof(dfname)), sprint_hex(dfname, sizeof(dfname))); + } + PrintKeySettings(data[3], data[4], true, true); + PrintAndLogEx(INFO, "---------------------------"); + } + + res = DesfireCreateApplication(&dctx, data, datalen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Desfire application %06x successfully " _GREEN_("created"), appid); + + + // step 2 - create capability container (CC File) + + // authenticae to the new AID 00 00 01 + uint8_t aes_key[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + dctx.secureChannel = DACNone; + DesfireSetKey(&dctx, 0, T_AES, aes_key); + DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0); + DesfireSetCommandSet(&dctx, DCCNativeISO); + DesfireSetCommMode(&dctx, DCMPlain); + res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose); + if (res != PM3_SUCCESS) { + DropField(); + PrintAndLogEx(INFO, "failed aid auth.."); + return res; + } + + // hf mfdes createfile --aid 000001 --fid 01 --isofid E103 --amode plain --size 00000F + // --rrights free --wrights key0 --rwrights key0 --chrights key0 + // -n 0 -t aes -k 00000000000000000000000000000000 -m plain + uint8_t fid = 0x01; + uint16_t isofid = 0xE103; + uint32_t fsize = 0x0F; + uint8_t filetype = 0x00; // standard file + + // file access mode: plain 0x00 + // read access: free 0x0E + // write access: key0 0x00 + // r/w access: key0 0x00 + // change access: key0 0x00 + memset(data, 0x00, sizeof(data)); + datalen = 0; + + data[0] = fid; + data[1] = isofid & 0xff; + data[2] = (isofid >> 8) & 0xff; + datalen = 3; + + uint8_t *settings = &data[datalen]; + settings[0] = 0x00; + datalen++; + + DesfireEncodeFileAcessMode(&settings[1], 0x0E, 0x00, 0x00, 0x00) ; + datalen += 2; + + Uint3byteToMemLe(&data[datalen], fsize); + datalen += 3; + + if (verbose) { + PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); + } + + DesfirePrintCreateFileSettings(filetype, data, datalen); + + res = DesfireCreateFile(&dctx, filetype, data, datalen, true); // check length only if we dont use raw mode + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid); + + + + // hf mfdes write --aid 000001 --fid 01 -d 000F20003B00340406E10400FF00FF + // -n 0 -t aes -k 00000000000000000000000000000000 -m plain + res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose); + if (res != PM3_SUCCESS) { + DropField(); + PrintAndLogEx(INFO, "failed aid auth.."); + return res; + } + + uint8_t fnum = 0x01; + uint32_t offset = 0; + uint8_t cc_data[] = {0x00, 0x0F, 0x20, 0x00, 0x3B, 0x00, 0x34, 0x04, 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00}; + + res = DesfireWriteFile(&dctx, fnum, offset, sizeof(cc_data), cc_data); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire WriteFile command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (verbose) { + PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum); + } + + + + // step 3 - create NDEF record file + // hf mfdes write --aid 000001 --fid 02 -d 000CD1010855016E78702E636F6DFE + // -n 0 -t aes -k 00000000000000000000000000000000 -m plain + + fid = 0x02; + isofid = 0xE104; + fsize = 0xFF; + filetype = 0x00; // standard file + + // file access mode: plain 0x00 + // read access: free 0x0E + // write access: key0 0x00 + // r/w access: key0 0x00 + // change access: key0 0x00 + memset(data, 0x00, sizeof(data)); + datalen = 0; + + data[0] = fid; + data[1] = isofid & 0xff; + data[2] = (isofid >> 8) & 0xff; + datalen = 3; + + settings = &data[datalen]; + settings[0] = 0x00; + datalen++; + + DesfireEncodeFileAcessMode(&settings[1], 0x0E, 0x00, 0x00, 0x00) ; + datalen += 2; + + Uint3byteToMemLe(&data[datalen], fsize); + datalen += 3; + + if (verbose) { + PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); + } + + DesfirePrintCreateFileSettings(filetype, data, datalen); + + res = DesfireCreateFile(&dctx, filetype, data, datalen, true); // check length only if we dont use raw mode + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid); + + DropField(); + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "finished"); + return PM3_SUCCESS; +} + + +int CmdHF14ANdefWrite(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a ndefwrite", + "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.\n", + "hf 14a ndefwrite -d 0300FE -> write empty record to tag\n" + "hf 14a ndefwrite -f myfilename\n" + "hf 14a ndefwrite -d 003fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("d", NULL, "", "raw NDEF hex bytes"), + arg_str0("f", "file", "", "write raw NDEF file to tag"), + arg_lit0("p", NULL, "fix NDEF record headers / terminator block if missing"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + uint8_t raw[256] = {0}; + int rawlen = 0; + CLIGetHexWithReturn(ctx, 1, raw, &rawlen); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + + bool fix_msg = arg_get_lit(ctx, 3); + bool verbose = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + if (g_session.pm3_present == false) { + return PM3_ENOTTY; + } + + if ((rawlen && fnlen) || (rawlen == 0 && fnlen == 0)) { + PrintAndLogEx(WARNING, "Please specify either raw hex or filename"); + return PM3_EINVARG; + } + + int res = PM3_SUCCESS; + int32_t bytes = rawlen; + + // read dump file + if (fnlen) { + uint8_t *dump = NULL; + size_t bytes_read = 0; + res = pm3_load_dump(filename, (void **)&dump, &bytes_read, sizeof(raw)); + if (res != PM3_SUCCESS) { + return res; + } + memcpy(raw, dump, bytes_read); + bytes = bytes_read; + free(dump); + } + + if (verbose) { + PrintAndLogEx(INFO, "Num of bytes... %i (raw %i)", bytes, rawlen); + } + + // Has raw bytes ndef message header?bytes + switch (raw[0]) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0xFD: + case 0xFE: + break; + default: { + if (fix_msg == false) { + PrintAndLogEx(WARNING, "raw NDEF message doesn't have a proper header, continuing..."); + } else { + if (bytes + 2 > sizeof(raw)) { + PrintAndLogEx(WARNING, "no room for header, exiting..."); + return PM3_EMALLOC; + } + uint8_t tmp_raw[256]; + memcpy(tmp_raw, raw, sizeof(tmp_raw)); + raw[0] = 0x03; + raw[1] = bytes; + memcpy(raw + 2, tmp_raw, sizeof(raw) - 2); + bytes += 2; + PrintAndLogEx(SUCCESS, "Added generic message header (0x03)"); + } + } + } + + // Has raw bytes ndef a terminator block? + if (raw[bytes - 1] != 0xFE) { + if (fix_msg == false) { + PrintAndLogEx(WARNING, "raw NDEF message doesn't have a terminator block, continuing..."); + } else { + + if (bytes + 1 > sizeof(raw)) { + PrintAndLogEx(WARNING, "no room for terminator block, exiting..."); + return PM3_EMALLOC; + } + raw[bytes] = 0xFE; + bytes++; + PrintAndLogEx(SUCCESS, "Added terminator block (0xFE)"); + } + } + + if (verbose) { + PrintAndLogEx(INFO, "Num of Bytes... %u", bytes); + print_buffer(raw, bytes, 0); + } + + + // setup desfire authentication context + // authenticae to the new AID 00 00 01 + uint8_t aes_key[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + DesfireContext_t dctx; + dctx.secureChannel = DACNone; + DesfireSetKey(&dctx, 0, T_AES, aes_key); + DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0); + DesfireSetCommandSet(&dctx, DCCNativeISO); + DesfireSetCommMode(&dctx, DCMPlain); + res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose); + if (res != PM3_SUCCESS) { + DropField(); + PrintAndLogEx(INFO, "failed aid auth.."); + return res; + } + + // write ndef file + + // hf mfdes write --aid 000002 --fid 02 - + // -n 0 -t aes -k 00000000000000000000000000000000 -m plain + uint8_t fnum = 0x02; + uint32_t offset = 0; + + res = DesfireWriteFile(&dctx, fnum, offset, bytes, raw); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire WriteFile command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (verbose) { + PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum); + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "finished"); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { + {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"}, - {"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"}, - {"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"}, - {"ndefread", CmdHF14ANdefRead, IfPm3Iso14443a, "Read an NDEF file from ISO 14443-A Type 4 tag"}, - {"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "Collect n>0 ISO14443-a UIDs in one go"}, - {"sim", CmdHF14ASim, IfPm3Iso14443a, "Simulate ISO 14443-a tag"}, - {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"}, - {"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"}, - {"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"}, - {"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("operations") " ---------------------"}, {"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"}, {"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"}, + {"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "Collect n>0 ISO14443-a UIDs in one go"}, + {"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"}, + {"sim", CmdHF14ASim, IfPm3Iso14443a, "Simulate ISO 14443-a tag"}, + {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"}, + {"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"}, + {"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------- " _CYAN_("apdu") " -------------------------"}, + {"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"}, {"apdufind", CmdHf14AFindapdu, IfPm3Iso14443a, "Enumerate APDUs - CLA/INS/P1P2"}, + {"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------- " _CYAN_("ndef") " -------------------------"}, + {"ndefformat", CmdHF14ANdefFormat, IfPm3Iso14443a, "Format ISO 14443-A as NFC Type 4 tag"}, + {"ndefread", CmdHF14ANdefRead, IfPm3Iso14443a, "Read an NDEF file from ISO 14443-A Type 4 tag"}, + {"ndefwrite", CmdHF14ANdefWrite, IfPm3Iso14443a, "Write NDEF records to ISO 14443-A tag"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdhf14a.h b/client/src/cmdhf14a.h index 72d2e6e4f..2ac2672a1 100644 --- a/client/src/cmdhf14a.h +++ b/client/src/cmdhf14a.h @@ -37,9 +37,11 @@ typedef struct { } hintAIDList_t; int CmdHF14A(const char *Cmd); -int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff -int CmdHF14ASim(const char *Cmd); // used by hf mfu sim -int CmdHF14ANdefRead(const char *Cmd); +int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff +int CmdHF14ASim(const char *Cmd); // used by hf mfu sim +int CmdHF14ANdefRead(const char *Cmd); // used by cmdnfc.c +int CmdHF14ANdefFormat(const char *Cmd); // used by cmdnfc.c +int CmdHF14ANdefWrite(const char *Cmd); // used by cmdnfc.c int hf14a_getconfig(hf14a_config *config); int hf14a_setconfig(hf14a_config *config, bool verbose); diff --git a/client/src/cmdnfc.c b/client/src/cmdnfc.c index 7afb8a718..df87ee6f8 100644 --- a/client/src/cmdnfc.c +++ b/client/src/cmdnfc.c @@ -223,20 +223,28 @@ static int CmdNFCST25TARead(const char *Cmd) { return CmdHFST25TANdefRead(Cmd); } +static int CmdNFCType4AFormat(const char *Cmd) { + return CmdHF14ANdefFormat(Cmd); +} + +static int CmdNFCType4AWrite(const char *Cmd) { + return CmdHF14ANdefWrite(Cmd); +} + static int CmdNFCType4AHelp(const char *Cmd); static command_t CommandNFCType4ATable[] = { - {"--------", CmdNFCType4AHelp, AlwaysAvailable, "--------- " _CYAN_("NFC Forum Tag Type 4 ISO14443A") " ----------"}, -// {"format", CmdNFCType4AFormat, IfPm3Iso14443a, "format ISO-14443-a tag as NFC Tag"}, - {"read", CmdNFCType4ARead, IfPm3Iso14443a, "read NFC Forum Tag Type 4 A"}, -// {"write", CmdNFCType4AWrite, IfPm3Iso14443a, "write NFC Forum Tag Type 4 A"}, + {"--------", CmdNFCType4AHelp, AlwaysAvailable, "--------- " _CYAN_("NFC Forum Tag Type 4 ISO14443A") " ----------"}, + {"format", CmdNFCType4AFormat, IfPm3Iso14443a, "format ISO-14443-a tag as NFC Tag"}, + {"read", CmdNFCType4ARead, IfPm3Iso14443a, "read NFC Forum Tag Type 4 A"}, + {"write", CmdNFCType4AWrite, IfPm3Iso14443a, "write NFC Forum Tag Type 4 A"}, // {"mfdesread", CmdNFCMFDESRead, IfPm3Iso14443a, "read NDEF from MIFARE DESfire"}, // hf mfdes ndefread // {"mfdesformat", CmdNFCMFDESFormat, IfPm3Iso14443a, "format MIFARE DESfire as NFC Forum Tag Type 4"}, - {"st25taread", CmdNFCST25TARead, IfPm3Iso14443a, "read ST25TA as NFC Forum Tag Type 4"}, + {"st25taread", CmdNFCST25TARead, IfPm3Iso14443a, "read ST25TA as NFC Forum Tag Type 4"}, - {"--------", CmdNFCType4AHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, - {"help", CmdNFCType4AHelp, AlwaysAvailable, "This help"}, + {"--------", CmdNFCType4AHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, + {"help", CmdNFCType4AHelp, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/pm3line_vocabulory.h b/client/src/pm3line_vocabulory.h index da7ccffd1..22abed93f 100644 --- a/client/src/pm3line_vocabulory.h +++ b/client/src/pm3line_vocabulory.h @@ -134,18 +134,20 @@ const static vocabulory_t vocabulory[] = { { 0, "hf sniff" }, { 1, "hf 14a help" }, { 1, "hf 14a list" }, - { 0, "hf 14a info" }, - { 0, "hf 14a reader" }, - { 0, "hf 14a ndefread" }, - { 0, "hf 14a cuids" }, - { 0, "hf 14a sim" }, - { 0, "hf 14a sniff" }, - { 0, "hf 14a apdu" }, - { 0, "hf 14a chaining" }, - { 0, "hf 14a raw" }, { 0, "hf 14a antifuzz" }, { 0, "hf 14a config" }, + { 0, "hf 14a cuids" }, + { 0, "hf 14a info" }, + { 0, "hf 14a sim" }, + { 0, "hf 14a sniff" }, + { 0, "hf 14a raw" }, + { 0, "hf 14a reader" }, + { 0, "hf 14a apdu" }, { 0, "hf 14a apdufind" }, + { 0, "hf 14a chaining" }, + { 0, "hf 14a ndefformat" }, + { 0, "hf 14a ndefread" }, + { 0, "hf 14a ndefwrite" }, { 1, "hf 14b help" }, { 0, "hf 14b apdu" }, { 0, "hf 14b dump" }, @@ -713,6 +715,7 @@ const static vocabulory_t vocabulory[] = { { 1, "nfc type1 help" }, { 0, "nfc type2 read" }, { 1, "nfc type2 help" }, + { 0, "nfc type4a format" }, { 0, "nfc type4a read" }, { 0, "nfc type4a st25taread" }, { 1, "nfc type4a help" }, diff --git a/doc/commands.json b/doc/commands.json index d31d40d8c..94d01e31b 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -1074,6 +1074,29 @@ ], "usage": "hf 14a apdu [-hsktde] [-m ] [-l ] []..." }, + "hf 14a apdufind": { + "command": "hf 14a apdufind", + "description": "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1/P2 commands. It loops all 256 possible values for each byte. The loop oder is INS -> P1/P2 (alternating) -> CLA. Tag must be on antenna before running.", + "notes": [ + "hf 14a apdufind", + "hf 14a apdufind --cla 80", + "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0 --with-le" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-c, --cla Start value of CLASS (1 hex byte)", + "-i, --ins Start value of INSTRUCTION (1 hex byte)", + "--p1 Start value of P1 (1 hex byte)", + "--p2 Start value of P2 (1 hex byte)", + "-r, --reset Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes", + "-e, --error-limit Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512.", + "-s, --skip-ins Do not test an instruction (can be specified multiple times)", + "-l, --with-le Search for APDUs with Le=0 (case 2S) as well", + "-v, --verbose Verbose output" + ], + "usage": "hf 14a apdufind [-hlv] [-c ] [-i ] [--p1 ] [--p2 ] [-r ] [-e ] [-s ]..." + }, "hf 14a chaining": { "command": "hf 14a chaining", "description": "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", @@ -1089,25 +1112,12 @@ }, "hf 14a config": { "command": "hf 14a config", - "description": "--------------------------------------------------------------------------------------- hf 14a apdufind available offline: no", + "description": "--------------------------------------------------------------------------------------- hf 14a cuids available offline: no", "notes": [], "offline": false, "options": [], "usage": "" }, - "hf 14a cuids": { - "command": "hf 14a cuids", - "description": "Collect n>0 ISO14443-a UIDs in one go", - "notes": [ - "hf 14a cuids -n 5 -> Collect 5 UIDs" - ], - "offline": false, - "options": [ - "-h, --help This help", - "-n, --num Number of UIDs to collect" - ], - "usage": "hf 14a cuids [-h] [-n ]" - }, "hf 14a help": { "command": "hf 14a help", "description": "help This help list List ISO 14443-a history", @@ -1152,6 +1162,19 @@ ], "usage": "hf 14a list [-h1fcrux] [--dict ]" }, + "hf 14a ndefformat": { + "command": "hf 14a ndefformat", + "description": "Format ISO14443-a Tag as a NFC tag with Data Exchange Format (NDEF)", + "notes": [ + "hf 14a ndefformat" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-v, --verbose show technical data" + ], + "usage": "hf 14a ndefformat [-hv]" + }, "hf 14a ndefread": { "command": "hf 14a ndefread", "description": "Read NFC Data Exchange Format (NDEF) file on Type 4 NDEF tag", @@ -1167,6 +1190,24 @@ ], "usage": "hf 14a ndefread [-hv] [-f ]" }, + "hf 14a ndefwrite": { + "command": "hf 14a ndefwrite", + "description": "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.", + "notes": [ + "hf 14a ndefwrite -d 0300FE -> write empty record to tag", + "hf 14a ndefwrite -f myfilename", + "hf 14a ndefwrite -d 033fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-d raw NDEF hex bytes", + "-f, --file write raw NDEF file to tag", + "-p fix NDEF record headers / terminator block if missing", + "-v, --verbose verbose output" + ], + "usage": "hf 14a ndefwrite [-hpv] [-d ] [-f ]" + }, "hf 14a raw": { "command": "hf 14a raw", "description": "Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.", @@ -10666,6 +10707,19 @@ ], "usage": "hf mfu ndefread [-hlv] [-k Replace default key for NDEF] [-f ]" }, + "nfc type4a format": { + "command": "nfc type4a format", + "description": "Format ISO14443-a Tag as a NFC tag with Data Exchange Format (NDEF)", + "notes": [ + "hf 14a ndefformat" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-v, --verbose show technical data" + ], + "usage": "hf 14a ndefformat [-hv]" + }, "nfc type4a help": { "command": "nfc type4a help", "description": "-------- --------- NFC Forum Tag Type 4 ISO14443A ---------- -------- --------------------- General --------------------- help This help", @@ -11420,8 +11474,8 @@ } }, "metadata": { - "commands_extracted": 722, + "commands_extracted": 725, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2022-10-23T01:18:01" + "extracted_on": "2022-10-24T16:21:33" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index e8f272b7f..a8a864d33 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -177,18 +177,20 @@ Check column "offline" for their availability. |------- |------- |----------- |`hf 14a help `|Y |`This help` |`hf 14a list `|Y |`List ISO 14443-a history` -|`hf 14a info `|N |`Tag information` -|`hf 14a reader `|N |`Act like an ISO14443-a reader` -|`hf 14a ndefread `|N |`Read an NDEF file from ISO 14443-A Type 4 tag` -|`hf 14a cuids `|N |`Collect n>0 ISO14443-a UIDs in one go` -|`hf 14a sim `|N |`Simulate ISO 14443-a tag` -|`hf 14a sniff `|N |`sniff ISO 14443-a traffic` -|`hf 14a apdu `|N |`Send ISO 14443-4 APDU to tag` -|`hf 14a chaining `|N |`Control ISO 14443-4 input chaining` -|`hf 14a raw `|N |`Send raw hex data to tag` |`hf 14a antifuzz `|N |`Fuzzing the anticollision phase. Warning! Readers may react strange` |`hf 14a config `|N |`Configure 14a settings (use with caution)` +|`hf 14a cuids `|N |`Collect n>0 ISO14443-a UIDs in one go` +|`hf 14a info `|N |`Tag information` +|`hf 14a sim `|N |`Simulate ISO 14443-a tag` +|`hf 14a sniff `|N |`sniff ISO 14443-a traffic` +|`hf 14a raw `|N |`Send raw hex data to tag` +|`hf 14a reader `|N |`Act like an ISO14443-a reader` +|`hf 14a apdu `|N |`Send ISO 14443-4 APDU to tag` |`hf 14a apdufind `|N |`Enumerate APDUs - CLA/INS/P1P2` +|`hf 14a chaining `|N |`Control ISO 14443-4 input chaining` +|`hf 14a ndefformat `|N |`Format ISO 14443-A as NFC Type 4 tag` +|`hf 14a ndefread `|N |`Read an NDEF file from ISO 14443-A Type 4 tag` +|`hf 14a ndefwrite `|N |`Write NDEF records to ISO 14443-A tag` ### hf 14b @@ -1284,6 +1286,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- +|`nfc type4a format `|N |`format ISO-14443-a tag as NFC Tag` |`nfc type4a read `|N |`read NFC Forum Tag Type 4 A` |`nfc type4a st25taread `|N |`read ST25TA as NFC Forum Tag Type 4` |`nfc type4a help `|Y |`This help`