From 85d4e99ae9f552fb6632c7e693a0ced30bb3953e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 23 Jun 2023 17:51:39 +0200 Subject: [PATCH] mfp changes... --- client/src/cmdhfmfp.c | 278 ++++++++++++++++++++++++++++-------------- client/src/cmdhfmfp.h | 20 +++ 2 files changed, 204 insertions(+), 94 deletions(-) diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 9434d88ed..2368e0f74 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -34,19 +34,12 @@ #include "protocols.h" #include "crypto/libpcrypto.h" #include "cmdhfmf.h" // printblock, header +#include "cmdtrace.h" -static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -static uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; +static const uint8_t mfp_default_key[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +static uint16_t mfp_card_adresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; -typedef enum { - MFP_UNKNOWN = 0, - DESFIRE_MF3ICD40, - DESFIRE_EV1, - DESFIRE_EV2, - DESFIRE_EV3, - DESFIRE_LIGHT, - PLUS_EV1, -} nxp_cardtype_t; +#define MFP_KEY_FILE_SIZE 14 + (2 * 64 * (AES_KEY_LEN + 1)) static int CmdHelp(const char *Cmd); @@ -233,9 +226,10 @@ static int get_plus_signature(uint8_t *signature, int *signature_len) { *signature_len = 0; retval = PM3_ESOFT; } - mfpSetVerboseMode(false); + return retval; } + // GET VERSION static int plus_print_version(uint8_t *version) { PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(version + 14, 7)); @@ -261,12 +255,12 @@ static int plus_print_version(uint8_t *version) { PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(version[13], false)); return PM3_SUCCESS; } + static int get_plus_version(uint8_t *version, int *version_len) { int resplen = 0, retval = PM3_SUCCESS; mfpSetVerboseMode(false); MFPGetVersion(true, false, version, *version_len, &resplen); - mfpSetVerboseMode(false); *version_len = resplen; if (resplen != 28) { @@ -484,16 +478,16 @@ static int CmdHFMFPWritePerso(const char *Cmd) { mfpSetVerboseMode(verbose); if (!keyLen) { - memmove(key, DefaultKey, 16); + memmove(key, mfp_default_key, 16); keyLen = 16; } if (keyNumLen != 2) { - PrintAndLogEx(ERR, "Key number length must be 2 bytes instead of: %d", keyNumLen); + PrintAndLogEx(ERR, "Key number length must be 2 bytes. Got %d", keyNumLen); return PM3_EINVARG; } if (keyLen != 16) { - PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); + PrintAndLogEx(ERR, "Key length must be 16 bytes. Got %d", keyLen); return PM3_EINVARG; } @@ -507,7 +501,7 @@ static int CmdHFMFPWritePerso(const char *Cmd) { } if (datalen != 3) { - PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); + PrintAndLogEx(ERR, "Command must return 3 bytes. Got %d", datalen); return PM3_ESOFT; } @@ -539,17 +533,18 @@ static int CmdHFMFPInitPerso(const char *Cmd) { bool verbose2 = arg_get_lit(ctx, 1) > 1; uint8_t key[256] = {0}; - int keyLen = 0; - CLIGetHexWithReturn(ctx, 2, key, &keyLen); + int keylen = 0; + CLIGetHexWithReturn(ctx, 2, key, &keylen); CLIParserFree(ctx); - if (keyLen && keyLen != 16) { - PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); + if (keylen && keylen != 16) { + PrintAndLogEx(FAILED, "Key length must be 16 bytes. Got %d", keylen); return PM3_EINVARG; } - if (!keyLen) - memmove(key, DefaultKey, 16); + if (keylen == 0) { + memmove(key, mfp_default_key, sizeof(mfp_default_key)); + } uint8_t keyNum[2] = {0}; uint8_t data[250] = {0}; @@ -572,15 +567,15 @@ static int CmdHFMFPInitPerso(const char *Cmd) { } mfpSetVerboseMode(verbose); - for (int i = 0; i < ARRAYLEN(CardAddresses); i++) { - keyNum[0] = CardAddresses[i] >> 8; - keyNum[1] = CardAddresses[i] & 0xff; + for (int i = 0; i < ARRAYLEN(mfp_card_adresses); i++) { + keyNum[0] = mfp_card_adresses[i] >> 8; + keyNum[1] = mfp_card_adresses[i] & 0xff; res = MFPWritePerso(keyNum, key, false, true, data, sizeof(data), &datalen); if (!res && (datalen == 3) && data[0] == 0x09) { - PrintAndLogEx(WARNING, "Skipped[%04x]...", CardAddresses[i]); + PrintAndLogEx(WARNING, "Skipped[%04x]...", mfp_card_adresses[i]); } else { if (res || (datalen != 3) || data[0] != 0x90) { - PrintAndLogEx(ERR, "Write error on address %04x", CardAddresses[i]); + PrintAndLogEx(ERR, "Write error on address %04x", mfp_card_adresses[i]); break; } } @@ -597,7 +592,9 @@ static int CmdHFMFPInitPerso(const char *Cmd) { static int CmdHFMFPCommitPerso(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp commitp", - "Executes Commit Perso command. Can be used in SL0 mode only.\nOBS! This command will not be executed if CardConfigKey, CardMasterKey and L3SwitchKey AES keys are not written.", + "Executes Commit Perso command. Can be used in SL0 mode only.\n" + "OBS! This command will not be executed if \n" + "CardConfigKey, CardMasterKey and L3SwitchKey AES keys are not written.", "hf mfp commitp\n" // "hf mfp commitp --sl 1" ); @@ -625,7 +622,7 @@ static int CmdHFMFPCommitPerso(const char *Cmd) { } if (datalen != 3) { - PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); + PrintAndLogEx(ERR, "Command must return 3 bytes. Got %d", datalen); return PM3_EINVARG; } @@ -633,7 +630,7 @@ static int CmdHFMFPCommitPerso(const char *Cmd) { PrintAndLogEx(ERR, "Command error: %02x %s", data[0], mfpGetErrorDescription(data[0])); return PM3_EINVARG; } - PrintAndLogEx(INFO, "Switch level ( " _GREEN_("ok") " )"); + PrintAndLogEx(INFO, "Switched security level ( " _GREEN_("ok") " )"); return PM3_SUCCESS; } @@ -645,7 +642,7 @@ static int CmdHFMFPAuth(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp auth", - "Executes AES authentication command for Mifare Plus card", + "Executes AES authentication command for MIFARE Plus card", "hf mfp auth --ki 4000 --key 000102030405060708090a0b0c0d0e0f -> executes authentication\n" "hf mfp auth --ki 9003 --key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data"); @@ -664,12 +661,12 @@ static int CmdHFMFPAuth(const char *Cmd) { CLIParserFree(ctx); if (keynlen != 2) { - PrintAndLogEx(ERR, "ERROR: must be 2 bytes long instead of: %d", keynlen); + PrintAndLogEx(ERR, "ERROR: must be 2 bytes. Got %d", keynlen); return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, "ERROR: must be 16 bytes long instead of: %d", keylen); + PrintAndLogEx(ERR, "ERROR: must be 16 bytes. Got %d", keylen); return PM3_EINVARG; } @@ -679,7 +676,7 @@ static int CmdHFMFPAuth(const char *Cmd) { static int CmdHFMFPRdbl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp rdbl", - "Reads several blocks from Mifare Plus card", + "Reads blocks from MIFARE Plus card", "hf mfp rdbl --blk 0 --key 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" "hf mfp rdbl --blk 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF"); @@ -710,23 +707,23 @@ static int CmdHFMFPRdbl(const char *Cmd) { mfpSetVerboseMode(verbose); if (!keylen) { - memmove(key, DefaultKey, 16); + memmove(key, mfp_default_key, 16); keylen = 16; } if (blockn > 255) { - PrintAndLogEx(ERR, " must be in range [0..255] got: %d", blockn); + PrintAndLogEx(ERR, " must be in range [0..255]. got %d", blockn); return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long. got: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes. Got %d", keylen); return PM3_EINVARG; } // 3 blocks - wo iso14443-4 chaining if (blocksCount > 3) { - PrintAndLogEx(ERR, "blocks count must be less than 3. got: %d", blocksCount); + PrintAndLogEx(ERR, "blocks count must be less than 3. Got %d", blocksCount); return PM3_EINVARG; } @@ -763,7 +760,7 @@ static int CmdHFMFPRdbl(const char *Cmd) { } if (datalen != 1 + blocksCount * 16 + 8 + 2) { - PrintAndLogEx(ERR, "Error return length:%d", datalen); + PrintAndLogEx(ERR, "Error return length: %d", datalen); return PM3_ESOFT; } @@ -820,17 +817,17 @@ static int CmdHFMFPRdsc(const char *Cmd) { mfpSetVerboseMode(verbose); if (!keylen) { - memmove(key, DefaultKey, 16); + memmove(key, mfp_default_key, 16); keylen = 16; } if (sectorNum > 39) { - PrintAndLogEx(ERR, " must be in range [0..39] got: %d", sectorNum); + PrintAndLogEx(ERR, " must be in range [0..39]. Got %d", sectorNum); return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long. got: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes. Got %d", keylen); return PM3_EINVARG; } @@ -894,7 +891,7 @@ static int CmdHFMFPRdsc(const char *Cmd) { static int CmdHFMFPWrbl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp wrbl", - "Writes one block to Mifare Plus card", + "Writes one block to MIFARE Plus card", "hf mfp wrbl --blk 1 -d ff0000000000000000000000000000ff --key 000102030405060708090a0b0c0d0e0f -> write block 1 data\n" "hf mfp wrbl --blk 2 -d ff0000000000000000000000000000ff -v -> write block 2 data with default key 0xFF..0xFF" ); @@ -928,22 +925,22 @@ static int CmdHFMFPWrbl(const char *Cmd) { mfpSetVerboseMode(verbose); if (!keylen) { - memmove(key, DefaultKey, 16); + memmove(key, mfp_default_key, 16); keylen = 16; } if (blockNum > 255) { - PrintAndLogEx(ERR, " must be in range [0..255] got: %d", blockNum); + PrintAndLogEx(ERR, " must be in range [0..255]. Got %d", blockNum); return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long. got: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes. Got %d", keylen); return PM3_EINVARG; } if (datainlen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long. got: %d", datainlen); + PrintAndLogEx(ERR, " must be 16 bytes. Got %d", datainlen); return PM3_EINVARG; } @@ -997,11 +994,8 @@ static int CmdHFMFPWrbl(const char *Cmd) { return PM3_SUCCESS; } -#define AES_KEY_LEN 16 -#define MAX_KEYS_LIST_LEN 1024 - static int plus_key_check(uint8_t startSector, uint8_t endSector, uint8_t startKeyAB, uint8_t endKeyAB, - uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1], + uint8_t keyList[MAX_AES_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1], bool verbose) { int res; bool selectCard = true; @@ -1088,7 +1082,7 @@ static int plus_key_check(uint8_t startSector, uint8_t endSector, uint8_t startK return PM3_SUCCESS; } -static void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], uint32_t *keyListLen, uint32_t *startPattern) { +static void Fill2bPattern(uint8_t keyList[MAX_AES_KEYS_LIST_LEN][AES_KEY_LEN], uint32_t *keyListLen, uint32_t *startPattern) { for (uint32_t pt = *startPattern; pt < 0x10000; pt++) { keyList[*keyListLen][0] = (pt >> 8) & 0xff; keyList[*keyListLen][1] = pt & 0xff; @@ -1097,7 +1091,7 @@ static void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], uint3 memcpy(&keyList[*keyListLen][8], &keyList[*keyListLen][0], 8); (*keyListLen)++; *startPattern = pt; - if (*keyListLen == MAX_KEYS_LIST_LEN) + if (*keyListLen == MAX_AES_KEYS_LIST_LEN) break; } (*startPattern)++; @@ -1111,7 +1105,7 @@ static int CmdHFMFPChk(const char *Cmd) { "hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" "hf mfp chk -s 2 -a -> check default key list on sector 2, only key A\n" "hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n" - "hf mfp chk --pattern1b -j keys -> check all 1-byte keys pattern and save found keys to json\n" + "hf mfp chk --pattern1b --dump -> check all 1-byte keys pattern and save found keys to file\n" "hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00"); void *argtable[] = { @@ -1125,7 +1119,7 @@ static int CmdHFMFPChk(const char *Cmd) { arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), arg_str0(NULL, "startp2b", "", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"), - arg_str0("j", "json", "", "Json filename to save keys"), + arg_lit0(NULL, "dump", "Dump found keys to JSON file"), arg_lit0("v", "verbose", "Verbose mode"), arg_param_end }; @@ -1136,7 +1130,7 @@ static int CmdHFMFPChk(const char *Cmd) { uint8_t startSector = arg_get_int_def(ctx, 3, 0); uint8_t endSector = arg_get_int_def(ctx, 4, 0); - uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {{0}}; + uint8_t keyList[MAX_AES_KEYS_LIST_LEN][AES_KEY_LEN] = {{0}}; uint32_t keyListLen = 0; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {{{0}}}; @@ -1148,7 +1142,7 @@ static int CmdHFMFPChk(const char *Cmd) { memcpy(&keyList[keyListLen], vkey, 16); keyListLen++; } else { - PrintAndLogEx(ERR, "Specified key must have 16 bytes length."); + PrintAndLogEx(ERR, "Specified key must have 16 bytes. Got %d", vkeylen); CLIParserFree(ctx); return PM3_EINVARG; } @@ -1185,7 +1179,7 @@ static int CmdHFMFPChk(const char *Cmd) { if (vpatternlen <= 2) { startPattern = (vpattern[0] << 8) + vpattern[1]; } else { - PrintAndLogEx(ERR, "Pattern must be 2-byte length."); + PrintAndLogEx(ERR, "Pattern must be 2-bytes. Got %d", vpatternlen); CLIParserFree(ctx); return PM3_EINVARG; } @@ -1193,17 +1187,8 @@ static int CmdHFMFPChk(const char *Cmd) { PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search."); } - uint8_t jsonname[250] = {0}; - int jsonnamelen = 0; - if (CLIParamStrToBuf(arg_get_str(ctx, 10), jsonname, sizeof(jsonname), &jsonnamelen)) { - PrintAndLogEx(ERR, "Invalid json name."); - CLIParserFree(ctx); - return PM3_EINVARG; - } - jsonname[jsonnamelen] = 0; - + bool create_dumpfile = arg_get_lit(ctx, 10); bool verbose = arg_get_lit(ctx, 11); - CLIParserFree(ctx); uint8_t startKeyAB = 0; @@ -1227,8 +1212,9 @@ static int CmdHFMFPChk(const char *Cmd) { } // 2-byte pattern search mode - if (pattern2b) + if (pattern2b) { Fill2bPattern(keyList, &keyListLen, &startPattern); + } int res = PM3_SUCCESS; @@ -1291,19 +1277,30 @@ static int CmdHFMFPChk(const char *Cmd) { keyListLen = keycnt; } + PrintAndLogEx(INFO, "ICE pos... %zu - %zu", old_pos, endFilePosition); continue; } break; } - if (verbose == false) + + if (verbose == false) { PrintAndLogEx(NORMAL, ""); + } // print result char strA[46 + 1] = {0}; char strB[46 + 1] = {0}; + uint8_t ndef_key[] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; + bool has_ndef_key = false; bool printedHeader = false; for (uint8_t s = startSector; s <= endSector; s++) { + + if ((memcmp(&foundKeys[0][s][1], ndef_key, AES_KEY_LEN) == 0) || + (memcmp(&foundKeys[1][s][1], ndef_key, AES_KEY_LEN) == 0)) { + has_ndef_key = true; + } + if (printedHeader == false) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------"); @@ -1333,7 +1330,13 @@ static int CmdHFMFPChk(const char *Cmd) { PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------\n"); // save keys to json - if ((jsonnamelen > 0) && printedHeader) { + if (create_dumpfile && printedHeader) { + + size_t keys_len = (2 * 64 * (AES_KEY_LEN + 1)); + + uint8_t data[10 + 1 + 2 + 1 + 256 + keys_len]; + memset(data, 0, sizeof(data)); + // Mifare Plus info SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); @@ -1344,8 +1347,6 @@ static int CmdHFMFPChk(const char *Cmd) { memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - - uint8_t data[10 + 1 + 2 + 1 + 256 + 2 * 64 * (AES_KEY_LEN + 1)] = {0}; uint8_t atslen = 0; if (select_status == 1 || select_status == 2) { memcpy(data, card.uid, card.uidlen); @@ -1357,9 +1358,16 @@ static int CmdHFMFPChk(const char *Cmd) { memcpy(&data[14], card.ats, atslen); } + char *fptr = calloc(sizeof(char) * (strlen("hf-mfp-") + strlen("-key")) + card.uidlen * 2 + 1, sizeof(uint8_t)); + strcpy(fptr, "hf-mfp-"); + + FillFileNameByUID(fptr, card.uid, "-key", card.uidlen); + // length: UID(10b)+SAK(1b)+ATQA(2b)+ATSlen(1b)+ATS(atslen)+foundKeys[2][64][AES_KEY_LEN + 1] - memcpy(&data[14 + atslen], foundKeys, 2 * 64 * (AES_KEY_LEN + 1)); - saveFileJSON((char *)jsonname, jsfMfPlusKeys, data, 64, NULL); + memcpy(&data[14 + atslen], foundKeys, keys_len); + // 64 here is for how many "rows" there is in the data array. A bit confusing + saveFileJSON(fptr, jsfMfPlusKeys, data, 64, NULL); + free(fptr); } return PM3_SUCCESS; @@ -1369,7 +1377,7 @@ static int CmdHFMFPMAD(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp mad", - "Checks and prints Mifare Application Directory (MAD)", + "Checks and prints MIFARE Application Directory (MAD)", "hf mfp mad\n" "hf mfp mad --aid e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> read and print NDEF data from MAD aid"); @@ -1411,9 +1419,7 @@ static int CmdHFMFPMAD(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Mifare App Directory Information") " ----------------"); - PrintAndLogEx(INFO, "-----------------------------------------------------"); + MADPrintHeader(); if (verbose) { PrintAndLogEx(SUCCESS, "Raw:"); @@ -1427,7 +1433,7 @@ static int CmdHFMFPMAD(const char *Cmd) { if (haveMAD2) { if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(ERR, "error, read sector 0x10. card doesn't have MAD or doesn't have MAD on default keys"); + PrintAndLogEx(ERR, "error, read sector " _YELLOW_("0x10") ". Card doesn't have MAD or doesn't have MAD on default keys"); return PM3_ESOFT; } @@ -1505,6 +1511,36 @@ static int CmdHFMFPMAD(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHFMFPNDEFFormat(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfp ndefformat", + "format MIFARE Plus Tag as a NFC tag with Data Exchange Format (NDEF)\n" + "If no given, UID will be used as filename. \n" + "It will try default keys and MAD keys to detect if tag is already formatted in order to write.\n" + "\n" + "If not, it will try finding a key file based on your UID. ie, if you ran autopwn before", + "hf mfp ndefformat\n" + "hf mfp ndefformat --keys hf-mf-01020304-key.bin --> with keys from specified file\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "keys", "", "filename of keys"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int keyfnlen = 0; + char keyFilename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen); + + CLIParserFree(ctx); + + PrintAndLogEx(SUCCESS, "Not implemented yet. Feel free to contribute!"); + PrintAndLogEx(NORMAL, ""); + return PM3_SUCCESS; +} + int CmdHFMFPNDEFRead(const char *Cmd) { CLIParserContext *ctx; @@ -1641,20 +1677,74 @@ int CmdHFMFPNDEFRead(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHFMFPNDEFWrite(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfp ndefwrite", + "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.\n", + "hf mfp ndefwrite -d 0300FE -> write empty record to tag\n" + "hf mfp ndefwrite -f myfilename\n" + "hf mfp ndefwrite -d 033fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031\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[4096] = {0}; + int rawlen; + 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 (fix_msg) { + PrintAndLogEx(NORMAL, "called with fix NDEF message param"); + } + + if (verbose) { + PrintAndLogEx(NORMAL, ""); + } + PrintAndLogEx(SUCCESS, "Not implemented yet. Feel free to contribute!"); + PrintAndLogEx(NORMAL, ""); + return PM3_SUCCESS; +} + +static int CmdHFMFPList(const char *Cmd) { + return CmdTraceListAlias(Cmd, "hf mf", "mf"); +} + static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"info", CmdHFMFPInfo, IfPm3Iso14443a, "Info about Mifare Plus tag"}, - {"wrp", CmdHFMFPWritePerso, IfPm3Iso14443a, "Write Perso command"}, - {"initp", CmdHFMFPInitPerso, IfPm3Iso14443a, "Fill all the card's keys in SL0 mode"}, - {"commitp", CmdHFMFPCommitPerso, IfPm3Iso14443a, "Move card to SL1 or SL3 mode"}, - {"auth", CmdHFMFPAuth, IfPm3Iso14443a, "Authentication"}, - {"rdbl", CmdHFMFPRdbl, IfPm3Iso14443a, "Read blocks"}, - {"rdsc", CmdHFMFPRdsc, IfPm3Iso14443a, "Read sectors"}, - {"wrbl", CmdHFMFPWrbl, IfPm3Iso14443a, "Write blocks"}, - {"chk", CmdHFMFPChk, IfPm3Iso14443a, "Check keys"}, - {"mad", CmdHFMFPMAD, IfPm3Iso14443a, "Check and print MAD"}, - {"ndefread", CmdHFMFPNDEFRead, IfPm3Iso14443a, "Read and print NDEF records from card"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"list", CmdHFMFPList, AlwaysAvailable, "List MIFARE Plus history"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "------------------- " _CYAN_("operations") " ---------------------"}, + {"auth", CmdHFMFPAuth, IfPm3Iso14443a, "Authentication"}, + {"chk", CmdHFMFPChk, IfPm3Iso14443a, "Check keys"}, + {"dump", CmdHFMFPDump, IfPm3Iso14443a, "Dump MIFARE Classic tag to binary file"}, + {"info", CmdHFMFPInfo, IfPm3Iso14443a, "Info about MIFARE Plus tag"}, + {"mad", CmdHFMFPMAD, IfPm3Iso14443a, "Check and print MAD"}, + {"rdbl", CmdHFMFPRdbl, IfPm3Iso14443a, "Read blocks from card"}, + {"rdsc", CmdHFMFPRdsc, IfPm3Iso14443a, "Read sectors from card"}, + {"wrbl", CmdHFMFPWrbl, IfPm3Iso14443a, "Write block to card"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "---------------- " _CYAN_("personalization") " -------------------"}, + {"commitp", CmdHFMFPCommitPerso, IfPm3Iso14443a, "Move card to SL1 or SL3 mode"}, + {"initp", CmdHFMFPInitPerso, IfPm3Iso14443a, "Fill all the card's keys in SL0 mode"}, + {"wrp", CmdHFMFPWritePerso, IfPm3Iso14443a, "Write Perso command"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("ndef") " ------------------------"}, + {"ndefformat", CmdHFMFPNDEFFormat, IfPm3Iso14443a, "Format MIFARE Plus Tag as NFC Tag"}, + {"ndefread", CmdHFMFPNDEFRead, IfPm3Iso14443a, "Read and print NDEF records from card"}, + {"ndefwrite", CmdHFMFPNDEFWrite, IfPm3Iso14443a, "Write NDEF records to card"}, + {NULL, NULL, 0, NULL} }; static int CmdHelp(const char *Cmd) { diff --git a/client/src/cmdhfmfp.h b/client/src/cmdhfmfp.h index 2a4d7cd2c..29723b204 100644 --- a/client/src/cmdhfmfp.h +++ b/client/src/cmdhfmfp.h @@ -24,6 +24,26 @@ #define AES_KEY_LEN 16 #define MAX_AES_KEYS_LIST_LEN 1024 +typedef enum { + MFP_UNKNOWN = 0, + DESFIRE_MF3ICD40, + DESFIRE_EV1, + DESFIRE_EV2, + DESFIRE_EV3, + DESFIRE_LIGHT, + PLUS_EV1, +} nxp_cardtype_t; + +typedef struct mfp_key_item { + uint8_t a[16]; + uint8_t b[16]; +} mfp_key_item_t; + +typedef struct mfp_keys { + uint8_t success; + mfp_key_item_t *keys; +} mfp_keys_t; + int CmdHFMFP(const char *Cmd); int CmdHFMFPNDEFRead(const char *Cmd);