Merge branch 'master' into desf_update2

This commit is contained in:
Oleg Moiseenko 2021-07-06 12:17:31 +03:00 committed by GitHub
commit a20db915df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 177 additions and 102 deletions

View file

@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Added one new key from gun cloner found in wild (@scott4290)
- Fix `hf_msdsal` standalone in simulation flow (@netxing)
- Added a picture viewer in QT. To be used with `hf emrtd info` (@iceman1001) - Added a picture viewer in QT. To be used with `hf emrtd info` (@iceman1001)
- Fix - move des functions to libcrypto (@merlokk) - Fix - move des functions to libcrypto (@merlokk)
- Added `CLIGetOptionList` to cliparser that makes it easier to implement text options in the cli (@merlokk) - Added `CLIGetOptionList` to cliparser that makes it easier to implement text options in the cli (@merlokk)

View file

@ -52,36 +52,40 @@ void ModInfo(void) {
* technologies. Be brave enough to share your knowledge & inspire others. Salvador Mendoza. * technologies. Be brave enough to share your knowledge & inspire others. Salvador Mendoza.
*/ */
static uint8_t ppdol [255] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00}; // Default GET PROCESSING // Default GET PROCESSING
static uint8_t ppdol [255] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00};
// Generate GET PROCESSING
static uint8_t treatPDOL(uint8_t *apdu) {
static uint8_t treatPDOL(uint8_t *apdu) { //Generate GET PROCESSING
uint8_t plen = 7; 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 // PDOL Format: 80 A8 00 00 + (PDOL Length+2) + 83 + PDOL Length + PDOL + 00
if (apdu[i] == 0x9F && apdu[i + 1] == 0x66) { //Terminal Transaction Qualifiers 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] = 0xF6;
ppdol[plen + 1] = 0x20; ppdol[plen + 1] = 0x20;
ppdol[plen + 2] = 0xC0; ppdol[plen + 2] = 0xC0;
ppdol[plen + 3] = 0x00; ppdol[plen + 3] = 0x00;
plen += 4; plen += 4;
i += 2; i += 2;
} else if (apdu[i] == 0x9F && apdu[i + 1] == 0x1A) { //Terminal Country Code } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x1A) { // Terminal Country Code
ppdol[plen] = 0x9F; ppdol[plen] = 0x9F;
ppdol[plen + 1] = 0x1A; ppdol[plen + 1] = 0x1A;
plen += 2; plen += 2;
i += 2; i += 2;
} else if (apdu[i] == 0x5F && apdu[i + 1] == 0x2A) { //Transaction Currency Code } else if (apdu[i] == 0x5F && apdu[i + 1] == 0x2A) { // Transaction Currency Code
ppdol[plen] = 0x5F; ppdol[plen] = 0x5F;
ppdol[plen + 1] = 0x2A; ppdol[plen + 1] = 0x2A;
plen += 2; plen += 2;
i += 2; i += 2;
} else if (apdu[i] == 0x9A) { //Transaction Date } else if (apdu[i] == 0x9A) { // Transaction Date
ppdol[plen] = 0x9A; ppdol[plen] = 0x9A;
ppdol[plen + 1] = 0x9A; ppdol[plen + 1] = 0x9A;
ppdol[plen + 2] = 0x9A; ppdol[plen + 2] = 0x9A;
plen += 3; plen += 3;
i += 1; i += 1;
} else if (apdu[i] == 0x95) { //Terminal Verification Results } else if (apdu[i] == 0x95) { // Terminal Verification Results
ppdol[plen] = 0x95; ppdol[plen] = 0x95;
ppdol[plen + 1] = 0x95; ppdol[plen + 1] = 0x95;
ppdol[plen + 2] = 0x95; ppdol[plen + 2] = 0x95;
@ -89,18 +93,18 @@ static uint8_t treatPDOL(uint8_t *apdu) { //Generate GET PROCES
ppdol[plen + 4] = 0x95; ppdol[plen + 4] = 0x95;
plen += 5; plen += 5;
i += 1; i += 1;
} else if (apdu[i] == 0x9C) { //Transaction Type } else if (apdu[i] == 0x9C) { // Transaction Type
ppdol[plen] = 0x9C; ppdol[plen] = 0x9C;
plen += 1; plen += 1;
i += 1; i += 1;
} else if (apdu[i] == 0x9F && apdu[i + 1] == 0x37) { //Unpredictable Number } else if (apdu[i] == 0x9F && apdu[i + 1] == 0x37) { // Unpredictable Number
ppdol[plen] = 0x9F; ppdol[plen] = 0x9F;
ppdol[plen + 1] = 0x37; ppdol[plen + 1] = 0x37;
ppdol[plen + 2] = 0x9F; ppdol[plen + 2] = 0x9F;
ppdol[plen + 3] = 0x37; ppdol[plen + 3] = 0x37;
plen += 4; plen += 4;
i += 2; i += 2;
} else { //To the others, add "0" to complete the format depending on its range } else { // To the others, add "0" to complete the format depending on its range
uint8_t u = apdu[i + 2]; uint8_t u = apdu[i + 2];
while (u > 0) { while (u > 0) {
ppdol[plen] = 0; ppdol[plen] = 0;
@ -124,16 +128,25 @@ void RunMod(void) {
//For reading process //For reading process
iso14a_card_select_t card_a_info; iso14a_card_select_t card_a_info;
uint8_t apdubuffer[MAX_FRAME_SIZE] = { 0x00 }; uint8_t apdubuffer[MAX_FRAME_SIZE] = { 0x00 };
//Specific for Visa cards: select ppse, select Visa AID, GET PROCESSING, SFI //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 ppse[20] = {
uint8_t visa[13] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x00}; 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 processing [8] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00};
uint8_t sfi[5] = {0x00, 0xb2, 0x01, 0x0c, 0x00}; uint8_t sfi[5] = {0x00, 0xb2, 0x01, 0x0c, 0x00};
uint8_t *apdus[4] = {ppse, visa, processing, sfi}; uint8_t *apdus[4] = {ppse, visa, processing, sfi};
uint8_t apdusLen [4] = { sizeof(ppse), sizeof(visa), sizeof(processing), sizeof(sfi)}; uint8_t apduslen[4] = { sizeof(ppse), sizeof(visa), sizeof(processing), sizeof(sfi)};
uint8_t pdol[50], plen = 8; uint8_t pdol[50], plen = 8;
@ -153,20 +166,15 @@ void RunMod(void) {
char token[19] = {0x00}; char token[19] = {0x00};
bool chktoken = false; bool chktoken = false;
//For emulation steps // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
#define ATQA 0 // Such a response is less time critical, so we can prepare them on the fly
#define UIDC1 1 #define DYNAMIC_RESPONSE_BUFFER_SIZE 64
#define SAKC1 3 #define DYNAMIC_MODULATION_BUFFER_SIZE 512
#define RATS 5
#define SIGNATURE 7
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it // UID 4 bytes(could be 7 bytes if needed it)
// Such a response is less time critical, so we can prepare them on the fly uint8_t flags = FLAG_4B_UID_IN_DATA;
#define DYNAMIC_RESPONSE_BUFFER_SIZE 64 // in case there is a read command received we shouldn't break
#define DYNAMIC_MODULATION_BUFFER_SIZE 512 uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
uint8_t flags = FLAG_4B_UID_IN_DATA; //UID 4 bytes(could be 7 bytes if needed it)
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; // in case there is a read command received we shouldn't break
uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04}; uint8_t visauid[7] = {0x01, 0x02, 0x03, 0x04};
memcpy(data, visauid, 4); memcpy(data, visauid, 4);
@ -203,7 +211,7 @@ void RunMod(void) {
uint8_t state = STATE_READ; uint8_t state = STATE_READ;
//Checking if the user wants to go directly to emulation mode using a hardcoded track 2 // Checking if the user wants to go directly to emulation mode using a hardcoded track 2
if (chktoken == true && token[0] != 0x00) { if (chktoken == true && token[0] != 0x00) {
state = STATE_EMU; state = STATE_EMU;
DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]")); DbpString(_YELLOW_("[ ") "Initialized emulation mode" _YELLOW_(" ]"));
@ -222,11 +230,14 @@ void RunMod(void) {
// Was our button held down or pressed? // Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000); int button_pressed = BUTTON_HELD(1000);
if (button_pressed == BUTTON_HOLD) //Holding down the button
if (button_pressed == BUTTON_HOLD)
break; break;
else if (button_pressed == BUTTON_SINGLE_CLICK) { //Pressing one time change between reading & emulation else if (button_pressed == BUTTON_SINGLE_CLICK) {
// pressing one time change between reading & emulation
if (state == STATE_READ) { if (state == STATE_READ) {
if (chktoken == true && token[0] != 0x00) { //Only change to emulation if it saved a track 2 in memory if (chktoken == true && token[0] != 0x00) {
// only change to emulation if it saved a track 2 in memory
state = STATE_EMU; state = STATE_EMU;
DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]")); DbpString(_YELLOW_("[ ") "In emulation mode" _YELLOW_(" ]"));
} else } else
@ -254,28 +265,33 @@ void RunMod(void) {
chktoken = false; chktoken = false;
LED_C_OFF(); LED_C_OFF();
LED_B_ON(); LED_B_ON();
uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apdusLen[i], false, apdubuffer, NULL); uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apduslen[i], false, apdubuffer, NULL);
if (apdulen > 0) { if (apdulen > 0) {
DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]")); DbpString(_YELLOW_("[ ") "Proxmark command" _YELLOW_(" ]"));
Dbhexdump(apdusLen[i], apdus[i], false); Dbhexdump(apduslen[i], apdus[i], false);
DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]")); DbpString(_GREEN_("[ ") "Card answer" _GREEN_(" ]"));
Dbhexdump(apdulen - 2, apdubuffer, false); Dbhexdump(apdulen - 2, apdubuffer, false);
DbpString("----"); DbpString("----");
for (uint8_t u = 0; u < apdulen; u++) { for (uint8_t u = 0; u < apdulen; u++) {
if (i == 1) { if (i == 1) {
if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) { //Check for PDOL
// check for PDOL
if (apdubuffer[u] == 0x9F && apdubuffer[u + 1] == 0x38) {
for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++) for (uint8_t e = 0; e <= apdubuffer[u + 2]; e++)
pdol[e] = apdubuffer[u + e + 2]; pdol[e] = apdubuffer[u + e + 2];
plen = treatPDOL(pdol); //Generate a challenge // generate a challenge
plen = treatPDOL(pdol);
apdus[2] = ppdol; apdus[2] = ppdol;
apdusLen[2] = plen; apduslen[2] = plen;
existpdol = true; existpdol = true;
} }
} else if (i == 3) { } else if (i == 3) {
if (apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) { //Find track 2
// find track 2
if (apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) {
chktoken = true; chktoken = true;
memcpy(&token, &apdubuffer[u + 2], 19); memcpy(&token, &apdubuffer[u + 2], 19);
break; break;
@ -307,6 +323,7 @@ void RunMod(void) {
} }
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF(); LED_D_OFF();
} else if (state == STATE_EMU) { } else if (state == STATE_EMU) {
LED_A_OFF(); LED_A_OFF();
LED_C_ON(); LED_C_ON();
@ -328,15 +345,18 @@ void RunMod(void) {
// We need to listen to the high-frequency, peak-detected path. // We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
int len = 0; // command length // command length
int retval = PM3_SUCCESS; // to check emulation status int len = 0;
// to check emulation status
int retval = PM3_SUCCESS;
bool odd_reply = true;
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
for (;;) { for (;;) {
LED_B_OFF(); LED_B_OFF();
// Clean receive command buffer // clean receive command buffer
if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
DbpString(_YELLOW_("!!") "Emulator stopped"); DbpString(_YELLOW_("!!") "Emulator stopped");
retval = PM3_EOPABORTED; retval = PM3_EOPABORTED;
@ -348,50 +368,84 @@ void RunMod(void) {
// dynamic_response_info will be in charge of responses // dynamic_response_info will be in charge of responses
dynamic_response_info.response_n = 0; dynamic_response_info.response_n = 0;
// Checking the commands order is important and elemental // received a REQUEST
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) {
DbpString(_YELLOW_("+") "REQUEST Received"); odd_reply = !odd_reply;
p_response = &responses[ATQA]; if (odd_reply) {
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT p_response = &responses[RESP_INDEX_ATQA];
}
// received a HALT
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) {
DbpString(_YELLOW_("+") "Received a HALT"); DbpString(_YELLOW_("+") "Received a HALT");
p_response = NULL; p_response = NULL;
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP //Este!!
// received a WAKEUP
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) {
DbpString(_YELLOW_("+") "WAKEUP Received"); DbpString(_YELLOW_("+") "WAKEUP Received");
p_response = &responses[ATQA];
prevCmd = 0; prevCmd = 0;
} 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_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"); DbpString(_YELLOW_("+") "Request for UID C1");
p_response = &responses[UIDC1]; p_response = &responses[RESP_INDEX_UIDC1];
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
// 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"); DbpString(_YELLOW_("+") "Request for SELECT S1");
p_response = &responses[SAKC1]; p_response = &responses[RESP_INDEX_SAKC1];
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
// received a RATS request
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) {
DbpString(_YELLOW_("+") "Request for RATS"); DbpString(_YELLOW_("+") "Request for RATS");
p_response = &responses[RATS]; prevCmd = 0;
p_response = &responses[RESP_INDEX_RATS];
} else { } else {
DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]")); DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]"));
Dbhexdump(len, receivedCmd, false); Dbhexdump(len, receivedCmd, false);
if (receivedCmd[0] == 0x02 || receivedCmd[0] == 0x03) { //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]; dynamic_response_info.response[0] = receivedCmd[0];
//Depending on card reader commands, the Proxmark will answer to fool the reader // depending on card reader commands, the Proxmark will answer to fool the reader
if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) { //Respond with PPSE // respond with PPSE
uint8_t ppsea[39] = {0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00}; if (receivedCmd[2] == 0xA4 && receivedCmd[6] == 0x32 && prevCmd == 0) {
uint8_t ppsea[39] = {
0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59,
0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46,
0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61,
0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03,
0x10, 0x10, 0x87, 0x01, 0x01, 0x90, 0x00
};
memcpy(&dynamic_response_info.response[1], ppsea, sizeof(ppsea)); memcpy(&dynamic_response_info.response[1], ppsea, sizeof(ppsea));
dynamic_response_info.response_n = sizeof(ppsea) + 1; dynamic_response_info.response_n = sizeof(ppsea) + 1;
prevCmd++; prevCmd++;
} else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) { //Respond Visa AID
uint8_t visauid_long[34] = {0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56, 0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02, 0x90, 0x00}; // respond Visa AID
} else if (receivedCmd[2] == 0xA4 && receivedCmd[10] == 0x03 && receivedCmd[11] == 0x10 && prevCmd == 1) {
uint8_t visauid_long[34] = {
0x6F, 0x1E, 0x84, 0x07, 0xA0, 0x00, 0x00, 0x00,
0x03, 0x10, 0x10, 0xA5, 0x13, 0x50, 0x0B, 0x56,
0x49, 0x53, 0x41, 0x20, 0x43, 0x52, 0x45, 0x44,
0x49, 0x54, 0x9F, 0x38, 0x03, 0x9F, 0x66, 0x02,
0x90, 0x00
};
memcpy(&dynamic_response_info.response[1], visauid_long, sizeof(visauid_long)); memcpy(&dynamic_response_info.response[1], visauid_long, sizeof(visauid_long));
dynamic_response_info.response_n = sizeof(visauid_long) + 1; dynamic_response_info.response_n = sizeof(visauid_long) + 1;
prevCmd++; prevCmd++;
} else if (receivedCmd[1] == 0x80 && receivedCmd[2] == 0xA8 && receivedCmd[6] == 0x83 && prevCmd == 2) { //GET PROCESSING
// GET PROCESSING
} else if (receivedCmd[1] == 0x80 && receivedCmd[2] == 0xA8 && receivedCmd[6] == 0x83 && prevCmd == 2) {
uint8_t processing_long[10] = {0x80, 0x06, 0x00, 0x80, 0x08, 0x01, 0x01, 0x00, 0x90, 0x00}; uint8_t processing_long[10] = {0x80, 0x06, 0x00, 0x80, 0x08, 0x01, 0x01, 0x00, 0x90, 0x00};
memcpy(&dynamic_response_info.response[1], processing_long, sizeof(processing_long)); memcpy(&dynamic_response_info.response[1], processing_long, sizeof(processing_long));
dynamic_response_info.response_n = sizeof(processing_long) + 1; dynamic_response_info.response_n = sizeof(processing_long) + 1;
prevCmd++; prevCmd++;
} else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) { //SFI
// SFI
} else if (receivedCmd[1] == 0x00 && receivedCmd[2] == 0xB2 && prevCmd == 3) {
uint8_t last[4] = {0x70, 0x15, 0x57, 0x13}; uint8_t last[4] = {0x70, 0x15, 0x57, 0x13};
uint8_t statusapdu[2] = {0x90, 0x00}; uint8_t statusapdu[2] = {0x90, 0x00};
uint8_t card[25]; uint8_t card[25];
@ -401,6 +455,7 @@ void RunMod(void) {
memcpy(&dynamic_response_info.response[1], card, sizeof(card)); memcpy(&dynamic_response_info.response[1], card, sizeof(card));
dynamic_response_info.response_n = sizeof(card) + 1; dynamic_response_info.response_n = sizeof(card) + 1;
prevCmd++; prevCmd++;
} else { } else {
uint8_t finished[2] = {0x6f, 0x00}; uint8_t finished[2] = {0x6f, 0x00};
memcpy(&dynamic_response_info.response[1], finished, sizeof(finished)); memcpy(&dynamic_response_info.response[1], finished, sizeof(finished));
@ -424,7 +479,7 @@ void RunMod(void) {
Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false); Dbhexdump(dynamic_response_info.response_n, dynamic_response_info.response, false);
DbpString("----"); DbpString("----");
// Add CRC bytes, always used in ISO 14443A-4 compliant cards // add CRC bytes, always used in ISO 14443A-4 compliant cards
AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n);
dynamic_response_info.response_n += 2; dynamic_response_info.response_n += 2;
@ -449,4 +504,4 @@ void RunMod(void) {
} }
DbpString(_YELLOW_("[=]") "exiting"); DbpString(_YELLOW_("[=]") "exiting");
LEDsoff(); LEDsoff();
} }

View file

@ -313,10 +313,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array
int val = -1; int val = -1;
int cntr = 0; int cntr = 0;
for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) {
// end of array
if (option_array[i].text == NULL)
break;
// exact match // exact match
if (strcmp(option_array[i].text, data) == 0) { if (strcmp(option_array[i].text, data) == 0) {
*value = option_array[i].code; *value = option_array[i].code;
@ -345,10 +342,8 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array
const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) {
static const char *errmsg = "n/a"; static const char *errmsg = "n/a";
for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { for (int i = 0; i < CLI_MAX_OPTLIST_LEN && option_array[i].text != NULL; i++) {
if (option_array[i].text == NULL)
break;
if (option_array[i].code == value) if (option_array[i].code == value)
return option_array[i].text; return option_array[i].text;
} }

View file

@ -38,6 +38,8 @@ E9920427
50520901 50520901
# iCopy-X # iCopy-X
20206666 20206666
# ID/HID CARD COPER SK-663
65857569
# Default pwd, simple: # Default pwd, simple:
00000000 00000000
11111111 11111111

View file

@ -231,7 +231,7 @@ static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag *
return; return;
} }
uint32_t val = asn1_value_integer(tlv, 0, tlv->len * 2); uint32_t val = asn1_value_integer(tlv, 0, tlv->len * 2);
PrintAndLogEx(NORMAL, " value: %lu (0x%X)", val, val); PrintAndLogEx(NORMAL, " value: %" PRIu32 " (0x%X)", val, val);
} }
static char *asn1_oid_description(const char *oid, bool with_group_desc) { static char *asn1_oid_description(const char *oid, bool with_group_desc) {
@ -327,7 +327,7 @@ bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump) {
*/ */
PrintAndLogEx(INFO, PrintAndLogEx(INFO,
"%*s-- %02X [%02X] '"_YELLOW_("%s") "'" NOLF "%*s-- %02X [%02ZX] '"_YELLOW_("%s") "'" NOLF
, (level * 4) , (level * 4)
, " " , " "
, tlv->tag , tlv->tag

View file

@ -105,8 +105,13 @@ void ProxGuiQT::_HideGraphWindow(void) {
// picture viewer // picture viewer
void ProxGuiQT::_ShowPictureWindow(char *fn) { void ProxGuiQT::_ShowPictureWindow(char *fn) {
if (!plotapp)
return;
if (fn == NULL) if (fn == NULL)
return; return;
size_t slen = strlen(fn); size_t slen = strlen(fn);
if (slen == 0) if (slen == 0)
return; return;
@ -117,16 +122,13 @@ void ProxGuiQT::_ShowPictureWindow(char *fn) {
memcpy(myfn, fn, slen); memcpy(myfn, fn, slen);
if (!plotapp)
return;
if (!pictureWidget) { if (!pictureWidget) {
#if defined(__MACH__) && defined(__APPLE__) #if defined(__MACH__) && defined(__APPLE__)
makeFocusable(); makeFocusable();
#endif #endif
pictureWidget = new QWidget(); pictureWidget = new PictureWidget();
} }
QPixmap pm; QPixmap pm;
@ -169,14 +171,6 @@ void ProxGuiQT::_Exit(void) {
delete this; delete this;
} }
void ProxGuiQT::closeEvent(QCloseEvent *event) {
event->ignore();
pictureWidget->hide();
}
void ProxGuiQT::hideEvent(QHideEvent *event) {
pictureWidget->hide();
}
void ProxGuiQT::_StartProxmarkThread(void) { void ProxGuiQT::_StartProxmarkThread(void) {
if (!proxmarkThread) if (!proxmarkThread)
return; return;
@ -190,11 +184,19 @@ void ProxGuiQT::_StartProxmarkThread(void) {
void ProxGuiQT::MainLoop() { void ProxGuiQT::MainLoop() {
plotapp = new QApplication(argc, argv); plotapp = new QApplication(argc, argv);
// Setup the picture widget // Setup the picture widget
pictureWidget = new QWidget(); pictureWidget = new PictureWidget();
pictureController = new Ui::PictureForm(); pictureController = new Ui::PictureForm();
pictureController->setupUi(pictureWidget); pictureController->setupUi(pictureWidget);
// pictureWidget->setAttribute(Qt::WA_DeleteOnClose,true);
// Set picture widget position if no settings.
if (session.preferences_loaded == false) {
// Move controller widget below plot
//pictureController->move(x(), y() + frameSize().height());
//pictureController->resize(size().width(), 200);
}
connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow())); connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow()));
connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow())); connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow()));
@ -207,7 +209,6 @@ void ProxGuiQT::MainLoop() {
connect(this, SIGNAL(RepaintPictureWindowSignal()), this, SLOT(_RepaintPictureWindow())); connect(this, SIGNAL(RepaintPictureWindowSignal()), this, SLOT(_RepaintPictureWindow()));
connect(this, SIGNAL(HidePictureWindowSignal()), this, SLOT(_HidePictureWindow())); connect(this, SIGNAL(HidePictureWindowSignal()), this, SLOT(_HidePictureWindow()));
//start proxmark thread after starting event loop //start proxmark thread after starting event loop
QTimer::singleShot(200, this, SLOT(_StartProxmarkThread())); QTimer::singleShot(200, this, SLOT(_StartProxmarkThread()));
@ -216,12 +217,12 @@ void ProxGuiQT::MainLoop() {
makeUnfocusable(); makeUnfocusable();
#endif #endif
plotapp->exec(); plotapp->exec();
} }
ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) : plotapp(NULL), plotwidget(NULL), ProxGuiQT::ProxGuiQT(int argc, char **argv, WorkerThread *wthread) :
argc(argc), argv(argv), proxmarkThread(wthread) { plotapp(NULL), plotwidget(NULL), pictureController(NULL), pictureWidget(NULL), argc(argc), argv(argv), proxmarkThread(wthread) {
} }
ProxGuiQT::~ProxGuiQT(void) { ProxGuiQT::~ProxGuiQT(void) {
@ -243,6 +244,24 @@ ProxGuiQT::~ProxGuiQT(void) {
} }
} }
// -------------------------------------------------
// Slider Widget form based on a class to enable
// Event override functions
// -------------------------------------------------
PictureWidget::PictureWidget() {
// Set the initail postion and size from settings
// if (session.preferences_loaded)
// setGeometry(session.pw.x, session.pw.y, session.pw.w, session.pw.h);
// else
resize(400, 400);
}
void PictureWidget::closeEvent(QCloseEvent *event) {
this->hide();
event->ignore();
}
// ------------------------------------------------- // -------------------------------------------------
// Slider Widget form based on a class to enable // Slider Widget form based on a class to enable
// Event override functions // Event override functions
@ -318,8 +337,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) {
resize(800, 400); resize(800, 400);
// Setup the controller widget // Setup the controller widget
controlWidget = new SliderWidget(); //new QWidget(); controlWidget = new SliderWidget();
opsController = new Ui::Form(); opsController = new Ui::Form();
opsController->setupUi(controlWidget); opsController->setupUi(controlWidget);
//Due to quirks in QT Designer, we need to fiddle a bit //Due to quirks in QT Designer, we need to fiddle a bit
@ -355,7 +373,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) {
show(); show();
// Set Slider/Overlay position if no settings. // Set Slider/Overlay position if no settings.
if (!session.preferences_loaded) { if (session.preferences_loaded == false) {
// Move controller widget below plot // Move controller widget below plot
controlWidget->move(x(), y() + frameSize().height()); controlWidget->move(x(), y() + frameSize().height());
controlWidget->resize(size().width(), 200); controlWidget->resize(size().width(), 200);

View file

@ -71,6 +71,14 @@ class SliderWidget : public QWidget {
SliderWidget(); SliderWidget();
}; };
// Added class for SliderWidget to allow move/resize event override
class PictureWidget : public QWidget {
protected:
void closeEvent(QCloseEvent *event);
public:
PictureWidget();
};
/** /**
* The window with plot and controls * The window with plot and controls
*/ */
@ -126,10 +134,9 @@ class ProxGuiQT : public QObject {
private: private:
QApplication *plotapp; QApplication *plotapp;
ProxWidget *plotwidget; ProxWidget *plotwidget;
Ui::PictureForm *pictureController; Ui::PictureForm *pictureController;
QWidget *pictureWidget; PictureWidget *pictureWidget;
int argc; int argc;
char **argv; char **argv;
//void (*main_func)(void); //void (*main_func)(void);
@ -150,10 +157,6 @@ class ProxGuiQT : public QObject {
void MainLoop(void); void MainLoop(void);
void Exit(void); void Exit(void);
protected:
void closeEvent(QCloseEvent *event);
void hideEvent(QHideEvent *event);
private slots: private slots:
void _ShowGraphWindow(void); void _ShowGraphWindow(void);
void _RepaintGraphWindow(void); void _RepaintGraphWindow(void);