X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/9ca155ba443e8f2a9feb7640f4b461842cce9e35..5ff9150e3bfecdeee84fcabcc712ef595c33d2d6:/client/cmdhfmf.c diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index ee72dad5..ed3394e5 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -9,10 +9,10 @@ //----------------------------------------------------------------------------- #include "cmdhfmf.h" +#include "proxmark3.h" static int CmdHelp(const char *Cmd); - int CmdHF14AMifare(const char *Cmd) { uint32_t uid = 0; @@ -255,6 +255,201 @@ int CmdHF14AMfRdSc(const char *Cmd) return 0; } +int CmdHF14AMfDump1k(const char *Cmd) +{ + int i, j; + + uint8_t keyType = 0; + uint8_t c[3][4]; + uint8_t keyA[16][6]; + uint8_t keyB[16][6]; + uint8_t rights[16][4]; + + uint8_t isOK = 0; + uint8_t *data = NULL; + + FILE *fin; + FILE *fout; + + UsbCommand *resp; + + if ((fin = fopen("dumpkeys.bin","rb")) == NULL) { + PrintAndLog("Could not find file keys.bin"); + return 1; + } + + if ((fout = fopen("dumpdata.bin","wb")) == NULL) { + PrintAndLog("Could not create file name dump.bin"); + return 1; + } + + // Read key file + + for (i=0 ; i<16 ; i++) { + fread ( keyA[i], 1, 6, fin ); + } + for (i=0 ; i<16 ; i++) { + fread ( keyB[i], 1, 6, fin ); + } + + // Read access rights to sectors + + PrintAndLog("|-----------------------------------------|"); + PrintAndLog("|------ Reading sector access bits...-----|"); + PrintAndLog("|-----------------------------------------|"); + + for (i = 0 ; i < 16 ; i++) { + UsbCommand c = {CMD_MIFARE_READBL, {4*i + 3, 0, 0}}; + memcpy(c.d.asBytes, keyA[i], 6); + SendCommand(&c); + resp = WaitForResponseTimeout(CMD_ACK, 1500); + + if (resp != NULL) { + uint8_t isOK = resp->arg[0] & 0xff; + uint8_t *data = resp->d.asBytes; + if (isOK){ + rights[i][0] = ((data[7] & 0x10)>>4) | ((data[8] & 0x1)<<1) | ((data[8] & 0x10)>>2); + rights[i][1] = ((data[7] & 0x20)>>5) | ((data[8] & 0x2)<<0) | ((data[8] & 0x20)>>3); + rights[i][2] = ((data[7] & 0x40)>>6) | ((data[8] & 0x4)>>1) | ((data[8] & 0x40)>>4); + rights[i][3] = ((data[7] & 0x80)>>7) | ((data[8] & 0x8)>>2) | ((data[8] & 0x80)>>5); + } + else{ + PrintAndLog("Could not get access rights for block %d", i); + } + } + else { + PrintAndLog("Command execute timeout"); + } + } + + // Read blocks and print to file + + PrintAndLog("|-----------------------------------------|"); + PrintAndLog("|----- Dumping all blocks to file... -----|"); + PrintAndLog("|-----------------------------------------|"); + + for (i=0 ; i<16 ; i++) { + for (j=0 ; j<4 ; j++) { + + if (j == 3){ + UsbCommand c = {CMD_MIFARE_READBL, {i*4 + j, 0, 0}}; + memcpy(c.d.asBytes, keyA[i], 6); + SendCommand(&c); + resp = WaitForResponseTimeout(CMD_ACK, 1500); + } + else{ + if ((rights[i][j] == 6) | (rights[i][j] == 5)) { + UsbCommand c = {CMD_MIFARE_READBL, {i*4+j, 1, 0}}; + memcpy(c.d.asBytes, keyB[i], 6); + SendCommand(&c); + resp = WaitForResponseTimeout(CMD_ACK, 1500); + } + else if (rights[i][j] == 7) { + PrintAndLog("Access rights do not allow reading of sector %d block %d",i,j); + } + else { + UsbCommand c = {CMD_MIFARE_READBL, {i*4+j, 0, 0}}; + memcpy(c.d.asBytes, keyA[i], 6); + SendCommand(&c); + resp = WaitForResponseTimeout(CMD_ACK, 1500); + } + } + + if (resp != NULL) { + uint8_t isOK = resp->arg[0] & 0xff; + uint8_t *data = resp->d.asBytes; + if (isOK) { + fwrite ( data, 1, 16, fout ); + } + else { + PrintAndLog("Could not get access rights for block %d", i); + } + } + else { + PrintAndLog("Command execute timeout"); + } + } + } + + fclose(fin); + fclose(fout); + + return 0; +} + +int CmdHF14AMfRestore1k(const char *Cmd) +{ + + int i,j; + uint8_t keyType = 0; + uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t keyA[16][6]; + uint8_t keyB[16][6]; + + FILE *fdump; + FILE *fkeys; + + if ((fdump = fopen("dumpdata.bin","rb")) == NULL) { + PrintAndLog("Could not find file dump.bin"); + return 1; + } + if ((fkeys = fopen("dumpkeys.bin","rb")) == NULL) { + PrintAndLog("Could not find file keys.bin"); + return 1; + } + + for (i=0 ; i<16 ; i++) { + fread(keyA[i], 1, 6, fkeys); + } + for (i=0 ; i<16 ; i++) { + fread(keyB[i], 1, 6, fkeys); + } + + PrintAndLog("going..."); + + for (i=0 ; i<16 ; i++) { + for( j=0 ; j<4 ; j++) { + UsbCommand c = {CMD_MIFARE_WRITEBL, {i*4 + j, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + + fread(bldata, 1, 16, fdump); + + if (j == 3) { + bldata[0] = (keyA[i][0]); + bldata[1] = (keyA[i][1]); + bldata[2] = (keyA[i][2]); + bldata[3] = (keyA[i][3]); + bldata[4] = (keyA[i][4]); + bldata[5] = (keyA[i][5]); + bldata[10] = (keyB[i][0]); + bldata[11] = (keyB[i][1]); + bldata[12] = (keyB[i][2]); + bldata[13] = (keyB[i][3]); + bldata[14] = (keyB[i][4]); + bldata[15] = (keyB[i][5]); + } + + PrintAndLog("writing to block %2d: %s confirm?", i*4+j, sprint_hex(bldata, 16)); + + memcpy(c.d.asBytes + 10, bldata, 16); + SendCommand(&c); + UsbCommand *resp = WaitForResponseTimeout(CMD_ACK, 1500); + + if (resp != NULL) { + uint8_t isOK = resp->arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + } + } + + fclose(fdump); + fclose(fkeys); + return 0; +} + int CmdHF14AMfNested(const char *Cmd) { int i, j, res, iterations; @@ -268,17 +463,25 @@ int CmdHF14AMfNested(const char *Cmd) uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint8_t keyBlock[16 * 6]; uint64_t key64 = 0; + int transferToEml = 0; + + int createDumpFile = 0; + FILE *fkeys; char cmdp, ctmp; if (strlen(Cmd)<3) { PrintAndLog("Usage:"); - PrintAndLog(" all sectors: hf mf nested "); + PrintAndLog(" all sectors: hf mf nested [t,d]"); PrintAndLog(" one sector: hf mf nested o "); - PrintAndLog(" "); + PrintAndLog(" [t]"); PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLog("t - transfer keys into emulator memory"); + PrintAndLog("d - write keys to binary file"); PrintAndLog(" "); PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF "); + PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF t "); + PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF d "); PrintAndLog(" sample2: hf mf nested o 0 A FFFFFFFFFFFF 4 A"); return 0; } @@ -296,7 +499,7 @@ int CmdHF14AMfNested(const char *Cmd) return 1; } - if (cmdp =='o' || cmdp == 'O') { + if (cmdp == 'o' || cmdp == 'O') { cmdp = 'o'; trgBlockNo = param_get8(Cmd, 4); ctmp = param_getchar(Cmd, 5); @@ -314,8 +517,14 @@ int CmdHF14AMfNested(const char *Cmd) default: SectorsCnt = 16; } } + + ctmp = param_getchar(Cmd, 4); + if (ctmp == 't' || ctmp == 'T') transferToEml = 1; + ctmp = param_getchar(Cmd, 6); + transferToEml |= (ctmp == 't' || ctmp == 'T'); + createDumpFile |= (ctmp == 'd' || ctmp == 'D'); - PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); + PrintAndLog("--block no:%02x key type:%02x key:%s etrans:%d", blockNo, keyType, sprint_hex(key, 6), transferToEml); if (cmdp == 'o') PrintAndLog("--target block no:%02x target key type:%02x ", trgBlockNo, trgKeyType); @@ -333,10 +542,22 @@ int CmdHF14AMfNested(const char *Cmd) res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64); if (res) res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64); - if (!res) + if (!res) { PrintAndLog("Found valid key:%012llx", key64); - else + + // transfer key to the emulator + if (transferToEml) { + mfEmlGetMem(keyBlock, (trgBlockNo / 4) * 4 + 3, 1); + + if (!trgKeyType) + num_to_bytes(key64, 6, keyBlock); + else + num_to_bytes(key64, 6, &keyBlock[10]); + mfEmlSetMem(keyBlock, (trgBlockNo / 4) * 4 + 3, 1); + } + } else { PrintAndLog("No valid key found"); + } } else // ------------------------------------ multiple sectors working { blDiff = blockNo % 4; @@ -401,6 +622,33 @@ int CmdHF14AMfNested(const char *Cmd) } PrintAndLog("|---|----------------|---|----------------|---|"); + // transfer them to the emulator + if (transferToEml) { + for (i = 0; i < SectorsCnt; i++) { + mfEmlGetMem(keyBlock, i * 4 + 3, 1); + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[0], 6, keyBlock); + if (e_sector[i].foundKey[1]) + num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]); + mfEmlSetMem(keyBlock, i * 4 + 3, 1); + } + } + + if (createDumpFile) { + if ((fkeys = fopen("dumpkeys.bin","wb")) == NULL) { + PrintAndLog("Could not create file keys.bin"); + free(e_sector); + return 1; + } + for(i=0; i<16; i++) { + fwrite ( e_sector[i].Key, sizeof(e_sector[i].Key[0]), 1, fkeys ); + } + for(i=0; i<16; i++) { + fwrite ( e_sector[i].Key, sizeof(e_sector[i].Key[1]), 1, fkeys ); + } + fclose(fkeys); + } + free(e_sector); } @@ -421,7 +669,7 @@ int CmdHF14AMfChk(const char *Cmd) if (strlen(Cmd)<3) { PrintAndLog("Usage: hf mf chk []"); - PrintAndLog(" sample: hf mf chk 0 A FFFFFFFFFFFF a0a1a2a3a4a5 b01b2b3b4b5 "); + PrintAndLog(" sample: hf mf chk 0 A FFFFFFFFFFFF a0a1a2a3a4a5 b0b1b2b3b4b5 "); return 0; } @@ -488,7 +736,12 @@ int CmdHF14AMf1kSim(const char *Cmd) int CmdHF14AMfDbg(const char *Cmd) { - if (strlen(Cmd) < 1) { + int dbgMode = param_get32ex(Cmd, 0, 0, 10); + if (dbgMode > 4) { + PrintAndLog("Max debud mode parameter is 4 \n"); + } + + if (strlen(Cmd) < 1 || !param_getchar(Cmd, 0) || dbgMode > 4) { PrintAndLog("Usage: hf mf dbg "); PrintAndLog(" 0 - no debug messages"); PrintAndLog(" 1 - error messages"); @@ -497,49 +750,277 @@ int CmdHF14AMfDbg(const char *Cmd) return 0; } - PrintAndLog("No code here ("); + UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}}; + SendCommand(&c); + return 0; } int CmdHF14AMfEGet(const char *Cmd) { - PrintAndLog("No code here ("); + uint8_t blockNo = 0; + uint8_t data[3 * 16]; + int i; + + if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { + PrintAndLog("Usage: hf mf eget "); + PrintAndLog(" sample: hf mf eget 0 "); + return 0; + } + + blockNo = param_get8(Cmd, 0); + if (blockNo >= 16 * 4) { + PrintAndLog("Block number must be in [0..63] as in MIFARE classic."); + return 1; + } + + PrintAndLog(" "); + if (!mfEmlGetMem(data, blockNo, 3)) { + for (i = 0; i < 3; i++) { + PrintAndLog("data[%d]:%s", blockNo + i, sprint_hex(data + i * 16, 16)); + } + } else { + PrintAndLog("Command execute timeout"); + } + + return 0; +} + +int CmdHF14AMfEClear(const char *Cmd) +{ + if (param_getchar(Cmd, 0) == 'h') { + PrintAndLog("Usage: hf mf eclr"); + PrintAndLog("It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n"); + return 0; + } + + UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}}; + SendCommand(&c); return 0; } int CmdHF14AMfESet(const char *Cmd) { - PrintAndLog("No code here ("); + uint8_t memBlock[16]; + uint8_t blockNo = 0; + + memset(memBlock, 0x00, sizeof(memBlock)); + + if (strlen(Cmd) < 3 || param_getchar(Cmd, 0) == 'h') { + PrintAndLog("Usage: hf mf eset "); + PrintAndLog(" sample: hf mf eset 1 000102030405060708090a0b0c0d0e0f "); + return 0; + } + + blockNo = param_get8(Cmd, 0); + if (blockNo >= 16 * 4) { + PrintAndLog("Block number must be in [0..63] as in MIFARE classic."); + return 1; + } + + if (param_gethex(Cmd, 1, memBlock, 32)) { + PrintAndLog("block data must include 32 HEX symbols"); + return 1; + } + + // 1 - blocks count + UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNo, 1, 0}}; + memcpy(c.d.asBytes, memBlock, 16); + SendCommand(&c); return 0; } int CmdHF14AMfELoad(const char *Cmd) { - PrintAndLog("No code here ("); + FILE * f; + char filename[20]; + char * fnameptr = filename; + char buf[64]; + uint8_t buf8[64]; + int i, len, blockNum; + + memset(filename, 0, sizeof(filename)); + memset(buf, 0, sizeof(buf)); + + if (param_getchar(Cmd, 0) == 'h') { + PrintAndLog("It loads emul dump from the file `filename.eml`"); + PrintAndLog("Usage: hf mf eload "); + PrintAndLog(" sample: hf mf eload filename"); + return 0; + } + + len = strlen(Cmd); + if (len > 14) len = 14; + + if (len < 1) { + } + + memcpy(filename, Cmd, len); + fnameptr += len; + + sprintf(fnameptr, ".eml"); + + // open file + f = fopen(filename, "r"); + if (f == NULL) { + PrintAndLog("File not found or locked."); + return 1; + } + + blockNum = 0; + while(!feof(f)){ + memset(buf, 0, sizeof(buf)); + fgets(buf, sizeof(buf), f); + if (strlen(buf) < 32){ + PrintAndLog("File content error. Block data must include 32 HEX symbols"); + return 2; + } + for (i = 0; i < 32; i += 2) + sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]); +// PrintAndLog("data[%02d]:%s", blockNum, sprint_hex(buf8, 16)); + + if (mfEmlSetMem(buf8, blockNum, 1)) { + PrintAndLog("Cant set emul block: %d", blockNum); + return 3; + } + blockNum++; + + if (blockNum >= 16 * 4) break; + } + fclose(f); + + if (blockNum != 16 * 4){ + PrintAndLog("File content error. There must be 64 blocks"); + return 4; + } + PrintAndLog("Loaded from file: %s", filename); return 0; } int CmdHF14AMfESave(const char *Cmd) { - PrintAndLog("No code here ("); + FILE * f; + char filename[20]; + char * fnameptr = filename; + uint8_t buf[64]; + int i, j, len; + + memset(filename, 0, sizeof(filename)); + memset(buf, 0, sizeof(buf)); + + if (param_getchar(Cmd, 0) == 'h') { + PrintAndLog("It saves emul dump into the file `filename.eml` or `cardID.eml`"); + PrintAndLog("Usage: hf mf esave [file name w/o `.eml`]"); + PrintAndLog(" sample: hf mf esave "); + PrintAndLog(" hf mf esave filename"); + return 0; + } + + len = strlen(Cmd); + if (len > 14) len = 14; + + if (len < 1) { + // get filename + if (mfEmlGetMem(buf, 0, 1)) { + PrintAndLog("Cant get block: %d", 0); + return 1; + } + for (j = 0; j < 7; j++, fnameptr += 2) + sprintf(fnameptr, "%02x", buf[j]); + } else { + memcpy(filename, Cmd, len); + fnameptr += len; + } + + sprintf(fnameptr, ".eml"); + + // open file + f = fopen(filename, "w+"); + + // put hex + for (i = 0; i < 16 * 4; i++) { + if (mfEmlGetMem(buf, i, 1)) { + PrintAndLog("Cant get block: %d", i); + break; + } + for (j = 0; j < 16; j++) + fprintf(f, "%02x", buf[j]); + fprintf(f,"\n"); + } + fclose(f); + + PrintAndLog("Saved to file: %s", filename); + return 0; } -static command_t CommandTable[] = +int CmdHF14AMfECFill(const char *Cmd) +{ + uint8_t keyType = 0; + + if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { + PrintAndLog("Usage: hf mf efill "); + PrintAndLog("sample: hf mf efill A"); + PrintAndLog("Card data blocks transfers to card emulator memory."); + PrintAndLog("Keys must be laid in the simulator memory. \n"); + return 0; + } + + char ctmp = param_getchar(Cmd, 0); + if (ctmp == 0x00) { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (ctmp != 'A' && ctmp != 'a') keyType = 1; + + UsbCommand c = {CMD_MIFARE_EML_CARDLOAD, {0, keyType, 0}}; + SendCommand(&c); + return 0; +} + +int CmdHF14AMfEKeyPrn(const char *Cmd) +{ + int i; + uint8_t data[16]; + uint64_t keyA, keyB; + + PrintAndLog("|---|----------------|----------------|"); + PrintAndLog("|sec|key A |key B |"); + PrintAndLog("|---|----------------|----------------|"); + for (i = 0; i < 16; i++) { + if (mfEmlGetMem(data, i * 4 + 3, 1)) { + PrintAndLog("error get block %d", i * 4 + 3); + break; + } + keyA = bytes_to_num(data, 6); + keyB = bytes_to_num(data + 10, 6); + PrintAndLog("|%03d| %012llx | %012llx |", i, keyA, keyB); + } + PrintAndLog("|---|----------------|----------------|"); + + return 0; +} + +static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, + {"help", CmdHelp, 1, "This help"}, + {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, + {"dump1k", CmdHF14AMfDump1k, 0, "Dump MIFARE classic tag to binary file"}, + {"restore1k", CmdHF14AMfRestore1k, 0, "Restore MIFARE classic binary file to BLANK tag"}, {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, - {"chk", CmdHF14AMfChk, 0, "Test block up to 8 keys"}, + {"chk", CmdHF14AMfChk, 0, "Test block up to 8 keys"}, {"mifare", CmdHF14AMifare, 0, "Read parity error messages. param - "}, {"nested", CmdHF14AMfNested, 0, "Test nested authentication"}, - {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE 1k card"}, - {"eget", CmdHF14AMfEGet, 0, "Set simulator memory block"}, - {"eset", CmdHF14AMfESet, 0, "Get simulator memory block"}, + {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE 1k card"}, + {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"}, + {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, + {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"}, {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"}, + {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"}, + {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"}, {NULL, NULL, 0, NULL} };