mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
@@ -18,6 +18,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Added detection for FM11NT021 (@iceman1001)
|
||||
- Added detection of a magic NTAG 215 (@iceman1001)
|
||||
- Fixed hardnested on AVX512F #2410 (@xianglin1998)
|
||||
- Added `hf 14a aidsim` - simulates a PICC (like `14a sim`), and allows you to respond to specific AIDs and getData responses (@evildaemond)
|
||||
|
||||
## [Backdoor.4.18994][2024-09-10]
|
||||
- Changed flashing messages to be less scary (@iceman1001)
|
||||
|
||||
+20
-1
@@ -1634,9 +1634,28 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
uint16_t flags;
|
||||
uint8_t uid[10];
|
||||
uint8_t exitAfter;
|
||||
uint8_t rats[20];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid, payload->exitAfter); // ## Simulate iso14443a tag - pass tag type & UID
|
||||
SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid, payload->exitAfter, payload->rats); // ## Simulate iso14443a tag - pass tag type & UID
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_SIM_AID: {
|
||||
struct p {
|
||||
uint8_t tagtype;
|
||||
uint16_t flags;
|
||||
uint8_t uid[10];
|
||||
uint8_t rats[20];
|
||||
uint8_t aid[30];
|
||||
uint8_t response[100];
|
||||
uint8_t apdu[100];
|
||||
int aid_len;
|
||||
int respond_len;
|
||||
int apdu_len;
|
||||
bool enumerate;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SimulateIso14443aTagAID(payload->tagtype, payload->flags, payload->uid, payload->rats, payload->aid, payload->response, payload->apdu, payload->aid_len, payload->respond_len, payload->apdu_len, payload->enumerate); // ## Simulate iso14443a tag - pass tag type, UID, rats, aid, resp, apdu
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_ANTIFUZZ: {
|
||||
|
||||
+251
-3
@@ -1086,7 +1086,7 @@ 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,
|
||||
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *iRATs, 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).
|
||||
@@ -1248,6 +1248,13 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// copy the iRATs if supplied
|
||||
if ((flags & RATS_IN_DATA) == RATS_IN_DATA) {
|
||||
memcpy(rRATS ,iRATs, sizeof(iRATs));
|
||||
// rats len is dictated by the first char of the string, add 2 crc bytes
|
||||
rRATS_len = (iRATs[0] + 2);
|
||||
}
|
||||
|
||||
// if uid not supplied then get from emulator memory
|
||||
if ((memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10) == 0) || ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL)) {
|
||||
@@ -1342,6 +1349,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AddCrc14A(rRATS, rRATS_len - 2);
|
||||
|
||||
AddCrc14A(rPPS, sizeof(rPPS) - 2);
|
||||
@@ -1417,7 +1426,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r
|
||||
// response to send, and send it.
|
||||
// 'hf 14a sim'
|
||||
//-----------------------------------------------------------------------------
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads) {
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads, uint8_t *iRATs) {
|
||||
|
||||
#define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack()
|
||||
|
||||
@@ -1459,7 +1468,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
||||
.modulation_n = 0
|
||||
};
|
||||
|
||||
if (SimulateIso14443aInit(tagType, flags, data, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
if (SimulateIso14443aInit(tagType, flags, data, iRATs, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||
return;
|
||||
@@ -3865,3 +3874,242 @@ void DetectNACKbug(void) {
|
||||
hf_field_off();
|
||||
set_tracing(false);
|
||||
}
|
||||
|
||||
/* ///
|
||||
Based upon the SimulateIso14443aTag, this aims to instead take an AID Value you've supplied, and return your selected response.
|
||||
It can also continue after the AID has been selected, and respond to other request types.
|
||||
This was forked from the original function to allow for more flexibility in the future, and to increase the processing speed of the original function.
|
||||
/// */
|
||||
|
||||
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *iRATs, uint8_t *aid, uint8_t *resp, uint8_t *apdu, int aidLen, int respondLen, int apduLen, bool enumerate) {
|
||||
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 };
|
||||
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
// Increased the buffer size to allow for more complex responses
|
||||
#define DYNAMIC_RESPONSE_BUFFER2_SIZE 512
|
||||
#define DYNAMIC_MODULATION_BUFFER2_SIZE 1536
|
||||
|
||||
uint8_t * dynamic_response_buffer2 = BigBuf_calloc(DYNAMIC_RESPONSE_BUFFER2_SIZE);
|
||||
uint8_t * dynamic_modulation_buffer2 = BigBuf_calloc(DYNAMIC_MODULATION_BUFFER2_SIZE);
|
||||
tag_response_info_t dynamic_response_info = {
|
||||
.response = dynamic_response_buffer2,
|
||||
.response_n = 0,
|
||||
.modulation = dynamic_modulation_buffer2,
|
||||
.modulation_n = 0
|
||||
};
|
||||
|
||||
if (SimulateIso14443aInit(tagType, flags, data, iRATs, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||
|
||||
iso14a_set_timeout(201400); // 106 * 19ms default *100?
|
||||
|
||||
int len = 0;
|
||||
int retval = PM3_SUCCESS;
|
||||
int sentCount = 0;
|
||||
bool odd_reply = true;
|
||||
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
LED_A_ON();
|
||||
|
||||
// Filters for when this comes through
|
||||
static uint8_t aidFilter[30] = { 0x00 }; // Default AID Value
|
||||
static uint8_t aidResponse[100] = { 0x00 }; // Default AID Response
|
||||
static uint8_t apduCommand [100] = { 0x00 }; // Default APDU GetData Response
|
||||
|
||||
// Copy the AID, AID Response, and the GetData APDU response into our variables
|
||||
if (aid != 0) {
|
||||
memcpy(aidFilter, aid, aidLen);
|
||||
}
|
||||
if (resp != 0) {
|
||||
memcpy(aidResponse, resp, respondLen);
|
||||
}
|
||||
if (apdu != 0) {
|
||||
memcpy(apduCommand, apdu, apduLen);
|
||||
}
|
||||
|
||||
|
||||
// main loop
|
||||
bool finished = false;
|
||||
while (finished == false) {
|
||||
// BUTTON_PRESS check done in GetIso14443aCommandFromReader
|
||||
WDT_HIT();
|
||||
|
||||
tag_response_info_t *p_response = NULL;
|
||||
|
||||
// Clean receive command buffer
|
||||
if (GetIso14443aCommandFromReader(receivedCmd, sizeof(receivedCmd), receivedCmdPar, &len) == false) {
|
||||
Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
|
||||
retval = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST, but in HALTED, skip
|
||||
odd_reply = !odd_reply;
|
||||
if (odd_reply) {
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
}
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 2) { // Received request for UID (cascade 1)
|
||||
p_response = &responses[RESP_INDEX_UIDC1];
|
||||
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 2) { // Received request for UID (cascade 2)
|
||||
p_response = &responses[RESP_INDEX_UIDC2];
|
||||
} else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && len == 2) { // Received request for UID (cascade 3)
|
||||
p_response = &responses[RESP_INDEX_UIDC3];
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
|
||||
p_response = &responses[RESP_INDEX_SAKC1];
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 9) { // Received a SELECT (cascade 2)
|
||||
p_response = &responses[RESP_INDEX_SAKC2];
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && len == 9) { // Received a SELECT (cascade 3)
|
||||
p_response = &responses[RESP_INDEX_SAKC3];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_PPS) {
|
||||
p_response = &responses[RESP_INDEX_PPS];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT
|
||||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
p_response = NULL;
|
||||
finished = true;
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
} else {
|
||||
// clear old dynamic responses
|
||||
dynamic_response_info.response_n = 0;
|
||||
dynamic_response_info.modulation_n = 0;
|
||||
|
||||
// Check for ISO 14443A-4 compliant commands, look at left nibble
|
||||
switch (receivedCmd[0]) {
|
||||
case 0x0B:
|
||||
case 0x0A: { // IBlock (command CID)
|
||||
dynamic_response_info.response[0] = receivedCmd[0];
|
||||
dynamic_response_info.response[1] = 0x00;
|
||||
|
||||
switch (receivedCmd[3]) { // APDU Class Byte
|
||||
// receivedCmd in this case is expecting to structured with a CID, then the APDU command for SelectFile
|
||||
// | IBlock (CID) | CID | APDU Command | CRC |
|
||||
|
||||
case 0xA4: { // SELECT FILE
|
||||
// Select File AID uses the following format for GlobalPlatform
|
||||
//
|
||||
// | 00 | A4 | 04 | 00 | xx | AID | 00 |
|
||||
// xx in this case is len of the AID value in hex
|
||||
|
||||
// aid len is found as a hex value in receivedCmd[6] (Index Starts at 0)
|
||||
int aid_len = receivedCmd[6];
|
||||
uint8_t* recieved_aid = &receivedCmd[7];
|
||||
|
||||
// aid enumeration flag
|
||||
if (enumerate == true) {
|
||||
Dbprintf("Received AID (%d):", aid_len);
|
||||
Dbhexdump(aid_len, recieved_aid, false);
|
||||
}
|
||||
|
||||
if (memcmp(aidFilter, recieved_aid, aid_len) == 0) { // Evaluate the AID sent by the Reader to the AID supplied
|
||||
// AID Response will be parsed here
|
||||
memcpy(dynamic_response_info.response + 2 , aidResponse, respondLen + 2);
|
||||
dynamic_response_info.response_n = respondLen + 2;
|
||||
} else { // Any other SELECT FILE command will return with a Not Found
|
||||
dynamic_response_info.response[2] = 0x6A;
|
||||
dynamic_response_info.response[3] = 0x82;
|
||||
dynamic_response_info.response_n = 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xDA: { // PUT DATA
|
||||
// Just send them a 90 00 response
|
||||
dynamic_response_info.response[2] = 0x90;
|
||||
dynamic_response_info.response[3] = 0x00;
|
||||
dynamic_response_info.response_n = 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xCA: { // GET DATA
|
||||
if (sentCount == 0) {
|
||||
// APDU Command will just be parsed here
|
||||
memcpy(dynamic_response_info.response + 2 , apduCommand, apduLen + 2);
|
||||
dynamic_response_info.response_n = respondLen + 2;
|
||||
} else {
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
sentCount++;
|
||||
}
|
||||
break;
|
||||
default : {
|
||||
// Any other non-listed command
|
||||
// Respond Not Found
|
||||
dynamic_response_info.response[2] = 0x6A;
|
||||
dynamic_response_info.response[3] = 0x82;
|
||||
dynamic_response_info.response_n = 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xCA:
|
||||
case 0xC2: { // Readers sends deselect command
|
||||
dynamic_response_info.response[0] = 0xCA;
|
||||
dynamic_response_info.response[1] = 0x00;
|
||||
dynamic_response_info.response_n = 2;
|
||||
finished = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
// Never seen this command before
|
||||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
Dbprintf("Received unknown command (len=%d):", len);
|
||||
Dbhexdump(len, receivedCmd, false);
|
||||
}
|
||||
// Do not respond
|
||||
dynamic_response_info.response_n = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (dynamic_response_info.response_n > 0) {
|
||||
|
||||
// Copy the CID from the reader query
|
||||
dynamic_response_info.response[1] = receivedCmd[1];
|
||||
|
||||
// Add CRC bytes, always used in ISO 14443A-4 compliant cards
|
||||
AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n);
|
||||
dynamic_response_info.response_n += 2;
|
||||
|
||||
if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
|
||||
if (g_dbglevel >= DBG_DEBUG) DbpString("Error preparing tag response");
|
||||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
p_response = &dynamic_response_info;
|
||||
}
|
||||
}
|
||||
|
||||
// Send response
|
||||
EmSendPrecompiledCmd(p_response);
|
||||
}
|
||||
|
||||
switch_off();
|
||||
|
||||
set_tracing(false);
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
|
||||
}
|
||||
|
||||
+3
-2
@@ -140,8 +140,8 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
|
||||
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
||||
|
||||
void RAMFUNC SniffIso14443a(uint8_t param);
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads);
|
||||
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);
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads, uint8_t *iRATs);
|
||||
bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *iRATs, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages);
|
||||
bool GetIso14443aCommandFromReader(uint8_t *received, uint16_t received_maxlen, uint8_t *par, int *len);
|
||||
void iso14443a_antifuzz(uint32_t flags);
|
||||
void ReaderIso14443a(PacketCommandNG *c);
|
||||
@@ -174,6 +174,7 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
||||
|
||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||
void DetectNACKbug(void);
|
||||
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *iRATs, uint8_t *aid, uint8_t *resp, uint8_t *apdu, int aid_len, int respond_len, int apdu_len, bool enumerate);
|
||||
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint16_t resp_len, uint8_t *received_len);
|
||||
|
||||
|
||||
@@ -3628,6 +3628,183 @@ int CmdHF14ANdefWrite(const char *Cmd) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values
|
||||
* These AID Values can be responded to and include extra APDU commands after verification
|
||||
*/
|
||||
|
||||
int CmdHF14AAIDSim(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a simaid",
|
||||
"Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values\n"
|
||||
"These AID Values can be responded to and include extra APDU commands on GetData after response\n",
|
||||
"hf 14a simaid -t 3 -> MIFARE Desfire\n"
|
||||
"hf 14a simaid -t 4 -> ISO/IEC 14443-4\n"
|
||||
"hf 14a simaid -t 11 -> Javacard (JCOP)\n"
|
||||
"hf 14a simaid -t 3 --aid a000000000000000000000 --response 9000 --apdu 9000 -> AID, Response and APDU\n"
|
||||
"hf 14a simaid -t 3 --rats 05788172220101 --response 01009000 --apdu 86009000 -> Custom RATS Added\n"
|
||||
"hf 14a simaid -t 3 --rats 05788172220101 -x -> Enumerate AID Values\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int1("t", "type", "<1-12> ", "Simulation type to use"),
|
||||
arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
|
||||
arg_str0("r", "rats", "<hex>", "<0-20> hex bytes RATS"),
|
||||
arg_str0("a", "aid", "<hex>", "<0-100> hex bytes for AID to respond to (Default: A000000000000000000000)"),
|
||||
arg_str0("e", "response", "<hex>", "<0-100> hex bytes for APDU Response to AID Select (Default: 9000)"),
|
||||
arg_str0("p", "apdu", "<hex>", "<0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)"),
|
||||
arg_lit0("x", "enumerate", "Enumerate all AID values via returning Not Found and print them to console "),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int tagtype = arg_get_int_def(ctx, 1, 1);
|
||||
|
||||
bool enumerate = arg_get_lit(ctx, 7);
|
||||
|
||||
int uid_len = 0;
|
||||
int rats_len = 0;
|
||||
int aid_len = 0;
|
||||
int respond_len = 0;
|
||||
int apdu_len = 0;
|
||||
|
||||
uint8_t uid[10] = {0};
|
||||
uint8_t rats[20] = {0};
|
||||
uint8_t aid[30] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t response[100] = {0x90, 0x00};
|
||||
uint8_t apdu[100] = {0x90, 0x00};
|
||||
|
||||
CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
|
||||
CLIGetHexWithReturn(ctx, 3, rats, &rats_len);
|
||||
CLIGetHexWithReturn(ctx, 4, aid, &aid_len);
|
||||
CLIGetHexWithReturn(ctx, 5, response, &respond_len);
|
||||
CLIGetHexWithReturn(ctx, 6, apdu, &apdu_len);
|
||||
|
||||
// default value fill for the AID, response, and apdu
|
||||
if (aid_len == 0) {
|
||||
aid_len = 11;
|
||||
}
|
||||
if (respond_len == 0) {
|
||||
respond_len = 2;
|
||||
}
|
||||
if (apdu_len == 0) {
|
||||
apdu_len = 2;
|
||||
}
|
||||
|
||||
uint16_t flags = 0;
|
||||
bool useUIDfromEML = true;
|
||||
|
||||
if (uid_len > 0) {
|
||||
switch (uid_len) {
|
||||
case 10:
|
||||
flags |= FLAG_10B_UID_IN_DATA;
|
||||
break;
|
||||
case 7:
|
||||
flags |= FLAG_7B_UID_IN_DATA;
|
||||
break;
|
||||
case 4:
|
||||
flags |= FLAG_4B_UID_IN_DATA;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
|
||||
useUIDfromEML = false;
|
||||
}
|
||||
|
||||
if (rats_len > 0) {
|
||||
flags |= RATS_IN_DATA;
|
||||
}
|
||||
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (tagtype > 12) {
|
||||
PrintAndLogEx(ERR, "Undefined tag %d", tagtype);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (useUIDfromEML) {
|
||||
flags |= FLAG_UID_IN_EMUL;
|
||||
}
|
||||
|
||||
struct {
|
||||
uint8_t tagtype;
|
||||
uint16_t flags;
|
||||
uint8_t uid[10];
|
||||
uint8_t rats[20];
|
||||
uint8_t aid[30];
|
||||
uint8_t response[100];
|
||||
uint8_t apdu[100];
|
||||
int aid_len;
|
||||
int respond_len;
|
||||
int apdu_len;
|
||||
bool enumerate;
|
||||
} PACKED payload;
|
||||
|
||||
payload.tagtype = tagtype;
|
||||
payload.flags = flags;
|
||||
payload.enumerate = enumerate;
|
||||
|
||||
// Copy data to payload
|
||||
memcpy(payload.uid, uid, uid_len);
|
||||
memcpy(payload.rats, rats, rats_len);
|
||||
memcpy(payload.aid, aid, aid_len);
|
||||
memcpy(payload.response, response, respond_len);
|
||||
memcpy(payload.apdu, apdu, apdu_len);
|
||||
|
||||
// copy the lengths data to the payload
|
||||
memcpy(&payload.aid_len, &aid_len, sizeof(aid_len));
|
||||
memcpy(&payload.respond_len, &respond_len, sizeof(respond_len));
|
||||
memcpy(&payload.apdu_len, &apdu_len, sizeof(apdu_len));
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO14443A_SIM_AID, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp = {0};
|
||||
|
||||
sector_t *k_sector = NULL;
|
||||
size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR;
|
||||
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
|
||||
bool keypress = kbd_enter_pressed();
|
||||
while (keypress == false) {
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
|
||||
continue;
|
||||
|
||||
if (resp.status != PM3_SUCCESS)
|
||||
break;
|
||||
|
||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
|
||||
break;
|
||||
|
||||
keypress = kbd_enter_pressed();
|
||||
}
|
||||
|
||||
if (keypress) {
|
||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||
// inform device to break the sim loop since client has exited
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
}
|
||||
|
||||
if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
|
||||
//iceman: readerAttack call frees k_sector , this call is useless.
|
||||
showSectorTable(k_sector, k_sectors_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace list -t 14a")"` to view captured tracelog");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
@@ -3638,6 +3815,7 @@ static command_t CommandTable[] = {
|
||||
{"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "Collect n>0 ISO14443-a UIDs in one go"},
|
||||
{"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"},
|
||||
{"sim", CmdHF14ASim, IfPm3Iso14443a, "Simulate ISO 14443-a tag"},
|
||||
{"simaid", CmdHF14AAIDSim, IfPm3Iso14443a, "Simulate ISO 14443-a AID Selection"},
|
||||
{"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"},
|
||||
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
|
||||
{"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"},
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef enum {
|
||||
int CmdHF14A(const char *Cmd);
|
||||
int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff
|
||||
int CmdHF14ASim(const char *Cmd); // used by hf mfu sim
|
||||
int CmdHF14AAIDSim(const char *Cmd);
|
||||
int CmdHF14ANdefRead(const char *Cmd); // used by cmdnfc.c
|
||||
int CmdHF14ANdefFormat(const char *Cmd); // used by cmdnfc.c
|
||||
int CmdHF14ANdefWrite(const char *Cmd); // used by cmdnfc.c
|
||||
|
||||
@@ -605,6 +605,7 @@ typedef struct {
|
||||
|
||||
#define CMD_HF_ISO14443A_SNIFF 0x0383
|
||||
#define CMD_HF_ISO14443A_SIMULATE 0x0384
|
||||
#define CMD_HF_ISO14443A_SIM_AID 0x1420
|
||||
|
||||
#define CMD_HF_ISO14443A_READER 0x0385
|
||||
|
||||
@@ -775,6 +776,7 @@ typedef struct {
|
||||
#define FLAG_FORCED_ATQA 0x800
|
||||
#define FLAG_FORCED_SAK 0x1000
|
||||
#define FLAG_CVE21_0430 0x2000
|
||||
#define RATS_IN_DATA 0x3000
|
||||
|
||||
|
||||
#define MODE_SIM_CSN 0
|
||||
|
||||
Reference in New Issue
Block a user