mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
Merge branch 'master' into allin
update 201110
This commit is contained in:
commit
8a1558757c
62 changed files with 2074 additions and 1149 deletions
|
@ -3,9 +3,12 @@ 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...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Fix 'hf iclass wrbl' - dealing with tags in unsecured vs secured pagemode now is correct (@iceman1001)
|
||||
- Change many commands to cliparser (@iceman1001, @tcprst, @mwalker33,...)
|
||||
- ...
|
||||
- Added `HF_TCPRST` standalone mode which read and emulate IKEA Rothult cards (@tcprst)
|
||||
- Added compilation options for 256k Proxmark versions, see doc (@doegox)
|
||||
- Added support for 10b UID in `hf 14a sim` (@doegox)
|
||||
- Added `HF_TCPRST` standalone mode which read and emulate IKEA Rothult cards (@tcprst)
|
||||
- Add Gallagher key checking/KDF on MIFARE Desfire (@NZSmartie)
|
||||
- Add dictionaries with common words of proper size (@will-caruana)
|
||||
- Add `hf mf supercard` (@iceman1001)
|
||||
|
|
|
@ -129,6 +129,16 @@ uint8_t *BigBuf_malloc(uint16_t chunksize) {
|
|||
return (uint8_t *)BigBuf + s_bigbuf_hi;
|
||||
}
|
||||
|
||||
// allocate a chunk of memory from BigBuf, and returns a pointer to it.
|
||||
// sets the memory to zero
|
||||
uint8_t *BigBuf_calloc(uint16_t chunksize) {
|
||||
uint8_t *mem = BigBuf_malloc(chunksize);
|
||||
if (mem != NULL) {
|
||||
memset(mem, 0x00, chunksize);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
|
||||
void BigBuf_free(void) {
|
||||
s_bigbuf_hi = s_bigbuf_size;
|
||||
|
|
|
@ -34,6 +34,7 @@ void BigBuf_Clear_ext(bool verbose);
|
|||
void BigBuf_Clear_keep_EM(void);
|
||||
void BigBuf_Clear_EM(void);
|
||||
uint8_t *BigBuf_malloc(uint16_t);
|
||||
uint8_t *BigBuf_calloc(uint16_t);
|
||||
void BigBuf_free(void);
|
||||
void BigBuf_free_keep_EM(void);
|
||||
void BigBuf_print_status(void);
|
||||
|
@ -46,10 +47,8 @@ bool get_tracing(void);
|
|||
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||
bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, uint8_t *parity, bool reader2tag);
|
||||
|
||||
|
||||
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
|
||||
|
||||
|
||||
typedef struct {
|
||||
int max;
|
||||
int bit;
|
||||
|
|
|
@ -132,7 +132,7 @@ static void download_instructions(uint8_t t) {
|
|||
DbpString("The collected data was saved to SPIFFS. The file names below may differ");
|
||||
DbpString("1. " _YELLOW_("mem spiffs tree"));
|
||||
DbpString("2. " _YELLOW_("mem spiffs dump o " HF_ICLASS_ATTACK_BIN " f " HF_ICLASS_ATTACK_BIN));
|
||||
DbpString("3. " _YELLOW_("hf iclass loclass f " HF_ICLASS_ATTACK_BIN));
|
||||
DbpString("3. " _YELLOW_("hf iclass loclass -f " HF_ICLASS_ATTACK_BIN));
|
||||
break;
|
||||
}
|
||||
case ICE_STATE_READER: {
|
||||
|
|
|
@ -90,15 +90,6 @@ void RunMod(void) {
|
|||
// Did we get the NDEF file contents from the card
|
||||
bool gotndef = false;
|
||||
|
||||
//For emulation steps
|
||||
#define ATQA 0
|
||||
#define UIDC1 1
|
||||
#define UIDC2 2
|
||||
#define SAKC1 3
|
||||
#define SAKC2 4
|
||||
#define RATS 5
|
||||
#define SIGNATURE 7
|
||||
#define PPS 8
|
||||
|
||||
//ST25TA Rothult values
|
||||
#define SAK 0x20
|
||||
|
@ -173,12 +164,12 @@ void RunMod(void) {
|
|||
DbpString(_YELLOW_("+") "Found ISO 14443 Type A!");
|
||||
|
||||
if (card_a_info.sak == SAK && card_a_info.atqa[0] == ATQA0 && card_a_info.atqa[1] == ATQA1 && card_a_info.uidlen == 7) {
|
||||
DbpString(_YELLOW_("+") "Found ST25TA with UID: ");
|
||||
Dbhexdump(card_a_info.uidlen, card_a_info.uid, 0);
|
||||
memcpy(stuid, card_a_info.uid, card_a_info.uidlen);
|
||||
state = STATE_SIM;
|
||||
DbpString(_YELLOW_("+") "Found ST25TA with UID: ");
|
||||
Dbhexdump(card_a_info.uidlen, card_a_info.uid, 0);
|
||||
memcpy(stuid, card_a_info.uid, card_a_info.uidlen);
|
||||
state = STATE_SIM;
|
||||
} else {
|
||||
DbpString("Found non-ST25TA card, ignoring.");
|
||||
DbpString("Found non-ST25TA card, ignoring.");
|
||||
}
|
||||
}
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -232,23 +223,23 @@ void RunMod(void) {
|
|||
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST
|
||||
odd_reply = !odd_reply;
|
||||
if (odd_reply)
|
||||
p_response = &responses[ATQA];
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT
|
||||
p_response = NULL;
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
|
||||
p_response = &responses[ATQA];
|
||||
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[UIDC1];
|
||||
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[UIDC2];
|
||||
p_response = &responses[RESP_INDEX_UIDC2];
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
|
||||
p_response = &responses[SAKC1];
|
||||
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[SAKC2];
|
||||
p_response = &responses[RESP_INDEX_SAKC2];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
|
||||
p_response = &responses[RATS];
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_PPS) {
|
||||
p_response = &responses[PPS];
|
||||
p_response = &responses[RESP_INDEX_PPS];
|
||||
} else {
|
||||
DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]"));
|
||||
Dbhexdump(len, receivedCmd, false);
|
||||
|
@ -413,23 +404,23 @@ void RunMod(void) {
|
|||
if (receivedCmd[0] == ISO14443A_CMD_REQA && len == 1) { // Received a REQUEST
|
||||
odd_reply = !odd_reply;
|
||||
if (odd_reply)
|
||||
p_response = &responses[ATQA];
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_HALT && len == 4) { // Received a HALT
|
||||
p_response = NULL;
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
|
||||
p_response = &responses[ATQA];
|
||||
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[UIDC1];
|
||||
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[UIDC2];
|
||||
p_response = &responses[RESP_INDEX_UIDC2];
|
||||
} else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1)
|
||||
p_response = &responses[SAKC1];
|
||||
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[SAKC2];
|
||||
p_response = &responses[RESP_INDEX_SAKC2];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request
|
||||
p_response = &responses[RATS];
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_PPS) {
|
||||
p_response = &responses[PPS];
|
||||
p_response = &responses[RESP_INDEX_PPS];
|
||||
} else {
|
||||
DbpString(_YELLOW_("[ ") "Card reader command" _YELLOW_(" ]"));
|
||||
Dbhexdump(len, receivedCmd, false);
|
||||
|
|
|
@ -65,6 +65,9 @@
|
|||
#include "spiffs.h"
|
||||
#endif
|
||||
|
||||
int DBGLEVEL = DBG_ERROR;
|
||||
uint8_t g_trigger = 0;
|
||||
bool g_hf_field_active = false;
|
||||
extern uint32_t _stack_start, _stack_end;
|
||||
struct common_area common_area __attribute__((section(".commonarea")));
|
||||
static int button_status = BUTTON_NO_CLICK;
|
||||
|
@ -88,6 +91,12 @@ int tearoff_hook(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void hf_field_off(void) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
g_hf_field_active = false;
|
||||
}
|
||||
|
||||
void send_wtx(uint16_t wtx) {
|
||||
if (allow_send_wtx) {
|
||||
reply_ng(CMD_WTX, PM3_SUCCESS, (uint8_t *)&wtx, sizeof(wtx));
|
||||
|
@ -1545,9 +1554,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
struct p {
|
||||
uint8_t counter;
|
||||
uint32_t tearoff_time;
|
||||
uint8_t value[4];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareU_Counter_Tearoff(payload->counter, payload->tearoff_time);
|
||||
MifareU_Counter_Tearoff(payload->counter, payload->tearoff_time, payload->value);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_STATIC_NONCE: {
|
||||
|
@ -2341,14 +2351,6 @@ void __attribute__((noreturn)) AppMain(void) {
|
|||
*p = 0xdeadbeef;
|
||||
}
|
||||
|
||||
if (common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
|
||||
/* Initialize common area */
|
||||
memset(&common_area, 0, sizeof(common_area));
|
||||
common_area.magic = COMMON_AREA_MAGIC;
|
||||
common_area.version = 1;
|
||||
}
|
||||
common_area.flags.osimage_present = 1;
|
||||
|
||||
LEDsoff();
|
||||
|
||||
// The FPGA gets its clock from us from PCK0 output, so set that up.
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
extern int g_rsamples; // = 0;
|
||||
extern uint8_t g_trigger;
|
||||
|
||||
extern bool g_hf_field_active;
|
||||
void hf_field_off(void);
|
||||
int tearoff_hook(void);
|
||||
|
||||
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
|
||||
|
|
81
armsrc/epa.c
81
armsrc/epa.c
|
@ -22,10 +22,12 @@
|
|||
#include "commonutil.h"
|
||||
#include "ticks.h"
|
||||
|
||||
#ifdef WITH_ISO14443a
|
||||
// Protocol and Parameter Selection Request for ISO 14443 type A cards
|
||||
// use regular (1x) speed in both directions
|
||||
// CRC is already included
|
||||
static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6};
|
||||
#endif
|
||||
|
||||
// APDUs for communication with German Identification Card
|
||||
|
||||
|
@ -116,9 +118,25 @@ static char iso_type = 0;
|
|||
static int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response, uint16_t respmaxlen) {
|
||||
switch (iso_type) {
|
||||
case 'a':
|
||||
#ifdef WITH_ISO14443a
|
||||
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
|
||||
#else
|
||||
(void) apdu;
|
||||
(void) length;
|
||||
(void) response;
|
||||
(void) respmaxlen;
|
||||
return PM3_ENOTIMPL;
|
||||
#endif
|
||||
case 'b':
|
||||
#ifdef WITH_ISO14443b
|
||||
return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL);
|
||||
#else
|
||||
(void) apdu;
|
||||
(void) length;
|
||||
(void) response;
|
||||
(void) respmaxlen;
|
||||
return PM3_ENOTIMPL;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -522,39 +540,46 @@ void EPA_PACE_Replay(PacketCommandNG *c) {
|
|||
//-----------------------------------------------------------------------------
|
||||
int EPA_Setup(void) {
|
||||
|
||||
// first, look for type A cards
|
||||
// power up the field
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
iso14a_card_select_t card_a_info;
|
||||
int return_code = iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false);
|
||||
#ifdef WITH_ISO14443a
|
||||
{
|
||||
// first, look for type A cards
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
// power up the field
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
iso14a_card_select_t card_a_info;
|
||||
int return_code = iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false);
|
||||
|
||||
if (return_code == 1) {
|
||||
uint8_t pps_response[3];
|
||||
uint8_t pps_response_par[1];
|
||||
// send the PPS request
|
||||
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
|
||||
return_code = ReaderReceive(pps_response, pps_response_par);
|
||||
if (return_code != 3 || pps_response[0] != 0xD0) {
|
||||
return return_code == 0 ? 2 : return_code;
|
||||
if (return_code == 1) {
|
||||
uint8_t pps_response[3];
|
||||
uint8_t pps_response_par[1];
|
||||
// send the PPS request
|
||||
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
|
||||
return_code = ReaderReceive(pps_response, pps_response_par);
|
||||
if (return_code != 3 || pps_response[0] != 0xD0) {
|
||||
return return_code == 0 ? 2 : return_code;
|
||||
}
|
||||
Dbprintf("ISO 14443 Type A");
|
||||
iso_type = 'a';
|
||||
return 0;
|
||||
}
|
||||
Dbprintf("ISO 14443 Type A");
|
||||
iso_type = 'a';
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_ISO14443b
|
||||
{
|
||||
// if we're here, there is no type A card, so we look for type B
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
// power up the field
|
||||
iso14443b_setup();
|
||||
iso14b_card_select_t card_b_info;
|
||||
int return_code = iso14443b_select_card(&card_b_info);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
// if we're here, there is no type A card, so we look for type B
|
||||
// power up the field
|
||||
iso14443b_setup();
|
||||
iso14b_card_select_t card_b_info;
|
||||
return_code = iso14443b_select_card(&card_b_info);
|
||||
|
||||
if (return_code == 0) {
|
||||
Dbprintf("ISO 14443 Type B");
|
||||
iso_type = 'b';
|
||||
return 0;
|
||||
if (return_code == 0) {
|
||||
Dbprintf("ISO 14443 Type B");
|
||||
iso_type = 'b';
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Dbprintf("No card found");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -103,8 +103,6 @@ static bool end = false;
|
|||
#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
|
||||
#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
|
||||
|
||||
#define DBGLEVEL 0
|
||||
|
||||
/*
|
||||
* Implementation of the crc8 calculation from Hitag S
|
||||
* from http://www.proxmark.org/files/Documents/125%20kHz%20-%20Hitag/HitagS.V11.pdf
|
||||
|
|
|
@ -714,7 +714,7 @@ void SmartCardAtr(void) {
|
|||
I2C_Reset_EnterMainProgram();
|
||||
smart_card_atr_t card;
|
||||
int res = GetATR(&card, true) ? PM3_SUCCESS : PM3_ETIMEOUT;
|
||||
reply_ng(CMD_SMART_ATR, res, (uint8_t*)&card, sizeof(smart_card_atr_t));
|
||||
reply_ng(CMD_SMART_ATR, res, (uint8_t *)&card, sizeof(smart_card_atr_t));
|
||||
set_tracing(false);
|
||||
LEDsoff();
|
||||
}
|
||||
|
|
|
@ -1776,13 +1776,19 @@ void iClass_Dump(uint8_t *msg) {
|
|||
BigBuf_free();
|
||||
}
|
||||
|
||||
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac) {
|
||||
static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac, bool use_mac) {
|
||||
|
||||
// write command: cmd, 1 blockno, 8 data, 4 mac
|
||||
uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
|
||||
uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
|
||||
uint8_t write_len = 14;
|
||||
memcpy(write + 2, data, 8);
|
||||
memcpy(write + 10, mac, 4);
|
||||
AddCrc(write + 1, 13);
|
||||
|
||||
if (use_mac) {
|
||||
memcpy(write + 10, mac, 4);
|
||||
} else {
|
||||
AddCrc(write + 1, 9);
|
||||
write_len -= 2;
|
||||
}
|
||||
|
||||
uint8_t resp[10] = {0};
|
||||
uint32_t eof_time = 0, start_time = 0;
|
||||
|
@ -1819,7 +1825,8 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
|
||||
iclass_writeblock_req_t *payload = (iclass_writeblock_req_t *)msg;
|
||||
|
||||
uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno };
|
||||
uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno };
|
||||
uint8_t write_len = 14;
|
||||
|
||||
Iso15693InitReader();
|
||||
|
||||
|
@ -1844,23 +1851,30 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
}
|
||||
}
|
||||
|
||||
// calc new mac for write
|
||||
uint8_t wb[9];
|
||||
wb[0] = payload->req.blockno;
|
||||
memcpy(wb + 1, payload->data, 8);
|
||||
// new block data
|
||||
memcpy(write + 2, payload->data, 8);
|
||||
|
||||
if (payload->req.use_replay) {
|
||||
doMAC_N(wb, sizeof(wb), payload->req.key + 4, mac);
|
||||
uint8_t pagemap = get_pagemap(&hdr);
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
// Unsecured tags uses CRC16, but don't include the UPDATE operation code
|
||||
// byte0 = update op
|
||||
// byte1 = block no
|
||||
// byte2..9 = new block data
|
||||
AddCrc(write + 1, 9);
|
||||
write_len -= 2;
|
||||
} else {
|
||||
// Secure tags uses MAC
|
||||
uint8_t wb[9];
|
||||
wb[0] = payload->req.blockno;
|
||||
memcpy(wb + 1, payload->data, 8);
|
||||
|
||||
if (payload->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
}
|
||||
|
||||
memcpy(write + 2, payload->data, 8); // data
|
||||
memcpy(write + 10, mac, sizeof(mac)); // mac
|
||||
AddCrc(write + 1, 13);
|
||||
memcpy(write + 10, mac, sizeof(mac));
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
|
||||
|
@ -1869,7 +1883,7 @@ void iClass_WriteBlock(uint8_t *msg) {
|
|||
uint8_t tries = 3;
|
||||
while (tries-- > 0) {
|
||||
|
||||
iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time);
|
||||
iclass_send_as_reader(write, write_len, &start_time, &eof_time);
|
||||
|
||||
if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured
|
||||
res = false;
|
||||
|
@ -1961,22 +1975,30 @@ void iClass_Restore(iclass_restore_req_t *msg) {
|
|||
}
|
||||
|
||||
// main loop
|
||||
bool use_mac;
|
||||
for (uint8_t i = 0; i < msg->item_cnt; i++) {
|
||||
|
||||
iclass_restore_item_t item = msg->blocks[i];
|
||||
|
||||
// calc new mac for data, using 1b blockno, 8b data,
|
||||
uint8_t wb[9] = {0};
|
||||
wb[0] = item.blockno;
|
||||
memcpy(wb + 1, item.data, 8);
|
||||
uint8_t pagemap = get_pagemap(&hdr);
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
// Unsecured tags uses CRC16
|
||||
use_mac = false;
|
||||
} else {
|
||||
// Secure tags uses MAC
|
||||
use_mac = true;
|
||||
uint8_t wb[9] = {0};
|
||||
wb[0] = item.blockno;
|
||||
memcpy(wb + 1, item.data, 8);
|
||||
|
||||
if (msg->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
if (msg->req.use_credit_key)
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||
else
|
||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||
}
|
||||
|
||||
// data + mac
|
||||
if (iclass_writeblock_ext(item.blockno, item.data, mac)) {
|
||||
if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) {
|
||||
Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno);
|
||||
written++;
|
||||
} else {
|
||||
|
|
|
@ -28,12 +28,9 @@
|
|||
|
||||
#define MAX_ISO14A_TIMEOUT 524288
|
||||
static uint32_t iso14a_timeout;
|
||||
// if iso14443a not active - transmit/receive dont try to execute
|
||||
static bool hf_field_active = false;
|
||||
|
||||
static uint8_t colpos = 0;
|
||||
int g_rsamples = 0;
|
||||
uint8_t g_trigger = 0;
|
||||
|
||||
// the block number for the ISO14443-4 PCB
|
||||
static uint8_t iso14_pcb_blocknum = 0;
|
||||
|
||||
|
@ -161,7 +158,7 @@ void printHf14aConfig(void) {
|
|||
);
|
||||
Dbprintf(" [r] RATS override.......%i %s%s%s",
|
||||
hf14aconfig.forcerats,
|
||||
(hf14aconfig.forcerats == 0) ? "( " _GREEN_("No") " q follow standard " : "",
|
||||
(hf14aconfig.forcerats == 0) ? "( " _GREEN_("No") " ) follow standard " : "",
|
||||
(hf14aconfig.forcerats == 1) ? "( " _RED_("Yes") " ) always do RATS" : "",
|
||||
(hf14aconfig.forcerats == 2) ? "( " _RED_("Yes") " ) always skip RATS" : ""
|
||||
);
|
||||
|
@ -1005,10 +1002,14 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
static uint8_t rUIDc1[5] = { 0x00 };
|
||||
// For UID size 7,
|
||||
static uint8_t rUIDc2[5] = { 0x00 };
|
||||
// Prepare the mandatory SAK (for 4 and 7 byte UID)
|
||||
// For UID size 10,
|
||||
static uint8_t rUIDc3[5] = { 0x00 };
|
||||
// Prepare the mandatory SAK (for 4, 7 and 10 byte UID)
|
||||
static uint8_t rSAKc1[3] = { 0x00 };
|
||||
// Prepare the optional second SAK (for 7 byte UID), drop the cascade bit
|
||||
// Prepare the optional second SAK (for 7 and 10 byte UID), drop the cascade bit for 7b
|
||||
static uint8_t rSAKc2[3] = { 0x00 };
|
||||
// Prepare the optional third SAK (for 10 byte UID), drop the cascade bit
|
||||
static uint8_t rSAKc3[3] = { 0x00 };
|
||||
// dummy ATS (pseudo-ATR), answer to RATS
|
||||
// static uint8_t rRATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 };
|
||||
static uint8_t rRATS[] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00 };
|
||||
|
@ -1017,7 +1018,7 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
static uint8_t rVERSION[10] = { 0x00 };
|
||||
// READ_SIG response for EV1/NTAG
|
||||
static uint8_t rSIGN[34] = { 0x00 };
|
||||
// PPS respoonse
|
||||
// PPS response
|
||||
static uint8_t rPPS[3] = { 0xD0 };
|
||||
|
||||
switch (tagType) {
|
||||
|
@ -1101,7 +1102,7 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
case 10: { // ST25TA IKEA Rothult
|
||||
rATQA[0] = 0x42;
|
||||
rATQA[1] = 0x00;
|
||||
sak = 0x00;
|
||||
sak = 0x20;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1127,11 +1128,25 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
}
|
||||
}
|
||||
|
||||
if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
|
||||
if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) {
|
||||
rUIDc1[0] = data[0];
|
||||
rUIDc1[1] = data[1];
|
||||
rUIDc1[2] = data[2];
|
||||
rUIDc1[3] = data[3];
|
||||
rUIDc1[4] = rUIDc1[0] ^ rUIDc1[1] ^ rUIDc1[2] ^ rUIDc1[3];
|
||||
|
||||
// Configure the ATQA and SAK accordingly
|
||||
rATQA[0] &= 0xBF;
|
||||
rSAKc1[0] = sak & 0xFB;
|
||||
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
|
||||
|
||||
*cuid = bytes_to_num(data, 4);
|
||||
} else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
|
||||
rUIDc1[0] = 0x88; // Cascade Tag marker
|
||||
rUIDc1[1] = data[0];
|
||||
rUIDc1[2] = data[1];
|
||||
rUIDc1[3] = data[2];
|
||||
rUIDc1[4] = rUIDc1[0] ^ rUIDc1[1] ^ rUIDc1[2] ^ rUIDc1[3];
|
||||
|
||||
rUIDc2[0] = data[3];
|
||||
rUIDc2[1] = data[4];
|
||||
|
@ -1140,37 +1155,49 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
rUIDc2[4] = rUIDc2[0] ^ rUIDc2[1] ^ rUIDc2[2] ^ rUIDc2[3];
|
||||
|
||||
// Configure the ATQA and SAK accordingly
|
||||
rATQA[0] &= 0xBF;
|
||||
rATQA[0] |= 0x40;
|
||||
sak |= 0x04;
|
||||
rSAKc1[0] = 0x04;
|
||||
rSAKc2[0] = sak & 0xFB;
|
||||
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
|
||||
AddCrc14A(rSAKc2, sizeof(rSAKc2) - 2);
|
||||
|
||||
*cuid = bytes_to_num(data + 3, 4);
|
||||
} else if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) {
|
||||
memcpy(rUIDc1, data, 4);
|
||||
} else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) {
|
||||
rUIDc1[0] = 0x88; // Cascade Tag marker
|
||||
rUIDc1[1] = data[0];
|
||||
rUIDc1[2] = data[1];
|
||||
rUIDc1[3] = data[2];
|
||||
rUIDc1[4] = rUIDc1[0] ^ rUIDc1[1] ^ rUIDc1[2] ^ rUIDc1[3];
|
||||
|
||||
rUIDc2[0] = 0x88; // Cascade Tag marker
|
||||
rUIDc2[1] = data[3];
|
||||
rUIDc2[2] = data[4];
|
||||
rUIDc2[3] = data[5];
|
||||
rUIDc2[4] = rUIDc2[0] ^ rUIDc2[1] ^ rUIDc2[2] ^ rUIDc2[3];
|
||||
|
||||
rUIDc3[0] = data[6];
|
||||
rUIDc3[1] = data[7];
|
||||
rUIDc3[2] = data[8];
|
||||
rUIDc3[3] = data[9];
|
||||
rUIDc3[4] = rUIDc3[0] ^ rUIDc3[1] ^ rUIDc3[2] ^ rUIDc3[3];
|
||||
|
||||
// Configure the ATQA and SAK accordingly
|
||||
rATQA[0] &= 0xBF;
|
||||
sak &= 0xFB;
|
||||
*cuid = bytes_to_num(data, 4);
|
||||
rATQA[0] |= 0x80;
|
||||
rSAKc1[0] = 0x04;
|
||||
rSAKc2[0] = 0x04;
|
||||
rSAKc3[0] = sak & 0xFB;
|
||||
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
|
||||
AddCrc14A(rSAKc2, sizeof(rSAKc2) - 2);
|
||||
AddCrc14A(rSAKc3, sizeof(rSAKc3) - 2);
|
||||
|
||||
*cuid = bytes_to_num(data + 3 + 3, 4);
|
||||
} else {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("[-] ERROR: UID size not defined");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate BCC for the first 4 bytes of the UID.
|
||||
rUIDc1[4] = rUIDc1[0] ^ rUIDc1[1] ^ rUIDc1[2] ^ rUIDc1[3];
|
||||
|
||||
|
||||
if (tagType == 10) {
|
||||
rSAKc1[0] = 0x04;
|
||||
rSAKc2[0] = 0x20;
|
||||
} else {
|
||||
rSAKc1[0] = sak;
|
||||
rSAKc2[0] = sak & 0xFB;
|
||||
}
|
||||
|
||||
// crc
|
||||
AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2);
|
||||
AddCrc14A(rSAKc2, sizeof(rSAKc2) - 2);
|
||||
|
||||
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
|
||||
// TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
|
||||
// TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us)
|
||||
|
@ -1179,24 +1206,25 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
|
||||
AddCrc14A(rPPS, sizeof(rPPS) - 2);
|
||||
|
||||
#define TAG_RESPONSE_COUNT 9
|
||||
static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
|
||||
static tag_response_info_t responses_init[] = {
|
||||
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
|
||||
{ .response = rUIDc1, .response_n = sizeof(rUIDc1) }, // Anticollision cascade1 - respond with uid
|
||||
{ .response = rUIDc2, .response_n = sizeof(rUIDc2) }, // Anticollision cascade2 - respond with 2nd half of uid if asked
|
||||
{ .response = rUIDc3, .response_n = sizeof(rUIDc3) }, // Anticollision cascade3 - respond with 3rd half of uid if asked
|
||||
{ .response = rSAKc1, .response_n = sizeof(rSAKc1) }, // Acknowledge select - cascade 1
|
||||
{ .response = rSAKc2, .response_n = sizeof(rSAKc2) }, // Acknowledge select - cascade 2
|
||||
{ .response = rSAKc3, .response_n = sizeof(rSAKc3) }, // Acknowledge select - cascade 3
|
||||
{ .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS
|
||||
{ .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response
|
||||
{ .response = rSIGN, .response_n = sizeof(rSIGN) }, // EV1/NTAG READ_SIG response
|
||||
{ .response = rPPS, .response_n = sizeof(rPPS) } // PPS response
|
||||
};
|
||||
|
||||
// "precompile" responses. There are 9 predefined responses with a total of 72 bytes data to transmit.
|
||||
// "precompile" responses. There are 11 predefined responses with a total of 80 bytes data to transmit.
|
||||
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
|
||||
// 72 * 8 data bits, 72 * 1 parity bits, 9 start bits, 9 stop bits, 9 correction bits -- 677 bytes buffer
|
||||
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 675
|
||||
// 576 + 72 + 9 + 9 + 9 == 675
|
||||
// 80 * 8 data bits, 80 * 1 parity bits, 11 start bits, 11 stop bits, 11 correction bits
|
||||
// 80 * 8 + 80 + 11 + 11 + 11 == 753
|
||||
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 753
|
||||
|
||||
uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
|
||||
// modulation buffer pointer and current buffer free space size
|
||||
|
@ -1205,7 +1233,7 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
|
||||
// Prepare the responses of the anticollision phase
|
||||
// there will be not enough time to do this at the moment the reader sends it REQA
|
||||
for (size_t i = 0; i < TAG_RESPONSE_COUNT; i++) {
|
||||
for (size_t i = 0; i < ARRAYLEN(responses_init); i++) {
|
||||
if (prepare_allocated_tag_modulation(&responses_init[i], &free_buffer_pointer, &free_buffer_size) == false) {
|
||||
BigBuf_free_keep_EM();
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Not enough modulation buffer size, exit after %d elements", i);
|
||||
|
@ -1215,16 +1243,6 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i
|
|||
|
||||
*responses = responses_init;
|
||||
|
||||
// indices into responses array:
|
||||
#define ATQA 0
|
||||
#define UIDC1 1
|
||||
#define UIDC2 2
|
||||
#define SAKC1 3
|
||||
#define SAKC2 4
|
||||
#define RATS 5
|
||||
#define VERSION 6
|
||||
#define SIGNATURE 7
|
||||
#define PPS 8
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1289,16 +1307,18 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
|
||||
// To control where we are in the protocol
|
||||
#define ORDER_NONE 0
|
||||
#define ORDER_REQA 1
|
||||
#define ORDER_SELECT_ALL_CL1 2
|
||||
#define ORDER_SELECT_CL1 3
|
||||
//#define ORDER_REQA 1
|
||||
//#define ORDER_SELECT_ALL_CL1 2
|
||||
//#define ORDER_SELECT_CL1 3
|
||||
#define ORDER_HALTED 5
|
||||
#define ORDER_WUPA 6
|
||||
#define ORDER_AUTH 7
|
||||
#define ORDER_SELECT_ALL_CL2 20
|
||||
#define ORDER_SELECT_CL2 30
|
||||
//#define ORDER_SELECT_ALL_CL2 20
|
||||
//#define ORDER_SELECT_CL2 25
|
||||
//#define ORDER_SELECT_ALL_CL3 30
|
||||
//#define ORDER_SELECT_CL3 35
|
||||
#define ORDER_EV1_COMP_WRITE 40
|
||||
#define ORDER_RATS 70
|
||||
//#define ORDER_RATS 70
|
||||
|
||||
uint8_t order = ORDER_NONE;
|
||||
int retval = PM3_SUCCESS;
|
||||
|
@ -1416,19 +1436,23 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
} else 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[ATQA];
|
||||
p_response = &responses[RESP_INDEX_ATQA];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_WUPA && len == 1) { // Received a WAKEUP
|
||||
p_response = &responses[ATQA];
|
||||
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[UIDC1];
|
||||
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[UIDC2];
|
||||
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[SAKC1];
|
||||
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[SAKC2];
|
||||
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[PPS];
|
||||
p_response = &responses[RESP_INDEX_PPS];
|
||||
} else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK && len == 4) { // Received a (plain) READ
|
||||
uint8_t block = receivedCmd[1];
|
||||
// if Ultralight or NTAG (4 byte blocks)
|
||||
|
@ -1450,7 +1474,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
// FM11005SH. 16blocks, 4bytes / block.
|
||||
// block0 = 2byte Customer ID (CID), 2byte Manufacture ID (MID)
|
||||
// block1 = 4byte UID.
|
||||
p_response = &responses[UIDC1];
|
||||
p_response = &responses[RESP_INDEX_UIDC1];
|
||||
} else { // all other tags (16 byte block tags)
|
||||
uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
|
||||
emlGetMemBt(emdata, block, 16);
|
||||
|
@ -1512,7 +1536,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
}
|
||||
p_response = NULL;
|
||||
} else if (receivedCmd[0] == MIFARE_ULEV1_READSIG && len == 4 && tagType == 7) { // Received a READ SIGNATURE --
|
||||
p_response = &responses[SIGNATURE];
|
||||
p_response = &responses[RESP_INDEX_SIGNATURE];
|
||||
} else if (receivedCmd[0] == MIFARE_ULEV1_READ_CNT && len == 4 && tagType == 7) { // Received a READ COUNTER --
|
||||
uint8_t index = receivedCmd[1];
|
||||
if (index > 2) {
|
||||
|
@ -1561,7 +1585,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
p_response = NULL;
|
||||
order = ORDER_HALTED;
|
||||
} else if (receivedCmd[0] == MIFARE_ULEV1_VERSION && len == 3 && (tagType == 2 || tagType == 7)) {
|
||||
p_response = &responses[VERSION];
|
||||
p_response = &responses[RESP_INDEX_VERSION];
|
||||
} else if ((receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) && len == 4 && tagType != 2 && tagType != 7) { // Received an authentication request
|
||||
cardAUTHKEY = receivedCmd[0] - 0x60;
|
||||
cardAUTHSC = receivedCmd[1] / 4; // received block num
|
||||
|
@ -1579,7 +1603,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) {
|
|||
EmSend4bit(CARD_NACK_NA);
|
||||
p_response = NULL;
|
||||
} else {
|
||||
p_response = &responses[RATS];
|
||||
p_response = &responses[RESP_INDEX_RATS];
|
||||
}
|
||||
} else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication
|
||||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
|
@ -1787,7 +1811,7 @@ static void PrepareDelayedTransfer(uint16_t delay) {
|
|||
//-------------------------------------------------------------------------------------
|
||||
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
|
||||
|
||||
if (!hf_field_active) {
|
||||
if (!g_hf_field_active) {
|
||||
Dbprintf("Warning: HF field is off, ignoring TransmitFor14443a command");
|
||||
return;
|
||||
}
|
||||
|
@ -2187,7 +2211,7 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
|||
//-----------------------------------------------------------------------------
|
||||
bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *received_len) {
|
||||
|
||||
if (!hf_field_active) {
|
||||
if (!g_hf_field_active) {
|
||||
Dbprintf("Warning: HF field is off, ignoring GetIso14443aAnswerFromTag_Thinfilm command");
|
||||
return false;
|
||||
}
|
||||
|
@ -2237,7 +2261,7 @@ bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *rec
|
|||
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) {
|
||||
uint32_t c = 0;
|
||||
|
||||
if (!hf_field_active)
|
||||
if (!g_hf_field_active)
|
||||
return false;
|
||||
|
||||
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||
|
@ -2731,13 +2755,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
|
|||
NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER;
|
||||
iso14a_set_timeout(1060); // 106 * 10ms default
|
||||
|
||||
hf_field_active = true;
|
||||
}
|
||||
|
||||
void hf_field_off(void) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
hf_field_active = false;
|
||||
g_hf_field_active = true;
|
||||
}
|
||||
|
||||
/* Peter Fillmore 2015
|
||||
|
|
|
@ -84,6 +84,21 @@ typedef struct {
|
|||
uint8_t *parity;
|
||||
} tUart14a;
|
||||
|
||||
// indices into responses array:
|
||||
typedef enum {
|
||||
RESP_INDEX_ATQA,
|
||||
RESP_INDEX_UIDC1,
|
||||
RESP_INDEX_UIDC2,
|
||||
RESP_INDEX_UIDC3,
|
||||
RESP_INDEX_SAKC1,
|
||||
RESP_INDEX_SAKC2,
|
||||
RESP_INDEX_SAKC3,
|
||||
RESP_INDEX_RATS,
|
||||
RESP_INDEX_VERSION,
|
||||
RESP_INDEX_SIGNATURE,
|
||||
RESP_INDEX_PPS
|
||||
} resp_index_t;
|
||||
|
||||
#ifndef AddCrc14A
|
||||
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
||||
#endif
|
||||
|
@ -129,7 +144,6 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u
|
|||
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
|
||||
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
void hf_field_off(void);
|
||||
|
||||
int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
|
||||
int EmSend4bit(uint8_t resp);
|
||||
|
|
|
@ -717,6 +717,211 @@ void SimulateIso14443bTag(uint8_t *pupi) {
|
|||
switch_off(); //simulate
|
||||
}
|
||||
|
||||
/*
|
||||
void Simulate_iso14443b_srx_tag(uint8_t *uid) {
|
||||
|
||||
LED_A_ON();
|
||||
/ SRI512
|
||||
|
||||
> initiate 06 00 ISO14443B_INITIATE
|
||||
< xx crc crc
|
||||
> select 0e xx ISO14443B_SELECT
|
||||
< xx nn nn
|
||||
|
||||
> readblock 08 blck_no ISO14443B_READ_BLK
|
||||
< d0 d1 d2 d3 2byte crc
|
||||
|
||||
> get uid ISO14443B_GET_UID
|
||||
< 81 93 99 20 92 11 02 (8byte UID in MSB D002 199220 999381)
|
||||
|
||||
#define ISO14443B_REQB 0x05
|
||||
#define ISO14443B_ATTRIB 0x1D
|
||||
#define ISO14443B_HALT 0x50
|
||||
#define ISO14443B_INITIATE 0x06
|
||||
#define ISO14443B_SELECT 0x0E
|
||||
#define ISO14443B_GET_UID 0x0B
|
||||
#define ISO14443B_READ_BLK 0x08
|
||||
#define ISO14443B_WRITE_BLK 0x09
|
||||
#define ISO14443B_RESET 0x0C
|
||||
#define ISO14443B_COMPLETION 0x0F
|
||||
#define ISO14443B_AUTHENTICATE 0x0A
|
||||
#define ISO14443B_PING 0xBA
|
||||
#define ISO14443B_PONG 0xAB
|
||||
|
||||
|
||||
static const uint8_t resp_init_srx[] = { 0x73, 0x64, 0xb1 };
|
||||
uint8_t resp_select_srx[] = { 0x73, 0x64, 0xb1 };
|
||||
|
||||
// a default uid, or user supplied
|
||||
uint8_t resp_getuid_srx[10] = {
|
||||
0x81, 0x93, 0x99, 0x20, 0x92, 0x11, 0x02, 0xD0, 0x00, 0x00
|
||||
};
|
||||
|
||||
// ...UID supplied from user. Adjust ATQB response accordingly
|
||||
if (memcmp("\x00\x00\x00\x00\x00\x00\x00\x00", uid, 8) != 0) {
|
||||
memcpy(resp_getuid_srx, uid, 8);
|
||||
AddCrc14B(resp_getuid_srx, 8);
|
||||
}
|
||||
|
||||
// response to HLTB and ATTRIB
|
||||
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
|
||||
|
||||
// setup device.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
|
||||
// allocate command receive buffer
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
uint16_t len, cmdsReceived = 0;
|
||||
int cardSTATE = SIM_NOFIELD;
|
||||
int vHf = 0; // in mV
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
|
||||
// prepare "ATQB" tag answer (encoded):
|
||||
CodeIso14443bAsTag(respATQB, sizeof(respATQB));
|
||||
uint8_t *encodedATQB = BigBuf_malloc(ts->max);
|
||||
uint16_t encodedATQBLen = ts->max;
|
||||
memcpy(encodedATQB, ts->buf, ts->max);
|
||||
|
||||
|
||||
// prepare "OK" tag answer (encoded):
|
||||
CodeIso14443bAsTag(respOK, sizeof(respOK));
|
||||
uint8_t *encodedOK = BigBuf_malloc(ts->max);
|
||||
uint16_t encodedOKLen = ts->max;
|
||||
memcpy(encodedOK, ts->buf, ts->max);
|
||||
|
||||
// Simulation loop
|
||||
while (BUTTON_PRESS() == false) {
|
||||
WDT_HIT();
|
||||
|
||||
//iceman: limit with 2000 times..
|
||||
if (data_available()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// find reader field
|
||||
if (cardSTATE == SIM_NOFIELD) {
|
||||
|
||||
#if defined RDV4
|
||||
vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
|
||||
#else
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
||||
#endif
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
cardSTATE = SIM_IDLE;
|
||||
LED_A_ON();
|
||||
}
|
||||
}
|
||||
if (cardSTATE == SIM_NOFIELD) continue;
|
||||
|
||||
// Get reader command
|
||||
if (!GetIso14443bCommandFromReader(receivedCmd, &len)) {
|
||||
Dbprintf("button pressed, received %d commands", cmdsReceived);
|
||||
break;
|
||||
}
|
||||
|
||||
// ISO14443-B protocol states:
|
||||
// REQ or WUP request in ANY state
|
||||
// WUP in HALTED state
|
||||
if (len == 5) {
|
||||
if ((receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8) == 0x8 && cardSTATE == SIM_HALTED) ||
|
||||
receivedCmd[0] == ISO14443B_REQB) {
|
||||
LogTrace(receivedCmd, len, 0, 0, NULL, true);
|
||||
cardSTATE = SIM_SELECTING;
|
||||
}
|
||||
}
|
||||
|
||||
/
|
||||
* How should this flow go?
|
||||
* REQB or WUPB
|
||||
* send response ( waiting for Attrib)
|
||||
* ATTRIB
|
||||
* send response ( waiting for commands 7816)
|
||||
* HALT
|
||||
send halt response ( waiting for wupb )
|
||||
/
|
||||
|
||||
switch (cardSTATE) {
|
||||
//case SIM_NOFIELD:
|
||||
case SIM_HALTED:
|
||||
case SIM_IDLE: {
|
||||
LogTrace(receivedCmd, len, 0, 0, NULL, true);
|
||||
break;
|
||||
}
|
||||
case SIM_SELECTING: {
|
||||
TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
|
||||
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_WORK;
|
||||
break;
|
||||
}
|
||||
case SIM_HALTING: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_HALTED;
|
||||
break;
|
||||
}
|
||||
case SIM_ACKNOWLEDGE: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_IDLE;
|
||||
break;
|
||||
}
|
||||
case SIM_WORK: {
|
||||
if (len == 7 && receivedCmd[0] == ISO14443B_HALT) {
|
||||
cardSTATE = SIM_HALTED;
|
||||
} else if (len == 11 && receivedCmd[0] == ISO14443B_ATTRIB) {
|
||||
cardSTATE = SIM_ACKNOWLEDGE;
|
||||
} else {
|
||||
// Todo:
|
||||
// - SLOT MARKER
|
||||
// - ISO7816
|
||||
// - emulate with a memory dump
|
||||
if (DBGLEVEL >= DBG_DEBUG)
|
||||
Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived);
|
||||
|
||||
// CRC Check
|
||||
if (len >= 3) { // if crc exists
|
||||
|
||||
if (!check_crc(CRC_14443_B, receivedCmd, len)) {
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
DbpString("CRC fail");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
DbpString("CRC passed");
|
||||
}
|
||||
}
|
||||
cardSTATE = SIM_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
++cmdsReceived;
|
||||
}
|
||||
|
||||
if (DBGLEVEL >= DBG_DEBUG)
|
||||
Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
|
||||
|
||||
switch_off(); //simulate
|
||||
}
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
// An ISO 14443 Type B reader. We take layer two commands, code them
|
||||
// appropriately, and then send them to the tag. We then listen for the
|
||||
|
@ -1160,6 +1365,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t
|
|||
tosend_t *ts = get_tosend();
|
||||
CodeIso14443bAsReader(cmd, len);
|
||||
TransmitFor14443b_AsReader(start_time);
|
||||
if (g_trigger) LED_A_ON();
|
||||
*eof_time = *start_time + (10 * ts->max) + 10 + 2 + 10;
|
||||
LogTrace(cmd, len, *start_time, *eof_time, NULL, true);
|
||||
}
|
||||
|
@ -1572,10 +1778,10 @@ static int read_srx_block(uint8_t blocknr, uint8_t *block) {
|
|||
|
||||
if (DBGLEVEL >= DBG_DEBUG) {
|
||||
Dbprintf("Address=%02x, Contents=%08x, CRC=%04x",
|
||||
blocknr,
|
||||
(r_block[3] << 24) + (r_block[2] << 16) + (r_block[1] << 8) + r_block[0],
|
||||
(r_block[4] << 8) + r_block[5]
|
||||
);
|
||||
blocknr,
|
||||
(r_block[3] << 24) + (r_block[2] << 16) + (r_block[1] << 8) + r_block[0],
|
||||
(r_block[4] << 8) + r_block[5]
|
||||
);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
|
@ -1586,7 +1792,7 @@ void ReadSTBlock(uint8_t blocknr) {
|
|||
iso14b_card_select_t card;
|
||||
int res = iso14443b_select_srx_card(&card);
|
||||
// 0: OK -1 wrong len, -2: attrib fail, -3:crc fail,
|
||||
switch(res) {
|
||||
switch (res) {
|
||||
case -1:
|
||||
case -3: {
|
||||
reply_ng(CMD_HF_SRI_READ, PM3_EWRONGANSWER, NULL, 0);
|
||||
|
|
|
@ -450,7 +450,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|||
// 2 = use 0x1B authentication.
|
||||
// datain : 4 first bytes is data to be written.
|
||||
// : 4/16 next bytes is authentication key.
|
||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||
static void MifareUWriteBlockEx(uint8_t arg0, uint8_t arg1, uint8_t *datain, bool reply) {
|
||||
uint8_t blockNo = arg0;
|
||||
bool useKey = (arg1 == 1); //UL_C
|
||||
bool usePwd = (arg1 == 2); //UL_EV1/NTAG
|
||||
|
@ -507,12 +507,17 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|||
|
||||
if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
if (reply)
|
||||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
}
|
||||
|
||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||
MifareUWriteBlockEx(arg0, arg1, datain, true);
|
||||
}
|
||||
|
||||
// Arg0 : Block to write to.
|
||||
// Arg1 : 0 = use no authentication.
|
||||
// 1 = use 0x1A authentication.
|
||||
|
@ -2283,7 +2288,7 @@ void MifareCIdent(bool is_mfc) {
|
|||
|
||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res ) {
|
||||
if (res) {
|
||||
|
||||
// test for some MFC gen2
|
||||
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) {
|
||||
|
@ -2376,6 +2381,9 @@ void MifareHasStaticNonce(void) {
|
|||
int retval = PM3_SUCCESS;
|
||||
uint32_t nt = 0;
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
|
||||
memset(uid, 0x00, 10);
|
||||
|
||||
uint8_t data[1] = { NONCE_FAIL };
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
|
@ -2392,7 +2400,7 @@ void MifareHasStaticNonce(void) {
|
|||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t rec[1] = {0x00};
|
||||
uint8_t rec[4] = {0x00};
|
||||
uint8_t recpar[1] = {0x00};
|
||||
// Transmit MIFARE_CLASSIC_AUTH 0x60, block 0
|
||||
int len = mifare_sendcmd_short(pcs, false, MIFARE_AUTH_KEYA, 0, rec, recpar, NULL);
|
||||
|
@ -2412,6 +2420,8 @@ void MifareHasStaticNonce(void) {
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
CHK_TIMEOUT();
|
||||
|
||||
memset(rec, 0x00, sizeof(rec));
|
||||
}
|
||||
|
||||
if (counter) {
|
||||
|
@ -2715,7 +2725,8 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t tearoff_time, uint8_t *datain) {
|
|||
if (tearoff_time > 43000)
|
||||
tearoff_time = 43000;
|
||||
|
||||
MifareUWriteBlock(blockNo, 0, data_fullwrite);
|
||||
MifareUWriteBlockEx(blockNo, 0, data_fullwrite, false);
|
||||
|
||||
|
||||
LEDsoff();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
@ -2724,13 +2735,18 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t tearoff_time, uint8_t *datain) {
|
|||
|
||||
// write cmd to send, include CRC
|
||||
// 1b write, 1b block, 4b data, 2 crc
|
||||
uint8_t cmd[] = {MIFARE_ULC_WRITE, blockNo, data_testwrite[0], data_testwrite[1], data_testwrite[2], data_testwrite[3], 0, 0};
|
||||
uint8_t cmd[] = {
|
||||
MIFARE_ULC_WRITE, blockNo,
|
||||
data_testwrite[0], data_testwrite[1], data_testwrite[2], data_testwrite[3],
|
||||
0, 0
|
||||
};
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
|
||||
// anticollision / select card
|
||||
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
OnError(1);
|
||||
reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_EFAILED, NULL, 0);
|
||||
return;
|
||||
};
|
||||
// send
|
||||
|
@ -2748,7 +2764,7 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t tearoff_time, uint8_t *datain) {
|
|||
|
||||
//
|
||||
// Tear-off attack against MFU counter
|
||||
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time) {
|
||||
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time, uint8_t *datain) {
|
||||
|
||||
if (tearoff_time > 43000)
|
||||
tearoff_time = 43000;
|
||||
|
@ -2762,10 +2778,10 @@ void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time) {
|
|||
uint8_t cmd[] = {
|
||||
MIFARE_ULEV1_INCR_CNT,
|
||||
counter,
|
||||
0, // lsb
|
||||
0,
|
||||
0, // msb
|
||||
0, // rfu
|
||||
datain[0], // lsb
|
||||
datain[1],
|
||||
datain[2], // msb
|
||||
datain[3], // rfu
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
|
|
@ -64,5 +64,5 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
|||
|
||||
// Tear-off test for MFU
|
||||
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain);
|
||||
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time);
|
||||
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time, uint8_t *datain);
|
||||
#endif
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#include "protocols.h"
|
||||
#include "desfire_crypto.h"
|
||||
|
||||
int DBGLEVEL = DBG_ERROR;
|
||||
|
||||
// crypto1 helpers
|
||||
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out) {
|
||||
if (len != 1) {
|
||||
|
|
|
@ -18,14 +18,13 @@
|
|||
#include "BigBuf.h"
|
||||
#include "string.h"
|
||||
|
||||
static uint8_t *next_free_memory;
|
||||
extern struct common_area common_area;
|
||||
extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__;
|
||||
|
||||
|
||||
static void uncompress_data_section(void) {
|
||||
next_free_memory = BigBuf_get_addr();
|
||||
int avail_in;
|
||||
memcpy(&avail_in, &__data_start__, sizeof(int));
|
||||
memcpy(&avail_in, &__data_src_start__, sizeof(int));
|
||||
int avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct.
|
||||
// uncompress data segment to RAM
|
||||
uintptr_t p = (uintptr_t)&__data_src_start__;
|
||||
|
@ -34,13 +33,21 @@ static void uncompress_data_section(void) {
|
|||
if (res < 0)
|
||||
return;
|
||||
// save the size of the compressed data section
|
||||
common_area.arg1 = res;
|
||||
common_area.arg1 = avail_in;
|
||||
}
|
||||
|
||||
void __attribute__((section(".startos"))) Vector(void);
|
||||
void Vector(void) {
|
||||
/* Stack should have been set up by the bootloader */
|
||||
|
||||
if (common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
|
||||
/* Initialize common area */
|
||||
memset(&common_area, 0, sizeof(common_area));
|
||||
common_area.magic = COMMON_AREA_MAGIC;
|
||||
common_area.version = 1;
|
||||
}
|
||||
common_area.flags.osimage_present = 1;
|
||||
|
||||
uncompress_data_section();
|
||||
|
||||
/* Set up (that is: clear) BSS. */
|
||||
|
|
|
@ -216,6 +216,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/uart/uart_posix.c
|
||||
${PM3_ROOT}/client/src/uart/uart_win32.c
|
||||
${PM3_ROOT}/client/src/ui/overlays.ui
|
||||
${PM3_ROOT}/client/src/aiddesfire.c
|
||||
${PM3_ROOT}/client/src/aidsearch.c
|
||||
${PM3_ROOT}/client/src/cmdanalyse.c
|
||||
${PM3_ROOT}/client/src/cmdcrc.c
|
||||
|
|
|
@ -29,26 +29,31 @@ endif
|
|||
AMIIBOLIBPATH = ./deps/amiitool
|
||||
AMIIBOLIBINC = -I$(AMIIBOLIBPATH)
|
||||
AMIIBOLIB = $(AMIIBOLIBPATH)/libamiibo.a
|
||||
AMIIBOLIBLD =
|
||||
|
||||
## Cliparser / Argtable3
|
||||
CLIPARSERLIBPATH = ./deps/cliparser
|
||||
CLIPARSERLIBINC = -I$(CLIPARSERLIBPATH)
|
||||
CLIPARSERLIB = $(CLIPARSERLIBPATH)/libcliparser.a
|
||||
CLIPARSERLIBLD =
|
||||
|
||||
## Hardnested
|
||||
HARDNESTEDLIBPATH = ./deps/hardnested
|
||||
HARDNESTEDLIBINC = -I$(HARDNESTEDLIBPATH)
|
||||
HARDNESTEDLIB = $(HARDNESTEDLIBPATH)/libhardnested.a
|
||||
HARDNESTEDLIBLD =
|
||||
|
||||
## Jansson
|
||||
JANSSONLIBPATH = ./deps/jansson
|
||||
JANSSONLIBINC = -I$(JANSSONLIBPATH)
|
||||
JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a
|
||||
JANSSONLIBLD =
|
||||
|
||||
## Lua
|
||||
LUALIBPATH = ./deps/liblua
|
||||
LUALIBINC = -I$(LUALIBPATH)
|
||||
LUALIB = $(LUALIBPATH)/liblua.a
|
||||
LUALIBLD =
|
||||
LUAPLATFORM = generic
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
LUAPLATFORM = mingw
|
||||
|
@ -56,7 +61,7 @@ else
|
|||
ifeq ($(platform),Darwin)
|
||||
LUAPLATFORM = macosx
|
||||
else
|
||||
LUALIB += -ldl
|
||||
LUALIBLD += -ldl
|
||||
LUAPLATFORM = linux
|
||||
endif
|
||||
endif
|
||||
|
@ -65,16 +70,19 @@ endif
|
|||
REVENGLIBPATH = ./deps/reveng
|
||||
REVENGLIBINC = -I$(REVENGLIBPATH)
|
||||
REVENGLIB = $(REVENGLIBPATH)/libreveng.a
|
||||
REVENGLIBLD =
|
||||
|
||||
## Tinycbor
|
||||
TINYCBORLIBPATH = ./deps/tinycbor
|
||||
TINYCBORLIBINC = -I$(TINYCBORLIBPATH)
|
||||
TINYCBORLIB = $(TINYCBORLIBPATH)/tinycbor.a
|
||||
TINYCBORLIBLD =
|
||||
|
||||
## Whereami
|
||||
WHEREAMILIBPATH = ./deps/whereami
|
||||
WHEREAMILIBINC = -I$(WHEREAMILIBPATH)
|
||||
WHEREAMILIB = $(WHEREAMILIBPATH)/libwhereami.a
|
||||
WHEREAMILIBLD =
|
||||
|
||||
##########################
|
||||
# common local libraries #
|
||||
|
@ -91,17 +99,20 @@ MBEDTLSLIB = $(OBJDIR)/libmbedtls.a
|
|||
|
||||
## Amiibo
|
||||
# not distributed as system library
|
||||
LDLIBS += $(AMIIBOLIB)
|
||||
STATICLIBS += $(AMIIBOLIB)
|
||||
LDLIBS += $(AMIIBOLIBLD)
|
||||
INCLUDES += $(AMIIBOLIBINC)
|
||||
|
||||
## Cliparser / Argtable3
|
||||
# not distributed as system library
|
||||
LDLIBS += $(CLIPARSERLIB)
|
||||
STATICLIBS += $(CLIPARSERLIB)
|
||||
LDLIBS += $(CLIPARSERLIBLD)
|
||||
INCLUDES += $(CLIPARSERLIBINC)
|
||||
|
||||
## Hardnested
|
||||
# not distributed as system library
|
||||
LDLIBS += $(HARDNESTEDLIB)
|
||||
STATICLIBS += $(HARDNESTEDLIB)
|
||||
LDLIBS +=$(HARDNESTEDLIBLD)
|
||||
INCLUDES += $(HARDNESTEDLIBINC)
|
||||
|
||||
## Jansson
|
||||
|
@ -109,12 +120,14 @@ ifneq ($(SKIPJANSSONSYSTEM),1)
|
|||
JANSSONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags jansson 2>/dev/null)
|
||||
JANSSONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs jansson 2>/dev/null)
|
||||
ifneq ($(JANSSONLDLIBS),)
|
||||
JANSSONLIB = $(JANSSONLDLIBS)
|
||||
JANSSONLIB =
|
||||
JANSSONLIBLD = $(JANSSONLDLIBS)
|
||||
JANSSONLIBINC = $(JANSSONINCLUDES)
|
||||
JANSSON_FOUND = 1
|
||||
endif
|
||||
endif
|
||||
LDLIBS += $(JANSSONLIB)
|
||||
STATICLIBS += $(JANSSONLIB)
|
||||
LDLIBS += $(JANSSONLIBLD)
|
||||
INCLUDES += $(JANSSONLIBINC)
|
||||
|
||||
## Lua
|
||||
|
@ -122,38 +135,45 @@ ifneq ($(SKIPLUASYSTEM),1)
|
|||
LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua5.2 2>/dev/null)
|
||||
LUALDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs lua5.2 2>/dev/null)
|
||||
ifneq ($(LUALDLIBS),)
|
||||
LUALIB = $(LUALDLIBS)
|
||||
LUALIB =
|
||||
LUALIBLD = $(LUALDLIBS)
|
||||
LUALIBINC = $(LUAINCLUDES)
|
||||
LUA_FOUND = 1
|
||||
endif
|
||||
endif
|
||||
LDLIBS += $(LUALIB)
|
||||
STATICLIBS += $(LUALIB)
|
||||
LDLIBS += $(LUALIBLD)
|
||||
INCLUDES += $(LUALIBINC)
|
||||
|
||||
## mbed TLS
|
||||
# system library cannot be used because it is compiled by default without CMAC support
|
||||
LDLIBS +=$(MBEDTLSLIB)
|
||||
STATICLIBS += $(MBEDTLSLIB)
|
||||
LDLIBS += $(MBEDTLSLIBLD)
|
||||
INCLUDES += $(MBEDTLSLIBINC)
|
||||
|
||||
## Reveng
|
||||
# not distributed as system library
|
||||
LDLIBS += $(REVENGLIB)
|
||||
STATICLIBS += $(REVENGLIB)
|
||||
LDLIBS += $(REVENGLIBLD)
|
||||
INCLUDES += $(REVENGLIBINC)
|
||||
|
||||
## Tinycbor
|
||||
# not distributed as system library
|
||||
LDLIBS += $(TINYCBORLIB)
|
||||
STATICLIBS += $(TINYCBORLIB)
|
||||
LDLIBS += $(TINYCBORLIBLD)
|
||||
INCLUDES += $(TINYCBORLIBINC)
|
||||
|
||||
## Whereami
|
||||
ifneq ($(SKIPWHEREAMISYSTEM),1)
|
||||
ifneq (,$(wildcard /usr/include/whereami.h))
|
||||
WHEREAMILIB = -lwhereami
|
||||
WHEREAMILIB =
|
||||
WHEREAMILIBLD = -lwhereami
|
||||
WHEREAMILIBINC =
|
||||
WHEREAMI_FOUND = 1
|
||||
endif
|
||||
endif
|
||||
LDLIBS += $(WHEREAMILIB)
|
||||
STATICLIBS += $(WHEREAMILIB)
|
||||
LDLIBS += $(WHEREAMILIBLD)
|
||||
INCLUDES += $(WHEREAMILIBINC)
|
||||
|
||||
####################
|
||||
|
@ -176,12 +196,12 @@ ifneq ($(SKIPBT),1)
|
|||
BTINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags bluez 2>/dev/null)
|
||||
BTLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs bluez 2>/dev/null)
|
||||
ifneq ($(BTLDLIBS),)
|
||||
BTLIB = $(BTLDLIBS)
|
||||
BTLIBLD = $(BTLDLIBS)
|
||||
BTLIBINC = $(BTINCLUDES)
|
||||
BT_FOUND = 1
|
||||
endif
|
||||
endif
|
||||
LDLIBS += $(BTLIB)
|
||||
LDLIBS += $(BTLIBLD)
|
||||
INCLUDES += $(BTLIBINC)
|
||||
|
||||
## Math
|
||||
|
@ -198,7 +218,7 @@ ifneq ($(SKIPPYTHON),1)
|
|||
PYTHONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags python3 2>/dev/null)
|
||||
PYTHONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs python3 2>/dev/null)
|
||||
ifneq ($(PYTHONLDLIBS),)
|
||||
PYTHONLIB = $(PYTHONLDLIBS)
|
||||
PYTHONLIBLD = $(PYTHONLDLIBS)
|
||||
PYTHONLIBINC = $(PYTHONINCLUDES)
|
||||
PYTHON_FOUND = 1
|
||||
else
|
||||
|
@ -206,13 +226,13 @@ ifneq ($(SKIPPYTHON),1)
|
|||
PYTHONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags python3-embed 2>/dev/null)
|
||||
PYTHONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs python3-embed 2>/dev/null)
|
||||
ifneq ($(PYTHONLDLIBS),)
|
||||
PYTHONLIB = $(PYTHONLDLIBS)
|
||||
PYTHONLIBLD = $(PYTHONLDLIBS)
|
||||
PYTHONLIBINC = $(PYTHONINCLUDES)
|
||||
PYTHON_FOUND = 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
LDLIBS += $(PYTHONLIB)
|
||||
LDLIBS += $(PYTHONLIBLD)
|
||||
INCLUDES += $(PYTHONLIBINC)
|
||||
|
||||
## QT5 (or QT4 fallback) (optional)
|
||||
|
@ -410,7 +430,8 @@ POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@
|
|||
# enumerations #
|
||||
################
|
||||
|
||||
SRCS = aidsearch.c \
|
||||
SRCS = aiddesfire.c \
|
||||
aidsearch.c \
|
||||
cmdanalyse.c \
|
||||
cmdcrc.c \
|
||||
cmddata.c \
|
||||
|
@ -583,9 +604,9 @@ all: $(BINS)
|
|||
all-static: LDLIBS:=-static $(LDLIBS)
|
||||
all-static: $(BINS)
|
||||
|
||||
proxmark3: $(OBJS) amiibo cliparser jansson hardnested lua mbedtls reveng tinycbor whereami lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
|
||||
proxmark3: $(OBJS) $(STATICLIBS) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
|
||||
$(info [=] LD $@)
|
||||
$(Q)$(LD) $(PM3LDFLAGS) $(OBJS) $(LDLIBS) -o $@
|
||||
$(Q)$(LD) $(PM3LDFLAGS) $(OBJS) $(STATICLIBS) $(LDLIBS) -o $@
|
||||
|
||||
src/proxgui.cpp: src/ui/ui_overlays.h
|
||||
|
||||
|
@ -648,44 +669,43 @@ tarbin: $(BINS)
|
|||
###########################
|
||||
# local libraries targets #
|
||||
###########################
|
||||
|
||||
amiibo:
|
||||
$(AMIIBOLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all
|
||||
|
||||
cliparser:
|
||||
$(CLIPARSERLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(CLIPARSERLIBPATH) all
|
||||
|
||||
hardnested:
|
||||
$(HARDNESTEDLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDLIBPATH) all
|
||||
|
||||
jansson:
|
||||
$(JANSSONLIB): .FORCE
|
||||
ifneq ($(JANSSON_FOUND),1)
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all
|
||||
endif
|
||||
|
||||
lua:
|
||||
$(LUALIB): .FORCE
|
||||
ifneq ($(LUA_FOUND),1)
|
||||
$(info [*] MAKE $@ for $(LUAPLATFORM))
|
||||
$(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) $(LUAPLATFORM)
|
||||
endif
|
||||
|
||||
mbedtls:
|
||||
$(MBEDTLSLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all
|
||||
|
||||
reveng:
|
||||
$(REVENGLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) all
|
||||
|
||||
tinycbor:
|
||||
$(TINYCBORLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) all
|
||||
|
||||
whereami:
|
||||
$(WHEREAMILIB): .FORCE
|
||||
ifneq ($(WHEREAMI_FOUND),1)
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) all
|
||||
|
@ -695,7 +715,7 @@ endif
|
|||
# misc #
|
||||
########
|
||||
|
||||
.PHONY: all clean install uninstall tarbin amiibo cliparser hardnested jansson lua mbedtls reveng tinycbor whereami
|
||||
.PHONY: all clean install uninstall tarbin .FORCE
|
||||
|
||||
# version.c should be remade on every compilation
|
||||
src/version.c: default_version.c
|
||||
|
|
|
@ -94,6 +94,7 @@ add_library(pm3rrg_rdv4 SHARED
|
|||
${PM3_ROOT}/client/src/uart/uart_posix.c
|
||||
${PM3_ROOT}/client/src/uart/uart_win32.c
|
||||
${PM3_ROOT}/client/src/ui/overlays.ui
|
||||
${PM3_ROOT}/client/src/aiddesfire.c
|
||||
${PM3_ROOT}/client/src/aidsearch.c
|
||||
${PM3_ROOT}/client/src/cmdanalyse.c
|
||||
${PM3_ROOT}/client/src/cmdcrc.c
|
||||
|
|
|
@ -86,7 +86,7 @@ jint Console(JNIEnv *env, jobject instance, jstring cmd_) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
char *cmd = (char *) ((*env)->GetStringUTFChars(env, cmd_, 0));
|
||||
char *cmd = (char *)((*env)->GetStringUTFChars(env, cmd_, 0));
|
||||
int ret = CommandReceived(cmd);
|
||||
if (ret == 99) {
|
||||
// exit / quit
|
||||
|
@ -102,7 +102,7 @@ jint Console(JNIEnv *env, jobject instance, jstring cmd_) {
|
|||
* Is client running!
|
||||
* */
|
||||
jboolean IsClientRunning(JNIEnv *env, jobject instance) {
|
||||
return (jboolean) ((jboolean) conn.run);
|
||||
return (jboolean)((jboolean) conn.run);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -114,7 +114,7 @@ jboolean TestPm3(JNIEnv *env, jobject instance) {
|
|||
return false;
|
||||
}
|
||||
bool ret = (TestProxmark() == PM3_SUCCESS);
|
||||
return (jboolean) (ret);
|
||||
return (jboolean)(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -141,18 +141,18 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
|||
}
|
||||
jclass clz_test = (*jniEnv)->FindClass(jniEnv, "cn/rrg/devices/Proxmark3RRGRdv4");
|
||||
JNINativeMethod methods[] = {
|
||||
{"startExecute", "(Ljava/lang/String;)I", (void *) Console},
|
||||
{"stopExecute", "()V", (void *) ClosePm3},
|
||||
{"isExecuting", "()Z", (void *) IsClientRunning}
|
||||
{"startExecute", "(Ljava/lang/String;)I", (void *) Console},
|
||||
{"stopExecute", "()V", (void *) ClosePm3},
|
||||
{"isExecuting", "()Z", (void *) IsClientRunning}
|
||||
};
|
||||
|
||||
JNINativeMethod methods1[] = {
|
||||
{"testPm3", "()Z", (void *) TestPm3},
|
||||
{"closePm3", "()V", ClosePm3}
|
||||
{"testPm3", "()Z", (void *) TestPm3},
|
||||
{"closePm3", "()V", ClosePm3}
|
||||
};
|
||||
|
||||
if ((*jniEnv)->RegisterNatives(jniEnv, clazz, methods, sizeof(methods) / sizeof(methods[0])) !=
|
||||
JNI_OK) {
|
||||
JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,8 +132,7 @@
|
|||
"Vendor": "Clipper",
|
||||
"Country": "US",
|
||||
"Name": "Clipper Card/San Francisco Bay Area ",
|
||||
"Description": "(FIDs 02: current balance; 04: Refill History; 08: Card Information; 0E: Trip History)
|
||||
FFFFFF General Issuer Information (FIDs 00: MAD Version; 01: Card Holder; 02: Card Publisher)",
|
||||
"Description": "(FIDs 02: current balance; 04: Refill History; 08: Card Information; 0E: Trip History)\\nFFFFFF General Issuer Information (FIDs 00: MAD Version; 01: Card Holder; 02: Card Publisher)",
|
||||
"Type": "transport"
|
||||
},
|
||||
{
|
||||
|
|
133
client/src/aiddesfire.c
Normal file
133
client/src/aiddesfire.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// AID DESFire functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "aiddesfire.h"
|
||||
#include "pm3_cmd.h"
|
||||
#include "fileutils.h"
|
||||
#include "jansson.h"
|
||||
|
||||
static json_t *df_known_aids = NULL;
|
||||
|
||||
static int open_aiddf_file(json_t **root, bool verbose) {
|
||||
|
||||
char *path;
|
||||
int res = searchFile(&path, RESOURCES_SUBDIR, "aid_desfire", ".json", true);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
json_error_t error;
|
||||
|
||||
*root = json_load_file(path, 0, &error);
|
||||
if (!*root) {
|
||||
PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text);
|
||||
retval = PM3_ESOFT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!json_is_array(*root)) {
|
||||
PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", path);
|
||||
retval = PM3_ESOFT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
PrintAndLogEx(SUCCESS, "Loaded file " _YELLOW_("`%s`") " (%s) %zu records.", path, _GREEN_("ok"), json_array_size(*root));
|
||||
out:
|
||||
free(path);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int close_aiddf_file(json_t *root) {
|
||||
json_decref(root);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static const char *aiddf_json_get_str(json_t *data, const char *name) {
|
||||
|
||||
json_t *jstr = json_object_get(data, name);
|
||||
if (jstr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!json_is_string(jstr)) {
|
||||
PrintAndLogEx(WARNING, _YELLOW_("`%s`") " is not a string", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *cstr = json_string_value(jstr);
|
||||
if (strlen(cstr) == 0)
|
||||
return NULL;
|
||||
|
||||
return cstr;
|
||||
}
|
||||
|
||||
static int print_aiddf_description(json_t *root, uint8_t aid[3], char *fmt, bool verbose) {
|
||||
char laid[7] = {0};
|
||||
sprintf(laid, "%02x%02x%02x", aid[2], aid[1], aid[0]); // must be lowercase
|
||||
|
||||
json_t *elm = NULL;
|
||||
|
||||
for (uint32_t idx = 0; idx < json_array_size(root); idx++) {
|
||||
json_t *data = json_array_get(root, idx);
|
||||
if (!json_is_object(data)) {
|
||||
PrintAndLogEx(ERR, "data [%d] is not an object\n", idx);
|
||||
continue;
|
||||
}
|
||||
const char *faid = aiddf_json_get_str(data, "AID");
|
||||
char lfaid[strlen(faid) + 1];
|
||||
strcpy(lfaid, faid);
|
||||
str_lower(lfaid);
|
||||
if (strcmp(laid, lfaid) == 0) {
|
||||
elm = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (elm == NULL) {
|
||||
PrintAndLogEx(INFO, fmt, " (unknown)");
|
||||
return PM3_ENODATA;
|
||||
}
|
||||
const char *vaid = aiddf_json_get_str(elm, "AID");
|
||||
const char *vendor = aiddf_json_get_str(elm, "Vendor");
|
||||
const char *country = aiddf_json_get_str(elm, "Country");
|
||||
const char *name = aiddf_json_get_str(elm, "Name");
|
||||
const char *description = aiddf_json_get_str(elm, "Description");
|
||||
const char *type = aiddf_json_get_str(elm, "Type");
|
||||
|
||||
if (name && vendor) {
|
||||
char result[4 + strlen(name) + strlen(vendor)];
|
||||
sprintf(result, " %s [%s]", name, vendor);
|
||||
PrintAndLogEx(INFO, fmt, result);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(SUCCESS, " AID: %s", vaid);
|
||||
if (name)
|
||||
PrintAndLogEx(SUCCESS, " Name: %s", name);
|
||||
if (description)
|
||||
PrintAndLogEx(SUCCESS, " Description: %s", description);
|
||||
if (type)
|
||||
PrintAndLogEx(SUCCESS, " Type: %s", type);
|
||||
if (vendor)
|
||||
PrintAndLogEx(SUCCESS, " Vendor: %s", vendor);
|
||||
if (country)
|
||||
PrintAndLogEx(SUCCESS, " Country: %s", country);
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int AIDDFDecodeAndPrint(uint8_t aid[3]) {
|
||||
open_aiddf_file(&df_known_aids, false);
|
||||
|
||||
char fmt[50];
|
||||
sprintf(fmt, " DF AID Function %02X%02X%02X :" _YELLOW_("%s"), aid[2], aid[1], aid[0], "%s");
|
||||
print_aiddf_description(df_known_aids, aid, fmt, false);
|
||||
close_aiddf_file(df_known_aids);
|
||||
return PM3_SUCCESS;
|
||||
}
|
16
client/src/aiddesfire.h
Normal file
16
client/src/aiddesfire.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// AID DESFire functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _AIDDESFIRE_H_
|
||||
#define _AIDDESFIRE_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int AIDDFDecodeAndPrint(uint8_t aid[3]);
|
||||
|
||||
#endif // _AIDDESFIRE_H_
|
|
@ -398,19 +398,64 @@ static int CmdSetDebugMode(const char *Cmd) {
|
|||
//by marshmellow
|
||||
// max output to 512 bits if we have more
|
||||
// doesn't take inconsideration where the demod offset or bitlen found.
|
||||
void printDemodBuff(void) {
|
||||
int len = DemodBufferLen;
|
||||
if (len < 1) {
|
||||
PrintAndLogEx(INFO, "(printDemodBuff) no bits found in demod buffer");
|
||||
return;
|
||||
int printDemodBuff(uint8_t offset, bool strip_leading, bool invert, bool print_hex) {
|
||||
size_t len = DemodBufferLen;
|
||||
if (len == 0) {
|
||||
PrintAndLogEx(WARNING, "Demodbuffer is empty");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (len > 512) len = 512;
|
||||
|
||||
PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 32));
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
if (strip_leading) {
|
||||
buf = (DemodBuffer + offset);
|
||||
|
||||
if (len > (DemodBufferLen - offset))
|
||||
len = (DemodBufferLen - offset);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] == 1) break;
|
||||
}
|
||||
offset += i;
|
||||
}
|
||||
|
||||
if (len > (DemodBufferLen - offset)) {
|
||||
len = (DemodBufferLen - offset);
|
||||
}
|
||||
|
||||
if (len > 512) {
|
||||
len = 512;
|
||||
}
|
||||
|
||||
if (invert) {
|
||||
buf = (DemodBuffer + offset);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (buf[i] == 1)
|
||||
buf[i] = 0;
|
||||
else {
|
||||
if (buf[i] == 0)
|
||||
buf[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (print_hex) {
|
||||
buf = (DemodBuffer + offset);
|
||||
char hex[512] = {0x00};
|
||||
int num_bits = binarraytohex(hex, sizeof(hex), (char *)buf, len);
|
||||
if (num_bits == 0) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "DemodBuffer: %s", hex);
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, len, 32));
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdPrintDemodBuff(const char *Cmd) {
|
||||
bool hexMode = false;
|
||||
bool print_hex = false;
|
||||
bool errors = false;
|
||||
bool lstrip = false;
|
||||
bool invert = false;
|
||||
|
@ -422,7 +467,7 @@ int CmdPrintDemodBuff(const char *Cmd) {
|
|||
case 'h':
|
||||
return usage_data_printdemodbuf();
|
||||
case 'x':
|
||||
hexMode = true;
|
||||
print_hex = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'o':
|
||||
|
@ -452,45 +497,7 @@ int CmdPrintDemodBuff(const char *Cmd) {
|
|||
//Validations
|
||||
if (errors) return usage_data_printdemodbuf();
|
||||
|
||||
if (DemodBufferLen == 0) {
|
||||
PrintAndLogEx(WARNING, "Demodbuffer is empty");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (lstrip) {
|
||||
char *buf = (char *)(DemodBuffer + offset);
|
||||
length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length;
|
||||
uint32_t i;
|
||||
for (i = 0; i < length; i++) {
|
||||
if (buf[i] == 1) break;
|
||||
}
|
||||
offset += i;
|
||||
}
|
||||
length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length;
|
||||
|
||||
if (invert) {
|
||||
char *buf = (char *)(DemodBuffer + offset);
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
if (buf[i] == 1)
|
||||
buf[i] = 0;
|
||||
else {
|
||||
if (buf[i] == 0)
|
||||
buf[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hexMode) {
|
||||
char *buf = (char *)(DemodBuffer + offset);
|
||||
char hex[512] = {0x00};
|
||||
int numBits = binarraytohex(hex, sizeof(hex), buf, length);
|
||||
if (numBits == 0) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "DemodBuffer: %s", hex);
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, length, 32));
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
return printDemodBuff(offset, lstrip, invert, print_hex);
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
|
@ -596,7 +603,7 @@ int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, b
|
|||
else
|
||||
PrintAndLogEx(DEBUG, "ASK/Raw - Clock: %d - Decoded bitstream:", clk);
|
||||
|
||||
printDemodBuff();
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
uint64_t lo = 0;
|
||||
uint32_t hi = 0;
|
||||
|
@ -792,7 +799,7 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
|||
setClockGrid(clk, startIdx + clk * offset / 2);
|
||||
if (g_debugMode || verbose) {
|
||||
PrintAndLogEx(DEBUG, "Biphase Decoded using offset %d | clock %d | #errors %d | start index %d\ndata\n", offset, clk, errCnt, (startIdx + clk * offset / 2));
|
||||
printDemodBuff();
|
||||
printDemodBuff(offset, false, false, false);
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -1204,7 +1211,7 @@ int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bo
|
|||
if (verbose || g_debugMode) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) Using Clock:%u, invert:%u, fchigh:%u, fclow:%u", rfLen, invert, fchigh, fclow);
|
||||
PrintAndLogEx(NORMAL, "%s decoded bitstream:", GetFSKType(fchigh, fclow, invert));
|
||||
printDemodBuff();
|
||||
printDemodBuff(0, false, invert, false);
|
||||
}
|
||||
goto out;
|
||||
} else {
|
||||
|
@ -1327,7 +1334,7 @@ int NRZrawDemod(int clk, int invert, int maxErr, bool verbose) {
|
|||
if (verbose || g_debugMode) {
|
||||
PrintAndLogEx(NORMAL, "NRZ demoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
printDemodBuff();
|
||||
printDemodBuff(0, false, invert, false);
|
||||
}
|
||||
|
||||
free(bits);
|
||||
|
@ -1352,14 +1359,14 @@ static int CmdNRZrawDemod(const char *Cmd) {
|
|||
}
|
||||
|
||||
// by marshmellow
|
||||
// takes 3 arguments - clock, invert, maxErr as integers
|
||||
// takes 3 arguments - clock, invert, max_err as integers
|
||||
// attempts to demodulate psk only
|
||||
// prints binary found and saves in demodbuffer for further commands
|
||||
int CmdPSK1rawDemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1();
|
||||
int clk = 0, invert = 0, maxErr = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
int clk = 0, invert = 0, max_err = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &max_err);
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
|
@ -1368,7 +1375,7 @@ int CmdPSK1rawDemod(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
int ans = PSKDemod(clk, invert, maxErr, true);
|
||||
int ans = PSKDemod(clk, invert, max_err, true);
|
||||
//output
|
||||
if (ans != PM3_SUCCESS) {
|
||||
if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans);
|
||||
|
@ -1376,7 +1383,7 @@ int CmdPSK1rawDemod(const char *Cmd) {
|
|||
}
|
||||
PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
printDemodBuff();
|
||||
printDemodBuff(0, false, invert, false);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1385,8 +1392,8 @@ int CmdPSK1rawDemod(const char *Cmd) {
|
|||
static int CmdPSK2rawDemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2();
|
||||
int clk = 0, invert = 0, maxErr = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
int clk = 0, invert = 0, max_err = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &max_err);
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
|
@ -1395,7 +1402,7 @@ static int CmdPSK2rawDemod(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
int ans = PSKDemod(clk, invert, maxErr, true);
|
||||
int ans = PSKDemod(clk, invert, max_err, true);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans);
|
||||
return PM3_ESOFT;
|
||||
|
@ -1403,7 +1410,7 @@ static int CmdPSK2rawDemod(const char *Cmd) {
|
|||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
printDemodBuff();
|
||||
printDemodBuff(0, false, invert, false);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@ int PSKDemod(int clk, int invert, int maxErr, bool verbose);
|
|||
int NRZrawDemod(int clk, int invert, int maxErr, bool verbose); // used by cmd lf pac, lf t55xx
|
||||
|
||||
|
||||
void printDemodBuff(void);
|
||||
int printDemodBuff(uint8_t offset, bool strip_leading, bool invert, bool print_hex);
|
||||
|
||||
void setDemodBuff(uint8_t *buff, size_t size, size_t start_idx);
|
||||
bool getDemodBuff(uint8_t *buff, size_t *size);
|
||||
void save_restoreDB(uint8_t saveOpt);// option '1' to save DemodBuffer any other to restore
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "aidsearch.h"
|
||||
#include "cmdhf.h" // handle HF plot
|
||||
#include "protocols.h" // MAGIC_GEN_1A
|
||||
#include "emv/dump.h" // dump_buffer
|
||||
|
||||
bool APDUInFramingEnable = true;
|
||||
|
||||
|
@ -210,8 +211,7 @@ static int usage_hf_14a_config(void) {
|
|||
}
|
||||
|
||||
static int usage_hf_14a_sim(void) {
|
||||
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
|
||||
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n");
|
||||
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t <type> u <uid> [x] [e] [v]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h : This help");
|
||||
|
@ -225,8 +225,7 @@ static int usage_hf_14a_sim(void) {
|
|||
PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k");
|
||||
PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro");
|
||||
PrintAndLogEx(NORMAL, " 10 = JCOP 31/41 Rothult");
|
||||
// PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID");
|
||||
PrintAndLogEx(NORMAL, " u : 4, 7 byte UID");
|
||||
PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID");
|
||||
PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader");
|
||||
PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys");
|
||||
PrintAndLogEx(NORMAL, " v : (Optional) Verbose");
|
||||
|
@ -234,7 +233,7 @@ static int usage_hf_14a_sim(void) {
|
|||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344 x"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344556677"));
|
||||
// PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 112233445566778899AA"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14a_sniff(void) {
|
||||
|
@ -552,8 +551,8 @@ static int CmdHF14AReader(const char *Cmd) {
|
|||
res = PM3_ESOFT;
|
||||
goto plot;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
if (!(silent && continuous)) {
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]);
|
||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||
|
||||
|
@ -689,7 +688,9 @@ int CmdHF14ASim(const char *Cmd) {
|
|||
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
|
||||
uidlen >>= 1;
|
||||
switch (uidlen) {
|
||||
//case 10: flags |= FLAG_10B_UID_IN_DATA; break;
|
||||
case 10:
|
||||
flags |= FLAG_10B_UID_IN_DATA;
|
||||
break;
|
||||
case 7:
|
||||
flags |= FLAG_7B_UID_IN_DATA;
|
||||
break;
|
||||
|
@ -1442,7 +1443,7 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
|
|||
|
||||
CLIParserFree(ctx);
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ, (uint8_t*)¶m, sizeof(param));
|
||||
SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ, (uint8_t *)¶m, sizeof(param));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1838,34 +1839,38 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
}
|
||||
|
||||
if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
|
||||
|
||||
PrintAndLogEx(INFO, "-------------------------- " _CYAN_("ATS") " --------------------------");
|
||||
bool ta1 = 0, tb1 = 0, tc1 = 0;
|
||||
int pos;
|
||||
|
||||
if (select_status == 2) {
|
||||
PrintAndLogEx(INFO, "SAK incorrectly claims that card doesn't support RATS");
|
||||
PrintAndLogEx(INFO, "--> SAK incorrectly claims that card doesn't support RATS <--");
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, " ATS: %s", sprint_hex(card.ats, card.ats_len));
|
||||
PrintAndLogEx(SUCCESS, " - TL : length is %d bytes", card.ats[0]);
|
||||
|
||||
if (card.ats[0] != card.ats_len - 2) {
|
||||
PrintAndLogEx(SUCCESS, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len);
|
||||
PrintAndLogEx(WARNING, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len);
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "ATS: " _YELLOW_("%s")"[ %02x %02x ]", sprint_hex(card.ats, card.ats_len - 2), card.ats[card.ats_len - 1], card.ats[card.ats_len]);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02x") "............... TL length is " _GREEN_("%d") " bytes", card.ats[0], card.ats[0]);
|
||||
|
||||
if (card.ats[0] > 1) { // there is a format byte (T0)
|
||||
ta1 = (card.ats[1] & 0x10) == 0x10;
|
||||
tb1 = (card.ats[1] & 0x20) == 0x20;
|
||||
tc1 = (card.ats[1] & 0x40) == 0x40;
|
||||
int16_t fsci = card.ats[1] & 0x0f;
|
||||
|
||||
PrintAndLogEx(SUCCESS, " - T0 : TA1 is%s present, TB1 is%s present, "
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
|
||||
"TC1 is%s present, FSCI is %d (FSC = %d)",
|
||||
(ta1 ? "" : " NOT"),
|
||||
(tb1 ? "" : " NOT"),
|
||||
(tc1 ? "" : " NOT"),
|
||||
card.ats[1],
|
||||
(ta1 ? "" : _RED_(" NOT")),
|
||||
(tb1 ? "" : _RED_(" NOT")),
|
||||
(tc1 ? "" : _RED_(" NOT")),
|
||||
fsci,
|
||||
fsci < ARRAYLEN(atsFSC) ? atsFSC[fsci] : -1
|
||||
);
|
||||
}
|
||||
pos = 2;
|
||||
int pos = 2;
|
||||
if (ta1) {
|
||||
char dr[16], ds[16];
|
||||
dr[0] = ds[0] = '\0';
|
||||
|
@ -1877,19 +1882,23 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
if (card.ats[pos] & 0x04) strcat(dr, "8, ");
|
||||
if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
|
||||
if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
|
||||
PrintAndLogEx(SUCCESS, " - TA1 : different divisors are%s supported, "
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
|
||||
"DR: [%s], DS: [%s]",
|
||||
((card.ats[pos] & 0x80) ? " NOT" : ""),
|
||||
card.ats[pos],
|
||||
((card.ats[pos] & 0x80) ? _RED_(" NOT") : ""),
|
||||
dr,
|
||||
ds
|
||||
);
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (tb1) {
|
||||
uint32_t sfgi = card.ats[pos] & 0x0F;
|
||||
uint32_t fwi = card.ats[pos] >> 4;
|
||||
PrintAndLogEx(SUCCESS, " - TB1 : SFGI = %d (SFGT = %s%d/fc), FWI = %d (FWT = %d/fc)",
|
||||
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
|
||||
card.ats[pos],
|
||||
(sfgi),
|
||||
sfgi ? "" : "(not needed) ",
|
||||
sfgi ? (1 << 12) << sfgi : 0,
|
||||
|
@ -1900,31 +1909,39 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
}
|
||||
|
||||
if (tc1) {
|
||||
PrintAndLogEx(SUCCESS, " - TC1 : NAD is%s supported, CID is%s supported",
|
||||
(card.ats[pos] & 0x01) ? "" : " NOT",
|
||||
(card.ats[pos] & 0x02) ? "" : " NOT");
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
|
||||
card.ats[pos],
|
||||
(card.ats[pos] & 0x01) ? "" : _RED_(" NOT"),
|
||||
(card.ats[pos] & 0x02) ? "" : _RED_(" NOT")
|
||||
);
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2) {
|
||||
const char *tip = "";
|
||||
// ATS - Historial bytes and identify based on it
|
||||
if (card.ats[0] > pos && card.ats[0] <= card.ats_len - 2) {
|
||||
char tip[60];
|
||||
tip[0] = '\0';
|
||||
if (card.ats[0] - pos >= 7) {
|
||||
|
||||
snprintf(tip, sizeof(tip), " ");
|
||||
|
||||
if ((card.sak & 0x70) == 0x40) { // and no GetVersion()..
|
||||
|
||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||
tip = "-> MIFARE Plus X 2K/4K (SL3)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
|
||||
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||
|
||||
if ((card.atqa[0] & 0x02) == 0x02)
|
||||
tip = "-> MIFARE Plus S 2K (SL3)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
|
||||
else if ((card.atqa[0] & 0x04) == 0x04)
|
||||
tip = "-> MIFARE Plus S 4K (SL3)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
|
||||
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (17pF)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
|
||||
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (70pF)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
|
||||
}
|
||||
|
||||
} else { //SAK B4,5,6
|
||||
|
@ -1933,37 +1950,41 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
|
||||
|
||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||
tip = "-> MIFARE Plus X 2K (SL1)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||
tip = "-> MIFARE Plus S 2K (SL1)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (17pF)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
||||
tip = "-> MIFARE Plus SE 1K (70pF)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
|
||||
}
|
||||
} else {
|
||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||
tip = "-> MIFARE Plus X 4K (SL1)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
|
||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||
tip = "-> MIFARE Plus S 4K (SL1)";
|
||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip);
|
||||
|
||||
uint8_t calen = card.ats[0] - pos;
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " --------------------");
|
||||
|
||||
if (card.ats[pos] == 0xC1) {
|
||||
PrintAndLogEx(SUCCESS, " c1 -> Mifare or (multiple) virtual cards of various type");
|
||||
PrintAndLogEx(SUCCESS, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]);
|
||||
PrintAndLogEx(INFO, " %s%s", sprint_hex(card.ats + pos, calen), tip);
|
||||
PrintAndLogEx(SUCCESS, " C1..................... Mifare or (multiple) virtual cards of various type");
|
||||
PrintAndLogEx(SUCCESS, " %02x.................. length is " _YELLOW_("%d") " bytes", card.ats[pos + 1], card.ats[pos + 1]);
|
||||
switch (card.ats[pos + 2] & 0xf0) {
|
||||
case 0x10:
|
||||
PrintAndLogEx(SUCCESS, " 1x -> MIFARE DESFire");
|
||||
PrintAndLogEx(SUCCESS, " 1x............... MIFARE DESFire");
|
||||
isMifareDESFire = true;
|
||||
isMifareClassic = false;
|
||||
isMifarePlus = false;
|
||||
break;
|
||||
case 0x20:
|
||||
PrintAndLogEx(SUCCESS, " 2x -> MIFARE Plus");
|
||||
PrintAndLogEx(SUCCESS, " 2x............... MIFARE Plus");
|
||||
isMifarePlus = true;
|
||||
isMifareDESFire = false;
|
||||
isMifareClassic = false;
|
||||
|
@ -1971,51 +1992,53 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
}
|
||||
switch (card.ats[pos + 2] & 0x0f) {
|
||||
case 0x00:
|
||||
PrintAndLogEx(SUCCESS, " x0 -> <1 kByte");
|
||||
PrintAndLogEx(SUCCESS, " x0............... < 1 kByte");
|
||||
break;
|
||||
case 0x01:
|
||||
PrintAndLogEx(SUCCESS, " x1 -> 1 kByte");
|
||||
PrintAndLogEx(SUCCESS, " x1............... 1 kByte");
|
||||
break;
|
||||
case 0x02:
|
||||
PrintAndLogEx(SUCCESS, " x2 -> 2 kByte");
|
||||
PrintAndLogEx(SUCCESS, " x2............... 2 kByte");
|
||||
break;
|
||||
case 0x03:
|
||||
PrintAndLogEx(SUCCESS, " x3 -> 4 kByte");
|
||||
PrintAndLogEx(SUCCESS, " x3............... 4 kByte");
|
||||
break;
|
||||
case 0x04:
|
||||
PrintAndLogEx(SUCCESS, " x4 -> 8 kByte");
|
||||
PrintAndLogEx(SUCCESS, " x4............... 8 kByte");
|
||||
break;
|
||||
}
|
||||
switch (card.ats[pos + 3] & 0xf0) {
|
||||
case 0x00:
|
||||
PrintAndLogEx(SUCCESS, " 0x -> Engineering sample");
|
||||
PrintAndLogEx(SUCCESS, " 0x............ Engineering sample");
|
||||
break;
|
||||
case 0x20:
|
||||
PrintAndLogEx(SUCCESS, " 2x -> Released");
|
||||
PrintAndLogEx(SUCCESS, " 2x............ Released");
|
||||
break;
|
||||
}
|
||||
switch (card.ats[pos + 3] & 0x0f) {
|
||||
case 0x00:
|
||||
PrintAndLogEx(SUCCESS, " x0 -> Generation 1");
|
||||
PrintAndLogEx(SUCCESS, " x0............ Generation 1");
|
||||
break;
|
||||
case 0x01:
|
||||
PrintAndLogEx(SUCCESS, " x1 -> Generation 2");
|
||||
PrintAndLogEx(SUCCESS, " x1............ Generation 2");
|
||||
break;
|
||||
case 0x02:
|
||||
PrintAndLogEx(SUCCESS, " x2 -> Generation 3");
|
||||
PrintAndLogEx(SUCCESS, " x2............ Generation 3");
|
||||
break;
|
||||
}
|
||||
switch (card.ats[pos + 4] & 0x0f) {
|
||||
case 0x00:
|
||||
PrintAndLogEx(SUCCESS, " x0 -> Only VCSL supported");
|
||||
PrintAndLogEx(SUCCESS, " x0......... Only VCSL supported");
|
||||
break;
|
||||
case 0x01:
|
||||
PrintAndLogEx(SUCCESS, " x1 -> VCS, VCSL, and SVC supported");
|
||||
PrintAndLogEx(SUCCESS, " x1......... VCS, VCSL, and SVC supported");
|
||||
break;
|
||||
case 0x0E:
|
||||
PrintAndLogEx(SUCCESS, " xE -> no VCS command supported");
|
||||
PrintAndLogEx(SUCCESS, " xE......... no VCS command supported");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
dump_buffer(&card.ats[pos], calen, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2087,7 +2110,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
} else {
|
||||
PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported");
|
||||
if ((card.sak & 0x20) == 0x20) {
|
||||
PrintAndLogEx(INFO, "SAK incorrectly claims that card supports RATS");
|
||||
PrintAndLogEx(INFO, "--> SAK incorrectly claims that card supports RATS <--");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2134,6 +2157,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
if (isST)
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf st info`"));
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
DropField();
|
||||
return select_status;
|
||||
}
|
||||
|
|
|
@ -977,24 +977,24 @@ static int CmdHF14BSriRdBl(const char *Cmd) {
|
|||
int blockno = arg_get_int_def(ctx, 1, -1);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
/*
|
||||
iso14b_card_select_t card;
|
||||
if (get_14b_UID(&card) == false) {
|
||||
PrintAndLogEx(WARNING, "no tag found");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
/*
|
||||
iso14b_card_select_t card;
|
||||
if (get_14b_UID(&card) == false) {
|
||||
PrintAndLogEx(WARNING, "no tag found");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (card.uidlen != 8) {
|
||||
PrintAndLogEx(FAILED, "current read command only work with SRI4K / SRI512 tags");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
if (card.uidlen != 8) {
|
||||
PrintAndLogEx(FAILED, "current read command only work with SRI4K / SRI512 tags");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// detect cardsize
|
||||
// 1 = 4096
|
||||
// 2 = 512
|
||||
uint8_t cardtype = get_st_cardsize(card.uid);
|
||||
uint8_t blocks = (cardtype == 1) ? 0x7F : 0x0F;
|
||||
*/
|
||||
// detect cardsize
|
||||
// 1 = 4096
|
||||
// 2 = 512
|
||||
uint8_t cardtype = get_st_cardsize(card.uid);
|
||||
uint8_t blocks = (cardtype == 1) ? 0x7F : 0x0F;
|
||||
*/
|
||||
struct {
|
||||
uint8_t blockno;
|
||||
} PACKED payload;
|
||||
|
@ -1003,7 +1003,7 @@ static int CmdHF14BSriRdBl(const char *Cmd) {
|
|||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_SRI_READ, (uint8_t*)&payload, sizeof(payload));
|
||||
SendCommandNG(CMD_HF_SRI_READ, (uint8_t *)&payload, sizeof(payload));
|
||||
if (WaitForResponseTimeout(CMD_HF_SRI_READ, &resp, TIMEOUT) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
|
|
@ -66,22 +66,12 @@ static int usage_hf_iclass_sim(void) {
|
|||
PrintAndLogEx(NORMAL, " -- execute loclass attack online part");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass sim 2"));
|
||||
PrintAndLogEx(NORMAL, " -- simulate full iCLASS 2k tag");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass eload f hf-iclass-AA162D30F8FF12F1-dump.bin"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass sim 3"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_iclass_eload(void) {
|
||||
PrintAndLogEx(NORMAL, "Loads iCLASS tag dump into emulator memory on device\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf iclass eload [h] f <filename>\n");
|
||||
PrintAndLogEx(NORMAL, "Options");
|
||||
PrintAndLogEx(NORMAL, " h : Show this help");
|
||||
PrintAndLogEx(NORMAL, " f <filename> : filename of dump");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass eload f hf-iclass-AA162D30F8FF12F1-dump.bin"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_hf_iclass_esave(void) {
|
||||
PrintAndLogEx(NORMAL, "Save emulator memory to file.");
|
||||
PrintAndLogEx(NORMAL, "if not filename is supplied, CSN will be used.");
|
||||
|
@ -272,27 +262,6 @@ static int usage_hf_iclass_managekeys(void) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_iclass_loclass(void) {
|
||||
PrintAndLogEx(NORMAL, "Execute the offline part of loclass attack");
|
||||
PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of");
|
||||
PrintAndLogEx(NORMAL, " malicious CSNs, and their protocol responses");
|
||||
PrintAndLogEx(NORMAL, " The binary format of the file is expected to be as follows: ");
|
||||
PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
|
||||
PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
|
||||
PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
|
||||
PrintAndLogEx(NORMAL, " ... totalling N*24 bytes\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf iclass loclass [h] [t [l]] [f <filename>]\n");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h Show this help");
|
||||
PrintAndLogEx(NORMAL, " t Perform self-test");
|
||||
PrintAndLogEx(NORMAL, " t l Perform self-test, including long ones");
|
||||
PrintAndLogEx(NORMAL, " f <filename> Bruteforce iclass dumpfile");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass loclass f iclass-dump.bin"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass loclass t"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_iclass_chk(void) {
|
||||
PrintAndLogEx(NORMAL, "Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf iclass chk [h|e|r] [f (*.dic)]\n");
|
||||
|
@ -730,7 +699,7 @@ static int CmdHFiClassSim(const char *Cmd) {
|
|||
saveFile("iclass_mac_attack", ".bin", dump, datalen);
|
||||
free(dump);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass h") "` to recover elite key");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -h") "` to recover elite key");
|
||||
break;
|
||||
}
|
||||
case ICLASS_SIM_MODE_READER_ATTACK_KEYROLL: {
|
||||
|
@ -796,7 +765,7 @@ static int CmdHFiClassSim(const char *Cmd) {
|
|||
saveFile("iclass_mac_attack_keyroll_B", ".bin", dump, datalen);
|
||||
free(dump);
|
||||
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass h") "` to recover elite key");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -h") "` to recover elite key");
|
||||
break;
|
||||
}
|
||||
case ICLASS_SIM_MODE_CSN:
|
||||
|
@ -884,50 +853,54 @@ static int CmdHFiClassReader(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHFiClassELoad(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf iclass eload",
|
||||
"Loads iCLASS tag dump into emulator memory on device",
|
||||
"hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<filename>", "filename of dump"),
|
||||
arg_lit0(NULL, "json", "load JSON type dump"),
|
||||
arg_lit0(NULL, "eml", "load EML type dump"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
|
||||
if (strlen(filename) == 0) {
|
||||
PrintAndLogEx(ERR, "Error: Please specify a filename");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
DumpFileType_t dftype = BIN;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_hf_iclass_eload();
|
||||
case 'f':
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'j':
|
||||
dftype = JSON;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'e':
|
||||
dftype = EML;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
bool use_json = arg_get_lit(ctx, 2);
|
||||
bool use_eml = arg_get_lit(ctx, 3);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (use_json && use_eml) {
|
||||
PrintAndLogEx(ERR, "Error: can't specify both JSON & EML");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
return usage_hf_iclass_eload();
|
||||
if (use_json) {
|
||||
dftype = JSON;
|
||||
} else if (use_eml) {
|
||||
dftype = EML;
|
||||
}
|
||||
|
||||
size_t bytes_read = 2048;
|
||||
uint8_t *dump = calloc(2048, sizeof(uint8_t));
|
||||
if (!dump) {
|
||||
PrintAndLogEx(ERR, "error, cannot allocate memory ");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
size_t bytes_read = 2048;
|
||||
int res = 0;
|
||||
|
||||
switch (dftype) {
|
||||
|
@ -943,10 +916,10 @@ static int CmdHFiClassELoad(const char *Cmd) {
|
|||
res = loadFileJSON(filename, dump, 2048, &bytes_read, NULL);
|
||||
break;
|
||||
}
|
||||
case DICTIONARY:
|
||||
PrintAndLogEx(ERR, "No dictionary loaded");
|
||||
free(dump);
|
||||
return PM3_ESOFT;
|
||||
case DICTIONARY: {
|
||||
PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != PM3_SUCCESS) {
|
||||
|
@ -1787,7 +1760,7 @@ write_dump:
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose) {
|
||||
static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose, bool use_secure_pagemode) {
|
||||
|
||||
iclass_writeblock_req_t payload = {
|
||||
.req.use_raw = rawkey,
|
||||
|
@ -1796,7 +1769,7 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bo
|
|||
.req.use_replay = replay,
|
||||
.req.blockno = blockno,
|
||||
.req.send_reply = true,
|
||||
.req.do_auth = true,
|
||||
.req.do_auth = use_secure_pagemode,
|
||||
};
|
||||
memcpy(payload.req.key, KEY, 8);
|
||||
memcpy(payload.data, bldata, sizeof(payload.data));
|
||||
|
@ -1831,6 +1804,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
|
|||
bool use_replay = false;
|
||||
bool errors = false;
|
||||
bool verbose = false;
|
||||
bool use_secure_pagemode = false;
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
@ -1875,6 +1849,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "\nERROR: Credit Key is incorrect length\n");
|
||||
errors = true;
|
||||
}
|
||||
use_secure_pagemode = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'r':
|
||||
|
@ -1907,9 +1882,9 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
|
|||
errors = true;
|
||||
}
|
||||
|
||||
if (errors || cmdp < 6) return usage_hf_iclass_writeblock();
|
||||
if (errors || cmdp < 4) return usage_hf_iclass_writeblock();
|
||||
|
||||
int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose);
|
||||
int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose, use_secure_pagemode);
|
||||
switch (isok) {
|
||||
case PM3_SUCCESS:
|
||||
PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno);
|
||||
|
@ -2325,26 +2300,42 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHFiClass_loclass(const char *Cmd) {
|
||||
char opt = tolower(param_getchar(Cmd, 0));
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf iclass loclass",
|
||||
"Execute the offline part of loclass attack\n"
|
||||
" An iclass dumpfile is assumed to consist of an arbitrary number of\n"
|
||||
" malicious CSNs, and their protocol responses\n"
|
||||
" The binary format of the file is expected to be as follows: \n"
|
||||
" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>\n"
|
||||
" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>\n"
|
||||
" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>\n"
|
||||
" ... totalling N*24 bytes",
|
||||
"hf iclass loclass -f iclass-dump.bin\n"
|
||||
"hf iclass loclass --test");
|
||||
|
||||
if (strlen(Cmd) < 1 || opt == 'h')
|
||||
return usage_hf_iclass_loclass();
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<filename>", "filename of Bruteforce iclass dumpfile"),
|
||||
arg_lit0(NULL, "test", "Perform self-test"),
|
||||
arg_lit0(NULL, "long", "Perform self-test, including long ones"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
if (opt == 'f') {
|
||||
char fileName[FILE_PATH_SIZE] = {0};
|
||||
if (param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0) {
|
||||
return bruteforceFileNoKeys(fileName);
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "You must specify a filename");
|
||||
return PM3_EFILE;
|
||||
}
|
||||
} else if (opt == 't') {
|
||||
char opt2 = tolower(param_getchar(Cmd, 1));
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
|
||||
bool test = arg_get_lit(ctx, 2);
|
||||
bool longtest = arg_get_lit(ctx, 3);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (test || longtest) {
|
||||
int errors = testCipherUtils();
|
||||
errors += testMAC();
|
||||
errors += doKeyTests();
|
||||
errors += testElite(opt2 == 'l');
|
||||
errors += testElite(longtest);
|
||||
|
||||
if (errors != PM3_SUCCESS)
|
||||
PrintAndLogEx(ERR, "There were errors!!!");
|
||||
|
@ -2352,7 +2343,7 @@ static int CmdHFiClass_loclass(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
return usage_hf_iclass_loclass();
|
||||
return bruteforceFileNoKeys(filename);
|
||||
}
|
||||
|
||||
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
|
||||
|
@ -3576,10 +3567,11 @@ int info_iclass(void) {
|
|||
PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------");
|
||||
|
||||
uint8_t aia[8];
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE)
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
memcpy(aia, ns_hdr->app_issuer_area, sizeof(aia));
|
||||
else
|
||||
} else {
|
||||
memcpy(aia, hdr->app_issuer_area, sizeof(aia));
|
||||
}
|
||||
|
||||
// if CSN ends with FF12E0, it's inside HID CSN range.
|
||||
bool isHidRange = (memcmp(hdr->csn + 5, "\xFF\x12\xE0", 3) == 0);
|
||||
|
@ -3594,11 +3586,13 @@ int info_iclass(void) {
|
|||
if (se_enabled)
|
||||
PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS SE"));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " CSN..-....... " _YELLOW_("outside HID range"));
|
||||
PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("outside HID range"));
|
||||
}
|
||||
|
||||
uint8_t cardtype = get_mem_config(hdr);
|
||||
PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
|
|
@ -194,14 +194,16 @@ static int CmdHfLTOInfo(const char *Cmd) {
|
|||
return infoLTO(true);
|
||||
}
|
||||
|
||||
static const char* lto_print_size(uint8_t ti) {
|
||||
switch(ti) {
|
||||
static const char *lto_print_size(uint8_t ti) {
|
||||
switch (ti) {
|
||||
case 1:
|
||||
return "101 blocks / 3232 bytes";
|
||||
case 2:
|
||||
return "95 blocks / 3040 bytes";
|
||||
case 3:
|
||||
return "255 blocks / 8160 bytes";
|
||||
default :
|
||||
return "";
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,6 +224,9 @@ int infoLTO(bool verbose) {
|
|||
PrintAndLogEx(SUCCESS, "UID......... " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number)));
|
||||
PrintAndLogEx(SUCCESS, "Type info... " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info)));
|
||||
PrintAndLogEx(SUCCESS, "Memory...... " _YELLOW_("%s"), lto_print_size(type_info[1]));
|
||||
if (type_info[1] > 3) {
|
||||
PrintAndLogEx(INFO, "Unknown LTO tag, report to @iceman!");
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
@ -464,10 +469,13 @@ int dumpLTO(uint8_t *dump, bool verbose) {
|
|||
return ret_val;
|
||||
}
|
||||
// 0003 == 255 blocks x 32 = 8160 bytes
|
||||
// 0002 == 95 blocks x 32 = 3040 bytes
|
||||
// 0001 == 101 blocks x 32 = 3232 bytes
|
||||
uint8_t blocks = 0xFF;
|
||||
if (type_info[1] == 0x01) {
|
||||
blocks = 0x65;
|
||||
} else if (type_info[1] == 0x02) {
|
||||
blocks = 0x5F;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Found LTO tag w " _YELLOW_("%s") " memory", lto_print_size(type_info[1]));
|
||||
|
||||
|
|
|
@ -5397,10 +5397,10 @@ static int CmdHf14AMfSuperCard(const char *Cmd) {
|
|||
|
||||
if (res) {
|
||||
PrintAndLogEx(SUCCESS, "UID: %s Sector %02x key %c [ " _GREEN_("%12" PRIX64) " ]"
|
||||
, sprint_hex_inrow(outA, 4)
|
||||
, data.sector
|
||||
, (data.keytype == 0x60) ? 'A' : 'B'
|
||||
, key64);
|
||||
, sprint_hex_inrow(outA, 4)
|
||||
, data.sector
|
||||
, (data.keytype == 0x60) ? 'A' : 'B'
|
||||
, key64);
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "failed to recover any key");
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "mifare/ndef.h" // NDEF
|
||||
#include "mifare/mad.h"
|
||||
#include "generator.h"
|
||||
#include "aiddesfire.h"
|
||||
|
||||
#define MAX_KEY_LEN 24
|
||||
#define MAX_KEYS_LIST_LEN 1024
|
||||
|
@ -59,7 +60,7 @@ uint8_t k3kdefaultkeys[1][24] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|||
struct desfire_tag mf_state = {.session_key = NULL, .authentication_scheme = AS_LEGACY, .authenticated_key_no = NOT_YET_AUTHENTICATED, .crypto_buffer = NULL, .crypto_buffer_size = 0, .selected_application = 0};
|
||||
static desfiretag_t tag = &mf_state;
|
||||
|
||||
typedef struct {
|
||||
typedef struct mfdes_authinput {
|
||||
uint8_t mode;
|
||||
uint8_t algo;
|
||||
uint8_t keyno;
|
||||
|
@ -93,7 +94,6 @@ typedef struct {
|
|||
uint8_t details[14];
|
||||
} PACKED mfdes_info_res_t;
|
||||
|
||||
|
||||
typedef struct mfdes_value {
|
||||
uint8_t fileno; //01
|
||||
uint8_t value[16];
|
||||
|
@ -339,14 +339,36 @@ typedef enum {
|
|||
NTAG413DNA,
|
||||
} nxp_cardtype_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct dfname {
|
||||
uint8_t aid[3];
|
||||
uint8_t fid[2];
|
||||
uint8_t name[16];
|
||||
} dfname_t;
|
||||
} PACKED dfname_t;
|
||||
|
||||
typedef struct aidhdr {
|
||||
uint8_t aid[3];
|
||||
uint8_t keysetting1;
|
||||
uint8_t keysetting2;
|
||||
uint8_t fid[2];
|
||||
uint8_t name[16];
|
||||
} PACKED aidhdr_t;
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static const char *getEncryptionAlgoStr(uint8_t algo) {
|
||||
switch (algo) {
|
||||
case MFDES_ALGO_AES :
|
||||
return "AES";
|
||||
case MFDES_ALGO_3DES :
|
||||
return "3DES";
|
||||
case MFDES_ALGO_DES :
|
||||
return "DES";
|
||||
case MFDES_ALGO_3K3DES :
|
||||
return "3K3DES";
|
||||
default :
|
||||
return "";
|
||||
}
|
||||
}
|
||||
/*
|
||||
The 7 MSBits (= n) code the storage size itself based on 2^n,
|
||||
the LSBit is set to '0' if the size is exactly 2^n
|
||||
|
@ -1113,6 +1135,12 @@ static int handler_desfire_freemem(uint32_t *free_mem) {
|
|||
}
|
||||
|
||||
static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t new_algo, uint8_t *old_key, uint8_t old_algo, uint8_t aes_version) {
|
||||
|
||||
if (new_key == NULL || old_key == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// AID == 000000 6bits LSB needs to be 0
|
||||
key_no &= 0x0F;
|
||||
|
||||
/*
|
||||
|
@ -1120,24 +1148,34 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n
|
|||
* changing the card master key to one of them require a key_no tweak.
|
||||
*/
|
||||
if (0x000000 == tag->selected_application) {
|
||||
|
||||
// PICC master key, 6bits LSB needs to be 0
|
||||
key_no = 0x00;
|
||||
|
||||
// PICC master key, keyalgo specific 2bit MSB
|
||||
switch (new_algo) {
|
||||
case MFDES_ALGO_DES:
|
||||
break;
|
||||
case MFDES_ALGO_3DES:
|
||||
break; // 00xx xxx
|
||||
case MFDES_ALGO_3K3DES:
|
||||
key_no |= 0x40;
|
||||
key_no |= 0x40; // 01xx xxx
|
||||
break;
|
||||
case MFDES_ALGO_AES:
|
||||
key_no |= 0x80;
|
||||
key_no |= 0x80; // 10xx xxx
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t data[24 * 4] = {key_no};
|
||||
// Variable length ciphered key data 26-42 bytes plus padding..
|
||||
uint8_t data[64] = {key_no};
|
||||
sAPDU apdu = {0x90, MFDES_CHANGE_KEY, 0x00, 0x00, 0x01, data}; // 0xC4
|
||||
|
||||
uint8_t new_key_length = 16;
|
||||
switch (new_algo) {
|
||||
case MFDES_ALGO_DES:
|
||||
new_key_length = 8;
|
||||
break;
|
||||
case MFDES_ALGO_3DES:
|
||||
case MFDES_ALGO_AES:
|
||||
new_key_length = 16;
|
||||
break;
|
||||
|
@ -1222,7 +1260,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n
|
|||
tag->session_key = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// --- GET SIGNATURE
|
||||
|
@ -1247,7 +1285,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signat
|
|||
{"DESFire EV3", "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"},
|
||||
{"NTAG424DNA, NTAG424DNATT, DESFire Light EV2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3B"},
|
||||
{"DESFire Light", "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"},
|
||||
{"Mifare Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"}
|
||||
{"MIFARE Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"}
|
||||
};
|
||||
|
||||
|
||||
|
@ -1513,9 +1551,14 @@ static int handler_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) {
|
|||
|
||||
static int handler_desfire_select_application(uint8_t *aid) {
|
||||
if (g_debugMode > 1) {
|
||||
if (aid == NULL) PrintAndLogEx(ERR, "AID=NULL");
|
||||
if (aid == NULL) {
|
||||
PrintAndLogEx(ERR, "AID=NULL");
|
||||
}
|
||||
}
|
||||
if (aid == NULL) return PM3_EINVARG;
|
||||
if (aid == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a
|
||||
uint32_t recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
|
@ -1589,48 +1632,49 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t
|
|||
return res;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint8_t aid[3];
|
||||
uint8_t keysetting1;
|
||||
uint8_t keysetting2;
|
||||
uint8_t fid[2];
|
||||
uint8_t name[16];
|
||||
} aidhdr_t;
|
||||
|
||||
static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) {
|
||||
if (aidhdr == NULL) return PM3_EINVARG;
|
||||
|
||||
sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA
|
||||
|
||||
if (!usename) {
|
||||
apdu.Lc = apdu.Lc - 16;
|
||||
if (usename == false) {
|
||||
apdu.Lc = apdu.Lc - sizeof(aidhdr->name);
|
||||
}
|
||||
if (!usefid) {
|
||||
apdu.Lc = apdu.Lc - 2;
|
||||
if (usefid == false) {
|
||||
apdu.Lc = apdu.Lc - sizeof(aidhdr->fid);
|
||||
}
|
||||
uint8_t *data = NULL;
|
||||
if (!usefid && usename) {
|
||||
data = (uint8_t *)malloc(apdu.Lc);
|
||||
|
||||
// skip over FID if not used.
|
||||
if (usefid == false && usename) {
|
||||
data = calloc(apdu.Lc, sizeof(uint8_t));
|
||||
apdu.data = data;
|
||||
memcpy(data, aidhdr, apdu.Lc);
|
||||
memcpy(&data[3 + 1 + 1], aidhdr->name, 16);
|
||||
|
||||
memcpy(data, aidhdr->aid, sizeof(aidhdr->aid));
|
||||
data[3] = aidhdr->keysetting1;
|
||||
data[4] = aidhdr->keysetting2;
|
||||
memcpy(data + 5, aidhdr->name, sizeof(aidhdr->name));
|
||||
|
||||
PrintAndLogEx(INFO, "new data: %s", sprint_hex_inrow(data, apdu.Lc));
|
||||
}
|
||||
|
||||
uint16_t sw = 0;
|
||||
uint32_t recvlen = 0;
|
||||
int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true);
|
||||
if (data != NULL) free(data);
|
||||
if (data != NULL) {
|
||||
free(data);
|
||||
}
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"), GetErrorString(res, &sw));
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int handler_desfire_deleteapp(const uint8_t *aid) {
|
||||
if (aid == NULL) return PM3_EINVARG;
|
||||
if (aid == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, (uint8_t *)aid}; // 0xDA
|
||||
uint16_t sw = 0;
|
||||
uint32_t recvlen = 0;
|
||||
|
@ -1638,7 +1682,6 @@ static int handler_desfire_deleteapp(const uint8_t *aid) {
|
|||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), GetErrorString(res, &sw));
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -2115,19 +2158,20 @@ static int desfire_authenticate(int cmdAuthMode, int cmdAuthAlgo, uint8_t *aid,
|
|||
PrintAndLogEx(FAILED, "KDF AN10922 algo requires an input of length 1-31 bytes.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
break;
|
||||
case MFDES_KDF_ALGO_GALLAGHER:
|
||||
// TODO: 2TDEA and 3TDEA keys use an input length of 1-15 bytes
|
||||
if (cmdAuthAlgo != MFDES_ALGO_AES) {
|
||||
PrintAndLogEx(FAILED, "Crypto algo not valid for the KDF AN10922 algo.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
// KDF input arg is ignored as it'll be generated.
|
||||
break;
|
||||
// KDF input arg is ignored as it'll be generated.
|
||||
case MFDES_KDF_ALGO_NONE:
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "KDF algo %d is not supported.", cmdKdfAlgo);
|
||||
return PM3_EINVARG;
|
||||
break;
|
||||
}
|
||||
|
||||
// KEY
|
||||
|
@ -2198,12 +2242,12 @@ static int CmdHF14ADesSelectApp(const char *Cmd) {
|
|||
}
|
||||
|
||||
int res = handler_desfire_select_application(aid);
|
||||
DropField();
|
||||
if (res != PM3_SUCCESS) {
|
||||
DropField();
|
||||
PrintAndLogEx(ERR, "Error on selecting aid.");
|
||||
return res;
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "Successfully selected aid.");
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Successfully selected aid.");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2211,7 +2255,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes createaid",
|
||||
"Create Application ID",
|
||||
"hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E -n Test"
|
||||
"hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E --name Test"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
|
@ -2220,7 +2264,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
arg_strx0("f", "fid", "<fid>", "File ID to create (optional)"),
|
||||
arg_strx0("k", "ks1", "<keysetting1>", "Key Setting 1 (Application Master Key Settings)"),
|
||||
arg_strx0("l", "ks2", "<keysetting2>", "Key Setting 2"),
|
||||
arg_str0("n", "name", "<name>", "App ISO-4 Name (optional)"),
|
||||
arg_str0(NULL, "name", "<name>", "App ISO-4 Name (optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -2318,9 +2362,20 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
aidhdr.keysetting1 = keysetting1[0];
|
||||
aidhdr.keysetting2 = keysetting2[0];
|
||||
|
||||
if (usefid) memcpy(aidhdr.fid, fid, sizeof(fid));
|
||||
if (usefid)
|
||||
memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid));
|
||||
|
||||
if (usename) memcpy(aidhdr.name, name, sizeof(name));
|
||||
if (usename)
|
||||
memcpy(aidhdr.name, name, sizeof(aidhdr.name));
|
||||
|
||||
PrintAndLogEx(INFO, "Creating AID using:");
|
||||
PrintAndLogEx(INFO, "AID %s", sprint_hex_inrow(aidhdr.aid, sizeof(aidhdr.aid)));
|
||||
PrintAndLogEx(INFO, "Key set1 0x%02X", aidhdr.keysetting1);
|
||||
PrintAndLogEx(INFO, "Key Set2 0x%02X", aidhdr.keysetting2);
|
||||
if (usefid)
|
||||
PrintAndLogEx(INFO, "FID %s", sprint_hex_inrow(aidhdr.fid, sizeof(aidhdr.fid)));
|
||||
if (usename)
|
||||
PrintAndLogEx(INFO, "DF Name %s", aidhdr.name);
|
||||
|
||||
uint8_t rootaid[3] = {0x00, 0x00, 0x00};
|
||||
int res = handler_desfire_select_application(rootaid);
|
||||
|
@ -2331,7 +2386,9 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
|
||||
res = handler_desfire_createapp(&aidhdr, usename, usefid);
|
||||
DropField();
|
||||
PrintAndLogEx(SUCCESS, "Successfully created aid.");
|
||||
if (res == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Successfully created aid.");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2366,10 +2423,15 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
|
|||
|
||||
uint8_t rootaid[3] = {0x00, 0x00, 0x00};
|
||||
int res = handler_desfire_select_application(rootaid);
|
||||
if (res != PM3_SUCCESS) { DropField(); return res;}
|
||||
if (res != PM3_SUCCESS) {
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
res = handler_desfire_deleteapp(aid);
|
||||
DropField();
|
||||
PrintAndLogEx(SUCCESS, "Successfully deleted aid.");
|
||||
if (res == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Successfully deleted aid.");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -3571,6 +3633,20 @@ static int DecodeFileSettings(uint8_t *src, int src_len, int maclen) {
|
|||
}
|
||||
|
||||
static int CmdHF14ADesDump(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes dump",
|
||||
"Tries to dump all files on a DESFire tag",
|
||||
"hf mfdes dump");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
// arg_strx0("a", "aid", "<aid>", "Use specific AID (3 hex bytes, big endian)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
DropField();
|
||||
|
||||
|
@ -3597,7 +3673,7 @@ static int CmdHF14ADesDump(const char *Cmd) {
|
|||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-- Mifare DESFire Dump ----------------------");
|
||||
PrintAndLogEx(INFO, "-- " _CYAN_("MIFARE DESFire Dump") " ----------------------");
|
||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||
|
||||
for (uint32_t i = 0; i < app_ids_len; i += 3) {
|
||||
|
@ -3612,6 +3688,8 @@ static int CmdHF14ADesDump(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid);
|
||||
PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, cluster_to_text(short_aid >> 8));
|
||||
MADDFDecodeAndPrint(short_aid);
|
||||
} else {
|
||||
AIDDFDecodeAndPrint(aid);
|
||||
}
|
||||
for (uint8_t m = 0; m < dfname_count; m++) {
|
||||
if (dfnames[m].aid[0] == aid[0] && dfnames[m].aid[1] == aid[1] && dfnames[m].aid[2] == aid[2]) {
|
||||
|
@ -3757,7 +3835,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
|
|||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-- Mifare DESFire Enumerate applications --------------------");
|
||||
PrintAndLogEx(INFO, "-- MIFARE DESFire Enumerate applications --------------------");
|
||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||
PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") " application%c", app_ids_len / 3, (app_ids_len == 3) ? ' ' : 's');
|
||||
|
||||
|
@ -3782,6 +3860,8 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid);
|
||||
PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, cluster_to_text(short_aid >> 8));
|
||||
MADDFDecodeAndPrint(short_aid);
|
||||
} else {
|
||||
AIDDFDecodeAndPrint(aid);
|
||||
}
|
||||
for (uint8_t m = 0; m < dfname_count; m++) {
|
||||
if (dfnames[m].aid[0] == aid[0] && dfnames[m].aid[1] == aid[1] && dfnames[m].aid[2] == aid[2]) {
|
||||
|
@ -3832,7 +3912,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) {
|
|||
uint8_t newkeylength = 8;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes changekey",
|
||||
"Changes Mifare DESFire Key\n"
|
||||
"Changes MIFARE DESFire Key\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 -> DES,keynumber 0"
|
||||
);
|
||||
|
@ -3903,6 +3983,10 @@ static int CmdHF14ADesChangeKey(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "changing key number 0x%02x", cmdKeyNo);
|
||||
PrintAndLogEx(INFO, "old key: %s (%s)", sprint_hex_inrow(key, keylen), getEncryptionAlgoStr(cmdAuthAlgo));
|
||||
PrintAndLogEx(INFO, "new key: %s (%s)", sprint_hex_inrow(newkey, newkeylen), getEncryptionAlgoStr(newcmdAuthAlgo));
|
||||
|
||||
int error = mifare_desfire_change_key(cmdKeyNo, newkey, newcmdAuthAlgo, key, cmdAuthAlgo, aesversion);
|
||||
if (error == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, " Successfully changed key.");
|
||||
|
@ -3929,7 +4013,7 @@ static int CmdHF14ADesAuth(const char *Cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes auth",
|
||||
"Authenticates Mifare DESFire using Key",
|
||||
"Authenticates MIFARE DESFire using Key",
|
||||
"hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> AES,keynumber 0, aid 0x803201\n"
|
||||
"hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3DES,keynumber 1, aid 0x000000\n"
|
||||
"hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> DES,keynumber 2, aid 0x000000\n"
|
||||
|
@ -4308,7 +4392,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes chk",
|
||||
"Checks keys with Mifare Desfire card.",
|
||||
"Checks keys with MIFARE DESFire card.",
|
||||
"hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n"
|
||||
"hf mfdes chk -d mfdes_default_keys -> check keys from dictionary against all existing aid on card\n"
|
||||
"hf mfdes chk -d mfdes_default_keys -a 123456 -> check keys from dictionary against aid 0x123456\n"
|
||||
|
@ -4470,7 +4554,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " k3kdes keys", k3kkeyListLen);
|
||||
}
|
||||
|
||||
if (!verbose)
|
||||
if (verbose == false)
|
||||
PrintAndLogEx(INFO, "Search keys:");
|
||||
|
||||
bool result = false;
|
||||
|
@ -4520,7 +4604,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (dict_filenamelen && endFilePosition) {
|
||||
if (dict_filenamelen) {
|
||||
if (verbose == false)
|
||||
PrintAndLogEx(NORMAL, "d" NOLF);
|
||||
|
||||
|
@ -4547,7 +4631,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
|||
|
||||
// save keys to json
|
||||
if ((jsonnamelen > 0) && result) {
|
||||
// Mifare Desfire info
|
||||
// MIFARE DESFire info
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
|
||||
|
||||
PacketResponseNG resp;
|
||||
|
@ -4604,7 +4688,6 @@ static int CmdHF14aDesNDEF(const char *Cmd) {
|
|||
arg_litn("v", "verbose", 0, 2, "show technical data"),
|
||||
arg_str0("", "aid", "<aid>", "replace default aid for NDEF"),
|
||||
arg_str0("k", "key", "<key>", "replace default key for NDEF"),
|
||||
arg_lit0("b", "keyb", "use key B for access sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -4617,20 +4700,24 @@ static int CmdHF14aDesNDEF(const char *Cmd) {
|
|||
uint8_t key[16] = {0};
|
||||
int keylen;
|
||||
CLIGetHexWithReturn(ctx, 3, key, &keylen);
|
||||
bool keyB = arg_get_lit(ctx, 4);
|
||||
|
||||
uint16_t ndefAID = 0xe103;
|
||||
if (aidlen == 2)
|
||||
ndefAID = (aid[0] << 8) + aid[1];
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint32_t ndefAID = 0xEEEE10;
|
||||
if (aidlen == 2) {
|
||||
ndefAID = (aid[0] << 16) | (aid[1] << 8) | aid[2];
|
||||
}
|
||||
|
||||
// set default NDEF key
|
||||
uint8_t ndefkey[16] = {0};
|
||||
memcpy(ndefkey, g_mifarep_ndef_key, 16);
|
||||
|
||||
// user supplied key
|
||||
if (keylen == 16) {
|
||||
memcpy(ndefkey, key, 16);
|
||||
}
|
||||
|
||||
uint8_t data[4096] = {0};
|
||||
int datalen = 0;
|
||||
int file_ids_len = 0;
|
||||
|
||||
for (int j = (int)file_ids_len - 1; j >= 0; j--) {
|
||||
PrintAndLogEx(SUCCESS, "\n\n Fileid %d (0x%02x)", file_ids[j], file_ids[j]);
|
||||
|
@ -4638,7 +4725,7 @@ static int CmdHF14aDesNDEF(const char *Cmd) {
|
|||
uint8_t filesettings[20] = {0};
|
||||
uint32_t fileset_len = 0;
|
||||
|
||||
res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len);
|
||||
int res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len);
|
||||
if (res != PM3_SUCCESS) continue;
|
||||
|
||||
int maclen = 0; // To be implemented
|
||||
|
@ -4656,19 +4743,20 @@ static int CmdHF14aDesNDEF(const char *Cmd) {
|
|||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
fdata.data = data;
|
||||
int res = handler_desfire_readdata(&fdata, MFDES_DATA_FILE, filesettings[1]);
|
||||
if (res == PM3_SUCCESS) {
|
||||
uint32_t len = le24toh(fdata.length);
|
||||
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||
fdata.data = data;
|
||||
res = handler_desfire_readdata(&fdata, MFDES_DATA_FILE, filesettings[1]);
|
||||
if (res == PM3_SUCCESS) {
|
||||
uint32_t len = le24toh(fdata.length);
|
||||
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Couldn't read value. Error %d", res);
|
||||
res = handler_desfire_select_application(aid);
|
||||
if (res != PM3_SUCCESS) continue;
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Couldn't read value. Error %d", res);
|
||||
res = handler_desfire_select_application(aid);
|
||||
if (res != PM3_SUCCESS) continue;
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
// PrintAndLogEx(INFO, "reading data from tag");
|
||||
|
@ -4680,13 +4768,40 @@ static int CmdHF14aDesNDEF(const char *Cmd) {
|
|||
|
||||
if (verbose2) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("DESfire NDEF raw") " ----------------");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("DESFire NDEF raw") " ----------------");
|
||||
dump_buffer(data, datalen, stdout, 1);
|
||||
}
|
||||
|
||||
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfdes ndef -vv`") " for more details");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
static int CmdHF14aDesMAD(const char *Cmd) {
|
||||
DropField();
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes mad",
|
||||
"Prints MIFARE Application directory (MAD)",
|
||||
"hf mfdes mad -> shows MAD data\n"
|
||||
"hf mfdes mad -v -> shows MAD parsed and raw data\n"
|
||||
"hf mfdes mad -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows MAD data with custom AID and key");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data"),
|
||||
arg_str0("", "aid", "<aid>", "replace default aid for MAD"),
|
||||
arg_str0("k", "key", "<key>", "replace default key for MAD"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfdes mad -v`") " for more details");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
*/
|
||||
|
||||
/*static int CmdTest(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
|
@ -4714,28 +4829,32 @@ static int CmdHF14aDesNDEF(const char *Cmd) {
|
|||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("general") " -----------------------"},
|
||||
{"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "Tries a MIFARE DesFire Authentication"},
|
||||
{"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"},
|
||||
{"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"},
|
||||
{"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"},
|
||||
{"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"},
|
||||
{"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "Get random uid"},
|
||||
{"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"},
|
||||
{"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"},
|
||||
{"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"},
|
||||
{"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "Tries a MIFARE DesFire Authentication"},
|
||||
{"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "Get random uid"},
|
||||
{"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},
|
||||
// {"ndef", CmdHF14aDesNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
|
||||
// {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("AID") " -----------------------"},
|
||||
{"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"},
|
||||
{"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"},
|
||||
{"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"},
|
||||
{"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"},
|
||||
{"clearfile", CmdHF14ADesClearRecordFile, IfPm3Iso14443a, "Clear record File"},
|
||||
{"createfile", CmdHF14ADesCreateFile, IfPm3Iso14443a, "Create Standard/Backup File"},
|
||||
{"createvaluefile", CmdHF14ADesCreateValueFile, IfPm3Iso14443a, "Create Value File"},
|
||||
{"createrecordfile", CmdHF14ADesCreateRecordFile, IfPm3Iso14443a, "Create Linear/Cyclic Record File"},
|
||||
{"deletefile", CmdHF14ADesDeleteFile, IfPm3Iso14443a, "Create Delete File"},
|
||||
{"clearfile", CmdHF14ADesClearRecordFile, IfPm3Iso14443a, "Clear record File"},
|
||||
{"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"},
|
||||
{"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"},
|
||||
{"readdata", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"},
|
||||
{"writedata", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"},
|
||||
{"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"},
|
||||
{"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"},
|
||||
{"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"},
|
||||
{"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"},
|
||||
{"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"},
|
||||
{"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"},
|
||||
// {"ndef", CmdHF14aDesNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -330,8 +330,10 @@ int demodAWID(bool verbose) {
|
|||
free(bits);
|
||||
|
||||
PrintAndLogEx(DEBUG, "DEBUG: AWID idx: %d, Len: %zu Printing Demod Buffer:", idx, size);
|
||||
if (g_debugMode)
|
||||
printDemodBuff();
|
||||
if (g_debugMode) {
|
||||
printDemodBuff(0, false, false, true);
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -318,8 +318,9 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) {
|
|||
setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 1)*g_DemodClock));
|
||||
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %zu, Len: %zu, Printing Demod Buffer:", idx, size);
|
||||
if (g_debugMode)
|
||||
printDemodBuff();
|
||||
if (g_debugMode) {
|
||||
printDemodBuff(0, false, false, true);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printEM410x(*hi, *lo);
|
||||
|
|
|
@ -223,7 +223,7 @@ static bool detectPSK(void) {
|
|||
|
||||
// In order to hit the INVERT, we need to demod here
|
||||
if (DemodBufferLen < 11) {
|
||||
PrintAndLogEx(INFO," demod buff len less than PREAMBLE lEN");
|
||||
PrintAndLogEx(INFO, " demod buff len less than PREAMBLE lEN");
|
||||
}
|
||||
|
||||
size_t size = (11 > DemodBufferLen) ? DemodBufferLen : 11;
|
||||
|
@ -910,7 +910,7 @@ int CmdEM4x05Wipe(const char *Cmd) {
|
|||
|
||||
static const char *printEM4x05_known(uint32_t word) {
|
||||
|
||||
switch(word) {
|
||||
switch (word) {
|
||||
// case EM4305_DEFAULT_CONFIG_BLOCK:
|
||||
case EM4305_PRESCO_CONFIG_BLOCK: {
|
||||
return "EM4305 DEFAULT / PRESCO";
|
||||
|
@ -1066,7 +1066,7 @@ static void printEM4x05config(em_tech_type_t card_type, uint32_t wordData) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Config Information") " ------------------------");
|
||||
PrintAndLogEx(INFO, "ConfigWord: %08X ( " _YELLOW_("%s") " )", wordData, printEM4x05_known(wordData) );
|
||||
PrintAndLogEx(INFO, "ConfigWord: %08X ( " _YELLOW_("%s") " )", wordData, printEM4x05_known(wordData));
|
||||
|
||||
PrintAndLogEx(INFO, " Data Rate: %02u | "_YELLOW_("RF/%u"), wordData & 0x3F, datarate);
|
||||
PrintAndLogEx(INFO, " Encoder: %u | " _YELLOW_("%s"), encoder, enc);
|
||||
|
@ -1820,7 +1820,7 @@ int CmdEM4x05Unlock(const char *Cmd) {
|
|||
return exit_code;
|
||||
}
|
||||
|
||||
static size_t em4x05_Sniff_GetNextBitStart (size_t idx, size_t sc, int *data, size_t *pulsesamples) {
|
||||
static size_t em4x05_Sniff_GetNextBitStart(size_t idx, size_t sc, int *data, size_t *pulsesamples) {
|
||||
while ((idx < sc) && (data[idx] <= 10)) // find a going high
|
||||
idx++;
|
||||
|
||||
|
@ -1828,7 +1828,7 @@ static size_t em4x05_Sniff_GetNextBitStart (size_t idx, size_t sc, int *data, si
|
|||
idx++;
|
||||
|
||||
(*pulsesamples) = 0;
|
||||
while ((idx < sc) && ((data[idx+1] - data[idx]) < 10 )) { // find "sharp rise"
|
||||
while ((idx < sc) && ((data[idx + 1] - data[idx]) < 10)) { // find "sharp rise"
|
||||
(*pulsesamples)++;
|
||||
idx++;
|
||||
}
|
||||
|
@ -1836,7 +1836,7 @@ static size_t em4x05_Sniff_GetNextBitStart (size_t idx, size_t sc, int *data, si
|
|||
return idx;
|
||||
}
|
||||
|
||||
uint32_t static em4x05_Sniff_GetBlock (char *bits, bool fwd) {
|
||||
uint32_t static em4x05_Sniff_GetBlock(char *bits, bool fwd) {
|
||||
uint32_t value = 0;
|
||||
uint8_t idx;
|
||||
bool parityerror = false;
|
||||
|
@ -1882,7 +1882,7 @@ uint32_t static em4x05_Sniff_GetBlock (char *bits, bool fwd) {
|
|||
if (parity != (bits[35] - '0'))
|
||||
parityerror = true;
|
||||
|
||||
if (parityerror) printf ("parity error : ");
|
||||
if (parityerror) printf("parity error : ");
|
||||
|
||||
if (!fwd) {
|
||||
uint32_t t1 = value;
|
||||
|
@ -1923,19 +1923,21 @@ int CmdEM4x05Sniff(const char *Cmd) {
|
|||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("1", "buf","Use the data in the buffer"),
|
||||
arg_lit0("1", "buf", "Use the data in the buffer"),
|
||||
arg_lit0("r", "rev", "Reverse the bit order for data blocks"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
sampleData = !arg_get_lit(ctx,1);
|
||||
fwd = arg_get_lit(ctx,2);
|
||||
sampleData = !arg_get_lit(ctx, 1);
|
||||
fwd = arg_get_lit(ctx, 2);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// setup and sample data from Proxmark
|
||||
// if not directed to existing sample/graphbuffer
|
||||
if (sampleData) {
|
||||
if (!IfPm3Lf()) {
|
||||
if (IfPm3Lf() == false) {
|
||||
PrintAndLogEx(WARNING, "Only offline mode is available");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
@ -1955,26 +1957,26 @@ int CmdEM4x05Sniff(const char *Cmd) {
|
|||
haveData = false;
|
||||
pwd = false;
|
||||
|
||||
idx = em4x05_Sniff_GetNextBitStart (idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||
idx = em4x05_Sniff_GetNextBitStart(idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||
pktOffset = idx;
|
||||
if (pulseSamples >= 10) { // Should be 18 so a bit less to allow for processing
|
||||
|
||||
// Use first bit to get "0" bit samples as a reference
|
||||
ZeroWidth = idx;
|
||||
idx = em4x05_Sniff_GetNextBitStart (idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||
idx = em4x05_Sniff_GetNextBitStart(idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||
ZeroWidth = idx - ZeroWidth;
|
||||
|
||||
if (ZeroWidth <= 50) {
|
||||
pktOffset -= ZeroWidth;
|
||||
memset(bits,0x00,sizeof(bits));
|
||||
memset(bits, 0x00, sizeof(bits));
|
||||
bitidx = 0;
|
||||
|
||||
while ((idx < GraphTraceLen) && !eop) {
|
||||
CycleWidth = idx;
|
||||
idx = em4x05_Sniff_GetNextBitStart (idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||
idx = em4x05_Sniff_GetNextBitStart(idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||
|
||||
CycleWidth = idx - CycleWidth;
|
||||
if ((CycleWidth > 300) || (CycleWidth < (ZeroWidth-5))) { // to long or too short
|
||||
if ((CycleWidth > 300) || (CycleWidth < (ZeroWidth - 5))) { // to long or too short
|
||||
eop = true;
|
||||
bits[bitidx++] = '0'; // Append last zero from the last bit find
|
||||
cmdText[0] = 0;
|
||||
|
@ -1988,70 +1990,70 @@ int CmdEM4x05Sniff(const char *Cmd) {
|
|||
// -> disable 1010 11111111 0 11111111 0 11111111 0 11111111 0 00000000 0
|
||||
|
||||
// Check to see if we got the leading 0
|
||||
if (((strncmp (bits,"00011",5) == 0)&& (bitidx == 50)) ||
|
||||
((strncmp (bits,"00101",5) == 0)&& (bitidx == 57)) ||
|
||||
((strncmp (bits,"01001",5) == 0)&& (bitidx == 12)) ||
|
||||
((strncmp (bits,"01100",5) == 0)&& (bitidx == 50)) ||
|
||||
((strncmp (bits,"01010",5) == 0)&& (bitidx == 50))) {
|
||||
memcpy (bits,&bits[1],bitidx-1);
|
||||
bitidx--;
|
||||
printf ("Trim leading 0\n");
|
||||
if (((strncmp(bits, "00011", 5) == 0) && (bitidx == 50)) ||
|
||||
((strncmp(bits, "00101", 5) == 0) && (bitidx == 57)) ||
|
||||
((strncmp(bits, "01001", 5) == 0) && (bitidx == 12)) ||
|
||||
((strncmp(bits, "01100", 5) == 0) && (bitidx == 50)) ||
|
||||
((strncmp(bits, "01010", 5) == 0) && (bitidx == 50))) {
|
||||
memmove(bits, &bits[1], bitidx - 1);
|
||||
bitidx--;
|
||||
printf("Trim leading 0\n");
|
||||
}
|
||||
bits[bitidx] = 0;
|
||||
// printf ("==> %s\n",bits);
|
||||
// printf ("==> %s\n",bits);
|
||||
// logon
|
||||
if ((strncmp (bits,"0011",4) == 0) && (bitidx == 49)) {
|
||||
if ((strncmp(bits, "0011", 4) == 0) && (bitidx == 49)) {
|
||||
haveData = true;
|
||||
pwd = true;
|
||||
sprintf (cmdText,"Logon");
|
||||
sprintf (blkAddr," ");
|
||||
tmpValue = em4x05_Sniff_GetBlock (&bits[4], fwd);
|
||||
sprintf (dataText,"%08X",tmpValue);
|
||||
sprintf(cmdText, "Logon");
|
||||
sprintf(blkAddr, " ");
|
||||
tmpValue = em4x05_Sniff_GetBlock(&bits[4], fwd);
|
||||
sprintf(dataText, "%08X", tmpValue);
|
||||
}
|
||||
|
||||
// write
|
||||
if ((strncmp (bits,"0101",4) == 0) && (bitidx == 56)) {
|
||||
if ((strncmp(bits, "0101", 4) == 0) && (bitidx == 56)) {
|
||||
haveData = true;
|
||||
sprintf (cmdText,"Write");
|
||||
sprintf(cmdText, "Write");
|
||||
tmpValue = (bits[4] - '0') + ((bits[5] - '0') << 1) + ((bits[6] - '0') << 2) + ((bits[7] - '0') << 3);
|
||||
sprintf (blkAddr,"%d",tmpValue);
|
||||
sprintf(blkAddr, "%d", tmpValue);
|
||||
if (tmpValue == 2)
|
||||
pwd = true;
|
||||
tmpValue = em4x05_Sniff_GetBlock (&bits[11], fwd);
|
||||
sprintf (dataText,"%08X",tmpValue);
|
||||
tmpValue = em4x05_Sniff_GetBlock(&bits[11], fwd);
|
||||
sprintf(dataText, "%08X", tmpValue);
|
||||
}
|
||||
|
||||
// read
|
||||
if ((strncmp (bits,"1001",4) == 0) && (bitidx == 11)) {
|
||||
if ((strncmp(bits, "1001", 4) == 0) && (bitidx == 11)) {
|
||||
haveData = true;
|
||||
pwd = false;
|
||||
sprintf (cmdText,"Read");
|
||||
sprintf(cmdText, "Read");
|
||||
tmpValue = (bits[4] - '0') + ((bits[5] - '0') << 1) + ((bits[6] - '0') << 2) + ((bits[7] - '0') << 3);
|
||||
sprintf (blkAddr,"%d",tmpValue);
|
||||
sprintf (dataText," ");
|
||||
sprintf(blkAddr, "%d", tmpValue);
|
||||
sprintf(dataText, " ");
|
||||
}
|
||||
|
||||
// protect
|
||||
if ((strncmp (bits,"1100",4) == 0) && (bitidx == 49)) {
|
||||
if ((strncmp(bits, "1100", 4) == 0) && (bitidx == 49)) {
|
||||
haveData = true;
|
||||
pwd = false;
|
||||
sprintf (cmdText,"Protect");
|
||||
sprintf (blkAddr," ");
|
||||
tmpValue = em4x05_Sniff_GetBlock (&bits[11], fwd);
|
||||
sprintf (dataText,"%08X",tmpValue);
|
||||
sprintf(cmdText, "Protect");
|
||||
sprintf(blkAddr, " ");
|
||||
tmpValue = em4x05_Sniff_GetBlock(&bits[11], fwd);
|
||||
sprintf(dataText, "%08X", tmpValue);
|
||||
}
|
||||
|
||||
// disable
|
||||
if ((strncmp (bits,"1010",4) == 0) && (bitidx == 49)) {
|
||||
if ((strncmp(bits, "1010", 4) == 0) && (bitidx == 49)) {
|
||||
haveData = true;
|
||||
pwd = false;
|
||||
sprintf (cmdText,"Disable");
|
||||
sprintf (blkAddr," ");
|
||||
tmpValue = em4x05_Sniff_GetBlock (&bits[11], fwd);
|
||||
sprintf (dataText,"%08X",tmpValue);
|
||||
sprintf(cmdText, "Disable");
|
||||
sprintf(blkAddr, " ");
|
||||
tmpValue = em4x05_Sniff_GetBlock(&bits[11], fwd);
|
||||
sprintf(dataText, "%08X", tmpValue);
|
||||
}
|
||||
|
||||
// bits[bitidx] = 0;
|
||||
// bits[bitidx] = 0;
|
||||
} else {
|
||||
i = (CycleWidth - ZeroWidth) / 28;
|
||||
bits[bitidx++] = '0';
|
||||
|
@ -2066,9 +2068,9 @@ int CmdEM4x05Sniff(const char *Cmd) {
|
|||
// Print results
|
||||
if (haveData) { //&& (minWidth > 1) && (maxWidth > minWidth)){
|
||||
if (pwd)
|
||||
PrintAndLogEx(SUCCESS, "%6llu | %-10s | "_YELLOW_("%8s")" | "_YELLOW_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
|
||||
PrintAndLogEx(SUCCESS, "%6zu | %-10s | "_YELLOW_("%8s")" | "_YELLOW_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
|
||||
else
|
||||
PrintAndLogEx(SUCCESS, "%6llu | %-10s | "_GREEN_("%8s")" | "_GREEN_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
|
||||
PrintAndLogEx(SUCCESS, "%6zu | %-10s | "_GREEN_("%8s")" | "_GREEN_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,11 +137,17 @@ int demodHID(bool verbose) {
|
|||
}
|
||||
|
||||
wiegand_message_t packed = initialize_message_object(hi2, hi, lo);
|
||||
HIDTryUnpack(&packed, false);
|
||||
if (HIDTryUnpack(&packed, false) == false) {
|
||||
PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
|
||||
printDemodBuff(0, false, false, true);
|
||||
}
|
||||
|
||||
PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing Demod Buffer: ", idx, size);
|
||||
if (g_debugMode)
|
||||
printDemodBuff();
|
||||
if (g_debugMode) {
|
||||
PrintAndLogEx(DEBUG, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
|
||||
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) {
|
|||
|
||||
if (g_debugMode) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Indala - printing demodbuffer");
|
||||
printDemodBuff();
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -185,7 +185,8 @@ int demodIOProx(bool verbose) {
|
|||
PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox crc failed");
|
||||
|
||||
PrintAndLogEx(DEBUG, "DEBUG: IO prox idx: %d, Len: %zu, Printing demod buffer:", idx, size);
|
||||
printDemodBuff();
|
||||
printDemodBuff(0, false, false, true);
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -227,12 +227,12 @@ static int CmdKeriClone(const char *Cmd) {
|
|||
char cardtype[16] = {"T55x7"};
|
||||
if (arg_get_lit(ctx, 1)) {
|
||||
blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
|
||||
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
|
||||
q5 = true;
|
||||
}
|
||||
if (arg_get_lit(ctx, 5)) {
|
||||
blocks[0] = EM4305_KERI_CONFIG_BLOCK;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
|
||||
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
|
||||
em = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -192,8 +192,9 @@ int demodParadox(bool verbose) {
|
|||
);
|
||||
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Paradox idx: %d, len: %zu, Printing Demod Buffer:", idx, size);
|
||||
if (g_debugMode)
|
||||
printDemodBuff();
|
||||
if (g_debugMode) {
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -203,8 +203,9 @@ int demodPyramid(bool verbose) {
|
|||
);
|
||||
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Pyramid: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128);
|
||||
if (g_debugMode)
|
||||
printDemodBuff();
|
||||
if (g_debugMode) {
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1024,6 +1024,9 @@ static void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
|
|||
PrintAndLogEx(NORMAL, msg);
|
||||
}
|
||||
|
||||
// Define prototype to call from within detect.
|
||||
static int CmdT55xxWakeUp (const char *Cmd);
|
||||
|
||||
static int CmdT55xxDetect(const char *Cmd) {
|
||||
|
||||
bool errors = false;
|
||||
|
@ -1032,9 +1035,16 @@ static int CmdT55xxDetect(const char *Cmd) {
|
|||
bool try_with_pwd = false;
|
||||
bool try_all_dl_modes = true;
|
||||
bool found = false;
|
||||
bool usewake = false;
|
||||
uint64_t password = -1;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
char wakecmd[20] = { 0x00 };
|
||||
struct timespec sleepperiod;
|
||||
|
||||
// Setup the 90ms time value to sleep for after the wake, to allow delay init to complete (~70ms)
|
||||
sleepperiod.tv_sec = 0;
|
||||
sleepperiod.tv_nsec = 90000000;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
@ -1042,6 +1052,7 @@ static int CmdT55xxDetect(const char *Cmd) {
|
|||
return usage_t55xx_detect();
|
||||
case 'p':
|
||||
password = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
sprintf (wakecmd,"p %08x q",(uint32_t)(password & 0xFFFFFFFF));
|
||||
usepwd = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
@ -1064,6 +1075,7 @@ static int CmdT55xxDetect(const char *Cmd) {
|
|||
}
|
||||
if (errors) return usage_t55xx_detect();
|
||||
|
||||
|
||||
// detect called so clear data blocks
|
||||
T55x7_ClearAllBlockData();
|
||||
|
||||
|
@ -1072,38 +1084,61 @@ static int CmdT55xxDetect(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
|
||||
if (useGB == false) {
|
||||
// do ... while to check without password then loop back if password supplied
|
||||
// do ... while not found and not yet tried with wake (for AOR or Init Delay)
|
||||
do {
|
||||
// do ... while to check without password then loop back if password supplied
|
||||
do {
|
||||
|
||||
if (try_all_dl_modes) {
|
||||
for (uint8_t m = downlink_mode; m < 4; m++) {
|
||||
if (try_all_dl_modes) {
|
||||
for (uint8_t m = downlink_mode; m < 4; m++) {
|
||||
if (usewake) {
|
||||
// call wake
|
||||
if (try_with_pwd)
|
||||
CmdT55xxWakeUp (wakecmd);
|
||||
else
|
||||
CmdT55xxWakeUp ("q");
|
||||
// sleep 90 ms
|
||||
nanosleep (&sleepperiod, &sleepperiod);
|
||||
}
|
||||
|
||||
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, (try_with_pwd && usepwd), password, m) == false)
|
||||
continue;
|
||||
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, (try_with_pwd && usepwd), password, m) == false)
|
||||
continue;
|
||||
|
||||
if (t55xxTryDetectModulationEx(m, T55XX_PrintConfig, 0, (try_with_pwd && usepwd) ? password : -1) == false)
|
||||
continue;
|
||||
if (t55xxTryDetectModulationEx(m, T55XX_PrintConfig, 0, (try_with_pwd && usepwd) ? password : -1) == false)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
found = true;
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (usewake) {
|
||||
// call wake
|
||||
if (try_with_pwd)
|
||||
CmdT55xxWakeUp (wakecmd);
|
||||
else
|
||||
CmdT55xxWakeUp ("q");
|
||||
// sleep 90 ms
|
||||
nanosleep (&sleepperiod, &sleepperiod);
|
||||
}
|
||||
|
||||
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) {
|
||||
found = t55xxTryDetectModulationEx(downlink_mode, T55XX_PrintConfig, 0, (usepwd) ? password : -1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) {
|
||||
found = t55xxTryDetectModulationEx(downlink_mode, T55XX_PrintConfig, 0, (usepwd) ? password : -1);
|
||||
}
|
||||
}
|
||||
|
||||
// toggle so we loop back if not found and try with pwd
|
||||
if (!found && usepwd)
|
||||
try_with_pwd = !try_with_pwd;
|
||||
// toggle so we loop back if not found and try with pwd
|
||||
if (!found && usepwd)
|
||||
try_with_pwd = !try_with_pwd;
|
||||
|
||||
// force exit as detect block has been found
|
||||
if (found)
|
||||
try_with_pwd = false;
|
||||
|
||||
} while (try_with_pwd);
|
||||
// force exit as detect block has been found
|
||||
if (found)
|
||||
try_with_pwd = false;
|
||||
|
||||
} while (try_with_pwd);
|
||||
// Toggle so we loop back and try with wakeup.
|
||||
usewake = !usewake;
|
||||
} while (!found && usewake);
|
||||
} else {
|
||||
found = t55xxTryDetectModulation(downlink_mode, T55XX_PrintConfig);
|
||||
}
|
||||
|
@ -1619,6 +1654,7 @@ static int CmdT55xxWakeUp(const char *Cmd) {
|
|||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
uint8_t downlink_mode = config.downlink_mode;
|
||||
bool quiet = false;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
@ -1635,6 +1671,10 @@ static int CmdT55xxWakeUp(const char *Cmd) {
|
|||
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
|
@ -1659,7 +1699,9 @@ static int CmdT55xxWakeUp(const char *Cmd) {
|
|||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now");
|
||||
if (!quiet)
|
||||
PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3042,7 +3084,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
|
||||
if (errors) return usage_t55xx_chk();
|
||||
|
||||
if (strlen(filename) == 0){
|
||||
if (strlen(filename) == 0) {
|
||||
snprintf(filename, sizeof(filename), "t55xx_default_pwds");
|
||||
use_pwd_file = true;
|
||||
}
|
||||
|
|
|
@ -187,14 +187,14 @@ static int CmdVisa2kClone(const char *Cmd) {
|
|||
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
|
||||
if (q5) {
|
||||
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"Q5/T5555");
|
||||
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
|
||||
}
|
||||
|
||||
// EM4305
|
||||
bool em = tolower(param_getchar(Cmd, 1)) == 'e';
|
||||
if (em) {
|
||||
blocks[0] = EM4305_VISA2000_CONFIG_BLOCK;
|
||||
snprintf(cardtype, sizeof(cardtype) ,"EM4305/4469");
|
||||
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
|
||||
}
|
||||
|
||||
if (q5 && em) {
|
||||
|
|
|
@ -262,16 +262,16 @@ static command_t CommandTable[] = {
|
|||
{"hf", CmdHF, AlwaysAvailable, "{ High frequency commands... }"},
|
||||
{"hw", CmdHW, AlwaysAvailable, "{ Hardware commands... }"},
|
||||
{"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"},
|
||||
{"mem", CmdFlashMem, IfPm3Flash, "{ Flash Memory manipulation... }"},
|
||||
{"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software }"},
|
||||
{"mem", CmdFlashMem, IfPm3Flash, "{ Flash memory manipulation... }"},
|
||||
{"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software... }"},
|
||||
{"smart", CmdSmartcard, AlwaysAvailable, "{ Smart card ISO-7816 commands... }"},
|
||||
{"script", CmdScript, AlwaysAvailable, "{ Scripting commands }"},
|
||||
{"script", CmdScript, AlwaysAvailable, "{ Scripting commands... }"},
|
||||
{"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"},
|
||||
{"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"},
|
||||
{"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"},
|
||||
{"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"},
|
||||
{"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"},
|
||||
{"clear", CmdClear, AlwaysAvailable, "clear screen"},
|
||||
{"clear", CmdClear, AlwaysAvailable, "Clear screen"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help. Use " _YELLOW_("'<command> help'") " for details of a particular command."},
|
||||
{"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"},
|
||||
{"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"},
|
||||
|
|
|
@ -312,7 +312,7 @@ static void PrintATR(uint8_t *atr, size_t atrlen) {
|
|||
PrintAndLogEx(WARNING, "Invalid ATR length. len: %zu, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K);
|
||||
|
||||
if (K > 0)
|
||||
PrintAndLogEx(INFO, "Historical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]);
|
||||
PrintAndLogEx(INFO, "Historical bytes | len %02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]);
|
||||
|
||||
if (K > 1) {
|
||||
PrintAndLogEx(INFO, "\tHistorical bytes");
|
||||
|
@ -843,7 +843,7 @@ static int CmdSmartSetClock(const char *Cmd) {
|
|||
payload.new_clk = new_clk;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_SETCLOCK, (uint8_t*)&payload, sizeof(payload));
|
||||
SendCommandNG(CMD_SMART_SETCLOCK, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_SMART_SETCLOCK, &resp, 2500)) {
|
||||
PrintAndLogEx(WARNING, "smart card select failed");
|
||||
|
|
|
@ -606,8 +606,8 @@ int CmdTraceList(const char *Cmd) {
|
|||
"trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n"
|
||||
"trace list -t lto -> interpret as " _YELLOW_("LTO-CM") " communications\n"
|
||||
"trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") " communitcations\n"
|
||||
"trace list -t 14a f -> show frame delay times\n"
|
||||
"trace list -t 14a 1 -> use trace buffer "
|
||||
"trace list -t 14a -f -> show frame delay times\n"
|
||||
"trace list -t 14a -1 -> use trace buffer "
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
|
|
|
@ -517,3 +517,21 @@ void APDUPrintEx(APDUStruct apdu, size_t maxdatalen) {
|
|||
if (maxdatalen > 0)
|
||||
PrintAndLogEx(INFO, "data: %s%s", sprint_hex(apdu.data, MIN(apdu.lc, maxdatalen)), apdu.lc > maxdatalen ? "..." : "");
|
||||
}
|
||||
|
||||
void SAPDUPrint(sAPDU apdu, size_t maxdatalen) {
|
||||
PrintAndLogEx(INFO, "APDU: CLA 0x%02x, INS 0x%02x, P1 0x%02x, P2 0x%02x, Lc 0x%02x(%d)",
|
||||
apdu.CLA,
|
||||
apdu.INS,
|
||||
apdu.P1,
|
||||
apdu.P2,
|
||||
apdu.Lc,
|
||||
apdu.Lc
|
||||
);
|
||||
|
||||
size_t len = apdu.Lc;
|
||||
if (maxdatalen > 0)
|
||||
len = MIN(apdu.Lc, maxdatalen);
|
||||
|
||||
PrintAndLogEx(INFO, "data { %s%s }", sprint_hex(apdu.data, len), apdu.Lc > len ? "..." : "");
|
||||
}
|
||||
|
||||
|
|
|
@ -63,4 +63,5 @@ extern int APDUEncodeS(sAPDU *sapdu, bool extended, uint16_t le, uint8_t *data,
|
|||
extern void APDUPrint(APDUStruct apdu);
|
||||
extern void APDUPrintEx(APDUStruct apdu, size_t maxdatalen);
|
||||
|
||||
void SAPDUPrint(sAPDU apdu, size_t maxdatalen);
|
||||
#endif
|
||||
|
|
|
@ -122,6 +122,9 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs,
|
|||
}
|
||||
if (paddr < FLASH_START || (paddr + filesz) > flash_end) {
|
||||
PrintAndLogEx(ERR, "Error: PHDR is not contained in Flash");
|
||||
if ((paddr + filesz) > flash_end) {
|
||||
PrintAndLogEx(ERR, "Firmware probably too big for your device");
|
||||
}
|
||||
return PM3_EFILE;
|
||||
}
|
||||
if (vaddr >= FLASH_START && vaddr < flash_end && (flags & PF_W)) {
|
||||
|
|
|
@ -189,6 +189,29 @@ static bool Unpack_Kastle(wiegand_message_t *packed, wiegand_card_t *card) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool Pack_Kantech(wiegand_card_t *card, wiegand_message_t *packed) {
|
||||
memset(packed, 0, sizeof(wiegand_message_t));
|
||||
|
||||
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
|
||||
if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
|
||||
if (card->IssueLevel > 0) return false; // Not used in this format
|
||||
if (card->OEM > 0) return false; // Not used in this format
|
||||
|
||||
packed->Length = 32;
|
||||
set_linear_field(packed, card->FacilityCode, 7, 8);
|
||||
set_linear_field(packed, card->CardNumber, 15, 16);
|
||||
return add_HID_header(packed);
|
||||
}
|
||||
|
||||
static bool Unpack_Kantech(wiegand_message_t *packed, wiegand_card_t *card) {
|
||||
memset(card, 0, sizeof(wiegand_card_t));
|
||||
|
||||
if (packed->Length != 32) return false; // Wrong length? Stop here.
|
||||
card->FacilityCode = get_linear_field(packed, 7, 8);
|
||||
card->CardNumber = get_linear_field(packed, 15, 16);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Pack_D10202(wiegand_card_t *card, wiegand_message_t *packed) {
|
||||
memset(packed, 0, sizeof(wiegand_message_t));
|
||||
|
||||
|
@ -489,11 +512,12 @@ static bool Pack_H10304(wiegand_card_t *card, wiegand_message_t *packed) {
|
|||
if (card->OEM > 0) return false; // Not used in this format
|
||||
|
||||
packed->Length = 37; // Set number of bits
|
||||
packed->Bot |= (card->CardNumber & 0x0007FFFF) << 1;
|
||||
packed->Bot |= (card->FacilityCode & 0x00000FFF) << 20;
|
||||
packed->Mid |= (card->FacilityCode & 0x0000F000) >> 12;
|
||||
packed->Mid |= (evenparity32((packed->Mid & 0x0000000F) ^ (packed->Bot & 0xFFFC0000)) & 1) << 4;
|
||||
packed->Bot |= (oddparity32(packed->Bot & 0x0007FFFE) & 1);
|
||||
|
||||
set_linear_field(packed, card->FacilityCode, 1, 16);
|
||||
set_linear_field(packed, card->CardNumber, 17, 19);
|
||||
|
||||
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 18)), 0);
|
||||
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 18)), 36);
|
||||
return add_HID_header(packed);
|
||||
}
|
||||
|
||||
|
@ -502,11 +526,97 @@ static bool Unpack_H10304(wiegand_message_t *packed, wiegand_card_t *card) {
|
|||
|
||||
if (packed->Length != 37) return false; // Wrong length? Stop here.
|
||||
|
||||
card->CardNumber = (packed->Bot >> 1) & 0x0007FFFF;
|
||||
card->FacilityCode = ((packed->Mid & 0xF) << 12) | ((packed->Bot >> 20));
|
||||
card->FacilityCode = get_linear_field(packed, 1, 16);
|
||||
card->CardNumber = get_linear_field(packed, 17, 19);
|
||||
card->ParityValid =
|
||||
(evenparity32((packed->Mid & 0x0000000F) ^ (packed->Bot & 0xFFFC0000)) == ((packed->Mid >> 4) & 1)) &&
|
||||
(oddparity32(packed->Bot & 0x0007FFFE) == (packed->Bot & 1));
|
||||
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) &&
|
||||
(get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18)));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Pack_HGeneric37(wiegand_card_t *card, wiegand_message_t *packed) {
|
||||
memset(packed, 0, sizeof(wiegand_message_t));
|
||||
|
||||
if (card->FacilityCode > 0) return false; // Not used in this format
|
||||
if (card->CardNumber > 0x0007FFFF) return false; // Can't encode CN.
|
||||
if (card->IssueLevel > 0) return false; // Not used in this format
|
||||
if (card->OEM > 0) return false; // Not used in this format
|
||||
|
||||
packed->Length = 37; // Set number of bits
|
||||
|
||||
set_linear_field(packed, card->CardNumber, 4, 32);
|
||||
|
||||
set_bit_by_position(packed, 1, 36); // Always 1
|
||||
|
||||
// even1
|
||||
set_bit_by_position(packed,
|
||||
evenparity32(
|
||||
get_nonlinear_field(packed, 8, (uint8_t[]) {4, 8, 12, 16, 20, 24, 28, 32})
|
||||
)
|
||||
, 0
|
||||
);
|
||||
// odd1
|
||||
set_bit_by_position(packed,
|
||||
oddparity32(
|
||||
get_nonlinear_field(packed, 8, (uint8_t[]) {6, 10, 14, 18, 22, 26, 30, 34})
|
||||
)
|
||||
, 2
|
||||
);
|
||||
// even2
|
||||
set_bit_by_position(packed,
|
||||
evenparity32(
|
||||
get_nonlinear_field(packed, 8, (uint8_t[]) {7, 11, 15, 19, 23, 27, 31, 35})
|
||||
)
|
||||
, 3
|
||||
);
|
||||
return add_HID_header(packed);
|
||||
}
|
||||
|
||||
static bool Unpack_HGeneric37(wiegand_message_t *packed, wiegand_card_t *card) {
|
||||
memset(card, 0, sizeof(wiegand_card_t));
|
||||
|
||||
if (packed->Length != 37) return false; // Wrong length? Stop here.
|
||||
if (get_bit_by_position(packed, 36) != 1) return false; // Always 1 in this format
|
||||
|
||||
card->CardNumber = get_linear_field(packed, 4, 32);
|
||||
card->ParityValid =
|
||||
(get_bit_by_position(packed, 0) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]) {4, 8, 12, 16, 20, 24, 28, 32}))) &&
|
||||
(get_bit_by_position(packed, 2) == oddparity32(get_nonlinear_field(packed, 8, (uint8_t[]) {6, 10, 14, 18, 22, 28, 30, 34}))) &&
|
||||
(get_bit_by_position(packed, 3) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]) {7, 11, 15, 19, 23, 27, 31, 35})))
|
||||
;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Pack_MDI37(wiegand_card_t *card, wiegand_message_t *packed) {
|
||||
memset(packed, 0, sizeof(wiegand_message_t));
|
||||
|
||||
if (card->FacilityCode > 0x0000F) return false; // Can't encode FC.
|
||||
if (card->CardNumber > 0x1FFFFFFF) return false; // Can't encode CN.
|
||||
if (card->IssueLevel > 0) return false; // Not used in this format
|
||||
if (card->OEM > 0) return false; // Not used in this format
|
||||
|
||||
packed->Length = 37; // Set number of bits
|
||||
|
||||
set_linear_field(packed, card->FacilityCode, 3, 4);
|
||||
set_linear_field(packed, card->CardNumber, 7, 29);
|
||||
|
||||
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 18)), 0);
|
||||
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 18)), 36);
|
||||
return add_HID_header(packed);
|
||||
}
|
||||
|
||||
static bool Unpack_MDI37(wiegand_message_t *packed, wiegand_card_t *card) {
|
||||
memset(card, 0, sizeof(wiegand_card_t));
|
||||
|
||||
if (packed->Length != 37) return false; // Wrong length? Stop here.
|
||||
|
||||
card->FacilityCode = get_linear_field(packed, 3, 4);;
|
||||
card->CardNumber = get_linear_field(packed, 7, 29);
|
||||
|
||||
card->ParityValid =
|
||||
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) &&
|
||||
(get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18)))
|
||||
;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -705,6 +815,8 @@ static const cardformat_t FormatTable[] = {
|
|||
{"ATSW30", Pack_ATSW30, Unpack_ATSW30, "ATS Wiegand 30-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
|
||||
{"ADT31", Pack_ADT31, Unpack_ADT31, "HID ADT 31-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
|
||||
{"Kastle", Pack_Kastle, Unpack_Kastle, "Kastle 32-bit", {1, 1, 1, 0, 1}}, // from @xilni; PR #23 on RfidResearchGroup/proxmark3
|
||||
{"Kantech", Pack_Kantech, Unpack_Kantech, "Indala/Kantech KFS 32-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
|
||||
|
||||
{"D10202", Pack_D10202, Unpack_D10202, "HID D10202 33-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
|
||||
{"H10306", Pack_H10306, Unpack_H10306, "HID H10306 34-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
|
||||
{"N10002", Pack_N10002, Unpack_N10002, "HID N10002 34-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
|
||||
|
@ -717,7 +829,9 @@ static const cardformat_t FormatTable[] = {
|
|||
{"Sie36", Pack_Sie36, Unpack_Sie36, "HID 36-bit Siemens", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
|
||||
{"H10320", Pack_H10320, Unpack_H10320, "HID H10320 36-bit BCD", {1, 0, 0, 0, 1}}, // from Proxmark forums
|
||||
{"H10302", Pack_H10302, Unpack_H10302, "HID H10302 37-bit huge ID", {1, 0, 0, 0, 1}}, // from Proxmark forums
|
||||
{"H10304", Pack_H10304, Unpack_H10304, "HID H10304 37-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
|
||||
{"H10304", Pack_H10304, Unpack_H10304, "HID H10304 37-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
|
||||
{"HGeneric37", Pack_HGeneric37, Unpack_HGeneric37, "HID Generic 37-bit", {1, 0, 0, 0, 1}}, // from cardinfo.barkweb.com.au
|
||||
{"MDI37", Pack_MDI37, Unpack_MDI37, "PointGuard MDI 37-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
|
||||
{"P10001", Pack_P10001, Unpack_P10001, "HID P10001 Honeywell 40-bit", {1, 1, 0, 1, 0}}, // from cardinfo.barkweb.com.au
|
||||
{"Casi40", Pack_CasiRusco40, Unpack_CasiRusco40, "Casi-Rusco 40-bit", {1, 0, 0, 0, 0}}, // from cardinfo.barkweb.com.au
|
||||
{"C1k48s", Pack_C1k48s, Unpack_C1k48s, "HID Corporate 1000 48-bit standard layout", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
|
||||
|
@ -831,7 +945,8 @@ bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity) {
|
|||
++i;
|
||||
}
|
||||
if (result == false && packed->Length) {
|
||||
PrintAndLogEx(SUCCESS, "Unknown. Bit len %d", packed->Length);
|
||||
PrintAndLogEx(SUCCESS, "(wiegand unpack) unknown bit len %d", packed->Length);
|
||||
PrintAndLogEx(HINT, "Try 0xFFFF's http://cardinfo.barkweb.com.au/");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -1586,7 +1586,7 @@ int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream,
|
|||
* cost to copy the dictionary's tables into the active context,
|
||||
* so that the compression loop is only looking into one table.
|
||||
*/
|
||||
LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(LZ4_stream_t));
|
||||
LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr));
|
||||
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);
|
||||
} else {
|
||||
result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);
|
||||
|
|
|
@ -45,6 +45,23 @@ PLATFORM_EXTRAS=BTADDON
|
|||
Default standalone mode is $(DEFAULT_STANDALONE).
|
||||
To disable standalone modes, set explicitly an empty STANDALONE:
|
||||
STANDALONE=
|
||||
|
||||
For Proxmarks with only 256k, you can define
|
||||
PLATFORM_SIZE=256
|
||||
to be warned if the image is too big for your device
|
||||
and you can specify which parts to skip in order to reduce the size:
|
||||
SKIP_LF=1
|
||||
SKIP_HITAG=1
|
||||
SKIP_EM4x50=1
|
||||
SKIP_ISO15693=1
|
||||
SKIP_LEGICRF=1
|
||||
SKIP_ISO14443b=1
|
||||
SKIP_ISO14443a=1
|
||||
SKIP_ICLASS=1
|
||||
SKIP_FELICA=1
|
||||
SKIP_NFCBARCODE=1
|
||||
SKIP_HFSNIFF=1
|
||||
SKIP_HFPLOT=1
|
||||
endef
|
||||
|
||||
define KNOWN_DEFINITIONS
|
||||
|
@ -79,21 +96,44 @@ ifneq (,$(PLATFORM_EXTRAS_TMP))
|
|||
endif
|
||||
|
||||
# common LF support
|
||||
PLATFORM_DEFS += -DWITH_LF
|
||||
PLATFORM_DEFS += -DWITH_HITAG
|
||||
PLATFORM_DEFS += -DWITH_EM4x50
|
||||
ifneq ($(SKIP_LF),1)
|
||||
PLATFORM_DEFS += -DWITH_LF
|
||||
endif
|
||||
ifneq ($(SKIP_HITAG),1)
|
||||
PLATFORM_DEFS += -DWITH_HITAG
|
||||
endif
|
||||
ifneq ($(SKIP_EM4x50),1)
|
||||
PLATFORM_DEFS += -DWITH_EM4x50
|
||||
endif
|
||||
|
||||
# common HF support
|
||||
PLATFORM_DEFS += -DWITH_ISO15693
|
||||
PLATFORM_DEFS += -DWITH_LEGICRF
|
||||
PLATFORM_DEFS += -DWITH_ISO14443b
|
||||
PLATFORM_DEFS += -DWITH_ISO14443a
|
||||
PLATFORM_DEFS += -DWITH_ICLASS
|
||||
PLATFORM_DEFS += -DWITH_FELICA
|
||||
PLATFORM_DEFS += -DWITH_NFCBARCODE
|
||||
PLATFORM_DEFS += -DWITH_HFSNIFF
|
||||
PLATFORM_DEFS += -DWITH_HFPLOT
|
||||
|
||||
ifneq ($(SKIP_ISO15693),1)
|
||||
PLATFORM_DEFS += -DWITH_ISO15693
|
||||
endif
|
||||
ifneq ($(SKIP_LEGICRF),1)
|
||||
PLATFORM_DEFS += -DWITH_LEGICRF
|
||||
endif
|
||||
ifneq ($(SKIP_ISO14443b),1)
|
||||
PLATFORM_DEFS += -DWITH_ISO14443b
|
||||
endif
|
||||
ifneq ($(SKIP_ISO14443a),1)
|
||||
PLATFORM_DEFS += -DWITH_ISO14443a
|
||||
endif
|
||||
ifneq ($(SKIP_ICLASS),1)
|
||||
PLATFORM_DEFS += -DWITH_ICLASS
|
||||
endif
|
||||
ifneq ($(SKIP_FELICA),1)
|
||||
PLATFORM_DEFS += -DWITH_FELICA
|
||||
endif
|
||||
ifneq ($(SKIP_NFCBARCODE),1)
|
||||
PLATFORM_DEFS += -DWITH_NFCBARCODE
|
||||
endif
|
||||
ifneq ($(SKIP_HFSNIFF),1)
|
||||
PLATFORM_DEFS += -DWITH_HFSNIFF
|
||||
endif
|
||||
ifneq ($(SKIP_HFPLOT),1)
|
||||
PLATFORM_DEFS += -DWITH_HFPLOT
|
||||
endif
|
||||
|
||||
# Standalone mode
|
||||
ifneq ($(strip $(filter $(PLATFORM_DEFS),$(STANDALONE_REQ_DEFS))),$(strip $(STANDALONE_REQ_DEFS)))
|
||||
|
@ -133,6 +173,10 @@ ifeq (,$(PLATFORM_DEFS_INFO_STANDALONE))
|
|||
PLATFORM_DEFS_INFO_STANDALONE = No standalone mode selected
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM_SIZE),)
|
||||
PLATFORM_SIZE=512
|
||||
endif
|
||||
|
||||
PLATFORM_CHANGED=false
|
||||
ifneq ($(PLATFORM), $(CACHED_PLATFORM))
|
||||
PLATFORM_CHANGED=true
|
||||
|
@ -145,6 +189,7 @@ endif
|
|||
export PLATFORM
|
||||
export PLATFORM_EXTRAS
|
||||
export PLATFORM_EXTRAS_INFO
|
||||
export PLATFORM_SIZE
|
||||
export PLTNAME
|
||||
export PLATFORM_DEFS
|
||||
export PLATFORM_DEFS_INFO
|
||||
|
@ -154,6 +199,7 @@ export PLATFORM_CHANGED
|
|||
$(info ===================================================================)
|
||||
$(info Platform name: $(PLTNAME))
|
||||
$(info PLATFORM: $(PLATFORM))
|
||||
$(info PLATFORM_SIZE: $(PLATFORM_SIZE))
|
||||
$(info Platform extras: $(PLATFORM_EXTRAS_INFO))
|
||||
$(info Included options: $(PLATFORM_DEFS_INFO))
|
||||
$(info Standalone mode: $(PLATFORM_DEFS_INFO_STANDALONE))
|
||||
|
|
|
@ -135,7 +135,7 @@ Options
|
|||
---
|
||||
f <filename> : load iCLASS tag-dump filename
|
||||
|
||||
pm3 --> hf iclass eload f hf-iclass-db883702f8ff12e0.bin
|
||||
pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin
|
||||
```
|
||||
|
||||
Clone iCLASS Legacy Sequence
|
||||
|
@ -160,7 +160,7 @@ pm3 --> hf iclass sim 3
|
|||
Simulate iCLASS Sequence
|
||||
```
|
||||
pm3 --> hf iclass dump k 0
|
||||
pm3 --> hf iclass eload f hf-iclass-db883702f8ff12e0.bin
|
||||
pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin
|
||||
pm3 --> hf iclass sim 3
|
||||
```
|
||||
|
||||
|
@ -173,7 +173,7 @@ k <key> : Access Key as 16 hex symbols or 1 hex to select key from memory
|
|||
e : If 'e' is specified, elite computations applied to key
|
||||
|
||||
pm3 --> hf iclass sim 2
|
||||
pm3 --> hf iclass loclass f iclass_mac_attack.bin
|
||||
pm3 --> hf iclass loclass -f iclass_mac_attack.bin
|
||||
pm3 --> hf iclass managekeys n 7 k <Kcus>
|
||||
pm3 --> hf iclass dump k 7 e
|
||||
```
|
||||
|
|
|
@ -160,7 +160,7 @@ Check column "offline" for their availability.
|
|||
|`hf 14b reader `|N |`Act as a 14443B reader to identify a tag`
|
||||
|`hf 14b sim `|N |`Fake ISO 14443B tag`
|
||||
|`hf 14b sniff `|N |`Eavesdrop ISO 14443B`
|
||||
|`hf 14b sriread `|N |`Read contents of a SRI512 | SRIX4K tag`
|
||||
|`hf 14b rdbl `|N |`Read SRI512/SRIX4x block`
|
||||
|`hf 14b sriwrite `|N |`Write data to a SRI512 | SRIX4K tag`
|
||||
|
||||
|
||||
|
@ -203,7 +203,7 @@ Check column "offline" for their availability.
|
|||
|
||||
### hf felica
|
||||
|
||||
{ ISO18092 / Felica RFIDs... }
|
||||
{ ISO18092 / FeliCa RFIDs... }
|
||||
|
||||
|command |offline |description
|
||||
|------- |------- |-----------
|
||||
|
@ -325,6 +325,7 @@ Check column "offline" for their availability.
|
|||
|`hf mf chk `|N |`Check keys`
|
||||
|`hf mf fchk `|N |`Check keys fast, targets all keys on card`
|
||||
|`hf mf decrypt `|Y |`[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace`
|
||||
|`hf mf supercard `|N |`Extract info from a `super card``
|
||||
|`hf mf auth4 `|N |`ISO14443-4 AES authentication`
|
||||
|`hf mf dump `|N |`Dump MIFARE Classic tag to binary file`
|
||||
|`hf mf mad `|N |`Checks and prints MAD`
|
||||
|
@ -409,27 +410,27 @@ Check column "offline" for their availability.
|
|||
|command |offline |description
|
||||
|------- |------- |-----------
|
||||
|`hf mfdes help `|Y |`This help`
|
||||
|`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication`
|
||||
|`hf mfdes changekey `|N |`Change Key`
|
||||
|`hf mfdes chk `|N |`Check keys`
|
||||
|`hf mfdes enum `|N |`Tries enumerate all applications`
|
||||
|`hf mfdes formatpicc `|N |`Format PICC`
|
||||
|`hf mfdes getuid `|N |`Get random uid`
|
||||
|`hf mfdes info `|N |`Tag information`
|
||||
|`hf mfdes list `|Y |`List DESFire (ISO 14443A) history`
|
||||
|`hf mfdes enum `|N |`Tries enumerate all applications`
|
||||
|`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication`
|
||||
|`hf mfdes getuid `|N |`Get random uid`
|
||||
|`hf mfdes selectaid `|N |`Select Application ID`
|
||||
|`hf mfdes createaid `|N |`Create Application ID`
|
||||
|`hf mfdes deleteaid `|N |`Delete Application ID`
|
||||
|`hf mfdes selectaid `|N |`Select Application ID`
|
||||
|`hf mfdes changevalue `|N |`Write value of a value file (credit/debit/clear)`
|
||||
|`hf mfdes clearfile `|N |`Clear record File`
|
||||
|`hf mfdes createfile `|N |`Create Standard/Backup File`
|
||||
|`hf mfdes createvaluefile`|N |`Create Value File`
|
||||
|`hf mfdes createrecordfile`|N |`Create Linear/Cyclic Record File`
|
||||
|`hf mfdes deletefile `|N |`Create Delete File`
|
||||
|`hf mfdes clearfile `|N |`Clear record File`
|
||||
|`hf mfdes dump `|N |`Dump all files`
|
||||
|`hf mfdes getvalue `|N |`Get value of file`
|
||||
|`hf mfdes readdata `|N |`Read data from standard/backup/record file`
|
||||
|`hf mfdes writedata `|N |`Write data to standard/backup/record file`
|
||||
|`hf mfdes getvalue `|N |`Get value of file`
|
||||
|`hf mfdes changevalue `|N |`Write value of a value file (credit/debit/clear)`
|
||||
|`hf mfdes changekey `|N |`Change Key`
|
||||
|`hf mfdes formatpicc `|N |`Format PICC`
|
||||
|`hf mfdes dump `|N |`Dump all files`
|
||||
|`hf mfdes chk `|N |`Check keys`
|
||||
|
||||
|
||||
### hf st
|
||||
|
@ -591,10 +592,12 @@ Check column "offline" for their availability.
|
|||
|`lf em 4x05_read `|N |`read word data from EM4x05/EM4x69`
|
||||
|`lf em 4x05_write `|N |`write word data to EM4x05/EM4x69`
|
||||
|`lf em 4x05_unlock `|N |`execute tear off against EM4x05/EM4x69`
|
||||
|`lf em 4x05_sniff `|Y |`Attempt to recover em4x05 commands from sample buffer`
|
||||
|`lf em 4x05_brute `|N |`Bruteforce password`
|
||||
|`lf em 4x50_dump `|N |`dump EM4x50 tag`
|
||||
|`lf em 4x50_info `|N |`tag information EM4x50`
|
||||
|`lf em 4x50_write `|N |`write word data to EM4x50`
|
||||
|`lf em 4x50_write_password`|N |`change passwword of EM4x50 tag`
|
||||
|`lf em 4x50_write_password`|N |`change password of EM4x50 tag`
|
||||
|`lf em 4x50_read `|N |`read word data from EM4x50`
|
||||
|`lf em 4x50_wipe `|N |`wipe data from EM4x50`
|
||||
|
||||
|
|
|
@ -8,15 +8,15 @@ LOCLASS, is a two part attack. First is the online part where you gather needed
|
|||
|
||||
The second part is offline, where the information gathered from the first step is used in a series of DES operations to figure out the used
|
||||
masterkey.
|
||||
run `hf iclass loclass f abc.bin`
|
||||
run `hf iclass loclass -f abc.bin`
|
||||
|
||||
If you don't have access to a iClass SE reader configured in Elite mode there is a test file which you can use.
|
||||
`hf iclass loclass f iclass_dump.bin`
|
||||
`hf iclass loclass -f iclass_dump.bin`
|
||||
|
||||
|
||||
# Unit testing
|
||||
In order to verify that loclass is actually working, there is a "unit" test mode.
|
||||
run `hf iclass loclass t`.
|
||||
run `hf iclass loclass --test`.
|
||||
|
||||
This test mode uses two files.
|
||||
|
||||
|
|
|
@ -32,9 +32,7 @@ make SKIPBT=1
|
|||
By default, the firmware is of course tuned for the Proxmark3 Rdv4.0 device, which has built-in support for 256kb onboard flash SPI memory, Sim module (smart card support), FPC connector.
|
||||
These features make it very different from all other devices, there is non other like this one.
|
||||
|
||||
**Recommendation**: if you don't have a RDV4, we strongly recommend your device to have at least a 512kb arm chip, since this repo is on the very edge of 256kb limit.
|
||||
|
||||
A firmware built for the RDV4 can still run on the other platforms as it will auto-detect during boot that external SPI and Sim are not present, still it will boot faster if it's tuned to the platform, which solves USB enumeration issues on some OSes.
|
||||
**Recommendation**: if you don't have a RDV4, we strongly recommend your device to have at least a 512kb arm chip, since this repo is crossing 256kb limit. There is still a way to skip parts to make it fit on a 256kb device, see below.
|
||||
|
||||
If you need to tune things and save the configuration, create a file `Makefile.platform` in the root directory of the repository, see `Makefile.platform.sample`.
|
||||
For an up-to-date exhaustive list of options, you can run `make PLATFORM=`.
|
||||
|
@ -96,10 +94,55 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
|
|||
| HF_LEGIC | HF Legic Prime standalone - uhei
|
||||
| HF_MATTYRUN | Mifare sniff/clone - Matías A. Ré Medina
|
||||
| HF_MSDSAL (def)| EMV Read and emulation - Salvador Mendoza
|
||||
| HF_TCPRST | IKEA Rothult ST25TA, Standalone Master Key Dump/Emulation - Nick Draffen
|
||||
| HF_YOUNG | Mifare sniff/simulation - Craig Young
|
||||
|
||||
By default `STANDALONE=HF_MSDSAL`.
|
||||
|
||||
## 256kb versions
|
||||
|
||||
If you own a Proxmark3 Easy with only 256kb, you can use a few definitions to help you getting a smaller firmware.
|
||||
|
||||
First thing is of course to use the `PLATFORM=PM3OTHER`.
|
||||
Adding `PLATFORM_SIZE=256` will provoke an error during compilation of the recovery image if your image is too big, so you can detect the problem before trying to flash the Proxmark3, e.g.
|
||||
```
|
||||
[=] GEN proxmark3_recovery.bin
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
ERROR: Firmware image too large for your platform! 262768 > 262144
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
```
|
||||
|
||||
You can skip the standalone support by indicating `STANDALONE=` and
|
||||
a series of `SKIP_*` allow to skip some of the functionalities and to get a smaller image.
|
||||
|
||||
| Definitions | Rough estimation of the saved space |
|
||||
|---------------------|-------------------------------------|
|
||||
|STANDALONE= | 3.6kb
|
||||
|SKIP_LF=1 | 25.8kb
|
||||
|SKIP_HITAG=1 | 24.2kb
|
||||
|SKIP_EM4x50=1 | 2.9kb
|
||||
|SKIP_ISO15693=1 | 3.2kb
|
||||
|SKIP_LEGICRF=1 | 3.9kb
|
||||
|SKIP_ISO14443b=1 | 3.7kb
|
||||
|SKIP_ISO14443a=1 | 63.0kb
|
||||
|SKIP_ICLASS=1 | 10.5kb
|
||||
|SKIP_FELICA=1 | 4.0kb
|
||||
|SKIP_NFCBARCODE=1 | 1.4kb
|
||||
|SKIP_HFSNIFF=1 | 0.5kb
|
||||
|SKIP_HFPLOT=1 | 0.3kb
|
||||
|
||||
So for example, at the time of writing, this is a valid `Makefile.platform` compiling an image for 256k:
|
||||
```
|
||||
PLATFORM=PM3OTHER
|
||||
PLATFORM_SIZE=256
|
||||
STANDALONE=
|
||||
SKIP_LEGICRF=1
|
||||
SKIP_FELICA=1
|
||||
```
|
||||
Situation might change when the firmware is growing of course, requiring to skip more elements.
|
||||
|
||||
Last note: if you skip a tech, be careful not to use a standalone mode which requires that same tech, else the firmware size reduction won't be much.
|
||||
|
||||
## Next step
|
||||
|
||||
See [Compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)
|
||||
|
|
|
@ -6,10 +6,18 @@ ifneq (,$(FWTAG))
|
|||
else
|
||||
INSTALLFWTAG = $(notdir $(INSTALLFW))
|
||||
endif
|
||||
FWMAXSIZE = $(shell echo $$(($(PLATFORM_SIZE)*1024)))
|
||||
|
||||
BINS = bootrom.bin fullimage.bin $(INSTALLFW)
|
||||
|
||||
all: $(BINS)
|
||||
@FWSIZE=$$(stat -c "%s" $(INSTALLFW));\
|
||||
if [ $$FWSIZE -gt $(FWMAXSIZE) ]; then \
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; \
|
||||
echo "ERROR: Firmware image too large for your platform! $$FWSIZE > $(FWMAXSIZE)"; \
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
bootrom.bin: ../bootrom/obj/bootrom.elf
|
||||
$(info [=] GEN $@)
|
||||
|
|
|
@ -412,7 +412,7 @@ while true; do
|
|||
"Motorola - fmt: 26 FC: 258 Card: 2, Raw: A0000000A0002021"; then break; fi
|
||||
if ! CheckExecute slow "lf T55 nedap test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nedap.pm3; lf search 1'" "NEDAP ID found"; then break; fi
|
||||
if ! CheckExecute slow "lf T55 nedap test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nedap.pm3; lf nedap demod'" \
|
||||
"NEDAP - Card: 12345 subtype: 1 customer code: 123, Raw: FF 82 24 65 08 20 99 53"; then break; fi
|
||||
"NEDAP - Card: 12345 subtype: 1 customer code: 123, Raw: FF82246508209953"; then break; fi
|
||||
if ! CheckExecute slow "lf T55 nexwatch test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nexwatch.pm3; lf search 1'" "NexWatch ID found"; then break; fi
|
||||
if ! CheckExecute slow "lf T55 nexwatch test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nexwatch.pm3; lf nexwatch demod'" \
|
||||
"Raw : 56000000213C9F8F150C00"; then break; fi
|
||||
|
@ -450,10 +450,10 @@ while true; do
|
|||
echo -e "\n${C_BLUE}Testing HF:${C_NC}"
|
||||
if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "at_enc"; then break; fi
|
||||
if ! CheckExecute slow retry ignore "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested t 1 000000000000'" "found:"; then break; fi
|
||||
if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass t l'" "verified ok"; then break; fi
|
||||
if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass --long'" "verified ok"; then break; fi
|
||||
if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Test(s) \[ ok"; then break; fi
|
||||
if ! $SLOWTESTS; then
|
||||
if ! CheckExecute "hf iclass test" "$CLIENTBIN -c 'hf iclass loclass t'" "key diversification (ok)"; then break; fi
|
||||
if ! CheckExecute "hf iclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi
|
||||
if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test(s) \[ ok"; then break; fi
|
||||
fi
|
||||
fi
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue