appears to work - using normal mifare sim init

working demo

works

seems to work so far

more cleanup and works

working copy

working, clean one more pass

cleanup continues

back in buisness babyyy

final cleanup before PR I hope
This commit is contained in:
n-hutton
2025-01-21 23:39:25 +00:00
parent 32f06db2e8
commit 3eb0238481
7 changed files with 367 additions and 603 deletions
+317 -420
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -25,5 +25,6 @@
#define AUTHKEYNONE 0xff
void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);
void annotate(uint8_t *cmd, uint8_t cmdsize);
#endif
+6 -172
View File
@@ -36,11 +36,6 @@
#include "i2c.h"
#include "i2c_direct.h"
static uint8_t fci_template[] = {0x02, 0x6f, 0x5e, 0x84, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xa5, 0x53, 0x50, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0x9f, 0x38, 0x18, 0x9f, 0x66, 0x04, 0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03, 0x9c, 0x01, 0x9f, 0x37, 0x04, 0x5f, 0x2d, 0x02, 0x65, 0x6e, 0x9f, 0x11, 0x01, 0x01, 0x9f, 0x12, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0xbf, 0x0c, 0x13, 0x9f, 0x5a, 0x05, 0x31, 0x08, 0x26, 0x08, 0x26, 0x9f, 0x0a, 0x08, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xd8, 0x15};
static uint8_t pay1_response[] = { 0x6F, 0x1E, 0x84, 0x0E, 0x31, 0x50, 0x41, 0x59 };
static uint8_t pay2_response[] = { 0x03, 0x6f, 0x3e, 0x84, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0xa5, 0x2c, 0xbf, 0x0c, 0x29, 0x61, 0x27, 0x4f, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x50, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0x9f, 0x0a, 0x08, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x63, 0x04, 0xdf, 0x20, 0x01, 0x80, 0x90, 0x00, 0x07, 0x9d};
static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint8_t *output, uint16_t *olen) {
LED_D_ON();
@@ -50,9 +45,6 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
// check if alloacted...
smartcard_command_t flags = p->flags;
//if ((flags & SC_CLEARLOG) == SC_CLEARLOG)
//clear_trace();
if ((flags & SC_LOG) == SC_LOG)
set_tracing(true);
else
@@ -65,10 +57,9 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
if ((flags & SC_SELECT) == SC_SELECT) {
smart_card_atr_t card;
bool gotATR = GetATR(&card, true);
//reply_old(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
if (gotATR == false) {
Dbprintf("No ATR received...\n");
//reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
goto OUT;
}
}
@@ -92,8 +83,6 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
);
if (res == false && g_dbglevel > 3) {
//DbpString(I2C_ERROR);
//reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
Dbprintf("SmartCardDirectSend: I2C_BufferWrite failed\n");
goto OUT;
}
@@ -109,11 +98,8 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
}
if (len == 2 && resp[1] == 0x61) {
//Dbprintf("Data to be read: len = %d\n", len);
//Dbprintf("\n");
uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, resp[2]};
//smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + sizeof(cmd_getresp));
smart_card_raw_t *payload = (smart_card_raw_t *)BigBuf_calloc(sizeof(smart_card_raw_t) + sizeof(cmd_getresp));
payload->flags = SC_RAW | SC_LOG;
payload->len = sizeof(cmd_getresp);
@@ -129,8 +115,6 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
resp[2] = 0x82;
AddCrc14A(resp, 3);
//Dbhexdump(5, &resp[0], false); // special print
//EmSendCmd(&resp[0], 5);
memcpy(output, resp, 5);
*olen = 5;
}
@@ -142,9 +126,6 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
resp[2] = 0x82;
AddCrc14A(resp, 3);
//Dbhexdump(5, &resp[0], false); // special print
//EmSendCmd14443aRaw(&resp[0], 5);
//EmSendCmd(&resp[0], 5);
memcpy(output, resp, 5);
*olen = 5;
FpgaDisableTracing();
@@ -154,108 +135,23 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
Dbprintf("***** sending it over the wire... len: %d =>\n", len);
resp[1] = prepend;
// if we have a generate AC request, lets extract the data and populate the template
if (resp[1] != 0xff && resp[2] == 0x77) {
Dbprintf("we have detected a generate ac response, lets repackage it!");
Dbhexdump(len, &resp[1], false); // special print
// 11 and 12 are trans counter.
// 16 to 24 are the cryptogram
// 27 to 34 is issuer application data
Dbprintf("atc: %d %d, cryptogram: %d ", resp[11], resp[12], resp[13]);
// then, on the template:
// 61 and 62 for counter
// 46 to 54 for cryptogram
// 36 to 43 for issuer application data
uint8_t template[] = { 0x00, 0x00, 0x77, 0x47, 0x82, 0x02, 0x39, 0x00, 0x57, 0x13, 0x47, 0x62, 0x28, 0x00, 0x05, 0x93, 0x38, 0x64, 0xd2, 0x70, 0x92, 0x01, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x0f, 0x5f, 0x34, 0x01, 0x00, 0x9f, 0x10, 0x07, 0x06, 0x01, 0x12, 0x03, 0xa0, 0x20, 0x00, 0x9f, 0x26, 0x08, 0x56, 0xcb, 0x4e, 0xe1, 0xa4, 0xef, 0xac, 0x74, 0x9f, 0x27, 0x01, 0x80, 0x9f, 0x36, 0x02, 0x00, 0x07, 0x9f, 0x6c, 0x02, 0x3e, 0x00, 0x9f, 0x6e, 0x04, 0x20, 0x70, 0x00, 0x00, 0x90, 0x00, 0xff, 0xff};
// do the replacement
template[1] = resp[1]; // class bit
template[61] = resp[11];
template[62] = resp[12];
template[46] = resp[16];
template[47] = resp[17];
template[48] = resp[18];
template[49] = resp[19];
template[50] = resp[20];
template[51] = resp[21];
template[52] = resp[22];
template[53] = resp[23];
template[54] = resp[24];
template[36] = resp[27];
template[37] = resp[28];
template[38] = resp[29];
template[39] = resp[30];
template[40] = resp[31];
template[41] = resp[32];
template[42] = resp[33];
Dbprintf("\nrearranged is: ");
len = sizeof(template);
Dbhexdump(len, &template[0], false); // special print
AddCrc14A(&template[1], len - 3);
Dbprintf("\nafter crc rearranged is: ");
Dbhexdump(len, &template[0], false); // special print
Dbprintf("\n");
//EmSendCmd(&template[1], len-1);
memcpy(output, &template[1], len - 1);
*olen = len - 1;
BigBuf_free();
return;
}
//Dbhexdump(len, &resp[1], false); // special print
AddCrc14A(&resp[1], len);
Dbhexdump(len + 2, &resp[1], false); // special print
// Check we don't want to modify the response (application profile response)
//uint8_t modifyme[] = {0x03, 0x77, 0x0e, 0x82, 0x02};
Dbhexdump(len + 2, &resp[1], false);
BigBuf_free();
if (prepend == 0xff) {
Dbprintf("pdol request, we can can the response...");
Dbprintf("pdol request, we can ignore the response...");
return;
}
if (memcmp(&resp[2], &pay1_response[0], sizeof(pay1_response)) == 0 && true) {
Dbprintf("Switching out the pay1 response for a pay2 response...");
//EmSendCmd(&pay2_response[0], sizeof(pay2_response));
memcpy(output, &pay2_response[0], sizeof(pay2_response));
*olen = sizeof(pay2_response);
} else if (memcmp(&resp[1], &fci_template[0], 2) == 0 && true) {
Dbprintf("***** modifying response to have full fci template...!");
//EmSendCmd(&fci_template[0], sizeof(fci_template));
memcpy(output, &fci_template[0], sizeof(fci_template));
*olen = sizeof(fci_template);
} else {
//Dbprintf("***** not modifying response...");
//EmSendCmd(&resp[1], len + 2);
memcpy(output, &resp[1], len + 2);
*olen = len + 2;
}
memcpy(output, &resp[1], len + 2);
*olen = len + 2;
BigBuf_free();
//memcpy(saved_command, &resp[1], len+2);
//saved_command_len = len+2;
//EmSendCmd14443aRaw(&resp[1], len+2);
//FpgaDisableTracing();
//EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
}
//reply_ng(CMD_SMART_RAW, PM3_SUCCESS, resp, len);
OUT:
//BigBuf_free();
//set_tracing(false);
LEDsoff();
}
@@ -269,7 +165,6 @@ int CmdSmartRaw(const uint8_t prepend, const uint8_t *data, int dlen, uint8_t *o
dlen = data[4] + 5;
}
//smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + dlen);
smart_card_raw_t *payload = (smart_card_raw_t *)BigBuf_calloc(sizeof(smart_card_raw_t) + dlen);
if (payload == NULL) {
Dbprintf("failed to allocate memory");
@@ -285,7 +180,6 @@ int CmdSmartRaw(const uint8_t prepend, const uint8_t *data, int dlen, uint8_t *o
bool use_t0 = true;
if (active || active_select) {
payload->flags |= (SC_CONNECT | SC_CLEARLOG);
if (active_select)
payload->flags |= SC_SELECT;
@@ -296,7 +190,6 @@ int CmdSmartRaw(const uint8_t prepend, const uint8_t *data, int dlen, uint8_t *o
payload->flags |= SC_WAIT;
payload->wait_delay = timeout;
}
//Dbprintf("SIM Card timeout... %u ms", payload->wait_delay);
if (dlen > 0) {
if (use_t0)
@@ -305,66 +198,7 @@ int CmdSmartRaw(const uint8_t prepend, const uint8_t *data, int dlen, uint8_t *o
payload->flags |= SC_RAW;
}
////uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
//uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
//if (buf == NULL) {
// Dbprintf("failed to allocate memory");
// free(payload);
// return PM3_EMALLOC;
//}
//clearCommandBuffer();
//SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen);
//for (int i = 0; i < dlen; i++) {
// Dbprintf("%02x ", data[i]);
//}
SmartCardDirectSend(prepend, payload, output, olen);
//if (reply == false) {
// Dbprintf("failed to talk to smart card!!!");
// goto out;
//}
//// reading response from smart card
//int len = smart_response(buf, PM3_CMD_DATA_SIZE);
//if (len < 0) {
// free(payload);
// free(buf);
// return PM3_ESOFT;
//}
//if (buf[0] == 0x6C) {
// // request more bytes to download
// data[4] = buf[1];
// memcpy(payload->data, data, dlen);
// clearCommandBuffer();
// SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen);
// len = smart_response(buf, PM3_CMD_DATA_SIZE);
// data[4] = 0;
//}
//if (decode_tlv && len > 4) {
// TLVPrintFromBuffer(buf, len - 2);
//} else {
// if (len > 2) {
// Dbprintf("Response data:");
// Dbprintf(" # | bytes | ascii");
// Dbprintf("---+-------------------------------------------------+-----------------");
// print_hex_break(buf, len, 16);
// }
//}
//memcpy(buffer, buf, len);
//out:
//free(payload);
//free(buf);
return PM3_SUCCESS;
}
+3 -1
View File
@@ -198,7 +198,8 @@ static uint8_t MifareMaxSector(uint16_t flags) {
}
}
static bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
bool MifareSimInit (uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
//static bool MifareSimInitX(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
uint8_t uid_tmp[10] = {0};
// SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
@@ -293,6 +294,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t s
rSAK[0] = rSAK_1k;
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_2K_MAX_BYTES)) {
Dbprintf("We got this to happen!!!\n");
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
rSAK[0] = rSAK_2k;
*rats = rRATS;
+2
View File
@@ -21,6 +21,7 @@
#define __MIFARESIM_H
#include "common.h"
#include "mifare.h"
#ifndef CheckCrc14A
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
@@ -42,5 +43,6 @@
#define AUTHKEYNONE 0xff
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t atqa, uint8_t sak);
bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len);
#endif
+29 -10
View File
@@ -643,21 +643,21 @@ static int CmdEMVSmartToNFC(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int uid_len = 0;
int uidlen = 0;
uint8_t uid[7] = {0};
CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
CLIGetHexWithReturn(ctx, 2, uid, &uidlen);
if (uid_len == 0) {
if (uidlen == 0) {
PrintAndLogEx(SUCCESS, "No UID provided, using default.");
uint8_t default_uid[7] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
memcpy(uid, default_uid, sizeof(default_uid));
uid_len = sizeof(default_uid);
} else if (uid_len != 7) {
uidlen = sizeof(default_uid);
} else if (uidlen != 7) {
PrintAndLogEx(FAILED, "UID must be 7 bytes long.");
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "UID length is %d", uid_len);
PrintAndLogEx(SUCCESS, "UID length is %d", uidlen);
bool testMode = arg_get_lit(ctx, 1);
bool show_apdu = true;
@@ -670,7 +670,7 @@ static int CmdEMVSmartToNFC(const char *Cmd) {
CLIParserFree(ctx);
// todo: check this is relevant for us.
// todo for PR: check this is relevant for us.
SetAPDULogging(show_apdu);
struct {
@@ -681,14 +681,33 @@ static int CmdEMVSmartToNFC(const char *Cmd) {
uint8_t sak;
} PACKED payload;
memcpy(payload.uid, uid, uid_len);
payload.flags = 0x1204;
memcpy(payload.uid, uid, uidlen);
// Set up the flags for 2K mifare sim with RATS
uint16_t flags = 0;
FLAG_SET_UID_IN_DATA(flags, uidlen);
if (IS_FLAG_UID_IN_EMUL(flags)) {
PrintAndLogEx(WARNING, "Invalid parameter for UID");
CLIParserFree(ctx);
return PM3_EINVARG;
}
FLAG_SET_MF_SIZE(flags, MIFARE_2K_MAX_BYTES);
//snprintf(csize, sizeof(csize), "2K with RATS");
//k_sectors_cnt = MIFARE_2K_MAXSECTOR; // todo: delete
flags |= FLAG_ATQA_IN_DATA;
flags |= FLAG_SAK_IN_DATA;
payload.flags = flags;
//payload.flags = 0x1204;
payload.exitAfter = 0x1;
payload.atqa = 0x0;
payload.sak = 0x20;
clearCommandBuffer();
SendCommandNG(0x0386, (uint8_t *)&payload, sizeof(payload));
SendCommandNG(CMD_HF_ISO14443A_EMV_SIMULATE, (uint8_t *)&payload, sizeof(payload));
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
+9
View File
@@ -490,6 +490,15 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define ISO7816_GET_CHALLENGE 0x84
#define ISO7816_MANAGE_CHANNEL 0x70
#define ISO7816_APPLICATION_BLOCK 0x1E
#define ISO7816_APPLICATION_UNBLOCK 0x18
#define ISO7816_CARD_BLOCK 0x16
#define ISO7816_GENERATE_APPLICATION_CRYPTOGRAM 0xAE
#define ISO7816_GET_PROCESSING_OPTIONS 0xA8
#define ISO7816_PIN_CHANGE 0x24
#define ISO7816_PIN_CHANGE 0x24
#define ISO7816_GET_RESPONSE 0xC0
// ISO7816-4 For response APDU's