From 6c84c900179a0ff0959046ff0d65c68ab9077c50 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Apr 2016 13:18:02 +0200 Subject: [PATCH] FIX: this fixes the "hf mf sniff l d f" command, which has been broken for a while. The cuid is correct used for decrypting. FIX: The flushing of logentries. ADD: "hf mf sniff" - added the sniffing of UID's with a uidlen of 10. Whats left? The key is not always found even if we use the "mfkey64" approach. ADD: added the parity_zero attack in "hf mf mifare". Still not working since piwi's changes to the iso14443a.c, maybe needs a param to tell it to collect nonces for this special attack. CHG: extracted some help-texts into usage_* methods. Changed some text as well FIX: "hf mf sim" command now uses both mfkey32 and mfkey32_moebius version to find the key in attack mode. CHG: "hf mf sim" also now defaults to emul_memory to read a 4 byte UID. --- client/cmdhfmf.c | 526 ++++++++++++++++++++++---------------------- client/mifarehost.c | 120 ++++------ client/mifarehost.h | 5 +- client/scripting.c | 1 - 4 files changed, 313 insertions(+), 339 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 797b5657..ec5d4487 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -13,9 +13,60 @@ #include "nonce2key/nonce2key.h" static int CmdHelp(const char *Cmd); +int usage_hf14_mifare(void){ + PrintAndLog("Usage: hf mf mifare [h] "); + PrintAndLog("options:"); + PrintAndLog(" h this help"); + PrintAndLog(" (Optional) target other key A than block 0."); + PrintAndLog("sample:"); + PrintAndLog(" hf mf mifare"); + PrintAndLog(" hf mf mifare 16"); + return 0; +} +int usage_hf14_mf1ksim(void){ + PrintAndLog("Usage: hf mf sim [h] u n i x"); + PrintAndLog("options:"); + PrintAndLog(" h this help"); + PrintAndLog(" u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used"); + PrintAndLog(" n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); + PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); + PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)"); + PrintAndLog("samples:"); + PrintAndLog(" hf mf sim u 0a0a0a0a"); + PrintAndLog(" hf mf sim u 11223344556677"); + PrintAndLog(" hf mf sim u 112233445566778899AA"); + return 0; +} +int usage_hf14_dbg(void){ + PrintAndLog("Usage: hf mf dbg [h] "); + PrintAndLog("options:"); + PrintAndLog(" h this help"); + PrintAndLog(" (Optional) see list for valid levels"); + PrintAndLog(" 0 - no debug messages"); + PrintAndLog(" 1 - error messages"); + PrintAndLog(" 2 - plus information messages"); + PrintAndLog(" 3 - plus debug messages"); + PrintAndLog(" 4 - print even debug messages in timing critical functions"); + PrintAndLog(" Note: this option therefore may cause malfunction itself"); + PrintAndLog("samples:"); + PrintAndLog(" hf mf dbg 3"); + return 0; +} +int usage_hf14_sniff(void){ + PrintAndLog("It continuously gets data from the field and saves it to: log, emulator, emulator file."); + PrintAndLog("Usage: hf mf sniff [h] [l] [d] [f]"); + PrintAndLog("options:"); + PrintAndLog(" h this help"); + PrintAndLog(" l save encrypted sequence to logfile `uid.log`"); + PrintAndLog(" d decrypt sequence and put it to log file `uid.log`"); +// PrintAndLog(" n/a e decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory"); + PrintAndLog(" f decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`"); + PrintAndLog("sample:"); + PrintAndLog(" hf mf sniff l d f"); + return 0; +} -int CmdHF14AMifare(const char *Cmd) -{ +int CmdHF14AMifare(const char *Cmd) { uint32_t uid = 0; uint32_t nt = 0, nr = 0; uint64_t par_list = 0, ks_list = 0, r_key = 0; @@ -24,21 +75,16 @@ int CmdHF14AMifare(const char *Cmd) uint8_t blockNo = 0; char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'H' || cmdp == 'h') { - PrintAndLog("Usage: hf mf mifare "); - PrintAndLog(" sample: hf mf mifare 0"); - return 0; - } + if ( cmdp == 'H' || cmdp == 'h') return usage_hf14_mifare(); blockNo = param_get8(Cmd, 0); UsbCommand c = {CMD_READER_MIFARE, {true, blockNo, 0}}; // message printf("-------------------------------------------------------------------------\n"); - printf("Executing command. Expected execution time: 25sec on average :-)\n"); + printf("Executing darkside attack. Expected execution time: 25sec on average :-)\n"); printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n"); printf("-------------------------------------------------------------------------\n"); - clock_t t1 = clock(); start: @@ -65,7 +111,13 @@ start: UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.arg[0]; - printf("\n\n"); + printf("\n"); + uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); + nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); + par_list = bytes_to_num(resp.d.asBytes + 8, 8); + ks_list = bytes_to_num(resp.d.asBytes + 16, 8); + nr = bytes_to_num(resp.d.asBytes + 24, 4); + switch (isOK) { case -1 : PrintAndLog("Button pressed. Aborted.\n"); break; case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break; @@ -74,17 +126,19 @@ start: PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break; default: ; } - uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); - nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); - par_list = bytes_to_num(resp.d.asBytes + 8, 8); - ks_list = bytes_to_num(resp.d.asBytes + 16, 8); - nr = bytes_to_num(resp.d.asBytes + 24, 4); break; } } - printf("\n"); + // par == 0 + if (isOK == -1 && par_list == 0) { + if (!nonce2key_ex(uid, nt, nr, ks_list, &r_key) ){ + PrintAndLog("Found valid key: %012"llx" \n", r_key); + goto END; + } + } + // error if (isOK != 1) return 1; @@ -98,7 +152,7 @@ start: } else { PrintAndLog("Found valid key: %012"llx" \n", r_key); } - +END: t1 = clock() - t1; if ( t1 > 0 ) PrintAndLog("Time in darkside: %.0f ticks\n", (float)t1); @@ -280,8 +334,7 @@ uint8_t NumBlocksPerSector(uint8_t sectorNo) } } -int CmdHF14AMfDump(const char *Cmd) -{ +int CmdHF14AMfDump(const char *Cmd) { uint8_t sectorNo, blockNo; uint8_t keyA[40][6]; @@ -453,8 +506,7 @@ int CmdHF14AMfDump(const char *Cmd) return 0; } -int CmdHF14AMfRestore(const char *Cmd) -{ +int CmdHF14AMfRestore(const char *Cmd) { uint8_t sectorNo,blockNo; uint8_t keyType = 0; uint8_t key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; @@ -563,8 +615,7 @@ int CmdHF14AMfRestore(const char *Cmd) return 0; } -int CmdHF14AMfNested(const char *Cmd) -{ +int CmdHF14AMfNested(const char *Cmd) { int i, j, res, iterations; sector *e_sector = NULL; uint8_t blockNo = 0; @@ -830,8 +881,7 @@ int CmdHF14AMfNested(const char *Cmd) return 0; } -int CmdHF14AMfNestedHard(const char *Cmd) -{ +int CmdHF14AMfNestedHard(const char *Cmd) { uint8_t blockNo = 0; uint8_t keyType = 0; uint8_t trgBlockNo = 0; @@ -946,8 +996,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) return 0; } -int CmdHF14AMfChk(const char *Cmd) -{ +int CmdHF14AMfChk(const char *Cmd) { if (strlen(Cmd)<3) { PrintAndLog("Usage: hf mf chk |<*card memory> [t|d] [] []"); PrintAndLog(" * - all sectors"); @@ -1236,116 +1285,242 @@ int CmdHF14AMfChk(const char *Cmd) return 0; } - int CmdHF14AMf1kSim(const char *Cmd) { uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t exitAfterNReads = 0; - uint8_t flags = 0; + uint8_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA); int uidlen = 0; + uint8_t pnr = 0; uint8_t cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mf sim u n i x"); - PrintAndLog(" h this help"); - PrintAndLog(" u (Optional) UID 4,7 or 10bytes. If not specified, the UID from emulator memory will be used"); - PrintAndLog(" n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); - PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); - PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)"); - PrintAndLog("samples:"); - PrintAndLog(" hf mf sim u 0a0a0a0a"); - PrintAndLog(" hf mf sim u 11223344556677"); - PrintAndLog(" hf mf sim u 112233445566778899AA"); - return 0; - } - uint8_t pnr = 0; - if (param_getchar(Cmd, pnr) == 'u') { - + if (cmdp == 'h' || cmdp == 'H') return usage_hf14_mf1ksim(); + + cmdp = param_getchar(Cmd, pnr); + if (cmdp == 'u' || cmdp == 'U') { param_gethex_ex(Cmd, pnr+1, uid, &uidlen); switch(uidlen){ - case 20: flags |= FLAG_10B_UID_IN_DATA; break; - case 14: flags |= FLAG_7B_UID_IN_DATA; break; - case 8: flags |= FLAG_4B_UID_IN_DATA; break; - default: - PrintAndLog("UID, if specified, must include 8, 14 or 20 HEX symbols , %d", uidlen>>1); - return 1; + case 20: flags = FLAG_10B_UID_IN_DATA; break; + case 14: flags = FLAG_7B_UID_IN_DATA; break; + case 8: flags = FLAG_4B_UID_IN_DATA; break; + default: return usage_hf14_mf1ksim(); } pnr +=2; } - - if (param_getchar(Cmd, pnr) == 'n') { - exitAfterNReads = param_get8(Cmd,pnr+1); + + cmdp = param_getchar(Cmd, pnr); + if (cmdp == 'n' || cmdp == 'N') { + exitAfterNReads = param_get8(Cmd, pnr+1); pnr += 2; } - - if (param_getchar(Cmd, pnr) == 'i' ) { + + cmdp = param_getchar(Cmd, pnr); + if (cmdp == 'i' || cmdp == 'I' ) { flags |= FLAG_INTERACTIVE; pnr++; } - if (param_getchar(Cmd, pnr) == 'x' ) { + cmdp = param_getchar(Cmd, pnr); + if (cmdp == 'x' || cmdp == 'X') { flags |= FLAG_NR_AR_ATTACK; } PrintAndLog(" uid:%s, numreads:%d, flags:%d (0x%02x) " - , (uidlen == 0 ) ? "N/A" : sprint_hex(uid, uidlen) + , (uidlen == 0 ) ? "N/A" : sprint_hex(uid, uidlen>>1) , exitAfterNReads , flags , flags); - UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}}; + UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads, 0}}; memcpy(c.d.asBytes, uid, sizeof(uid)); clearCommandBuffer(); SendCommand(&c); - if(flags & FLAG_INTERACTIVE) - { - uint8_t data[40]; - uint8_t key[6]; - + if(flags & FLAG_INTERACTIVE) { + uint8_t data[32]; + uint64_t key; UsbCommand resp; PrintAndLog("Press pm3-button or send another cmd to abort simulation"); - while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; - memset(data, 0x00, sizeof(data)); - memset(key, 0x00, sizeof(key)); + memset(data, 0x00, sizeof(data)); int len = (resp.arg[1] > sizeof(data)) ? sizeof(data) : resp.arg[1]; - - memcpy(data, resp.d.asBytes, len); - - // CUID is always 4 first bytes. - uint64_t cuid = bytes_to_num(data, 4 ); - - // this needs to be fixed. ICEMAN - if ( memcmp(data, "\x00\x00\x00\x00", 4) == 0 ) { - tryMfk32(cuid, data, key); - } else { - tryMfk64(cuid, data, key); - } + + memcpy(data, resp.d.asBytes, len); + key = 0; + bool found = tryMfk32(data, &key); + found ^= tryMfk32_moebius(data, &key); + if ( found ) break; } } return 0; } +int CmdHF14AMfSniff(const char *Cmd){ + bool wantLogToFile = FALSE; + bool wantDecrypt = FALSE; + //bool wantSaveToEml = FALSE; TODO + bool wantSaveToEmlFile = FALSE; + + //var + int tmpchar; + int res = 0; + int len = 0; + int blockLen = 0; + int pckNum = 0; + int num = 0; + uint8_t uid[10]; + uint8_t uid_len = 0; + uint8_t atqa[2] = {0x00, 0x00}; + uint8_t sak = 0; + bool isTag = FALSE; + uint8_t *buf = NULL; + uint16_t bufsize = 0; + uint8_t *bufPtr = NULL; + uint16_t traceLen = 0; + + memset(uid, 0x00, sizeof(uid)); + + char ctmp = param_getchar(Cmd, 0); + if ( ctmp == 'h' || ctmp == 'H' ) return usage_hf14_sniff(); + + for (int i = 0; i < 4; i++) { + ctmp = param_getchar(Cmd, i); + if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true; + if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true; + //if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO + if (ctmp == 'f' || ctmp == 'F') wantSaveToEmlFile = true; + } + + printf("-------------------------------------------------------------------------\n"); + printf("Executing mifare sniffing command. \n"); + printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); + printf("Press the key on pc keyboard to abort the client.\n"); + printf("-------------------------------------------------------------------------\n"); + + UsbCommand c = {CMD_MIFARE_SNIFFER, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + + // wait cycle + while (true) { + printf("."); + fflush(stdout); + if (ukbhit()) { + tmpchar = getchar(); + (void)tmpchar; + printf("\naborted via keyboard!\n"); + break; + } + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + res = resp.arg[0] & 0xff; + traceLen = resp.arg[1]; + len = resp.arg[2]; + + // we are done? + if (res == 0) { + free(buf); + return 0; + } + + if (res == 1) { // there is (more) data to be transferred + if (pckNum == 0) { // first packet, (re)allocate necessary buffer + if (traceLen > bufsize) { + uint8_t *p; + if (buf == NULL) // not yet allocated + p = malloc(traceLen); + else // need more memory + p = realloc(buf, traceLen); + + if (p == NULL) { + PrintAndLog("Cannot allocate memory for trace"); + free(buf); + return 2; + } + buf = p; + } + bufPtr = buf; + bufsize = traceLen; + memset(buf, 0x00, traceLen); + } + if (bufPtr == NULL) { + PrintAndLog("Cannot allocate memory for trace"); + free(buf); + return 2; + } + // what happens if LEN is bigger then TRACELEN --iceman + memcpy(bufPtr, resp.d.asBytes, len); + bufPtr += len; + pckNum++; + } + + if (res == 2) { // received all data, start displaying + blockLen = bufPtr - buf; + bufPtr = buf; + printf(">\n"); + PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum); + while (bufPtr - buf < blockLen) { + bufPtr += 6; // skip (void) timing information + len = *((uint16_t *)bufPtr); + if(len & 0x8000) { + isTag = true; + len &= 0x7fff; + } else { + isTag = false; + } + bufPtr += 2; + if ((len == 17) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[15] == 0xff) && (bufPtr[16] == 0xff)) { + memcpy(uid, bufPtr + 2, 10); + memcpy(atqa, bufPtr + 2 + 10, 2); + switch (atqa[0] & 0xC0) { + case 0x80: uid_len = 10; break; + case 0x40: uid_len = 7; break; + default: uid_len = 4; break; + } + sak = bufPtr[14]; + PrintAndLog("tag select uid| %s atqa:0x%02x%02x sak:0x%02x", + sprint_hex(uid, uid_len), + atqa[1], + atqa[0], + sak); + if (wantLogToFile || wantDecrypt) { + FillFileNameByUID(logHexFileName, uid, ".log", uid_len); + AddLogCurrentDT(logHexFileName); + } + if (wantDecrypt) + mfTraceInit(uid, uid_len, atqa, sak, wantSaveToEmlFile); + } else { + PrintAndLog("%03d| %s |%s", num, isTag ? "TAG" : "RDR", sprint_hex(bufPtr, len)); + if (wantLogToFile) + AddLogHex(logHexFileName, isTag ? "TAG| ":"RDR| ", bufPtr, len); + if (wantDecrypt) + mfTraceDecode(bufPtr, len, wantSaveToEmlFile); + num++; + } + bufPtr += len; + bufPtr += ((len-1)/8+1); // ignore parity + } + pckNum = 0; + } + } // resp not NULL + } // while (true) + + free(buf); + return 0; +} + int CmdHF14AMfDbg(const char *Cmd) { - int dbgMode = param_get32ex(Cmd, 0, 0, 10); - if (dbgMode > 4) - PrintAndLog("Max debug 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"); - PrintAndLog(" 2 - plus information messages"); - PrintAndLog(" 3 - plus debug messages"); - PrintAndLog(" 4 - print even debug messages in timing critical functions"); - PrintAndLog(" Note: this option therefore may cause malfunction itself"); - return 0; - } + + char ctmp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 1 || ctmp == 'h'|| ctmp == 'H') return usage_hf14_dbg(); + + uint8_t dbgMode = param_get8ex(Cmd, 0, 0, 10); + if (dbgMode > 4) return usage_hf14_dbg(); UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}}; SendCommand(&c); @@ -2066,172 +2241,9 @@ int CmdHF14AMfCSave(const char *Cmd) { } } - - -int CmdHF14AMfSniff(const char *Cmd){ - - bool wantLogToFile = 0; - bool wantDecrypt = 0; - //bool wantSaveToEml = 0; TODO - bool wantSaveToEmlFile = 0; - - //var - int tmpchar; - int res = 0; - int len = 0; - int blockLen = 0; - int pckNum = 0; - int num = 0; - uint8_t uid[10]; - uint8_t uid_len = 0; - uint8_t atqa[2] = {0x00, 0x00}; - uint8_t sak = 0; - bool isTag; - uint8_t *buf = NULL; - uint16_t bufsize = 0; - uint8_t *bufPtr = NULL; - - memset(uid, 0x00, sizeof(uid)); - - char ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'h' || ctmp == 'H' ) { - PrintAndLog("It continuously gets data from the field and saves it to: log, emulator, emulator file."); - PrintAndLog("You can specify:"); - PrintAndLog(" l - save encrypted sequence to logfile `uid.log`"); - PrintAndLog(" d - decrypt sequence and put it to log file `uid.log`"); - PrintAndLog(" n/a e - decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory"); - PrintAndLog(" f - decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`"); - PrintAndLog("Usage: hf mf sniff [l][d][e][f]"); - PrintAndLog(" sample: hf mf sniff l d e"); - return 0; - } - - for (int i = 0; i < 4; i++) { - ctmp = param_getchar(Cmd, i); - if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true; - if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true; - //if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO - if (ctmp == 'f' || ctmp == 'F') wantSaveToEmlFile = true; - } - - printf("-------------------------------------------------------------------------\n"); - printf("Executing command. \n"); - printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); - printf("Press the key on pc keyboard to abort the client.\n"); - printf("-------------------------------------------------------------------------\n"); - - UsbCommand c = {CMD_MIFARE_SNIFFER, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - - // wait cycle - while (true) { - printf("."); - fflush(stdout); - if (ukbhit()) { - tmpchar = getchar(); - (void)tmpchar; - printf("\naborted via keyboard!\n"); - break; - } - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) { - res = resp.arg[0] & 0xff; - uint16_t traceLen = resp.arg[1]; - len = resp.arg[2]; - - // we are done? - if (res == 0) { - free(buf); - return 0; - } - - if (res == 1) { // there is (more) data to be transferred - if (pckNum == 0) { // first packet, (re)allocate necessary buffer - if (traceLen > bufsize) { - uint8_t *p; - if (buf == NULL) { // not yet allocated - p = malloc(traceLen); - } else { // need more memory - p = realloc(buf, traceLen); - } - if (p == NULL) { - PrintAndLog("Cannot allocate memory for trace"); - free(buf); - return 2; - } - buf = p; - } - bufPtr = buf; - bufsize = traceLen; - memset(buf, 0x00, traceLen); - } - if (bufPtr == NULL) { - PrintAndLog("Cannot allocate memory for trace"); - free(buf); - return 2; - } - memcpy(bufPtr, resp.d.asBytes, len); - bufPtr += len; - pckNum++; - } - - if (res == 2) { // received all data, start displaying - blockLen = bufPtr - buf; - bufPtr = buf; - printf(">\n"); - PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum); - while (bufPtr - buf < blockLen) { - bufPtr += 6; // skip (void) timing information - len = *((uint16_t *)bufPtr); - if(len & 0x8000) { - isTag = true; - len &= 0x7fff; - } else { - isTag = false; - } - bufPtr += 2; - if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) { - memcpy(uid, bufPtr + 2, 7); - memcpy(atqa, bufPtr + 2 + 7, 2); - uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4; - sak = bufPtr[11]; - PrintAndLog("tag select uid| %s atqa:0x%02x%02x sak:0x%02x", - sprint_hex(uid + (7 - uid_len), uid_len), - atqa[1], - atqa[0], - sak); - if (wantLogToFile || wantDecrypt) { - FillFileNameByUID(logHexFileName, uid + (10 - uid_len), ".log", uid_len); - AddLogCurrentDT(logHexFileName); - } - if (wantDecrypt) - mfTraceInit(uid, atqa, sak, wantSaveToEmlFile); - } else { - PrintAndLog("%03d| %s |%s", num, isTag ? "TAG" : "RDR", sprint_hex(bufPtr, len)); - if (wantLogToFile) - AddLogHex(logHexFileName, isTag ? "TAG| ":"RDR| ", bufPtr, len); - if (wantDecrypt) - mfTraceDecode(bufPtr, len, wantSaveToEmlFile); - num++; - } - bufPtr += len; - bufPtr += ((len-1)/8+1); // ignore parity - } - pckNum = 0; - } - } // resp not NULL - } // while (true) - - free(buf); - return 0; -} - //needs nt, ar, at, Data to decrypt int CmdHf14MfDecryptBytes(const char *Cmd){ uint8_t data[50]; - uint32_t nt = param_get32ex(Cmd,0,0,16); uint32_t ar_enc = param_get32ex(Cmd,1,0,16); uint32_t at_enc = param_get32ex(Cmd,2,0,16); @@ -2280,9 +2292,7 @@ static command_t CommandTable[] = { }; int CmdHFMF(const char *Cmd) { - // flush clearCommandBuffer(); - //WaitForResponseTimeout(CMD_ACK,NULL,100); CmdsParse(CommandTable, Cmd); return 0; } diff --git a/client/mifarehost.c b/client/mifarehost.c index 3e8362c5..1939b92b 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -342,12 +342,11 @@ static uint8_t traceCurKey = 0; struct Crypto1State *traceCrypto1 = NULL; struct Crypto1State *revstate = NULL; - uint64_t key = 0; uint32_t ks2 = 0; uint32_t ks3 = 0; -uint32_t uid = 0; // serial number +uint32_t cuid = 0; // serial number uint32_t nt =0; // tag challenge uint32_t nr_enc =0; // encrypted reader challenge uint32_t ar_enc =0; // encrypted reader response @@ -368,7 +367,7 @@ int isBlockTrailer(int blockN) { return ((blockN & 0x03) == 0x03); } -int loadTraceCard(uint8_t *tuid) { +int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { FILE * f; char buf[64] = {0x00}; uint8_t buf8[64] = {0x00}; @@ -378,9 +377,9 @@ int loadTraceCard(uint8_t *tuid) { saveTraceCard(); memset(traceCard, 0x00, 4096); - memcpy(traceCard, tuid + 3, 4); + memcpy(traceCard, tuid, uidlen); - FillFileNameByUID(traceFileName, tuid, ".eml", 7); + FillFileNameByUID(traceFileName, tuid, ".eml", uidlen); f = fopen(traceFileName, "r"); if (!f) return 1; @@ -391,7 +390,7 @@ int loadTraceCard(uint8_t *tuid) { memset(buf, 0, sizeof(buf)); if (fgets(buf, sizeof(buf), f) == NULL) { - PrintAndLog("File reading error."); + PrintAndLog("No trace file found or reading error."); fclose(f); return 2; } @@ -403,35 +402,35 @@ int loadTraceCard(uint8_t *tuid) { return 2; } for (i = 0; i < 32; i += 2) - sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]); + sscanf(&buf[i], "%02X", (unsigned int *)&buf8[i / 2]); memcpy(traceCard + blockNum * 16, buf8, 16); blockNum++; } fclose(f); - return 0; } int saveTraceCard(void) { - FILE * f; if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0; + FILE * f; f = fopen(traceFileName, "w+"); if ( !f ) return 1; for (int i = 0; i < 64; i++) { // blocks for (int j = 0; j < 16; j++) // bytes - fprintf(f, "%02x", *(traceCard + i * 16 + j)); + fprintf(f, "%02X", *(traceCard + i * 16 + j)); fprintf(f,"\n"); } + fflush(f); fclose(f); return 0; } -int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) { +int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) { if (traceCrypto1) crypto1_destroy(traceCrypto1); @@ -439,16 +438,14 @@ int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFil traceCrypto1 = NULL; if (wantSaveToEmlFile) - loadTraceCard(tuid); + loadTraceCard(tuid, uidlen); traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3]; traceCard[5] = sak; memcpy(&traceCard[6], atqa, 2); traceCurBlock = 0; - uid = bytes_to_num(tuid + 3, 4); - + cuid = bytes_to_num(tuid+(uidlen-4), 4); traceState = TRACE_IDLE; - return 0; } @@ -471,30 +468,31 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i } int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { - - uint8_t data[64]; - memset(data, 0x00, sizeof(data)); - + if (traceState == TRACE_ERROR) return 1; - + if (len > 64) { traceState = TRACE_ERROR; return 1; } + uint8_t data[64]; + memset(data, 0x00, sizeof(data)); + memcpy(data, data_src, len); + if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) { mf_crypto1_decrypt(traceCrypto1, data, len, 0); - PrintAndLog("dec> %s", sprint_hex(data, len)); - AddLogHex(logHexFileName, "dec> ", data, len); + PrintAndLog("DEC| %s", sprint_hex(data, len)); + AddLogHex(logHexFileName, "DEC| ", data, len); } switch (traceState) { case TRACE_IDLE: // check packet crc16! if ((len >= 4) && (!CheckCrc14443(CRC_14443_A, data, len))) { - PrintAndLog("dec> CRC ERROR!!!"); - AddLogLine(logHexFileName, "dec> ", "CRC ERROR!!!"); + PrintAndLog("DEC| CRC ERROR!!!"); + AddLogLine(logHexFileName, "DEC| ", "CRC ERROR!!!"); traceState = TRACE_ERROR; // do not decrypt the next commands return 1; } @@ -526,10 +524,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { traceState = TRACE_ERROR; // do not decrypt the next commands return 0; } - return 0; - break; - case TRACE_READ_DATA: if (len == 18) { traceState = TRACE_IDLE; @@ -545,23 +540,19 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { traceState = TRACE_ERROR; return 1; } - break; - + break; case TRACE_WRITE_OK: if ((len == 1) && (data[0] == 0x0a)) { traceState = TRACE_WRITE_DATA; - return 0; } else { traceState = TRACE_ERROR; return 1; } - break; - + break; case TRACE_WRITE_DATA: if (len == 18) { traceState = TRACE_IDLE; - memcpy(traceCard + traceCurBlock * 16, data, 16); if (wantSaveToEmlFile) saveTraceCard(); return 0; @@ -569,8 +560,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { traceState = TRACE_ERROR; return 1; } - break; - + break; case TRACE_AUTH1: if (len == 4) { traceState = TRACE_AUTH2; @@ -580,12 +570,10 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { traceState = TRACE_ERROR; return 1; } - break; - + break; case TRACE_AUTH2: if (len == 8) { traceState = TRACE_AUTH_OK; - nr_enc = bytes_to_num(data, 4); ar_enc = bytes_to_num(data + 4, 4); return 0; @@ -593,12 +581,10 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { traceState = TRACE_ERROR; return 1; } - break; - + break; case TRACE_AUTH_OK: - if (len ==4) { + if (len == 4) { traceState = TRACE_IDLE; - at_enc = bytes_to_num(data, 4); // decode key here) @@ -608,73 +594,51 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, nr_enc, 1); - lfsr_rollback_word(revstate, uid ^ nt, 0); - + lfsr_rollback_word(revstate, cuid ^ nt, 0); crypto1_get_lfsr(revstate, &key); - printf("Key: %012"llx"\n",key); - AddLogUint64(logHexFileName, "key: ", key); + PrintAndLog("Found Key: [%012"llx"]", key); + + //if ( tryMfk64(cuid, nt, nr_enc, ar_enc, at_enc, &key) ) + AddLogUint64(logHexFileName, "Found Key: ", key); int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4); - if (traceCurKey) { + if (traceCurKey) num_to_bytes(key, 6, traceCard + blockShift + 10); - } else { + else num_to_bytes(key, 6, traceCard + blockShift); - } - if (wantSaveToEmlFile) saveTraceCard(); + + if (wantSaveToEmlFile) + saveTraceCard(); - if (traceCrypto1) { + if (traceCrypto1) crypto1_destroy(traceCrypto1); - } // set cryptosystem state traceCrypto1 = lfsr_recovery64(ks2, ks3); -// nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt; - - /* traceCrypto1 = crypto1_create(key); // key in lfsr - crypto1_word(traceCrypto1, nt ^ uid, 0); - crypto1_word(traceCrypto1, ar, 1); - crypto1_word(traceCrypto1, 0, 0); - crypto1_word(traceCrypto1, 0, 0);*/ - return 0; } else { traceState = TRACE_ERROR; return 1; } - break; - + break; default: traceState = TRACE_ERROR; return 1; } - return 0; } int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){ - /* - uint32_t nt; // tag challenge - uint32_t nr_enc; // encrypted reader challenge - uint32_t ar_enc; // encrypted reader response - uint32_t at_enc; // encrypted tag response - */ + PrintAndLog("\nEncrypted data: [%s]", sprint_hex(data, len) ); struct Crypto1State *pcs = NULL; - ks2 = ar_enc ^ prng_successor(nt, 64); ks3 = at_enc ^ prng_successor(nt, 96); - - PrintAndLog("Decrypting data with:"); - PrintAndLog(" nt: %08x",nt); - PrintAndLog(" ar_enc: %08x",ar_enc); - PrintAndLog(" at_enc: %08x",at_enc); - PrintAndLog("\nEncrypted data: [%s]", sprint_hex(data,len) ); - pcs = lfsr_recovery64(ks2, ks3); mf_crypto1_decrypt(pcs, data, len, FALSE); - PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) ); + PrintAndLog("Decrypted data: [%s]", sprint_hex(data, len) ); crypto1_destroy(pcs); return 0; } diff --git a/client/mifarehost.h b/client/mifarehost.h index a214ede4..2355017c 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -40,6 +40,7 @@ typedef struct { int foundKey[2]; } sector; +int compar_int(const void * a, const void * b); extern char logHexFileName[FILE_PATH_SIZE]; int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate); @@ -53,12 +54,12 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params); int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); -int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); +int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile); int isTraceCardEmpty(void); int isBlockEmpty(int blockN); int isBlockTrailer(int blockN); -int loadTraceCard(uint8_t *tuid); +int loadTraceCard(uint8_t *tuid, uint8_t uidlen); int saveTraceCard(void); int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); diff --git a/client/scripting.c b/client/scripting.c index 5189f59a..64fb2a8f 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -487,7 +487,6 @@ int setLuaPath( lua_State* L, const char* path ) return 0; // all done! } - int set_pm3_libraries(lua_State *L) { -- 2.39.2