X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/22e2470051913380bbfa50b0ef9b7ad999364cdc..fff6d2a3ba4bd387517df9c3aaef14ec823e552e:/client/cmdhfmfu.c?ds=sidebyside diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index e10c6519..9c2faa58 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -58,12 +58,21 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { }; #define MAX_UL_TYPES 18 -uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203, - NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL}; - -uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS, - MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213, - MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS}; +uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = { + UNKNOWN, UL, UL_C, + UL_EV1_48, UL_EV1_128, NTAG, + NTAG_203, NTAG_210, NTAG_212, + NTAG_213, NTAG_215, NTAG_216, + MY_D, MY_D_NFC, MY_D_MOVE, + MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL}; + +uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = { + MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, + MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS, MAX_NTAG_203, + MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, + MAX_NTAG_213, MAX_NTAG_215, MAX_NTAG_216, + MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, + MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS}; static int CmdHelp(const char *Cmd); @@ -259,7 +268,20 @@ static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){ return len; } -//make sure field is off before calling this function + +// Fudan check checks for which error is given for a command with incorrect crc +// NXP UL chip responds with 01, fudan 00. +// other possible checks: +// send a0 + crc +// UL responds with 00, fudan doesn't respond +// or +// send a200 + crc +// UL doesn't respond, fudan responds with 00 +// or +// send 300000 + crc (read with extra byte(s)) +// UL responds with read of page 0, fudan doesn't respond. +// +// make sure field is off before calling this function static int ul_fudan_check( void ){ iso14a_card_select_t card; if ( !ul_select(&card) ) @@ -438,6 +460,8 @@ static int ulev1_print_configuration( uint8_t *data, uint8_t startPage){ bool strg_mod_en = (data[0] & 2); uint8_t authlim = (data[4] & 0x07); + bool nfc_cnf_en = (data[4] & 0x08); + bool nfc_cnf_prot_pwd = (data[4] & 0x10); bool cfglck = (data[4] & 0x40); bool prot = (data[4] & 0x80); uint8_t vctid = data[5]; @@ -453,6 +477,10 @@ static int ulev1_print_configuration( uint8_t *data, uint8_t startPage){ PrintAndLog(" - Unlimited password attempts"); else PrintAndLog(" - Max number of password attempts is %d", authlim); + + PrintAndLog(" - NFC counter %s", (nfc_cnf_en) ? "enabled":"disabled"); + PrintAndLog(" - NFC counter %s", (nfc_cnf_prot_pwd) ? "not protected":"password protection enabled"); + PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); PrintAndLog(" - %02X, Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); @@ -786,6 +814,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } + // Read signature if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) { uint8_t ulev1_signature[32] = {0x00}; status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); @@ -801,6 +830,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } + // Get Version if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) { uint8_t version[10] = {0x00}; status = ulev1_getVersion(version, sizeof(version)); @@ -879,11 +909,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ uint8_t data[16] = {0x00}; uint8_t authenticationkey[16] = {0x00}; uint8_t *authKeyPtr = authenticationkey; - - // starting with getting tagtype - TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) return -1; - + while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) @@ -915,19 +941,8 @@ int CmdHF14AMfUWrBl(const char *Cmd){ case 'b': case 'B': blockNo = param_get8(Cmd, cmdp+1); - - uint8_t maxblockno = 0; - for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){ - if (tagtype & UL_TYPES_ARRAY[idx]) - maxblockno = UL_MEMORY_ARRAY[idx]; - } - if (blockNo < 0) { PrintAndLog("Wrong block number"); - errors = true; - } - if (blockNo > maxblockno){ - PrintAndLog("block number too large. Max block is %u/0x%02X \n", maxblockno,maxblockno); errors = true; } cmdp += 2; @@ -956,7 +971,20 @@ int CmdHF14AMfUWrBl(const char *Cmd){ } if ( blockNo == -1 ) return usage_hf_mfu_wrbl(); - + // starting with getting tagtype + TagTypeUL_t tagtype = GetHF14AMfU_Type(); + if (tagtype == UL_ERROR) return -1; + + uint8_t maxblockno = 0; + for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){ + if (tagtype & UL_TYPES_ARRAY[idx]) + maxblockno = UL_MEMORY_ARRAY[idx]; + } + if (blockNo > maxblockno){ + PrintAndLog("block number too large. Max block is %u/0x%02X \n", maxblockno,maxblockno); + return usage_hf_mfu_wrbl(); + } + // Swap endianness if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8); if (swapEndian && hasPwdKey) authKeyPtr = SwapEndian64(authenticationkey, 4, 4); @@ -1007,10 +1035,6 @@ int CmdHF14AMfURdBl(const char *Cmd){ uint8_t authenticationkey[16] = {0x00}; uint8_t *authKeyPtr = authenticationkey; - // starting with getting tagtype - TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) return -1; - while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) @@ -1042,19 +1066,8 @@ int CmdHF14AMfURdBl(const char *Cmd){ case 'b': case 'B': blockNo = param_get8(Cmd, cmdp+1); - - uint8_t maxblockno = 0; - for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){ - if (tagtype & UL_TYPES_ARRAY[idx]) - maxblockno = UL_MEMORY_ARRAY[idx]; - } - if (blockNo < 0) { PrintAndLog("Wrong block number"); - errors = true; - } - if (blockNo > maxblockno){ - PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno); errors = true; } cmdp += 2; @@ -1074,7 +1087,20 @@ int CmdHF14AMfURdBl(const char *Cmd){ } if ( blockNo == -1 ) return usage_hf_mfu_rdbl(); - + // start with getting tagtype + TagTypeUL_t tagtype = GetHF14AMfU_Type(); + if (tagtype == UL_ERROR) return -1; + + uint8_t maxblockno = 0; + for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){ + if (tagtype & UL_TYPES_ARRAY[idx]) + maxblockno = UL_MEMORY_ARRAY[idx]; + } + if (blockNo > maxblockno){ + PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno); + return usage_hf_mfu_rdbl(); + } + // Swap endianness if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8); if (swapEndian && hasPwdKey) authKeyPtr = SwapEndian64(authenticationkey, 4, 4); @@ -1177,7 +1203,61 @@ int usage_hf_mfu_wrbl(void) { return 0; } +int usage_hf_mfu_eload(void) { + PrintAndLog("It loads emulator dump from the file `filename.eml`\n"); + PrintAndLog("Usage: hf mfu eload t i \n"); + PrintAndLog(" Options:"); + PrintAndLog(" t : Tag memorysize/type"); + PrintAndLog(" i : file name w/o `.eml`"); + PrintAndLog(""); + PrintAndLog(" sample : hf mfu eload filename"); + PrintAndLog(" : hf mfu eload 4 filename"); + return 0; +} + +int usage_hf_mfu_ucauth(void) { + PrintAndLog("Usage: hf mfu cauth k "); + PrintAndLog(" 0 (default): 3DES standard key"); + PrintAndLog(" 1 : all 0x00 key"); + PrintAndLog(" 2 : 0x00-0x0F key"); + PrintAndLog(" 3 : nfc key"); + PrintAndLog(" 4 : all 0x01 key"); + PrintAndLog(" 5 : all 0xff key"); + PrintAndLog(" 6 : 0x00-0xFF key"); + PrintAndLog("\n sample : hf mfu cauth k"); + PrintAndLog(" : hf mfu cauth k 3"); + return 0; +} + +int usage_hf_mfu_ucsetpwd(void) { + PrintAndLog("Usage: hf mfu setpwd "); + PrintAndLog(" [password] - (32 hex symbols)"); + PrintAndLog(""); + PrintAndLog("sample: hf mfu setpwd 000102030405060708090a0b0c0d0e0f"); + PrintAndLog(""); + return 0; +} + +int usage_hf_mfu_ucsetuid(void) { + PrintAndLog("Usage: hf mfu setuid "); + PrintAndLog(" [uid] - (14 hex symbols)"); + PrintAndLog("\nThis only works for Magic Ultralight tags."); + PrintAndLog(""); + PrintAndLog("sample: hf mfu setuid 11223344556677"); + PrintAndLog(""); + return 0; +} + +int usage_hf_mfu_gendiverse(void){ + PrintAndLog("Usage: hf mfu gen "); + PrintAndLog(""); + PrintAndLog("sample: hf mfu gen 11223344"); + PrintAndLog(""); + return 0; +} + // + // Mifare Ultralight / Ultralight-C / Ultralight-EV1 // Read and Dump Card Contents, using auto detection of tag size. int CmdHF14AMfUDump(const char *Cmd){ @@ -1423,6 +1503,7 @@ int CmdHF14AMfUDump(const char *Cmd){ // Ultralight C Methods //------------------------------------------------------------------------------- + // // Ultralight C Authentication Demo {currently uses hard-coded key} // @@ -1440,22 +1521,9 @@ int CmdHF14AMfucAuth(const char *Cmd){ errors = true; } - if (cmdp == 'h' || cmdp == 'H') - errors = true; + if (cmdp == 'h' || cmdp == 'H') errors = true; - if (errors) { - PrintAndLog("Usage: hf mfu cauth k "); - PrintAndLog(" 0 (default): 3DES standard key"); - PrintAndLog(" 1 : all 0x00 key"); - PrintAndLog(" 2 : 0x00-0x0F key"); - PrintAndLog(" 3 : nfc key"); - PrintAndLog(" 4 : all 0x01 key"); - PrintAndLog(" 5 : all 0xff key"); - PrintAndLog(" 6 : 0x00-0xFF key"); - PrintAndLog("\n sample : hf mfu cauth k"); - PrintAndLog(" : hf mfu cauth k 3"); - return 0; - } + if (errors) return usage_hf_mfu_ucauth(); uint8_t *key = default_3des_keys[keyNo]; if (ulc_authentication(key, true)) @@ -1569,17 +1637,9 @@ int CmdTestDES(const char * cmd) int CmdHF14AMfucSetPwd(const char *Cmd){ uint8_t pwd[16] = {0x00}; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mfu setpwd "); - PrintAndLog(" [password] - (32 hex symbols)"); - PrintAndLog(""); - PrintAndLog("sample: hf mfu setpwd 000102030405060708090a0b0c0d0e0f"); - PrintAndLog(""); - return 0; - } + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_ucsetpwd(); if (param_gethex(Cmd, 0, pwd, 32)) { PrintAndLog("Password must include 32 HEX symbols"); @@ -1592,7 +1652,6 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ SendCommand(&c); UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { if ( (resp.arg[0] & 0xff) == 1) PrintAndLog("Ultralight-C new password: %s", sprint_hex(pwd,16)); @@ -1604,8 +1663,7 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ else { PrintAndLog("command execution time out"); return 1; - } - + } return 0; } @@ -1618,17 +1676,8 @@ int CmdHF14AMfucSetUid(const char *Cmd){ UsbCommand resp; uint8_t uid[7] = {0x00}; char cmdp = param_getchar(Cmd, 0); - - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mfu setuid "); - PrintAndLog(" [uid] - (14 hex symbols)"); - PrintAndLog("\nThis only works for Magic Ultralight tags."); - PrintAndLog(""); - PrintAndLog("sample: hf mfu setuid 11223344556677"); - PrintAndLog(""); - return 0; - } - + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_ucsetuid(); + if (param_gethex(Cmd, 0, uid, 14)) { PrintAndLog("UID must include 14 HEX symbols"); return 1; @@ -1692,14 +1741,20 @@ int CmdHF14AMfucSetUid(const char *Cmd){ } int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ + + uint8_t uid[4]; + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_gendiverse(); + + if (param_gethex(Cmd, 0, uid, 8)) { + PrintAndLog("UID must include 8 HEX symbols"); + return 1; + } uint8_t iv[8] = { 0x00 }; - uint8_t block = 0x07; + uint8_t block = 0x01; - // UL-EV1 - //04 57 b6 e2 05 3f 80 UID - //4a f8 4b 19 PWD - uint8_t uid[] = { 0xF4,0xEA, 0x54, 0x8E }; uint8_t mifarekeyA[] = { 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5 }; uint8_t mifarekeyB[] = { 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5 }; uint8_t dkeyA[8] = { 0x00 }; @@ -1728,15 +1783,13 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ , divkey // output ); - PrintAndLog("3DES version"); + PrintAndLog("-- 3DES version"); PrintAndLog("Masterkey :\t %s", sprint_hex(masterkey,sizeof(masterkey))); PrintAndLog("UID :\t %s", sprint_hex(uid, sizeof(uid))); - PrintAndLog("Sector :\t %0d", block); + PrintAndLog("block :\t %0d", block); PrintAndLog("Mifare key :\t %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA))); PrintAndLog("Message :\t %s", sprint_hex(mix, sizeof(mix))); PrintAndLog("Diversified key: %s", sprint_hex(divkey+1, 6)); - - PrintAndLog("\n DES version"); for (int i=0; i < sizeof(mifarekeyA); ++i){ dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; @@ -1766,20 +1819,19 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ , newpwd // output ); + PrintAndLog("\n-- DES version"); PrintAndLog("Mifare dkeyA :\t %s", sprint_hex(dkeyA, sizeof(dkeyA))); PrintAndLog("Mifare dkeyB :\t %s", sprint_hex(dkeyB, sizeof(dkeyB))); PrintAndLog("Mifare ABA :\t %s", sprint_hex(dmkey, sizeof(dmkey))); PrintAndLog("Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); + // next. from the diversify_key method. return 0; } // static uint8_t * diversify_key(uint8_t * key){ - // for(int i=0; i<16; i++){ - // if(i<=6) key[i]^=cuid[i]; - // if(i>6) key[i]^=cuid[i%7]; - // } + // return key; // } @@ -1790,6 +1842,96 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ // return; // } +int CmdHF14AMfuELoad(const char *Cmd) +{ + //FILE * f; + //char filename[FILE_PATH_SIZE]; + //char *fnameptr = filename; + //char buf[64] = {0x00}; + //uint8_t buf8[64] = {0x00}; + //int i, len, blockNum, numBlocks; + //int nameParamNo = 1; + + char ctmp = param_getchar(Cmd, 0); + + if ( ctmp == 'h' || ctmp == 0x00) return usage_hf_mfu_eload(); + +/* + switch (ctmp) { + case '0' : numBlocks = 5*4; break; + case '1' : + case '\0': numBlocks = 16*4; break; + case '2' : numBlocks = 32*4; break; + case '4' : numBlocks = 256; break; + default: { + numBlocks = 16*4; + nameParamNo = 0; + } + } + + len = param_getstr(Cmd,nameParamNo,filename); + + if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4; + + fnameptr += len; + + sprintf(fnameptr, ".eml"); + + // open file + f = fopen(filename, "r"); + if (f == NULL) { + PrintAndLog("File %s not found or locked", filename); + return 1; + } + + blockNum = 0; + while(!feof(f)){ + memset(buf, 0, sizeof(buf)); + + if (fgets(buf, sizeof(buf), f) == NULL) { + + if (blockNum >= numBlocks) break; + + PrintAndLog("File reading error."); + fclose(f); + return 2; + } + + if (strlen(buf) < 32){ + if(strlen(buf) && feof(f)) + break; + PrintAndLog("File content error. Block data must include 32 HEX symbols"); + fclose(f); + return 2; + } + + for (i = 0; i < 32; i += 2) { + sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]); + } + + if (mfEmlSetMem(buf8, blockNum, 1)) { + PrintAndLog("Cant set emul block: %3d", blockNum); + fclose(f); + return 3; + } + printf("."); + blockNum++; + + if (blockNum >= numBlocks) break; + } + fclose(f); + printf("\n"); + + if ((blockNum != numBlocks)) { + PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks); + return 4; + } + PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename); + */ + return 0; +} + + //------------------------------------ // Menu Stuff //------------------------------------ @@ -1800,7 +1942,8 @@ static command_t CommandTable[] = {"info", CmdHF14AMfUInfo, 0, "Tag information"}, {"dump", CmdHF14AMfUDump, 0, "Dump Ultralight / Ultralight-C / NTAG tag to binary file"}, {"rdbl", CmdHF14AMfURdBl, 0, "Read block"}, - {"wrbl", CmdHF14AMfUWrBl, 0, "Write block"}, + {"wrbl", CmdHF14AMfUWrBl, 0, "Write block"}, + {"eload", CmdHF14AMfuELoad, 0, " Load from file emulator dump"}, {"cauth", CmdHF14AMfucAuth, 0, "Authentication - Ultralight C"}, {"setpwd", CmdHF14AMfucSetPwd, 1, "Set 3des password - Ultralight-C"}, {"setuid", CmdHF14AMfucSetUid, 1, "Set UID - MAGIC tags only"},