0. its alpha version!!!

1. commands changed from "hf 14a" to "hf mf" 
2. some code cleaning and small bugfixes
3. alpha version hf mf sim
4. added internal function GetTickCount() for time measuring
This commit is contained in:
Merlokbr@gmail.com 2011-06-10 13:35:10 +00:00
parent 873014de8a
commit 9ca155ba44
14 changed files with 977 additions and 551 deletions

View file

@ -171,7 +171,7 @@ static int ReadAdc(int ch)
return d; return d;
} }
static int AvgAdc(int ch) int AvgAdc(int ch) // was static - merlok
{ {
int i; int i;
int a = 0; int a = 0;
@ -930,6 +930,8 @@ void __attribute__((noreturn)) AppMain(void)
// Load the FPGA image, which we have stored in our flash. // Load the FPGA image, which we have stored in our flash.
FpgaDownloadAndGo(); FpgaDownloadAndGo();
StartTickCount();
#ifdef WITH_LCD #ifdef WITH_LCD
LCDInit(); LCDInit();

View file

@ -33,6 +33,8 @@ void DbpString(char *str);
void Dbprintf(const char *fmt, ...); void Dbprintf(const char *fmt, ...);
void Dbhexdump(int len, uint8_t *d); void Dbhexdump(int len, uint8_t *d);
int AvgAdc(int ch);
void ToSendStuffBit(int b); void ToSendStuffBit(int b);
void ToSendReset(void); void ToSendReset(void);
void ListenReaderField(int limit); void ListenReaderField(int limit);

View file

@ -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 // 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; 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); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
AT91C_BASE_SSC->SSC_THR = 0x00; AT91C_BASE_SSC->SSC_THR = 0x00;
FpgaSetupSsc(); FpgaSetupSsc();
@ -1213,7 +1219,7 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
break; break;
} }
} }
*/
} }
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd); Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
@ -1398,6 +1404,133 @@ void CodeIso14443aAsReaderPar(const uint8_t * cmd, int len, uint32_t dwParity)
ToSendMax++; 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 // Wait a certain time for tag response
// If a response is captured return TRUE // 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) void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
{ {
int cardSTATE = MFEMUL_NOFIELD; 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
// -------------------------------------- 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) { 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()) { 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) { switch (cardSTATE) {
case MFEMUL_NOFIELD:{ case MFEMUL_NOFIELD:{
break; break;
} }
case MFEMUL_HALTED:{
// WUP request
if (!(len == 1 && receivedCmd[0] == 0x52)) break;
}
case MFEMUL_IDLE:{ 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; break;
} }
case MFEMUL_SELECT1:{ 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; break;
} }
case MFEMUL_SELECT2:{ 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; break;
} }
case MFEMUL_AUTH1:{ 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; break;
} }
case MFEMUL_AUTH2:{ case MFEMUL_AUTH2:{
LED_C_ON();
Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - timer);
break; 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; 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.");
} }

View file

@ -266,3 +266,4 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
return 0; return 0;
} }

View file

@ -8,15 +8,20 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// code for work with mifare cards. // code for work with mifare cards.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef __MIFAREUTIL_H #ifndef __MIFAREUTIL_H
#define __MIFAREUTIL_H #define __MIFAREUTIL_H
// mifare authentication
#define CRYPT_NONE 0 #define CRYPT_NONE 0
#define CRYPT_ALL 1 #define CRYPT_ALL 1
#define CRYPT_REQUEST 2 #define CRYPT_REQUEST 2
#define AUTH_FIRST 0 #define AUTH_FIRST 0
#define AUTH_NESTED 2 #define AUTH_NESTED 2
// reader voltage field detector
#define MF_MINFIELDV 4000
// debug // debug
// 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode // 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode
#define MF_DBG_NONE 0 #define MF_DBG_NONE 0
@ -33,14 +38,15 @@ extern int MF_DBGLEVEL;
#define NS_RETRIES_GETNONCE 15 #define NS_RETRIES_GETNONCE 15
#define NES_MAX_INFO 5 #define NES_MAX_INFO 5
//mifare emulate states //mifare emulator states
#define MFEMUL_NOFIELD 0 #define MFEMUL_NOFIELD 0
#define MFEMUL_IDLE 1 #define MFEMUL_IDLE 1
#define MFEMUL_SELECT1 2 #define MFEMUL_SELECT1 2
#define MFEMUL_SELECT2 3 #define MFEMUL_SELECT2 3
#define MFEMUL_AUTH1 4 #define MFEMUL_AUTH1 4
#define MFEMUL_AUTH2 5 #define MFEMUL_AUTH2 5
#define MFEMUL_HALTED 6 #define MFEMUL_WORK 6
#define MFEMUL_HALTED 7
//functions //functions
uint8_t* mifare_get_bigbufptr(void); uint8_t* mifare_get_bigbufptr(void);

