This commit is contained in:
iceman1001 2023-10-09 12:47:00 +02:00
commit 60ff2351ba
2 changed files with 92 additions and 78 deletions

View file

@ -30,7 +30,7 @@
#include "cmd.h"
void ModInfo(void) {
DbpString(" HF - Reading Visa cards & Emulating a Visa MSD Transaction(ISO14443) - (Salvador Mendoza)");
DbpString(" HF - Reading VISA cards & Emulating a VISA MSD Transaction(ISO14443) - (Salvador Mendoza)");
}
/* This standalone implements two different modes: reading and emulating.
@ -132,9 +132,15 @@ static uint8_t treatPDOL(const uint8_t *apdu) {
void RunMod(void) {
StandAloneMode();
DbpString(_YELLOW_(">>") "Reading Visa cards & Emulating a Visa MSD Transaction a.k.a. MSDSal Started " _YELLOW_("<<"));
DbpString("");
DbpString(_YELLOW_(">>>") " Reading VISA cards & Emulating a VISA MSD Transaction a.k.a. MSDSal Started " _YELLOW_("<<<"));
DbpString("");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// free eventually allocated BigBuf memory but keep Emulator Memory
// also sets HIGH pointer of BigBuf enabling us to malloc w/o fiddling w the reserved emulator memory
BigBuf_free_keep_EM();
//For reading process
iso14a_card_select_t card_a_info;
@ -161,7 +167,6 @@ void RunMod(void) {
bool existpdol;
// - MSD token card format -
//
//Card number: 4412 3456 0578 1234
@ -175,34 +180,31 @@ void RunMod(void) {
char token[19] = {0x00};
bool chktoken = false;
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
// Such a response is less time critical, so we can prepare them on the fly
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
#define DYNAMIC_MODULATION_BUFFER_SIZE 512
// UID 4 bytes(could be 7 bytes if needed it)
uint8_t flags = FLAG_4B_UID_IN_DATA;
// in case there is a read command received we shouldn't break
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04};
uint8_t visauid[7] = {0x04, 0x02, 0x03, 0x04};
memcpy(data, visauid, 4);
// to initialize the emulation
uint8_t tagType = 11; // 11 = ISO/IEC 14443-4 - javacard (JCOP)
tag_response_info_t *responses;
uint32_t cuid = 0;
uint32_t counters[3] = { 0x00, 0x00, 0x00 };
uint8_t tearings[3] = { 0xbd, 0xbd, 0xbd };
uint8_t pages = 0;
// command buffers
uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 };
uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 };
uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE] = {0};
uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE] = {0};
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
// Such a response is less time critical, so we can prepare them on the fly
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
#define DYNAMIC_MODULATION_BUFFER_SIZE 512
uint8_t *dynamic_response_buffer = BigBuf_calloc(DYNAMIC_RESPONSE_BUFFER_SIZE);
uint8_t *dynamic_modulation_buffer = BigBuf_calloc(DYNAMIC_MODULATION_BUFFER_SIZE);
// to know the transaction status
uint8_t prevCmd = 0;
@ -223,11 +225,11 @@ void RunMod(void) {
// Checking if the user wants to go directly to emulation mode using a hardcoded track 2
if (chktoken == true && token[0] != 0x00) {
state = STATE_EMU;
DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]"));
DbpString("\n"_YELLOW_("!!") "Waiting for a card reader...");
DbpString("Initialized [ " _BLUE_("emulation mode") " ]");
DbpString("Waiting for a card reader...");
} else {
DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]"));
DbpString("\n"_YELLOW_("!!") "Waiting for a Visa card...");
DbpString("Initialized [ " _YELLOW_("reading mode") " ]");
DbpString("Waiting for a VISA card...");
}
for (;;) {
@ -240,20 +242,20 @@ void RunMod(void) {
int button_pressed = BUTTON_HELD(1000);
if (button_pressed == BUTTON_HOLD)
if (button_pressed == BUTTON_HOLD) {
break;
else if (button_pressed == BUTTON_SINGLE_CLICK) {
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
// pressing one time change between reading & emulation
if (state == STATE_READ) {
if (chktoken == true && token[0] != 0x00) {
// only change to emulation if it saved a track 2 in memory
state = STATE_EMU;
DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]"));
DbpString("[ " _BLUE_("Emulation mode") " ]");
} else
DbpString(_YELLOW_("!!") "Nothing in memory to emulate");
DbpString(_YELLOW_("Nothing in memory to emulate"));
} else {
state = STATE_READ;
DbpString(_YELLOW_("[ ") "In reading mode" _YELLOW_(" ]"));
DbpString("[ " _YELLOW_("Reading mode") " ]");
}
}
@ -261,15 +263,14 @@ void RunMod(void) {
if (state == STATE_READ) {
LED_A_ON();
if (chktoken)
if (chktoken) {
LED_C_ON();
}
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
if (iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)) {
DbpString(_YELLOW_("+") "Found ISO 14443 Type A!");
for (uint8_t i = 0; i < 4; i++) {
chktoken = false;
LED_C_OFF();
@ -277,11 +278,11 @@ void RunMod(void) {
uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apduslen[i], false, apdubuffer, NULL);
if (apdulen > 0) {
DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]"));
DbpString("[ " _YELLOW_("Proxmark command") " ]");
Dbhexdump(apduslen[i], apdus[i], false);
DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]"));
DbpString("[ " _GREEN_( "Card answer") " ]");
Dbhexdump(apdulen - 2, apdubuffer, false);
DbpString("----");
DbpString("-------------------------------");
for (uint8_t u = 0; u < apdulen; u++) {
if (i == 1) {
@ -309,25 +310,27 @@ void RunMod(void) {
}
if (i == 1) {
DbpString(_GREEN_("[ ") "Challenge generated" _GREEN_(" ]"));
DbpString("[ "_GREEN_("Challenge generated") " ]");
Dbhexdump(plen, existpdol ? ppdol : processing, false);
}
} else {
DbpString(_YELLOW_("!!") "Error reading the card");
DbpString(_RED_("Error reading the card"));
}
LED_B_OFF();
}
if (chktoken) {
DbpString(_RED_("[ ") "Track 2" _RED_(" ]"));
DbpString("[ " _GREEN_("Track 2") " ]");
Dbhexdump(19, (uint8_t *)token, false);
DbpString(_YELLOW_("!!") "Card number");
DbpString("[ " _GREEN_("Card Number") " ]");
Dbhexdump(8, (uint8_t *)token, false);
DbpString("---");
DbpString("-------------------------------");
DbpString("");
DbpString("");
LED_C_ON();
state = STATE_EMU;
DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]"));
DbpString("\n"_YELLOW_("!!") "Waiting for a card reader...");
DbpString("Initialized [ " _BLUE_("emulation mode") " ]");
DbpString("Waiting for a card reader...");
}
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -340,14 +343,15 @@ void RunMod(void) {
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
// tag type: 11 = ISO/IEC 14443-4 - javacard (JCOP)
if (SimulateIso14443aInit(11, flags, data, &responses, &cuid, NULL, NULL, NULL) == false) {
BigBuf_free_keep_EM();
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
DbpString(_YELLOW_("!!") "Error initializing the emulation process!");
DbpString(_RED_("Error initializing the emulation process!"));
SpinDelay(500);
state = STATE_READ;
DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]"));
DbpString("\n" _YELLOW_("!!") "Waiting for a Visa card...");
DbpString("Initialized [ "_YELLOW_("reading mode") " ]");
DbpString("Waiting for a VISA card...");
continue;
}
@ -366,11 +370,12 @@ void RunMod(void) {
for (;;) {
LED_B_OFF();
// clean receive command buffer
if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
DbpString(_YELLOW_("!!") "Emulator stopped");
if (GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len) == false) {
DbpString("Emulator stopped");
retval = PM3_EOPABORTED;
break;
}
tag_response_info_t *p_response = NULL;
LED_B_ON();
@ -387,41 +392,33 @@ void RunMod(void) {
// received a HALT
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) {
//DbpString(_YELLOW_("+") "Received a HALT");
p_response = NULL;
// received a WAKEUP
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) {
//DbpString(_YELLOW_("+") "WAKEUP Received");
prevCmd = 0;
p_response = &responses[RESP_INDEX_ATQA];
// received request for UID (cascade 1)
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) {
//DbpString(_YELLOW_("+") "Request for UID C1");
p_response = &responses[RESP_INDEX_UIDC1];
// received a SELECT (cascade 1)
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) {
//DbpString(_YELLOW_("+") "Request for SELECT S1");
p_response = &responses[RESP_INDEX_SAKC1];
// received a RATS request
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) {
DbpString(_YELLOW_("+") "Request for RATS");
prevCmd = 0;
//p_response = &responses[RESP_INDEX_RATS];
static uint8_t rRATS[] = { 0x13, 0x78, 0x80, 0x72, 0x02, 0x80, 0x31, 0x80, 0x66, 0xb1, 0x84, 0x0c, 0x01, 0x6e, 0x01, 0x83, 0x00, 0x90, 0x00 };
memcpy(&dynamic_response_info.response[0], rRATS, sizeof(rRATS));
dynamic_response_info.response_n = sizeof(rRATS);
p_response = &responses[RESP_INDEX_RATS];
} else {
DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]"));
Dbhexdump(len, receivedCmd, false);
if (g_dbglevel == DBG_DEBUG ) {
DbpString("[ "_YELLOW_("Card reader command") " ]");
Dbhexdump(len, receivedCmd, false);
}
// emulate a Visa MSD(Magnetic stripe data) card
// emulate a Visa MSD (Magnetic stripe data) card
if (receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) {
dynamic_response_info.response[0] = receivedCmd[0];
@ -480,7 +477,7 @@ void RunMod(void) {
}
}
} else {
DbpString(_YELLOW_("!!") "Received unknown command!");
DbpString(_RED_("Received unknown command!"));
if (prevCmd < 4) {
memcpy(dynamic_response_info.response, receivedCmd, len);
dynamic_response_info.response_n = len;
@ -491,7 +488,7 @@ void RunMod(void) {
}
if (dynamic_response_info.response_n > 0) {
DbpString(_GREEN_("[ ") "Proxmark3 answer" _GREEN_(" ]"));
DbpString("[ " _GREEN_("Proxmark3 answer") " ]");
Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false);
DbpString("----");
@ -501,7 +498,7 @@ void RunMod(void) {
if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
SpinDelay(500);
DbpString(_YELLOW_("!!") "Error preparing Proxmark to answer!");
DbpString(_RED_("Error preparing Proxmark to answer!"));
continue;
}
p_response = &dynamic_response_info;
@ -518,6 +515,8 @@ void RunMod(void) {
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
}
}
DbpString(_YELLOW_("[=]") "exiting");
DbpString("Exit standalone mode!");
DbpString("");
SpinErr(15, 200, 3);
LEDsoff();
}

View file

@ -1021,7 +1021,8 @@ bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_
}
}
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages) {
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_response_info_t **responses,
uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages) {
uint8_t sak = 0;
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
static uint8_t rATQA[2] = { 0x00 };
@ -1038,8 +1039,13 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
// Prepare the optional third SAK (for 10 byte UID), drop the cascade bit
static uint8_t rSAKc3[3] = { 0x00 };
// dummy ATS (pseudo-ATR), answer to RATS
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
// TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
// TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us)
// TC(1) = 0x02: CID supported, NAD not supported
// static uint8_t rRATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 };
static uint8_t rRATS[] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 };
static uint8_t rRATS[40] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 };
uint8_t rRATS_len = 8;
// GET_VERSION response for EV1/NTAG
static uint8_t rVERSION[10] = { 0x00 };
@ -1092,6 +1098,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
rATQA[1] = 0x03;
sak = 0x20;
memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8);
rRATS_len = 8;
break;
}
case 4: { // ISO/IEC 14443-4 - javacard (JCOP)
@ -1158,7 +1165,10 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
sak = 0x20;
break;
}
case 11: { // ISO/IEC 14443-4 - javacard (JCOP)
case 11: { // ISO/IEC 14443-4 - javacard (JCOP) / EMV
memcpy(rRATS, "\x13\x78\x80\x72\x02\x80\x31\x80\x66\xb1\x84\x0c\x01\x6e\x01\x83\x00\x90\x00", 19);
rRATS_len = 19;
rATQA[0] = 0x04;
sak = 0x20;
break;
@ -1266,11 +1276,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
return false;
}
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
// TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
// TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us)
// TC(1) = 0x02: CID supported, NAD not supported
AddCrc14A(rRATS, sizeof(rRATS) - 2);
AddCrc14A(rRATS, rRATS_len - 2);
AddCrc14A(rPPS, sizeof(rPPS) - 2);
@ -1305,14 +1311,23 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
{ .response = rPACK, .response_n = sizeof(rPACK) } // PACK response
};
// "precompile" responses. There are 12 predefined responses with a total of 84 bytes data to transmit.
// since rats len is variable now.
responses_init[RESP_INDEX_RATS].response_n = rRATS_len;
// "precompiled" responses.
// These exist for speed reasons. There are no time in the anti collision phase to calculate responses.
// There are 12 predefined responses with a total of 84 bytes data to transmit.
//
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
// 85 * 8 data bits, 85 * 1 parity bits, 12 start bits, 12 stop bits, 12 correction bits
// 85 * 8 + 85 + 12 + 12 + 12 == 801
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 801
// CHG:
// 85 bytes normally (rats = 8 bytes)
// 77 bytes + ratslen,
uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE ( ((77 + rRATS_len) * 8) + 77 + rRATS_len + 12 + 12 + 12)
uint8_t *free_buffer = BigBuf_calloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
// modulation buffer pointer and current buffer free space size
uint8_t *free_buffer_pointer = free_buffer;
size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE;
@ -1328,7 +1343,6 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
}
*responses = responses_init;
return true;
}
@ -1362,12 +1376,16 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 };
uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 };
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
// Such a response is less time critical, so we can prepare them on the fly
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64
#define DYNAMIC_MODULATION_BUFFER_SIZE 512
uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE] = {0};
uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE] = {0};
uint8_t *dynamic_response_buffer = BigBuf_calloc(DYNAMIC_RESPONSE_BUFFER_SIZE);
uint8_t *dynamic_modulation_buffer = BigBuf_calloc(DYNAMIC_MODULATION_BUFFER_SIZE);
tag_response_info_t dynamic_response_info = {
.response = dynamic_response_buffer,
.response_n = 0,
@ -1375,9 +1393,6 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
.modulation_n = 0
};
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
BigBuf_free_keep_EM();
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);