diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 49718ee8..501f07a5 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -171,7 +171,7 @@ static int ReadAdc(int ch) return d; } -static int AvgAdc(int ch) +int AvgAdc(int ch) // was static - merlok { int i; int a = 0; @@ -930,6 +930,8 @@ void __attribute__((noreturn)) AppMain(void) // Load the FPGA image, which we have stored in our flash. FpgaDownloadAndGo(); + StartTickCount(); + #ifdef WITH_LCD LCDInit(); diff --git a/armsrc/apps.h b/armsrc/apps.h index 322f2674..3b461136 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -33,6 +33,8 @@ void DbpString(char *str); void Dbprintf(const char *fmt, ...); void Dbhexdump(int len, uint8_t *d); +int AvgAdc(int ch); + void ToSendStuffBit(int b); void ToSendReset(void); void ListenReaderField(int limit); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 9e1eea54..fb50cc82 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -932,6 +932,7 @@ static int GetIso14443aCommandFromReader(uint8_t *received, int *len, int maxLen } } } +static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, int correctionNeeded); //----------------------------------------------------------------------------- // Main loop of simulated tag: receive commands from reader, decide what @@ -1180,8 +1181,13 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); } if(respLen <= 0) continue; + //---------------------------- + u = 0; + b = 0x00; + fdt_indicator = FALSE; - // Modulate Manchester + EmSendCmd14443aRaw(resp, respLen, receivedCmd[0] == 0x52); +/* // Modulate Manchester FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); AT91C_BASE_SSC->SSC_THR = 0x00; FpgaSetupSsc(); @@ -1213,7 +1219,7 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); break; } } - +*/ } Dbprintf("%x %x %x", happened, happened2, cmdsRecvd); @@ -1398,6 +1404,133 @@ void CodeIso14443aAsReaderPar(const uint8_t * cmd, int len, uint32_t dwParity) ToSendMax++; } +//----------------------------------------------------------------------------- +// Wait for commands from reader +// Stop when button is pressed (return 1) or field was gone (return 2) +// Or return 0 when command is captured +//----------------------------------------------------------------------------- +static int EmGetCmd(uint8_t *received, int *len, int maxLen) +{ + *len = 0; + + uint32_t timer = 0, vtime = 0; + int analogCnt = 0; + int analogAVG = 0; + + // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen + // only, since we are receiving, not transmitting). + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); + + // Set ADC to read field strength + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; + AT91C_BASE_ADC->ADC_MR = + ADC_MODE_PRESCALE(32) | + ADC_MODE_STARTUP_TIME(16) | + ADC_MODE_SAMPLE_HOLD_TIME(8); + AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF); + // start ADC + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; + + // Now run a 'software UART' on the stream of incoming samples. + Uart.output = received; + Uart.byteCntMax = maxLen; + Uart.state = STATE_UNSYNCD; + + for(;;) { + WDT_HIT(); + + if (BUTTON_PRESS()) return 1; + + // test if the field exists + if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) { + analogCnt++; + analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF]; + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; + if (analogCnt >= 32) { + if ((33000 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) { + vtime = GetTickCount(); + if (!timer) timer = vtime; + // 50ms no field --> card to idle state + if (vtime - timer > 50) return 2; + } else + if (timer) timer = 0; + analogCnt = 0; + analogAVG = 0; + } + } + // transmit none + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + } + // receive and test the miller decoding + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + if(MillerDecoding((b & 0xf0) >> 4)) { + *len = Uart.byteCnt; + return 0; + } + if(MillerDecoding(b & 0x0f)) { + *len = Uart.byteCnt; + return 0; + } + } + } +} + +static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, int correctionNeeded) +{ + int i, u = 0; + uint8_t b = 0; + + // Modulate Manchester + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); + AT91C_BASE_SSC->SSC_THR = 0x00; + FpgaSetupSsc(); + + // include correction bit + i = 1; + if((Uart.parityBits & 0x01) || correctionNeeded) { + // 1236, so correction bit needed + i = 0; + } + + // send cycle + for(;;) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + (void)b; + } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + if(i > respLen) { + b = 0x00; + u++; + } else { + b = resp[i]; + i++; + } + AT91C_BASE_SSC->SSC_THR = b; + + if(u > 4) break; + } + if(BUTTON_PRESS()) { + break; + } + } + + return 0; +} + +static int EmSendCmdEx(uint8_t *resp, int respLen, int correctionNeeded){ + CodeIso14443aAsTag(resp, respLen); + return EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded); +} + +static int EmSendCmd(uint8_t *resp, int respLen){ + return EmSendCmdEx(resp, respLen, 0); +} + //----------------------------------------------------------------------------- // Wait a certain time for tag response // If a response is captured return TRUE @@ -2390,33 +2523,161 @@ void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { int cardSTATE = MFEMUL_NOFIELD; - - while (true) { - - if(BUTTON_PRESS()) { - break; - } + int vHf = 0; // in mV + int res; + uint32_t timer = 0; + int len = 0; + uint8_t cardAUTHSC = 0; + uint8_t cardAUTHKEY = 0xff; // no authentication + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint64_t key64 = 0xffffffffffffULL; + + uint8_t* receivedCmd = mifare_get_bigbufptr(); + + static uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k + + static uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; + static uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!! + + static uint8_t rSAK[] = {0x08, 0xb6, 0xdd}; + + static uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04}; + +// -------------------------------------- test area + + +// -------------------------------------- END test area + + // We need to listen to the high-frequency, peak-detected path. + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); + SpinDelay(200); + +Dbprintf("--> start"); + while (true) { + WDT_HIT(); +// timer = GetTickCount(); +// Dbprintf("time: %d", GetTickCount() - timer); + + // find reader field + // Vref = 3300mV, and an 10:1 voltage divider on the input + // can measure voltages up to 33000 mV + if (cardSTATE == MFEMUL_NOFIELD) { + vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10; + if (vHf > MF_MINFIELDV) { + cardSTATE = MFEMUL_IDLE; + LED_A_ON(); + } + } + + if (cardSTATE != MFEMUL_NOFIELD) { + res = EmGetCmd(receivedCmd, &len, 100); + if (res == 2) { + cardSTATE = MFEMUL_NOFIELD; + LEDsoff(); + continue; + } + if(res) break; + } + + if(BUTTON_PRESS()) { + break; + } + +// if (len) Dbprintf("len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]); + switch (cardSTATE) { case MFEMUL_NOFIELD:{ break; } + case MFEMUL_HALTED:{ + // WUP request + if (!(len == 1 && receivedCmd[0] == 0x52)) break; + } case MFEMUL_IDLE:{ + // REQ or WUP request + if (len == 1 && (receivedCmd[0] == 0x26 || receivedCmd[0] == 0x52)) { +timer = GetTickCount(); + EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52)); + cardSTATE = MFEMUL_SELECT1; + + // init crypto block + crypto1_destroy(pcs); + cardAUTHKEY = 0xff; + } break; } case MFEMUL_SELECT1:{ + // select all + if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) { + EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1)); + + if (rUIDBCC1[0] == 0x88) { + cardSTATE = MFEMUL_SELECT2; + } + } + + // select card + if (len == 9 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70)) { + EmSendCmd(rSAK, sizeof(rSAK)); + + cuid = bytes_to_num(rUIDBCC1, 4); + cardSTATE = MFEMUL_WORK; + LED_B_ON(); +Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - timer); + } + break; } case MFEMUL_SELECT2:{ + EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2)); + + cuid = bytes_to_num(rUIDBCC2, 4); + cardSTATE = MFEMUL_WORK; + LED_B_ON(); +Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - timer); break; } case MFEMUL_AUTH1:{ +if (len) Dbprintf("au1 len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]); + if (len == 8) { + + } break; } case MFEMUL_AUTH2:{ + + LED_C_ON(); +Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - timer); break; } - case MFEMUL_HALTED:{ + case MFEMUL_WORK:{ + // auth + if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) { +timer = GetTickCount(); + crypto1_create(pcs, key64); +// if (cardAUTHKEY == 0xff) { // first auth + crypto1_word(pcs, cuid ^ bytes_to_num(rAUTH_NT, 4), 0); // uid ^ nonce +// } else { // nested auth +// } + + EmSendCmd(rAUTH_NT, sizeof(rAUTH_NT)); + cardAUTHSC = receivedCmd[1]; + cardAUTHKEY = receivedCmd[0] - 0x60; + cardSTATE = MFEMUL_AUTH1; + } + + // halt + if (len == 4 && (receivedCmd[0] == 0x50 || receivedCmd[0] == 0x00)) { + cardSTATE = MFEMUL_HALTED; + LED_B_OFF(); + } break; } @@ -2424,4 +2685,8 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + + DbpString("Emulator stopped."); } diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 53e785f5..fc95de72 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -266,3 +266,4 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) return 0; } + diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 9a909a35..4433fe65 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -8,15 +8,20 @@ //----------------------------------------------------------------------------- // code for work with mifare cards. //----------------------------------------------------------------------------- + #ifndef __MIFAREUTIL_H #define __MIFAREUTIL_H +// mifare authentication #define CRYPT_NONE 0 #define CRYPT_ALL 1 #define CRYPT_REQUEST 2 #define AUTH_FIRST 0 #define AUTH_NESTED 2 +// reader voltage field detector +#define MF_MINFIELDV 4000 + // debug // 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode #define MF_DBG_NONE 0 @@ -33,14 +38,15 @@ extern int MF_DBGLEVEL; #define NS_RETRIES_GETNONCE 15 #define NES_MAX_INFO 5 -//mifare emulate states +//mifare emulator states #define MFEMUL_NOFIELD 0 #define MFEMUL_IDLE 1 #define MFEMUL_SELECT1 2 #define MFEMUL_SELECT2 3 #define MFEMUL_AUTH1 4 #define MFEMUL_AUTH2 5 -#define MFEMUL_HALTED 6 +#define MFEMUL_WORK 6 +#define MFEMUL_HALTED 7 //functions uint8_t* mifare_get_bigbufptr(void); diff --git a/armsrc/util.c b/armsrc/util.c index 5a8cfeec..9c6b3e8d 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -235,3 +235,30 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers strncat(dst, " ", len); strncat(dst, v->buildtime, len); } + +// ------------------------------------------------------------------------- +// timer lib +// ------------------------------------------------------------------------- +// test procedure: +// +// ti = GetTickCount(); +// SpinDelay(1000); +// ti = GetTickCount() - ti; +// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount()); + +void StartTickCount() +{ +// must be 0x40, but on my cpu - included divider is optimal +// 0x20 - 1 ms / bit +// 0x40 - 2 ms / bit + + AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST + 0x003B; +} + +/* +* Get the current count. +*/ +uint32_t RAMFUNC GetTickCount(){ + return AT91C_BASE_RTTC->RTTC_RTVR * 2; +} + diff --git a/armsrc/util.h b/armsrc/util.h index 34760ab1..080dac6b 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -14,6 +14,8 @@ #include #include +#define RAMFUNC __attribute((long_call, section(".ramfunc"))) + #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) #define LED_RED 1 @@ -37,4 +39,7 @@ int BUTTON_CLICKED(int ms); int BUTTON_HELD(int ms); void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information); +void StartTickCount(); +uint32_t RAMFUNC GetTickCount(); + #endif diff --git a/client/Makefile b/client/Makefile index cf647c38..c76edf52 100644 --- a/client/Makefile +++ b/client/Makefile @@ -58,6 +58,7 @@ CMDSRCS = \ cmdhf15.c \ cmdhflegic.c \ cmdhficlass.c \ + cmdhfmf.c \ cmdhw.c \ cmdlf.c \ cmdlfem4x.c \ diff --git a/client/cmdhf.c b/client/cmdhf.c index 15b9e984..87c819fb 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -19,6 +19,7 @@ #include "cmdhf15.h" #include "cmdhflegic.h" #include "cmdhficlass.h" +#include "cmdhfmf.h" static int CmdHelp(const char *Cmd); @@ -37,6 +38,7 @@ static command_t CommandTable[] = {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, {"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, + {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index f2774a16..2a8c1f87 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "util.h" #include "iso14443crc.h" #include "data.h" @@ -23,9 +22,6 @@ #include "cmdhf14a.h" #include "common.h" #include "cmdmain.h" -#include "nonce2key/nonce2key.h" -#include "nonce2key/crapto1.h" -#include "mifarehost.h" static int CmdHelp(const char *Cmd); @@ -161,500 +157,13 @@ void iso14a_set_timeout(uint32_t timeout) { SendCommand(&c); } -int CmdHF14AMifare(const char *Cmd) -{ - uint32_t uid = 0; - uint32_t nt = 0; - uint64_t par_list = 0, ks_list = 0, r_key = 0; - uint8_t isOK = 0; - uint8_t keyBlock[6] = {0,0,0,0,0,0}; - - if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, keyBlock, 8)) { - PrintAndLog("Nt must include 8 HEX symbols"); - return 1; - } - - UsbCommand c = {CMD_READER_MIFARE, {(uint32_t)bytes_to_num(keyBlock, 4), 0, 0}}; - SendCommand(&c); - - //flush queue - while (ukbhit()) getchar(); - - // message - printf("-------------------------------------------------------------------------\n"); - printf("Executing command. It may take up to 30 min.\n"); - printf("Press the key on proxmark3 device to abort proxmark3.\n"); - printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); - printf("-------------------------------------------------------------------------\n"); - - // wait cycle - while (true) { - printf("."); - if (ukbhit()) { - getchar(); - printf("\naborted via keyboard!\n"); - break; - } - - UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 2000); - if (resp != NULL) { - isOK = resp->arg[0] & 0xff; - - 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); - - printf("\n\n"); - PrintAndLog("isOk:%02x", isOK); - if (!isOK) PrintAndLog("Proxmark can't get statistic info. Execution aborted.\n"); - break; - } - } - printf("\n"); - - // error - if (isOK != 1) return 1; - - // execute original function from util nonce2key - if (nonce2key(uid, nt, par_list, ks_list, &r_key)) return 2; - printf("------------------------------------------------------------------\n"); - PrintAndLog("Key found:%012llx \n", r_key); - - num_to_bytes(r_key, 6, keyBlock); - isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key); - if (!isOK) - PrintAndLog("Found valid key:%012llx", r_key); - else - PrintAndLog("Found invalid key. ("); - - - return 0; -} - -int CmdHF14AMfWrBl(const char *Cmd) -{ - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - char cmdp = 0x00; - - if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf 14 mfwrbl "); - PrintAndLog(" sample: hf 14a mfwrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); - return 0; - } - - blockNo = param_get8(Cmd, 0); - cmdp = param_getchar(Cmd, 1); - if (cmdp == 0x00) { - PrintAndLog("Key type must be A or B"); - return 1; - } - if (cmdp != 'A' && cmdp != 'a') keyType = 1; - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLog("Key must include 12 HEX symbols"); - return 1; - } - if (param_gethex(Cmd, 3, bldata, 32)) { - PrintAndLog("Block data must include 32 HEX symbols"); - return 1; - } - PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6)); - PrintAndLog("--data: %s", sprint_hex(bldata, 16)); - - UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - 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"); - } - - return 0; -} - -int CmdHF14AMfRdBl(const char *Cmd) -{ - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - - char cmdp = 0x00; - - - if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf 14 mfrdbl "); - PrintAndLog(" sample: hf 14a mfrdbl 0 A FFFFFFFFFFFF "); - return 0; - } - - blockNo = param_get8(Cmd, 0); - cmdp = param_getchar(Cmd, 1); - if (cmdp == 0x00) { - PrintAndLog("Key type must be A or B"); - return 1; - } - if (cmdp != 'A' && cmdp != 'a') keyType = 1; - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLog("Key must include 12 HEX symbols"); - return 1; - } - PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); - - UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - SendCommand(&c); - UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500); - - if (resp != NULL) { - uint8_t isOK = resp->arg[0] & 0xff; - uint8_t * data = resp->d.asBytes; - - if (isOK) - PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16)); - else - PrintAndLog("isOk:%02x", isOK); - } else { - PrintAndLog("Command execute timeout"); - } - - return 0; -} - -int CmdHF14AMfRdSc(const char *Cmd) -{ - int i; - uint8_t sectorNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - - uint8_t isOK = 0; - uint8_t * data = NULL; - - char cmdp = 0x00; - - if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf 14 mfrdsc "); - PrintAndLog(" sample: hf 14a mfrdsc 0 A FFFFFFFFFFFF "); - return 0; - } - - sectorNo = param_get8(Cmd, 0); - if (sectorNo > 63) { - PrintAndLog("Sector number must be less than 64"); - return 1; - } - cmdp = param_getchar(Cmd, 1); - if (cmdp == 0x00) { - PrintAndLog("Key type must be A or B"); - return 1; - } - if (cmdp != 'A' && cmdp != 'a') keyType = 1; - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLog("Key must include 12 HEX symbols"); - return 1; - } - PrintAndLog("--sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6)); - - UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - SendCommand(&c); - UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500); - PrintAndLog(" "); - - if (resp != NULL) { - isOK = resp->arg[0] & 0xff; - data = resp->d.asBytes; - - PrintAndLog("isOk:%02x", isOK); - if (isOK) - for (i = 0; i < 2; i++) { - PrintAndLog("data:%s", sprint_hex(data + i * 16, 16)); - } - } else { - PrintAndLog("Command1 execute timeout"); - } - - // response2 - resp = WaitForResponseTimeout(CMD_ACK, 500); - PrintAndLog(" "); - - if (resp != NULL) { - isOK = resp->arg[0] & 0xff; - data = resp->d.asBytes; - - if (isOK) - for (i = 0; i < 2; i++) { - PrintAndLog("data:%s", sprint_hex(data + i * 16, 16)); - } - } else { - PrintAndLog("Command2 execute timeout"); - } - - return 0; -} - -int CmdHF14AMfNested(const char *Cmd) -{ - int i, j, res, iterations; - sector * e_sector = NULL; - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t trgBlockNo = 0; - uint8_t trgKeyType = 0; - uint8_t blDiff = 0; - int SectorsCnt = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t keyBlock[16 * 6]; - uint64_t key64 = 0; - - char cmdp, ctmp; - - if (strlen(Cmd)<3) { - PrintAndLog("Usage:"); - PrintAndLog(" all sectors: hf 14a nested "); - PrintAndLog(" one sector: hf 14a nested o "); - PrintAndLog(" "); - PrintAndLog("card memory - 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLog(" "); - PrintAndLog(" sample1: hf 14a nested 1 0 A FFFFFFFFFFFF "); - PrintAndLog(" sample2: hf 14a nested o 0 A FFFFFFFFFFFF 4 A"); - return 0; - } - - cmdp = param_getchar(Cmd, 0); - blockNo = param_get8(Cmd, 1); - ctmp = param_getchar(Cmd, 2); - if (ctmp == 0x00) { - PrintAndLog("Key type must be A or B"); - return 1; - } - if (ctmp != 'A' && ctmp != 'a') keyType = 1; - if (param_gethex(Cmd, 3, key, 12)) { - PrintAndLog("Key must include 12 HEX symbols"); - return 1; - } - - if (cmdp =='o' || cmdp == 'O') { - cmdp = 'o'; - trgBlockNo = param_get8(Cmd, 4); - ctmp = param_getchar(Cmd, 5); - if (ctmp == 0x00) { - PrintAndLog("Target key type must be A or B"); - return 1; - } - if (ctmp != 'A' && ctmp != 'a') trgKeyType = 1; - } else { - switch (cmdp) { - case '1': SectorsCnt = 16; break; - case '2': SectorsCnt = 32; break; - case '4': SectorsCnt = 64; break; - default: SectorsCnt = 16; - } - } - - PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); - if (cmdp == 'o') - PrintAndLog("--target block no:%02x target key type:%02x ", trgBlockNo, trgKeyType); - - if (cmdp == 'o') { - if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) { - PrintAndLog("Nested error."); - return 2; - } - - for (i = 0; i < 16; i++) { - PrintAndLog("cnt=%d key= %s", i, sprint_hex(keyBlock + i * 6, 6)); - } - - // test keys - res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64); - if (res) - res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64); - if (!res) - PrintAndLog("Found valid key:%012llx", key64); - else - PrintAndLog("No valid key found"); - } else // ------------------------------------ multiple sectors working - { - blDiff = blockNo % 4; - PrintAndLog("Block shift=%d", blDiff); - e_sector = calloc(SectorsCnt, sizeof(sector)); - if (e_sector == NULL) return 1; - - //test current key 4 sectors - memcpy(keyBlock, key, 6); - num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 1 * 6)); - num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 2 * 6)); - num_to_bytes(0xffffffffffff, 6, (uint8_t*)(keyBlock + 3 * 6)); - num_to_bytes(0x000000000000, 6, (uint8_t*)(keyBlock + 4 * 6)); - num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6)); - - PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt); - for (i = 0; i < SectorsCnt; i++) { - for (j = 0; j < 2; j++) { - if (e_sector[i].foundKey[j]) continue; - - res = mfCheckKeys(i * 4 + blDiff, j, 6, keyBlock, &key64); - - if (!res) { - e_sector[i].Key[j] = key64; - e_sector[i].foundKey[j] = 1; - } - } - } - - - // nested sectors - iterations = 0; - PrintAndLog("nested..."); - for (i = 0; i < NESTED_SECTOR_RETRY; i++) { - for (trgBlockNo = blDiff; trgBlockNo < SectorsCnt * 4; trgBlockNo = trgBlockNo + 4) - for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { - if (e_sector[trgBlockNo / 4].foundKey[trgKeyType]) continue; - if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) continue; - - iterations++; - - //try keys from nested - res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64); - if (res) - res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64); - if (!res) { - PrintAndLog("Found valid key:%012llx", key64); - e_sector[trgBlockNo / 4].foundKey[trgKeyType] = 1; - e_sector[trgBlockNo / 4].Key[trgKeyType] = key64; - } - } - } - - PrintAndLog("Iterations count: %d", iterations); - //print them - PrintAndLog("|---|----------------|---|----------------|---|"); - PrintAndLog("|blk|key A |res|key B |res|"); - PrintAndLog("|---|----------------|---|----------------|---|"); - for (i = 0; i < SectorsCnt; i++) { - PrintAndLog("|%03d| %012llx | %d | %012llx | %d |", i, - e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]); - } - PrintAndLog("|---|----------------|---|----------------|---|"); - - free(e_sector); - } - - return 0; -} - -int CmdHF14AMfChk(const char *Cmd) -{ - int i, res; - int keycnt = 0; - char ctmp = 0x00; - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t keyBlock[8 * 6]; - uint64_t key64 = 0; - - memset(keyBlock, 0x00, sizeof(keyBlock)); - - if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf 14a chk []"); - PrintAndLog(" sample: hf 14a chk 0 A FFFFFFFFFFFF a0a1a2a3a4a5 b01b2b3b4b5 "); - return 0; - } - - blockNo = param_get8(Cmd, 0); - ctmp = param_getchar(Cmd, 1); - if (ctmp == 0x00) { - PrintAndLog("Key type must be A or B"); - return 1; - } - if (ctmp != 'A' && ctmp != 'a') keyType = 1; - - for (i = 0; i < 6; i++) { - if (!isxdigit(param_getchar(Cmd, 2 + i))) break; - - if (param_gethex(Cmd, 2 + i, keyBlock + 6 * i, 12)) { - PrintAndLog("Key[%d] must include 12 HEX symbols", i); - return 1; - } - keycnt = i + 1; - } - - if (keycnt == 0) { - PrintAndLog("There is must be at least one key"); - return 1; - } - - PrintAndLog("--block no:%02x key type:%02x key count:%d ", blockNo, keyType, keycnt); - - res = mfCheckKeys(blockNo, keyType, keycnt, keyBlock, &key64); - if (res !=1) { - if (!res) - PrintAndLog("isOk:%02x valid key:%012llx", 1, key64); - else - PrintAndLog("isOk:%02x", 0); - } else { - PrintAndLog("Command execute timeout"); - } - - return 0; -} - -int CmdHF14AMf1kSim(const char *Cmd) -{ - int i, temp; - uint8_t uid[4] = {0, 0, 0, 0}; - - const char *cmdp = Cmd; - - - if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf 14a mfsim "); - PrintAndLog(" sample: hf 14a mfsim 0a0a0a0a "); - return 0; - } - - // skip spaces - while (*cmdp==' ' || *cmdp=='\t') cmdp++; - - if (strlen(cmdp) != 8) { - PrintAndLog("Length of UID must be 8 hex symbols"); - return 0; - } - - for(i = 0; i < 4; i++) { - sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp); - uid[i] = temp & 0xff; - cmdp++; - cmdp++; - } - PrintAndLog(" uid:%s ", sprint_hex(uid, 4)); - - UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {0, 0, 0}}; - memcpy(c.d.asBytes, uid, 6); - SendCommand(&c); - - return 0; -} - - int CmdHF14AReader(const char *Cmd) { UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; SendCommand(&c); UsbCommand * resp = WaitForResponse(CMD_ACK); uint8_t * uid = resp->d.asBytes; - iso14a_card_select_t * card = uid + 12; + iso14a_card_select_t * card = (iso14a_card_select_t *)(uid + 12); if(resp->arg[0] == 0) { PrintAndLog("iso14443a card select failed"); @@ -664,6 +173,18 @@ int CmdHF14AReader(const char *Cmd) PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]); PrintAndLog(" UID : %s", sprint_hex(uid, 12)); PrintAndLog(" SAK : %02x [%d]", card->sak, resp->arg[0]); + switch (card->sak) { + case 0: PrintAndLog(" SAK : MIFARE ultralight?"); break; + case 8: PrintAndLog(" SAK : MIFARE CLASSIC 1K"); break; + case 9: PrintAndLog(" SAK : MIFARE MINI"); break; + case 18: PrintAndLog(" SAK : MIFARE CLASSIC 4K"); break; + case 20: PrintAndLog(" SAK : MIFARE DESFIRE or JCOP 31/41"); break; + case 28: PrintAndLog(" SAK : JCOP31 or JCOP41 v2.3.1"); break; + case 38: PrintAndLog(" SAK : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; + case 88: PrintAndLog(" SAK : Infineon MIFARE CLASSIC 1K"); break; + case 98: PrintAndLog(" SAK : Gemplus MPCOS"); break; + default: ; + } if(resp->arg[0] == 1) PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len)); else @@ -702,13 +223,6 @@ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"list", CmdHF14AList, 0, "List ISO 14443a history"}, - {"mifare", CmdHF14AMifare, 0, "Read out sector 0 parity error messages. param - "}, - {"mfrdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, - {"mfrdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, - {"mfwrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, - {"nested", CmdHF14AMfNested, 0, "Test nested authentication"}, - {"chk", CmdHF14AMfChk, 0, "Test block up to 8 keys"}, - {"mfsim", CmdHF14AMf1kSim, 0, "Simulate MIFARE 1k card - NOT WORKING!!!"}, {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"}, {"sim", CmdHF14ASim, 0, " -- Fake ISO 14443a tag"}, {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"}, diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c new file mode 100644 index 00000000..ee72dad5 --- /dev/null +++ b/client/cmdhfmf.c @@ -0,0 +1,559 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2011 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE commands +//----------------------------------------------------------------------------- + +#include "cmdhfmf.h" + +static int CmdHelp(const char *Cmd); + + +int CmdHF14AMifare(const char *Cmd) +{ + uint32_t uid = 0; + uint32_t nt = 0; + uint64_t par_list = 0, ks_list = 0, r_key = 0; + uint8_t isOK = 0; + uint8_t keyBlock[6] = {0,0,0,0,0,0}; + + if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, keyBlock, 8)) { + PrintAndLog("Nt must include 8 HEX symbols"); + return 1; + } + + UsbCommand c = {CMD_READER_MIFARE, {(uint32_t)bytes_to_num(keyBlock, 4), 0, 0}}; + SendCommand(&c); + + //flush queue + while (ukbhit()) getchar(); + + // message + printf("-------------------------------------------------------------------------\n"); + printf("Executing command. It may take up to 30 min.\n"); + printf("Press the key on proxmark3 device to abort proxmark3.\n"); + printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); + printf("-------------------------------------------------------------------------\n"); + + // wait cycle + while (true) { + printf("."); + if (ukbhit()) { + getchar(); + printf("\naborted via keyboard!\n"); + break; + } + + UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 2000); + if (resp != NULL) { + isOK = resp->arg[0] & 0xff; + + 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); + + printf("\n\n"); + PrintAndLog("isOk:%02x", isOK); + if (!isOK) PrintAndLog("Proxmark can't get statistic info. Execution aborted.\n"); + break; + } + } + printf("\n"); + + // error + if (isOK != 1) return 1; + + // execute original function from util nonce2key + if (nonce2key(uid, nt, par_list, ks_list, &r_key)) return 2; + printf("------------------------------------------------------------------\n"); + PrintAndLog("Key found:%012llx \n", r_key); + + num_to_bytes(r_key, 6, keyBlock); + isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key); + if (!isOK) + PrintAndLog("Found valid key:%012llx", r_key); + else + PrintAndLog("Found invalid key. ( Nt=%08x", nt); + + + return 0; +} + +int CmdHF14AMfWrBl(const char *Cmd) +{ + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + char cmdp = 0x00; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mf wrbl "); + PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); + return 0; + } + + blockNo = param_get8(Cmd, 0); + cmdp = param_getchar(Cmd, 1); + if (cmdp == 0x00) { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (cmdp != 'A' && cmdp != 'a') keyType = 1; + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLog("Key must include 12 HEX symbols"); + return 1; + } + if (param_gethex(Cmd, 3, bldata, 32)) { + PrintAndLog("Block data must include 32 HEX symbols"); + return 1; + } + PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6)); + PrintAndLog("--data: %s", sprint_hex(bldata, 16)); + + UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + 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"); + } + + return 0; +} + +int CmdHF14AMfRdBl(const char *Cmd) +{ + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + + char cmdp = 0x00; + + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mf rdbl "); + PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF "); + return 0; + } + + blockNo = param_get8(Cmd, 0); + cmdp = param_getchar(Cmd, 1); + if (cmdp == 0x00) { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (cmdp != 'A' && cmdp != 'a') keyType = 1; + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLog("Key must include 12 HEX symbols"); + return 1; + } + PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); + + UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + SendCommand(&c); + UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500); + + if (resp != NULL) { + uint8_t isOK = resp->arg[0] & 0xff; + uint8_t * data = resp->d.asBytes; + + if (isOK) + PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16)); + else + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + + return 0; +} + +int CmdHF14AMfRdSc(const char *Cmd) +{ + int i; + uint8_t sectorNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + + uint8_t isOK = 0; + uint8_t * data = NULL; + + char cmdp = 0x00; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mf rdsc "); + PrintAndLog(" sample: hf mf rdsc 0 A FFFFFFFFFFFF "); + return 0; + } + + sectorNo = param_get8(Cmd, 0); + if (sectorNo > 63) { + PrintAndLog("Sector number must be less than 64"); + return 1; + } + cmdp = param_getchar(Cmd, 1); + if (cmdp == 0x00) { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (cmdp != 'A' && cmdp != 'a') keyType = 1; + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLog("Key must include 12 HEX symbols"); + return 1; + } + PrintAndLog("--sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6)); + + UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + SendCommand(&c); + UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500); + PrintAndLog(" "); + + if (resp != NULL) { + isOK = resp->arg[0] & 0xff; + data = resp->d.asBytes; + + PrintAndLog("isOk:%02x", isOK); + if (isOK) + for (i = 0; i < 2; i++) { + PrintAndLog("data:%s", sprint_hex(data + i * 16, 16)); + } + } else { + PrintAndLog("Command1 execute timeout"); + } + + // response2 + resp = WaitForResponseTimeout(CMD_ACK, 500); + PrintAndLog(" "); + + if (resp != NULL) { + isOK = resp->arg[0] & 0xff; + data = resp->d.asBytes; + + if (isOK) + for (i = 0; i < 2; i++) { + PrintAndLog("data:%s", sprint_hex(data + i * 16, 16)); + } + } else { + PrintAndLog("Command2 execute timeout"); + } + + return 0; +} + +int CmdHF14AMfNested(const char *Cmd) +{ + int i, j, res, iterations; + sector * e_sector = NULL; + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t trgBlockNo = 0; + uint8_t trgKeyType = 0; + uint8_t blDiff = 0; + int SectorsCnt = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t keyBlock[16 * 6]; + uint64_t key64 = 0; + + char cmdp, ctmp; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage:"); + PrintAndLog(" all sectors: hf mf nested "); + PrintAndLog(" one sector: hf mf nested o "); + PrintAndLog(" "); + PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLog(" "); + PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF "); + PrintAndLog(" sample2: hf mf nested o 0 A FFFFFFFFFFFF 4 A"); + return 0; + } + + cmdp = param_getchar(Cmd, 0); + blockNo = param_get8(Cmd, 1); + ctmp = param_getchar(Cmd, 2); + if (ctmp == 0x00) { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (ctmp != 'A' && ctmp != 'a') keyType = 1; + if (param_gethex(Cmd, 3, key, 12)) { + PrintAndLog("Key must include 12 HEX symbols"); + return 1; + } + + if (cmdp =='o' || cmdp == 'O') { + cmdp = 'o'; + trgBlockNo = param_get8(Cmd, 4); + ctmp = param_getchar(Cmd, 5); + if (ctmp == 0x00) { + PrintAndLog("Target key type must be A or B"); + return 1; + } + if (ctmp != 'A' && ctmp != 'a') trgKeyType = 1; + } else { + switch (cmdp) { + case '0': SectorsCnt = 05; break; + case '1': SectorsCnt = 16; break; + case '2': SectorsCnt = 32; break; + case '4': SectorsCnt = 64; break; + default: SectorsCnt = 16; + } + } + + PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); + if (cmdp == 'o') + PrintAndLog("--target block no:%02x target key type:%02x ", trgBlockNo, trgKeyType); + + if (cmdp == 'o') { + if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) { + PrintAndLog("Nested error."); + return 2; + } + + for (i = 0; i < 16; i++) { + PrintAndLog("cnt=%d key= %s", i, sprint_hex(keyBlock + i * 6, 6)); + } + + // test keys + res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64); + if (res) + res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64); + if (!res) + PrintAndLog("Found valid key:%012llx", key64); + else + PrintAndLog("No valid key found"); + } else // ------------------------------------ multiple sectors working + { + blDiff = blockNo % 4; + PrintAndLog("Block shift=%d", blDiff); + e_sector = calloc(SectorsCnt, sizeof(sector)); + if (e_sector == NULL) return 1; + + //test current key 4 sectors + memcpy(keyBlock, key, 6); + num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 1 * 6)); + num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 2 * 6)); + num_to_bytes(0xffffffffffff, 6, (uint8_t*)(keyBlock + 3 * 6)); + num_to_bytes(0x000000000000, 6, (uint8_t*)(keyBlock + 4 * 6)); + num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6)); + + PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt); + for (i = 0; i < SectorsCnt; i++) { + for (j = 0; j < 2; j++) { + if (e_sector[i].foundKey[j]) continue; + + res = mfCheckKeys(i * 4 + blDiff, j, 6, keyBlock, &key64); + + if (!res) { + e_sector[i].Key[j] = key64; + e_sector[i].foundKey[j] = 1; + } + } + } + + + // nested sectors + iterations = 0; + PrintAndLog("nested..."); + for (i = 0; i < NESTED_SECTOR_RETRY; i++) { + for (trgBlockNo = blDiff; trgBlockNo < SectorsCnt * 4; trgBlockNo = trgBlockNo + 4) + for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { + if (e_sector[trgBlockNo / 4].foundKey[trgKeyType]) continue; + if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) continue; + + iterations++; + + //try keys from nested + res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64); + if (res) + res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64); + if (!res) { + PrintAndLog("Found valid key:%012llx", key64); + e_sector[trgBlockNo / 4].foundKey[trgKeyType] = 1; + e_sector[trgBlockNo / 4].Key[trgKeyType] = key64; + } + } + } + + PrintAndLog("Iterations count: %d", iterations); + //print them + PrintAndLog("|---|----------------|---|----------------|---|"); + PrintAndLog("|sec|key A |res|key B |res|"); + PrintAndLog("|---|----------------|---|----------------|---|"); + for (i = 0; i < SectorsCnt; i++) { + PrintAndLog("|%03d| %012llx | %d | %012llx | %d |", i, + e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]); + } + PrintAndLog("|---|----------------|---|----------------|---|"); + + free(e_sector); + } + + return 0; +} + +int CmdHF14AMfChk(const char *Cmd) +{ + int i, res; + int keycnt = 0; + char ctmp = 0x00; + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t keyBlock[8 * 6]; + uint64_t key64 = 0; + + memset(keyBlock, 0x00, sizeof(keyBlock)); + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mf chk []"); + PrintAndLog(" sample: hf mf chk 0 A FFFFFFFFFFFF a0a1a2a3a4a5 b01b2b3b4b5 "); + return 0; + } + + blockNo = param_get8(Cmd, 0); + ctmp = param_getchar(Cmd, 1); + if (ctmp == 0x00) { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (ctmp != 'A' && ctmp != 'a') keyType = 1; + + for (i = 0; i < 6; i++) { + if (!isxdigit(param_getchar(Cmd, 2 + i))) break; + + if (param_gethex(Cmd, 2 + i, keyBlock + 6 * i, 12)) { + PrintAndLog("Key[%d] must include 12 HEX symbols", i); + return 1; + } + keycnt = i + 1; + } + + if (keycnt == 0) { + PrintAndLog("There is must be at least one key"); + return 1; + } + + PrintAndLog("--block no:%02x key type:%02x key count:%d ", blockNo, keyType, keycnt); + + res = mfCheckKeys(blockNo, keyType, keycnt, keyBlock, &key64); + if (res !=1) { + if (!res) + PrintAndLog("isOk:%02x valid key:%012llx", 1, key64); + else + PrintAndLog("isOk:%02x", 0); + } else { + PrintAndLog("Command execute timeout"); + } + + return 0; +} + +int CmdHF14AMf1kSim(const char *Cmd) +{ + uint8_t uid[4] = {0, 0, 0, 0}; + + if (param_getchar(Cmd, 0) == 'h') { + PrintAndLog("Usage: hf mf sim "); + PrintAndLog(" sample: hf mf sim 0a0a0a0a "); + return 0; + } + + if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, uid, 8)) { + PrintAndLog("UID must include 8 HEX symbols"); + return 1; + } + PrintAndLog(" uid:%s ", sprint_hex(uid, 4)); + + UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {0, 0, 0}}; + memcpy(c.d.asBytes, uid, 4); + SendCommand(&c); + + return 0; +} + +int CmdHF14AMfDbg(const char *Cmd) +{ + if (strlen(Cmd) < 1) { + PrintAndLog("Usage: hf mf dbg "); + PrintAndLog(" 0 - no debug messages"); + PrintAndLog(" 1 - error messages"); + PrintAndLog(" 2 - all messages"); + PrintAndLog(" 4 - extended debug mode"); + return 0; + } + + PrintAndLog("No code here ("); + return 0; +} + +int CmdHF14AMfEGet(const char *Cmd) +{ + PrintAndLog("No code here ("); + return 0; +} + +int CmdHF14AMfESet(const char *Cmd) +{ + PrintAndLog("No code here ("); + return 0; +} + +int CmdHF14AMfELoad(const char *Cmd) +{ + PrintAndLog("No code here ("); + return 0; +} + +int CmdHF14AMfESave(const char *Cmd) +{ + PrintAndLog("No code here ("); + return 0; +} + +static command_t CommandTable[] = +{ + {"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"}, + {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, + {"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"}, + {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, + {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFMF(const char *Cmd) +{ + // flush + while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ; + + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h new file mode 100644 index 00000000..a4ca7760 --- /dev/null +++ b/client/cmdhfmf.h @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2011 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE commands +//----------------------------------------------------------------------------- + +#ifndef CMDHFMF_H__ +#define CMDHFMF_H__ + +#include +#include +#include +#include +#include "iso14443crc.h" +#include "data.h" +#include "proxusb.h" +#include "ui.h" +#include "cmdparser.h" +#include "common.h" +#include "util.h" +#include "mifarehost.h" + +int CmdHFMF(const char *Cmd); + +#endif diff --git a/client/util.c b/client/util.c index 6825d721..c7764f70 100644 --- a/client/util.c +++ b/client/util.c @@ -89,6 +89,10 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) return num; } +// ------------------------------------------------------------------------- +// string parameters lib +// ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- // line - param line // bg, en - symbol numbers in param line of beginning an ending parameter diff --git a/include/usb_cmd.h b/include/usb_cmd.h index f4793cfc..3e8066b0 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -33,13 +33,13 @@ typedef struct { } PACKED UsbCommand; // For the bootloader -#define CMD_DEVICE_INFO 0x0000 -#define CMD_SETUP_WRITE 0x0001 -#define CMD_FINISH_WRITE 0x0003 -#define CMD_HARDWARE_RESET 0x0004 -#define CMD_START_FLASH 0x0005 -#define CMD_NACK 0x00fe -#define CMD_ACK 0x00ff +#define CMD_DEVICE_INFO 0x0000 +#define CMD_SETUP_WRITE 0x0001 +#define CMD_FINISH_WRITE 0x0003 +#define CMD_HARDWARE_RESET 0x0004 +#define CMD_START_FLASH 0x0005 +#define CMD_NACK 0x00fe +#define CMD_ACK 0x00ff // For general mucking around #define CMD_DEBUG_PRINT_STRING 0x0100 @@ -52,32 +52,32 @@ typedef struct { #define CMD_VERSION 0x0107 // For low-frequency tags -#define CMD_READ_TI_TYPE 0x0202 -#define CMD_WRITE_TI_TYPE 0x0203 -#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0204 -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0205 -#define CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0206 -#define CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K 0x0207 -#define CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K 0x0208 -#define CMD_DOWNLOADED_SIM_SAMPLES_125K 0x0209 -#define CMD_SIMULATE_TAG_125K 0x020A -#define CMD_HID_DEMOD_FSK 0x020B -#define CMD_HID_SIM_TAG 0x020C -#define CMD_SET_LF_DIVISOR 0x020D -#define CMD_LF_SIMULATE_BIDIR 0x020E -#define CMD_SET_ADC_MUX 0x020F +#define CMD_READ_TI_TYPE 0x0202 +#define CMD_WRITE_TI_TYPE 0x0203 +#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0204 +#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0205 +#define CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0206 +#define CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K 0x0207 +#define CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K 0x0208 +#define CMD_DOWNLOADED_SIM_SAMPLES_125K 0x0209 +#define CMD_SIMULATE_TAG_125K 0x020A +#define CMD_HID_DEMOD_FSK 0x020B +#define CMD_HID_SIM_TAG 0x020C +#define CMD_SET_LF_DIVISOR 0x020D +#define CMD_LF_SIMULATE_BIDIR 0x020E +#define CMD_SET_ADC_MUX 0x020F /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ // For the 13.56 MHz tags #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301 -#define CMD_READ_SRI512_TAG 0x0303 -#define CMD_READ_SRIX4K_TAG 0x0304 -#define CMD_READER_ISO_15693 0x0310 -#define CMD_SIMTAG_ISO_15693 0x0311 +#define CMD_READ_SRI512_TAG 0x0303 +#define CMD_READ_SRIX4K_TAG 0x0304 +#define CMD_READER_ISO_15693 0x0310 +#define CMD_SIMTAG_ISO_15693 0x0311 #define CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 0x0312 -#define CMD_ISO_15693_COMMAND 0x0313 -#define CMD_ISO_15693_COMMAND_DONE 0x0314 +#define CMD_ISO_15693_COMMAND 0x0313 +#define CMD_ISO_15693_COMMAND_DONE 0x0314 #define CMD_ISO_15693_FIND_AFI 0x0315 #define CMD_ISO_15693_DEBUG 0x0316 #define CMD_SIMULATE_TAG_HF_LISTEN 0x0380 @@ -86,28 +86,37 @@ typedef struct { #define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_READER_ISO_14443a 0x0385 -#define CMD_SIMULATE_MIFARE_CARD 0x0386 #define CMD_SIMULATE_TAG_LEGIC_RF 0x0387 #define CMD_READER_LEGIC_RF 0x0388 #define CMD_WRITER_LEGIC_RF 0x0399 -#define CMD_READER_MIFARE 0x0389 -#define CMD_MIFARE_NESTED 0x0390 -#define CMD_MIFARE_READBL 0x0391 -#define CMD_MIFARE_READSC 0x0393 -#define CMD_MIFARE_WRITEBL 0x0394 -#define CMD_MIFARE_CHKKEYS 0x0395 + #define CMD_SNOOP_ICLASS 0x0392 // For measurements of the antenna tuning -#define CMD_MEASURE_ANTENNA_TUNING 0x0400 -#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401 -#define CMD_MEASURED_ANTENNA_TUNING 0x0410 -#define CMD_LISTEN_READER_FIELD 0x0420 +#define CMD_MEASURE_ANTENNA_TUNING 0x0400 +#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401 +#define CMD_MEASURED_ANTENNA_TUNING 0x0410 +#define CMD_LISTEN_READER_FIELD 0x0420 // For direct FPGA control -#define CMD_FPGA_MAJOR_MODE_OFF 0x0500 +#define CMD_FPGA_MAJOR_MODE_OFF 0x0500 -#define CMD_UNKNOWN 0xFFFF +// For mifare commands +#define CMD_MIFARE_SET_DBGMODE 0x0600 +#define CMD_MIFARE_EML_MEMSET 0x0601 +#define CMD_MIFARE_EML_MEMGET 0x0602 + +#define CMD_SIMULATE_MIFARE_CARD 0x0603 + +#define CMD_READER_MIFARE 0x0605 +#define CMD_MIFARE_NESTED 0x0606 + +#define CMD_MIFARE_READBL 0x0610 +#define CMD_MIFARE_READSC 0x0611 +#define CMD_MIFARE_WRITEBL 0x0612 +#define CMD_MIFARE_CHKKEYS 0x0613 + +#define CMD_UNKNOWN 0xFFFF // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: /* Whether a bootloader that understands the common_area is present */