View file

@ -235,3 +235,30 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
strncat(dst, " ", len); strncat(dst, " ", len);
strncat(dst, v->buildtime, 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;
}

View file

@ -14,6 +14,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define RAMFUNC __attribute((long_call, section(".ramfunc")))
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
#define LED_RED 1 #define LED_RED 1
@ -37,4 +39,7 @@ int BUTTON_CLICKED(int ms);
int BUTTON_HELD(int ms); int BUTTON_HELD(int ms);
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information); void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
void StartTickCount();
uint32_t RAMFUNC GetTickCount();
#endif #endif

View file

@ -58,6 +58,7 @@ CMDSRCS = \
cmdhf15.c \ cmdhf15.c \
cmdhflegic.c \ cmdhflegic.c \
cmdhficlass.c \ cmdhficlass.c \
cmdhfmf.c \
cmdhw.c \ cmdhw.c \
cmdlf.c \ cmdlf.c \
cmdlfem4x.c \ cmdlfem4x.c \

View file

@ -19,6 +19,7 @@
#include "cmdhf15.h" #include "cmdhf15.h"
#include "cmdhflegic.h" #include "cmdhflegic.h"
#include "cmdhficlass.h" #include "cmdhficlass.h"
#include "cmdhfmf.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -37,6 +38,7 @@ static command_t CommandTable[] =
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"}, {"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -13,7 +13,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <ctype.h>
#include "util.h" #include "util.h"
#include "iso14443crc.h" #include "iso14443crc.h"
#include "data.h" #include "data.h"
@ -23,9 +22,6 @@
#include "cmdhf14a.h" #include "cmdhf14a.h"
#include "common.h" #include "common.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "nonce2key/nonce2key.h"
#include "nonce2key/crapto1.h"
#include "mifarehost.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -161,500 +157,13 @@ void iso14a_set_timeout(uint32_t timeout) {
SendCommand(&c); 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) int CmdHF14AReader(const char *Cmd)
{ {
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
SendCommand(&c); SendCommand(&c);
UsbCommand * resp = WaitForResponse(CMD_ACK); UsbCommand * resp = WaitForResponse(CMD_ACK);
uint8_t * uid = resp->d.asBytes; 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) { if(resp->arg[0] == 0) {
PrintAndLog("iso14443a card select failed"); 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("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
PrintAndLog(" UID : %s", sprint_hex(uid, 12)); PrintAndLog(" UID : %s", sprint_hex(uid, 12));
PrintAndLog(" SAK : %02x [%d]", card->sak, resp->arg[0]); 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) if(resp->arg[0] == 1)
PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len)); PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len));
else else
@ -702,13 +223,6 @@ static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"list", CmdHF14AList, 0, "List ISO 14443a history"}, {"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"}, {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
{"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"}, {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"}, {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},

559
client/cmdhfmf.c Normal file
View file

@ -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 <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
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 <block number> <key A/B> <key (12 hex symbols)>");
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 <sector number> <key A/B> <key (12 hex symbols)>");
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 <card memory> <block number> <key A/B> <key (12 hex symbols)>");
PrintAndLog(" one sector: hf mf nested o <block number> <key A/B> <key (12 hex symbols)>");
PrintAndLog(" <target block number> <target key A/B>");
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 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 <block number> <key A/B> [<key (12 hex symbols)>]");
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 <uid (8 hex symbols)>");
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 <debug level>");
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 - <used card nonce>"},
{"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;
}

29
client/cmdhfmf.h Normal file
View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#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

View file

@ -89,6 +89,10 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
return num; return num;
} }
// -------------------------------------------------------------------------
// string parameters lib
// -------------------------------------------------------------------------
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// line - param line // line - param line
// bg, en - symbol numbers in param line of beginning an ending parameter // bg, en - symbol numbers in param line of beginning an ending parameter

View file

@ -86,16 +86,10 @@ typedef struct {
#define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SNOOP_ISO_14443a 0x0383
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384
#define CMD_READER_ISO_14443a 0x0385 #define CMD_READER_ISO_14443a 0x0385
#define CMD_SIMULATE_MIFARE_CARD 0x0386
#define CMD_SIMULATE_TAG_LEGIC_RF 0x0387 #define CMD_SIMULATE_TAG_LEGIC_RF 0x0387
#define CMD_READER_LEGIC_RF 0x0388 #define CMD_READER_LEGIC_RF 0x0388
#define CMD_WRITER_LEGIC_RF 0x0399 #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 #define CMD_SNOOP_ICLASS 0x0392
// For measurements of the antenna tuning // For measurements of the antenna tuning
@ -107,6 +101,21 @@ typedef struct {
// For direct FPGA control // 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: // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: