X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/c3c241f389048bd14422d70504cecec6637b89f3..1d0ccbe04b6d04cc4e05aeb9bbcb7b7fa0cfdbd1:/client/cmdhfmfu.c?ds=sidebyside diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 5153e8ec..07609339 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -13,7 +13,7 @@ #include "cmdhf14a.h" #include "mifare.h" #include "util.h" -#include "../common/protocols.h" +#include "protocols.h" #include "data.h" #define MAX_UL_BLOCKS 0x0f @@ -26,6 +26,9 @@ #define MAX_NTAG_213 0x2c #define MAX_NTAG_215 0x86 #define MAX_NTAG_216 0xe6 +#define MAX_MY_D_NFC 0xff +#define MAX_MY_D_MOVE 0x25 +#define MAX_MY_D_MOVE_LEAN 0x0f #define KEYS_3DES_COUNT 7 uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = { @@ -54,17 +57,27 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) }; -#define MAX_UL_TYPES 16 -uint16_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}; +#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_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS}; +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); +// get version nxp product type char *getProductTypeStr( uint8_t id){ static char buf[20]; @@ -102,17 +115,20 @@ char *getUlev1CardSizeStr( uint8_t fsize ){ static void ul_switch_on_field(void) { UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + clearCommandBuffer(); SendCommand(&c); } void ul_switch_off_field(void) { UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}}; + clearCommandBuffer(); SendCommand(&c); } static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength ) { UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC, cmdlen, 0}}; memcpy(c.d.asBytes, cmd, cmdlen); + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; @@ -122,23 +138,7 @@ static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uin memcpy(response, resp.d.asBytes, resplen); return resplen; } -/* -static int ul_send_cmd_raw_crc( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength, bool append_crc ) { - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT , cmdlen, 0}}; - if (append_crc) - c.arg[0] |= ISO14A_APPEND_CRC; - memcpy(c.d.asBytes, cmd, cmdlen); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; - if (!resp.arg[0] && responseLength) return -1; - - uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; - memcpy(response, resp.d.asBytes, resplen); - return resplen; -} -*/ static int ul_select( iso14a_card_select_t *card ){ ul_switch_on_field(); @@ -193,6 +193,7 @@ static int ulc_authentication( uint8_t *key, bool switch_off_field ){ UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}}; memcpy(c.d.asBytes, key, 16); + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0; @@ -209,7 +210,6 @@ static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t pa } static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){ - if ( hasAuthKey && (tagtype & UL_C)) { //will select card automatically and close connection on error if (!ulc_authentication(authenticationkey, false)) { @@ -268,6 +268,38 @@ static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){ return len; } + +// 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) ) + return UL_ERROR; + + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT, 4, 0}}; + + uint8_t cmd[4] = {0x30,0x00,0x02,0xa7}; //wrong crc on purpose should be 0xa8 + memcpy(c.d.asBytes, cmd, 4); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return UL_ERROR; + if (resp.arg[0] != 1) return UL_ERROR; + + return (!resp.d.asBytes[0]) ? FUDAN_UL : UL; //if response == 0x00 then Fudan, else Genuine NXP +} + static int ul_print_default( uint8_t *data){ uint8_t uid[7]; @@ -281,12 +313,12 @@ static int ul_print_default( uint8_t *data){ PrintAndLog(" UID : %s ", sprint_hex(uid, 7)); PrintAndLog(" UID[0] : %02X, %s", uid[0], getTagInfo(uid[0]) ); - if ( uid[0] == 0x05 ) { + if ( uid[0] == 0x05 && ((uid[1] & 0xf0) >> 4) == 2 ) { // is infineon and 66RxxP uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip){ - case 0xc2: PrintAndLog(" IC type : SLE 66R04P"); break; - case 0xc4: PrintAndLog(" IC type : SLE 66R16P"); break; - case 0xc6: PrintAndLog(" IC type : SLE 66R32P"); break; + case 0xc2: PrintAndLog(" IC type : SLE 66R04P 770 Bytes"); break; //77 pages + case 0xc4: PrintAndLog(" IC type : SLE 66R16P 2560 Bytes"); break; //256 pages + case 0xc6: PrintAndLog(" IC type : SLE 66R32P 5120 Bytes"); break; //512 pages /2 sectors } } // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 @@ -327,7 +359,9 @@ static int ndef_print_CC(uint8_t *data) { PrintAndLog(" %02X : NDEF Magic Number", data[0]); PrintAndLog(" %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); PrintAndLog(" %02X : Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); - if ( data[2] == 0x12 ) + if ( data[2] == 0x96 ) + PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 48); + else if ( data[2] == 0x12 ) PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 144); else if ( data[2] == 0x3e ) PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 496); @@ -372,13 +406,17 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ else if ( tagtype & NTAG_I2C_2K ) PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); else if ( tagtype & MY_D ) - PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer); + PrintAndLog("%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); else if ( tagtype & MY_D_NFC ) - PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer); + PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer); else if ( tagtype & MY_D_MOVE ) - PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer); + PrintAndLog("%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer); else if ( tagtype & MY_D_MOVE_NFC ) - PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer); + PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer); + else if ( tagtype & MY_D_MOVE_LEAN ) + PrintAndLog("%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer); + else if ( tagtype & FUDAN_UL ) + PrintAndLog("%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype); return 0; @@ -612,13 +650,20 @@ uint32_t GetHF14AMfU_Type(void){ ul_switch_off_field(); } } + if (tagtype & UL) { + tagtype = ul_fudan_check(); + ul_switch_off_field(); + } } else { + ul_switch_off_field(); // Infinition MY-D tests Exam high nibble uint8_t nib = (card.uid[1] & 0xf0) >> 4; switch ( nib ){ - case 1: tagtype = MY_D; break; - case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two - case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two + // case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k + case 1: tagtype = MY_D; break; //or SLE 66RxxS ... up to 512 pages of 8 user bytes... + case 2: tagtype = (MY_D_NFC); break; //or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes) + case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two + case 7: tagtype = MY_D_MOVE_LEAN; break; //or SLE 66R01L // 16 pages of 4 bytes } } @@ -646,8 +691,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ int len = 0; char tempStr[50]; - clearCommandBuffer(); - while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) @@ -765,6 +808,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)); @@ -780,6 +824,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)); @@ -858,13 +903,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ uint8_t data[16] = {0x00}; uint8_t authenticationkey[16] = {0x00}; uint8_t *authKeyPtr = authenticationkey; - - clearCommandBuffer(); - - // 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)) @@ -896,19 +935,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; @@ -937,7 +965,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); @@ -960,6 +1001,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ memcpy(c.d.asBytes+4,authKeyPtr,4); } + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { @@ -987,12 +1029,6 @@ int CmdHF14AMfURdBl(const char *Cmd){ uint8_t authenticationkey[16] = {0x00}; uint8_t *authKeyPtr = authenticationkey; - clearCommandBuffer(); - - // 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)) @@ -1024,19 +1060,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; @@ -1054,8 +1079,22 @@ int CmdHF14AMfURdBl(const char *Cmd){ //Validations if(errors) return usage_hf_mfu_rdbl(); } + 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); @@ -1071,13 +1110,16 @@ int CmdHF14AMfURdBl(const char *Cmd){ memcpy(c.d.asBytes,authKeyPtr,4); } + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { uint8_t isOK = resp.arg[0] & 0xff; if (isOK) { uint8_t *data = resp.d.asBytes; - PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(data, 4)); + PrintAndLog("\nBlock# | Data | Ascii"); + PrintAndLog("-----------------------------"); + PrintAndLog("%02d/0x%02X | %s| %.4s\n", blockNo, blockNo, sprint_hex(data, 4), data); } else { PrintAndLog("Failed reading block: (%02x)", isOK); @@ -1155,7 +1197,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){ @@ -1185,8 +1281,6 @@ int CmdHF14AMfUDump(const char *Cmd){ uint8_t startPage = 0; char tempStr[50]; - clearCommandBuffer(); - while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) @@ -1264,6 +1358,8 @@ int CmdHF14AMfUDump(const char *Cmd){ memcpy(c.d.asBytes, authKeyPtr, dataLen); } + + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) { @@ -1322,11 +1418,11 @@ int CmdHF14AMfUDump(const char *Cmd){ } } - PrintAndLog("Block# | Data |lck| Ascii"); + PrintAndLog("\nBlock# | Data |lck| Ascii"); PrintAndLog("---------------------------------"); for (i = 0; i < Pages; ++i) { if ( i < 3 ) { - PrintAndLog("%02d/0x%02X | %s | |", i, i,sprint_hex(data + i * 4, 4)); + PrintAndLog("%02d/0x%02X | %s| | ", i+startPage, i+startPage, sprint_hex(data + i * 4, 4)); continue; } switch(i){ @@ -1373,7 +1469,7 @@ int CmdHF14AMfUDump(const char *Cmd){ case 43: tmplockbit = bit2[9]; break; //auth1 default: break; } - PrintAndLog("%02d/0x%02X | %s |%d| %.4s",i , i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4); + PrintAndLog("%02d/0x%02X | %s| %d | %.4s", i+startPage, i+startPage, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4); } PrintAndLog("---------------------------------"); @@ -1401,6 +1497,7 @@ int CmdHF14AMfUDump(const char *Cmd){ // Ultralight C Methods //------------------------------------------------------------------------------- + // // Ultralight C Authentication Demo {currently uses hard-coded key} // @@ -1411,8 +1508,6 @@ int CmdHF14AMfucAuth(const char *Cmd){ char cmdp = param_getchar(Cmd, 0); - clearCommandBuffer(); - //Change key to user defined one if (cmdp == 'k' || cmdp == 'K'){ keyNo = param_get8(Cmd, 1); @@ -1420,22 +1515,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)) @@ -1549,19 +1631,9 @@ int CmdTestDES(const char * cmd) int CmdHF14AMfucSetPwd(const char *Cmd){ uint8_t pwd[16] = {0x00}; - char cmdp = param_getchar(Cmd, 0); - clearCommandBuffer(); - - 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"); @@ -1570,10 +1642,10 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ UsbCommand c = {CMD_MIFAREUC_SETPWD}; memcpy( c.d.asBytes, pwd, 16); + clearCommandBuffer(); 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)); @@ -1585,8 +1657,7 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ else { PrintAndLog("command execution time out"); return 1; - } - + } return 0; } @@ -1599,19 +1670,8 @@ int CmdHF14AMfucSetUid(const char *Cmd){ UsbCommand resp; uint8_t uid[7] = {0x00}; char cmdp = param_getchar(Cmd, 0); - - clearCommandBuffer(); - - 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; @@ -1620,6 +1680,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){ // read block2. c.cmd = CMD_MIFAREU_READBL; c.arg[0] = 2; + clearCommandBuffer(); SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { PrintAndLog("Command execute timeout"); @@ -1637,6 +1698,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){ c.d.asBytes[1] = uid[1]; c.d.asBytes[2] = uid[2]; c.d.asBytes[3] = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; + clearCommandBuffer(); SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { PrintAndLog("Command execute timeout"); @@ -1649,6 +1711,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){ c.d.asBytes[1] = uid[4]; c.d.asBytes[2] = uid[5]; c.d.asBytes[3] = uid[6]; + clearCommandBuffer(); SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { PrintAndLog("Command execute timeout"); @@ -1661,6 +1724,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){ c.d.asBytes[1] = oldblock2[1]; c.d.asBytes[2] = oldblock2[2]; c.d.asBytes[3] = oldblock2[3]; + clearCommandBuffer(); SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { PrintAndLog("Command execute timeout"); @@ -1671,14 +1735,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 }; @@ -1707,15 +1777,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; @@ -1745,20 +1813,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; // } @@ -1769,6 +1836,97 @@ 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 //------------------------------------ @@ -1779,7 +1937,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"},