return d;
}
-static int AvgAdc(int ch)
+int AvgAdc(int ch) // was static - merlok
{
int i;
int a = 0;
// Load the FPGA image, which we have stored in our flash.
FpgaDownloadAndGo();
+ StartTickCount();
+
#ifdef WITH_LCD
LCDInit();
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);
}
}
}
+static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, int correctionNeeded);
//-----------------------------------------------------------------------------
// Main loop of simulated tag: receive commands from reader, decide what
}
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();
break;
}
}
-
+*/
}
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
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
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
{
int cardSTATE = MFEMUL_NOFIELD;
+ 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
- while (true) {
+// -------------------------------------- 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;
- }
+ 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;
}
}
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LEDsoff();
+
+ DbpString("Emulator stopped.");
}
//-----------------------------------------------------------------------------\r
// code for work with mifare cards.\r
//-----------------------------------------------------------------------------\r
+\r
#ifndef __MIFAREUTIL_H\r
#define __MIFAREUTIL_H\r
\r
+// mifare authentication\r
#define CRYPT_NONE 0\r
#define CRYPT_ALL 1\r
#define CRYPT_REQUEST 2\r
#define AUTH_FIRST 0\r
#define AUTH_NESTED 2\r
\r
+// reader voltage field detector\r
+#define MF_MINFIELDV 4000\r
+\r
// debug\r
// 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode\r
#define MF_DBG_NONE 0\r
#define NS_RETRIES_GETNONCE 15\r
#define NES_MAX_INFO 5\r
\r
-//mifare emulate states\r
+//mifare emulator states\r
#define MFEMUL_NOFIELD 0\r
#define MFEMUL_IDLE 1\r
#define MFEMUL_SELECT1 2\r
#define MFEMUL_SELECT2 3\r
#define MFEMUL_AUTH1 4\r
#define MFEMUL_AUTH2 5\r
-#define MFEMUL_HALTED 6\r
+#define MFEMUL_WORK 6\r
+#define MFEMUL_HALTED 7\r
\r
//functions\r
uint8_t* mifare_get_bigbufptr(void);\r
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;
+}
+
#include <stddef.h>
#include <stdint.h>
+#define RAMFUNC __attribute((long_call, section(".ramfunc")))
+
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
#define LED_RED 1
int BUTTON_HELD(int ms);
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
+void StartTickCount();
+uint32_t RAMFUNC GetTickCount();
+
#endif
cmdhf15.c \
cmdhflegic.c \
cmdhficlass.c \
+ cmdhfmf.c \
cmdhw.c \
cmdlf.c \
cmdlfem4x.c \
#include "cmdhf15.h"
#include "cmdhflegic.h"
#include "cmdhficlass.h"
+#include "cmdhfmf.h"
static int CmdHelp(const char *Cmd);
{"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}
};
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <ctype.h>
#include "util.h"
#include "iso14443crc.h"
#include "data.h"
#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);
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 <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
- 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 <block number> <key A/B> <key (12 hex symbols)>");
- 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 <sector number> <key A/B> <key (12 hex symbols)>");
- 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 <card memory> <block number> <key A/B> <key (12 hex symbols)>");
- PrintAndLog(" one sector: hf 14a nested o <block number> <key A/B> <key (12 hex symbols)>");
- PrintAndLog(" <target block number> <target key A/B>");
- PrintAndLog("card memory - 1 - 1K, 2 - 2K, 4 - 4K, <other> - 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 <block number> <key A/B> [<key (12 hex symbols)>]");
- 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 <uid (8 hex symbols)>");
- 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");
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
{
{"help", CmdHelp, 1, "This help"},
{"list", CmdHF14AList, 0, "List ISO 14443a history"},
- {"mifare", CmdHF14AMifare, 0, "Read out sector 0 parity error messages. param - <used card nonce>"},
- {"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, "<UID> -- Fake ISO 14443a tag"},
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
--- /dev/null
+//-----------------------------------------------------------------------------\r
+// Copyright (C) 2011 Merlok\r
+//\r
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,\r
+// at your option, any later version. See the LICENSE.txt file for the text of\r
+// the license.\r
+//-----------------------------------------------------------------------------\r
+// High frequency MIFARE commands\r
+//-----------------------------------------------------------------------------\r
+\r
+#include "cmdhfmf.h"\r
+\r
+static int CmdHelp(const char *Cmd);\r
+\r
+\r
+int CmdHF14AMifare(const char *Cmd)\r
+{\r
+ uint32_t uid = 0;\r
+ uint32_t nt = 0;\r
+ uint64_t par_list = 0, ks_list = 0, r_key = 0;\r
+ uint8_t isOK = 0;\r
+ uint8_t keyBlock[6] = {0,0,0,0,0,0};\r
+ \r
+ if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, keyBlock, 8)) {\r
+ PrintAndLog("Nt must include 8 HEX symbols");\r
+ return 1;\r
+ }\r
+ \r
+ UsbCommand c = {CMD_READER_MIFARE, {(uint32_t)bytes_to_num(keyBlock, 4), 0, 0}};\r
+ SendCommand(&c);\r
+ \r
+ //flush queue\r
+ while (ukbhit()) getchar();\r
+\r
+ // message\r
+ printf("-------------------------------------------------------------------------\n");\r
+ printf("Executing command. It may take up to 30 min.\n");\r
+ printf("Press the key on proxmark3 device to abort proxmark3.\n");\r
+ printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n");\r
+ printf("-------------------------------------------------------------------------\n");\r
+ \r
+ // wait cycle\r
+ while (true) {\r
+ printf(".");\r
+ if (ukbhit()) {\r
+ getchar();\r
+ printf("\naborted via keyboard!\n");\r
+ break;\r
+ }\r
+ \r
+ UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 2000);\r
+ if (resp != NULL) {\r
+ isOK = resp->arg[0] & 0xff;\r
+ \r
+ uid = (uint32_t)bytes_to_num(resp->d.asBytes + 0, 4);\r
+ nt = (uint32_t)bytes_to_num(resp->d.asBytes + 4, 4);\r
+ par_list = bytes_to_num(resp->d.asBytes + 8, 8);\r
+ ks_list = bytes_to_num(resp->d.asBytes + 16, 8);\r
+ \r
+ printf("\n\n");\r
+ PrintAndLog("isOk:%02x", isOK);\r
+ if (!isOK) PrintAndLog("Proxmark can't get statistic info. Execution aborted.\n");\r
+ break;\r
+ }\r
+ } \r
+ printf("\n");\r
+ \r
+ // error\r
+ if (isOK != 1) return 1;\r
+ \r
+ // execute original function from util nonce2key\r
+ if (nonce2key(uid, nt, par_list, ks_list, &r_key)) return 2;\r
+ printf("------------------------------------------------------------------\n");\r
+ PrintAndLog("Key found:%012llx \n", r_key);\r
+\r
+ num_to_bytes(r_key, 6, keyBlock);\r
+ isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key);\r
+ if (!isOK) \r
+ PrintAndLog("Found valid key:%012llx", r_key);\r
+ else\r
+ PrintAndLog("Found invalid key. ( Nt=%08x", nt); \r
+ \r
+ \r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfWrBl(const char *Cmd)\r
+{\r
+ uint8_t blockNo = 0;\r
+ uint8_t keyType = 0;\r
+ uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
+ uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r
+ \r
+ char cmdp = 0x00;\r
+\r
+ if (strlen(Cmd)<3) {\r
+ PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");\r
+ PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");\r
+ return 0;\r
+ } \r
+\r
+ blockNo = param_get8(Cmd, 0);\r
+ cmdp = param_getchar(Cmd, 1);\r
+ if (cmdp == 0x00) {\r
+ PrintAndLog("Key type must be A or B");\r
+ return 1;\r
+ }\r
+ if (cmdp != 'A' && cmdp != 'a') keyType = 1;\r
+ if (param_gethex(Cmd, 2, key, 12)) {\r
+ PrintAndLog("Key must include 12 HEX symbols");\r
+ return 1;\r
+ }\r
+ if (param_gethex(Cmd, 3, bldata, 32)) {\r
+ PrintAndLog("Block data must include 32 HEX symbols");\r
+ return 1;\r
+ }\r
+ PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));\r
+ PrintAndLog("--data: %s", sprint_hex(bldata, 16));\r
+ \r
+ UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};\r
+ memcpy(c.d.asBytes, key, 6);\r
+ memcpy(c.d.asBytes + 10, bldata, 16);\r
+ SendCommand(&c);\r
+ UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
+\r
+ if (resp != NULL) {\r
+ uint8_t isOK = resp->arg[0] & 0xff;\r
+\r
+ PrintAndLog("isOk:%02x", isOK);\r
+ } else {\r
+ PrintAndLog("Command execute timeout");\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfRdBl(const char *Cmd)\r
+{\r
+ uint8_t blockNo = 0;\r
+ uint8_t keyType = 0;\r
+ uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
+ \r
+ char cmdp = 0x00;\r
+\r
+\r
+ if (strlen(Cmd)<3) {\r
+ PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");\r
+ PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");\r
+ return 0;\r
+ } \r
+ \r
+ blockNo = param_get8(Cmd, 0);\r
+ cmdp = param_getchar(Cmd, 1);\r
+ if (cmdp == 0x00) {\r
+ PrintAndLog("Key type must be A or B");\r
+ return 1;\r
+ }\r
+ if (cmdp != 'A' && cmdp != 'a') keyType = 1;\r
+ if (param_gethex(Cmd, 2, key, 12)) {\r
+ PrintAndLog("Key must include 12 HEX symbols");\r
+ return 1;\r
+ }\r
+ PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));\r
+ \r
+ UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};\r
+ memcpy(c.d.asBytes, key, 6);\r
+ SendCommand(&c);\r
+ UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
+\r
+ if (resp != NULL) {\r
+ uint8_t isOK = resp->arg[0] & 0xff;\r
+ uint8_t * data = resp->d.asBytes;\r
+\r
+ if (isOK)\r
+ PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));\r
+ else\r
+ PrintAndLog("isOk:%02x", isOK);\r
+ } else {\r
+ PrintAndLog("Command execute timeout");\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfRdSc(const char *Cmd)\r
+{\r
+ int i;\r
+ uint8_t sectorNo = 0;\r
+ uint8_t keyType = 0;\r
+ uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
+ \r
+ uint8_t isOK = 0;\r
+ uint8_t * data = NULL;\r
+\r
+ char cmdp = 0x00;\r
+\r
+ if (strlen(Cmd)<3) {\r
+ PrintAndLog("Usage: hf mf rdsc <sector number> <key A/B> <key (12 hex symbols)>");\r
+ PrintAndLog(" sample: hf mf rdsc 0 A FFFFFFFFFFFF ");\r
+ return 0;\r
+ } \r
+ \r
+ sectorNo = param_get8(Cmd, 0);\r
+ if (sectorNo > 63) {\r
+ PrintAndLog("Sector number must be less than 64");\r
+ return 1;\r
+ }\r
+ cmdp = param_getchar(Cmd, 1);\r
+ if (cmdp == 0x00) {\r
+ PrintAndLog("Key type must be A or B");\r
+ return 1;\r
+ }\r
+ if (cmdp != 'A' && cmdp != 'a') keyType = 1;\r
+ if (param_gethex(Cmd, 2, key, 12)) {\r
+ PrintAndLog("Key must include 12 HEX symbols");\r
+ return 1;\r
+ }\r
+ PrintAndLog("--sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6));\r
+ \r
+ UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}};\r
+ memcpy(c.d.asBytes, key, 6);\r
+ SendCommand(&c);\r
+ UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
+ PrintAndLog(" ");\r
+\r
+ if (resp != NULL) {\r
+ isOK = resp->arg[0] & 0xff;\r
+ data = resp->d.asBytes;\r
+\r
+ PrintAndLog("isOk:%02x", isOK);\r
+ if (isOK) \r
+ for (i = 0; i < 2; i++) {\r
+ PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));\r
+ }\r
+ } else {\r
+ PrintAndLog("Command1 execute timeout");\r
+ }\r
+\r
+ // response2\r
+ resp = WaitForResponseTimeout(CMD_ACK, 500);\r
+ PrintAndLog(" ");\r
+\r
+ if (resp != NULL) {\r
+ isOK = resp->arg[0] & 0xff;\r
+ data = resp->d.asBytes;\r
+\r
+ if (isOK) \r
+ for (i = 0; i < 2; i++) {\r
+ PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));\r
+ }\r
+ } else {\r
+ PrintAndLog("Command2 execute timeout");\r
+ }\r
+ \r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfNested(const char *Cmd)\r
+{\r
+ int i, j, res, iterations;\r
+ sector * e_sector = NULL;\r
+ uint8_t blockNo = 0;\r
+ uint8_t keyType = 0;\r
+ uint8_t trgBlockNo = 0;\r
+ uint8_t trgKeyType = 0;\r
+ uint8_t blDiff = 0;\r
+ int SectorsCnt = 0;\r
+ uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
+ uint8_t keyBlock[16 * 6];\r
+ uint64_t key64 = 0;\r
+ \r
+ char cmdp, ctmp;\r
+\r
+ if (strlen(Cmd)<3) {\r
+ PrintAndLog("Usage:");\r
+ PrintAndLog(" all sectors: hf mf nested <card memory> <block number> <key A/B> <key (12 hex symbols)>");\r
+ PrintAndLog(" one sector: hf mf nested o <block number> <key A/B> <key (12 hex symbols)>");\r
+ PrintAndLog(" <target block number> <target key A/B>");\r
+ PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");\r
+ PrintAndLog(" ");\r
+ PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF ");\r
+ PrintAndLog(" sample2: hf mf nested o 0 A FFFFFFFFFFFF 4 A");\r
+ return 0;\r
+ } \r
+ \r
+ cmdp = param_getchar(Cmd, 0);\r
+ blockNo = param_get8(Cmd, 1);\r
+ ctmp = param_getchar(Cmd, 2);\r
+ if (ctmp == 0x00) {\r
+ PrintAndLog("Key type must be A or B");\r
+ return 1;\r
+ }\r
+ if (ctmp != 'A' && ctmp != 'a') keyType = 1;\r
+ if (param_gethex(Cmd, 3, key, 12)) {\r
+ PrintAndLog("Key must include 12 HEX symbols");\r
+ return 1;\r
+ }\r
+ \r
+ if (cmdp =='o' || cmdp == 'O') {\r
+ cmdp = 'o';\r
+ trgBlockNo = param_get8(Cmd, 4);\r
+ ctmp = param_getchar(Cmd, 5);\r
+ if (ctmp == 0x00) {\r
+ PrintAndLog("Target key type must be A or B");\r
+ return 1;\r
+ }\r
+ if (ctmp != 'A' && ctmp != 'a') trgKeyType = 1;\r
+ } else {\r
+ switch (cmdp) {\r
+ case '0': SectorsCnt = 05; break;\r
+ case '1': SectorsCnt = 16; break;\r
+ case '2': SectorsCnt = 32; break;\r
+ case '4': SectorsCnt = 64; break;\r
+ default: SectorsCnt = 16;\r
+ }\r
+ }\r
+ \r
+ PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));\r
+ if (cmdp == 'o')\r
+ PrintAndLog("--target block no:%02x target key type:%02x ", trgBlockNo, trgKeyType);\r
+\r
+ if (cmdp == 'o') {\r
+ if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) {\r
+ PrintAndLog("Nested error.");\r
+ return 2;\r
+ }\r
+\r
+ for (i = 0; i < 16; i++) {\r
+ PrintAndLog("cnt=%d key= %s", i, sprint_hex(keyBlock + i * 6, 6));\r
+ }\r
+ \r
+ // test keys\r
+ res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64);\r
+ if (res)\r
+ res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64);\r
+ if (!res)\r
+ PrintAndLog("Found valid key:%012llx", key64);\r
+ else\r
+ PrintAndLog("No valid key found");\r
+ } else // ------------------------------------ multiple sectors working\r
+ {\r
+ blDiff = blockNo % 4;\r
+ PrintAndLog("Block shift=%d", blDiff);\r
+ e_sector = calloc(SectorsCnt, sizeof(sector));\r
+ if (e_sector == NULL) return 1;\r
+ \r
+ //test current key 4 sectors\r
+ memcpy(keyBlock, key, 6);\r
+ num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 1 * 6));\r
+ num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 2 * 6));\r
+ num_to_bytes(0xffffffffffff, 6, (uint8_t*)(keyBlock + 3 * 6));\r
+ num_to_bytes(0x000000000000, 6, (uint8_t*)(keyBlock + 4 * 6));\r
+ num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6));\r
+\r
+ PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt);\r
+ for (i = 0; i < SectorsCnt; i++) {\r
+ for (j = 0; j < 2; j++) {\r
+ if (e_sector[i].foundKey[j]) continue;\r
+ \r
+ res = mfCheckKeys(i * 4 + blDiff, j, 6, keyBlock, &key64);\r
+ \r
+ if (!res) {\r
+ e_sector[i].Key[j] = key64;\r
+ e_sector[i].foundKey[j] = 1;\r
+ }\r
+ }\r
+ } \r
+ \r
+ \r
+ // nested sectors\r
+ iterations = 0;\r
+ PrintAndLog("nested...");\r
+ for (i = 0; i < NESTED_SECTOR_RETRY; i++) {\r
+ for (trgBlockNo = blDiff; trgBlockNo < SectorsCnt * 4; trgBlockNo = trgBlockNo + 4) \r
+ for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { \r
+ if (e_sector[trgBlockNo / 4].foundKey[trgKeyType]) continue;\r
+ if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) continue;\r
+ \r
+ iterations++;\r
+ \r
+ //try keys from nested\r
+ res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64);\r
+ if (res)\r
+ res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64);\r
+ if (!res) {\r
+ PrintAndLog("Found valid key:%012llx", key64); \r
+ e_sector[trgBlockNo / 4].foundKey[trgKeyType] = 1;\r
+ e_sector[trgBlockNo / 4].Key[trgKeyType] = key64;\r
+ }\r
+ }\r
+ }\r
+\r
+ PrintAndLog("Iterations count: %d", iterations);\r
+ //print them\r
+ PrintAndLog("|---|----------------|---|----------------|---|");\r
+ PrintAndLog("|sec|key A |res|key B |res|");\r
+ PrintAndLog("|---|----------------|---|----------------|---|");\r
+ for (i = 0; i < SectorsCnt; i++) {\r
+ PrintAndLog("|%03d| %012llx | %d | %012llx | %d |", i, \r
+ e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]);\r
+ }\r
+ PrintAndLog("|---|----------------|---|----------------|---|");\r
+ \r
+ free(e_sector);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfChk(const char *Cmd)\r
+{\r
+ int i, res;\r
+ int keycnt = 0;\r
+ char ctmp = 0x00;\r
+ uint8_t blockNo = 0;\r
+ uint8_t keyType = 0;\r
+ uint8_t keyBlock[8 * 6];\r
+ uint64_t key64 = 0;\r
+\r
+ memset(keyBlock, 0x00, sizeof(keyBlock));\r
+\r
+ if (strlen(Cmd)<3) {\r
+ PrintAndLog("Usage: hf mf chk <block number> <key A/B> [<key (12 hex symbols)>]");\r
+ PrintAndLog(" sample: hf mf chk 0 A FFFFFFFFFFFF a0a1a2a3a4a5 b01b2b3b4b5 ");\r
+ return 0;\r
+ } \r
+ \r
+ blockNo = param_get8(Cmd, 0);\r
+ ctmp = param_getchar(Cmd, 1);\r
+ if (ctmp == 0x00) {\r
+ PrintAndLog("Key type must be A or B");\r
+ return 1;\r
+ }\r
+ if (ctmp != 'A' && ctmp != 'a') keyType = 1;\r
+ \r
+ for (i = 0; i < 6; i++) {\r
+ if (!isxdigit(param_getchar(Cmd, 2 + i))) break;\r
+\r
+ if (param_gethex(Cmd, 2 + i, keyBlock + 6 * i, 12)) {\r
+ PrintAndLog("Key[%d] must include 12 HEX symbols", i);\r
+ return 1;\r
+ }\r
+ keycnt = i + 1;\r
+ }\r
+ \r
+ if (keycnt == 0) {\r
+ PrintAndLog("There is must be at least one key");\r
+ return 1;\r
+ }\r
+\r
+ PrintAndLog("--block no:%02x key type:%02x key count:%d ", blockNo, keyType, keycnt);\r
+ \r
+ res = mfCheckKeys(blockNo, keyType, keycnt, keyBlock, &key64);\r
+ if (res !=1) {\r
+ if (!res)\r
+ PrintAndLog("isOk:%02x valid key:%012llx", 1, key64);\r
+ else\r
+ PrintAndLog("isOk:%02x", 0);\r
+ } else {\r
+ PrintAndLog("Command execute timeout");\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMf1kSim(const char *Cmd)\r
+{\r
+ uint8_t uid[4] = {0, 0, 0, 0};\r
+ \r
+ if (param_getchar(Cmd, 0) == 'h') {\r
+ PrintAndLog("Usage: hf mf sim <uid (8 hex symbols)>");\r
+ PrintAndLog(" sample: hf mf sim 0a0a0a0a ");\r
+ return 0;\r
+ } \r
+ \r
+ if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, uid, 8)) {\r
+ PrintAndLog("UID must include 8 HEX symbols");\r
+ return 1;\r
+ }\r
+ PrintAndLog(" uid:%s ", sprint_hex(uid, 4));\r
+ \r
+ UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {0, 0, 0}};\r
+ memcpy(c.d.asBytes, uid, 4);\r
+ SendCommand(&c);\r
+\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfDbg(const char *Cmd)\r
+{\r
+ if (strlen(Cmd) < 1) {\r
+ PrintAndLog("Usage: hf mf dbg <debug level>");\r
+ PrintAndLog(" 0 - no debug messages");\r
+ PrintAndLog(" 1 - error messages");\r
+ PrintAndLog(" 2 - all messages");\r
+ PrintAndLog(" 4 - extended debug mode");\r
+ return 0;\r
+ } \r
+\r
+ PrintAndLog("No code here (");\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfEGet(const char *Cmd)\r
+{\r
+ PrintAndLog("No code here (");\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfESet(const char *Cmd)\r
+{\r
+ PrintAndLog("No code here (");\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfELoad(const char *Cmd)\r
+{\r
+ PrintAndLog("No code here (");\r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMfESave(const char *Cmd)\r
+{\r
+ PrintAndLog("No code here (");\r
+ return 0;\r
+}\r
+\r
+static command_t CommandTable[] = \r
+{\r
+ {"help", CmdHelp, 1, "This help"},\r
+ {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},\r
+ {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},\r
+ {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},\r
+ {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},\r
+ {"chk", CmdHF14AMfChk, 0, "Test block up to 8 keys"},\r
+ {"mifare", CmdHF14AMifare, 0, "Read parity error messages. param - <used card nonce>"},\r
+ {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},\r
+ {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE 1k card"},\r
+ {"eget", CmdHF14AMfEGet, 0, "Set simulator memory block"},\r
+ {"eset", CmdHF14AMfESet, 0, "Get simulator memory block"},\r
+ {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},\r
+ {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},\r
+ {NULL, NULL, 0, NULL}\r
+};\r
+\r
+int CmdHFMF(const char *Cmd)\r
+{\r
+ // flush\r
+ while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;\r
+\r
+ CmdsParse(CommandTable, Cmd);\r
+ return 0;\r
+}\r
+\r
+int CmdHelp(const char *Cmd)\r
+{\r
+ CmdsHelp(CommandTable);\r
+ return 0;\r
+}\r
--- /dev/null
+//-----------------------------------------------------------------------------\r
+// Copyright (C) 2011 Merlok\r
+//\r
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,\r
+// at your option, any later version. See the LICENSE.txt file for the text of\r
+// the license.\r
+//-----------------------------------------------------------------------------\r
+// High frequency MIFARE commands\r
+//-----------------------------------------------------------------------------\r
+\r
+#ifndef CMDHFMF_H__\r
+#define CMDHFMF_H__\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include "iso14443crc.h"\r
+#include "data.h"\r
+#include "proxusb.h"\r
+#include "ui.h"\r
+#include "cmdparser.h"\r
+#include "common.h"\r
+#include "util.h"\r
+#include "mifarehost.h"\r
+\r
+int CmdHFMF(const char *Cmd);\r
+\r
+#endif\r
return num;
}
+// -------------------------------------------------------------------------
+// string parameters lib
+// -------------------------------------------------------------------------
+
// -------------------------------------------------------------------------
// line - param line
// bg, en - symbol numbers in param line of beginning an ending parameter
} 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
#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
#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
+
+// 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
+#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 */