X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/5eae566a28d4494e70a9e3812e269dbd87d9bc07..5e336f53d9a6c26e48d259b63ac960ddfbf768ac:/client/cmdhfmfu.c diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 310d5bdc..85b824cf 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -11,6 +11,7 @@ #include "cmdhfmfu.h" #include "cmdhfmf.h" #include "cmdhf14a.h" +#include "mifare.h" #define MAX_ULTRA_BLOCKS 0x0f #define MAX_ULTRAC_BLOCKS 0x2f @@ -22,7 +23,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t datatemp[7] = {0x00}; uint8_t isOK = 0; - uint8_t *data = NULL; + uint8_t data[16] = {0x00}; UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}}; SendCommand(&c); @@ -30,7 +31,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.arg[0] & 0xff; - data = resp.d.asBytes; + memcpy(data, resp.d.asBytes, sizeof(data)); if (!isOK) { PrintAndLog("Error reading from tag"); @@ -40,11 +41,35 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("Command execute timed out"); return -1; } - - PrintAndLog(""); - PrintAndLog("-- Mifare Ultralight / Ultralight-C Tag Information ---------"); - PrintAndLog("-------------------------------------------------------------"); + PrintAndLog("\n-- Tag Information ---------"); + PrintAndLog("-------------------------------------------------------------"); + + UsbCommand cmd = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC , 1, 0}}; + cmd.d.asBytes[0] = 0x60; + SendCommand(&cmd); + WaitForResponse(CMD_ACK, &resp); + + if ( resp.arg[0] ) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + + uint8_t version[8] = {0,0,0,0,0,0,0,0}; + memcpy(&version, resp.d.asBytes, sizeof(version)); + uint8_t len = resp.arg[0] & 0xff; + switch (len) { + // todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command. + // UL-EV1, size, check version[6] == 0x0b (smaller) 0x0b * 4 == 48 + case 0x0A:PrintAndLog(" TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128); break; + case 0x01:PrintAndLog(" TYPE : NXP MIFARE Ultralight C");break; + case 0x00:PrintAndLog(" TYPE : NXP MIFARE Ultralight");break; + } + } + } + // TODO: + // Answers to 0x1A == UL-C + // NONCE seems to be fixed for my Magic UL-C. How to detect a Magic UL? + // maybe read Block0, change 1 byte, write back, and see if it failes or not. If magic, revert changes made? + // UID memcpy( datatemp, data, 3); memcpy( datatemp+3, data+4, 4); @@ -71,14 +96,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp, 2),printBits( 2, &datatemp) ); PrintAndLog(" OneTimePad : %s ", sprint_hex(data + 3*4, 4)); PrintAndLog(""); - - int len = CmdHF14AMfucAuth("K 0"); -// PrintAndLog("CODE: %d",len); -// Fix reading UL-C 's password higher blocks. - - PrintAndLog("Seems to be a Ultralight %s", (len==0) ? "-C" :""); - - return 0; } @@ -797,12 +814,15 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ // int CmdHF14AMfucSetUid(const char *Cmd){ + UsbCommand c; + 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(""); @@ -810,27 +830,60 @@ int CmdHF14AMfucSetUid(const char *Cmd){ } if (param_gethex(Cmd, 0, uid, 14)) { - PrintAndLog("Password must include 14 HEX symbols"); + PrintAndLog("UID must include 14 HEX symbols"); return 1; } - UsbCommand c = {CMD_MIFAREU_SETUID}; - memcpy( c.d.asBytes, uid, 14); + // read block2. + c.cmd = CMD_MIFAREU_READBL; + c.arg[0] = 2; SendCommand(&c); - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { - if ( (resp.arg[0] & 0xff) == 1) - PrintAndLog("New UID: %s", sprint_hex(uid,14)); - else{ - PrintAndLog("Failed writing new uid"); - return 1; - } + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + PrintAndLog("Command execute timeout"); + return 2; } - else { - PrintAndLog("command execution time out"); - return 1; + + // save old block2. + uint8_t oldblock2[4] = {0x00}; + memcpy(resp.d.asBytes, oldblock2, 4); + + // block 0. + c.cmd = CMD_MIFAREU_WRITEBL; + c.arg[0] = 0; + c.d.asBytes[0] = uid[0]; + c.d.asBytes[1] = uid[1]; + c.d.asBytes[2] = uid[2]; + c.d.asBytes[3] = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + PrintAndLog("Command execute timeout"); + return 3; } + + // block 1. + c.arg[0] = 1; + c.d.asBytes[0] = uid[3]; + c.d.asBytes[1] = uid[4]; + c.d.asBytes[2] = uid[5]; + c.d.asBytes[3] = uid[6]; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + PrintAndLog("Command execute timeout"); + return 4; + } + + // block 2. + c.arg[0] = 2; + c.d.asBytes[0] = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; + c.d.asBytes[1] = oldblock2[1]; + c.d.asBytes[2] = oldblock2[2]; + c.d.asBytes[3] = oldblock2[3]; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + PrintAndLog("Command execute timeout"); + return 5; + } + return 0; } @@ -839,17 +892,24 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ uint8_t iv[8] = { 0x00 }; uint8_t block = 0x07; + // UL-EV1 + //04 57 b6 e2 05 3f 80 UID + //4a f8 4b 19 PWD uint8_t uid[] = { 0xF4,0xEA, 0x54, 0x8E }; - uint8_t mifarekey[] = { 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5 }; + uint8_t mifarekeyA[] = { 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5 }; + uint8_t mifarekeyB[] = { 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5 }; + uint8_t dkeyA[8] = { 0x00 }; + uint8_t dkeyB[8] = { 0x00 }; + uint8_t masterkey[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; uint8_t mix[8] = { 0x00 }; uint8_t divkey[8] = { 0x00 }; - memcpy(mix, mifarekey, 4); + memcpy(mix, mifarekeyA, 4); - mix[4] = mifarekey[4] ^ uid[0]; - mix[5] = mifarekey[5] ^ uid[1]; + mix[4] = mifarekeyA[4] ^ uid[0]; + mix[5] = mifarekeyA[5] ^ uid[1]; mix[6] = block ^ uid[2]; mix[7] = uid[3]; @@ -868,14 +928,50 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ PrintAndLog("Masterkey :\t %s", sprint_hex(masterkey,sizeof(masterkey))); PrintAndLog("UID :\t %s", sprint_hex(uid, sizeof(uid))); PrintAndLog("Sector :\t %0d", block); - PrintAndLog("Mifare key :\t %s", sprint_hex(mifarekey, sizeof(mifarekey))); + 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; + dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i+1); + } + + for (int i=0; i < sizeof(mifarekeyB); ++i){ + dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i+1); + dkeyB[2+i] = (mifarekeyB[i] << 1) & 0xff; + } + + uint8_t zeros[8] = {0x00}; + uint8_t newpwd[8] = {0x00}; + uint8_t dmkey[24] = {0x00}; + memcpy(dmkey, dkeyA, 8); + memcpy(dmkey+8, dkeyB, 8); + memcpy(dmkey+16, dkeyA, 8); + memset(iv, 0x00, 8); + + des3_set3key_enc(&ctx, dmkey); + + des3_crypt_cbc(&ctx // des3_context + , DES_ENCRYPT // int mode + , sizeof(newpwd) // length + , iv // iv[8] + , zeros // input + , newpwd // output + ); + + 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))); + return 0; } -// uint8_t * diversify_key(uint8_t * key){ +// 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];