mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
chg: 'hf iclass rdbl' - now retries 10 ten times and uses NG
This commit is contained in:
parent
a037766e26
commit
305c54f3cf
3 changed files with 85 additions and 40 deletions
|
@ -1237,7 +1237,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ICLASS_READBL: {
|
case CMD_HF_ICLASS_READBL: {
|
||||||
iClass_ReadBlk(packet->oldarg[0]);
|
struct p {
|
||||||
|
uint8_t blockno;
|
||||||
|
} PACKED;
|
||||||
|
struct p *payload = (struct p *)packet->data.asBytes;
|
||||||
|
iClass_ReadBlk( payload->blockno );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ICLASS_AUTH: { //check
|
case CMD_HF_ICLASS_AUTH: { //check
|
||||||
|
|
|
@ -1720,7 +1720,7 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) {
|
||||||
static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int *wait) {
|
static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int *wait) {
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
volatile uint32_t b;
|
// volatile uint32_t b;
|
||||||
bool firstpart = true;
|
bool firstpart = true;
|
||||||
uint8_t sendbyte;
|
uint8_t sendbyte;
|
||||||
|
|
||||||
|
@ -1758,10 +1758,12 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent rx holding register from overflowing
|
// Prevent rx holding register from overflowing
|
||||||
|
/*
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
b = AT91C_BASE_SSC->SSC_RHR;
|
b = AT91C_BASE_SSC->SSC_RHR;
|
||||||
(void)b;
|
(void)b;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
time_rdr = GetCountSspClk();
|
time_rdr = GetCountSspClk();
|
||||||
|
@ -1949,12 +1951,11 @@ void setupIclassReader() {
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, uint8_t retries) {
|
bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, int8_t retries) {
|
||||||
while (retries-- > 0) {
|
while (retries-- > 0) {
|
||||||
|
|
||||||
ReaderTransmitIClass(command, cmdsize);
|
ReaderTransmitIClass(command, cmdsize);
|
||||||
|
|
||||||
|
|
||||||
//iceman - if received size is bigger than expected, we smash the stack here
|
//iceman - if received size is bigger than expected, we smash the stack here
|
||||||
// since its called with fixed sized arrays
|
// since its called with fixed sized arrays
|
||||||
|
|
||||||
|
@ -1967,7 +1968,7 @@ bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *re
|
||||||
// 0xBB is the internal debug separator byte..
|
// 0xBB is the internal debug separator byte..
|
||||||
if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) {
|
if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) {
|
||||||
//try again
|
//try again
|
||||||
SpinDelayUs(400);
|
SpinDelayUs(360);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2456,10 +2457,14 @@ bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len) {
|
||||||
// turn off afterwards
|
// turn off afterwards
|
||||||
// readblock 8 + 2. only want 8.
|
// readblock 8 + 2. only want 8.
|
||||||
void iClass_ReadBlk(uint8_t blockno) {
|
void iClass_ReadBlk(uint8_t blockno) {
|
||||||
uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
struct p {
|
||||||
bool isOK = iClass_ReadBlock(blockno, data, sizeof(data));
|
bool isOK;
|
||||||
reply_mix(CMD_ACK, isOK, 0, 0, data, sizeof(data));
|
uint8_t blockdata[8];
|
||||||
|
} PACKED result;
|
||||||
|
|
||||||
|
result.isOK = iClass_ReadBlock(blockno, result.blockdata, sizeof(result.blockdata));
|
||||||
switch_off();
|
switch_off();
|
||||||
|
reply_ng(CMD_HF_ICLASS_READBL, PM3_SUCCESS, (uint8_t *)&result, sizeof(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn off afterwards
|
// turn off afterwards
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#define NUM_CSNS 9
|
#define NUM_CSNS 9
|
||||||
#define ICLASS_KEYS_MAX 8
|
#define ICLASS_KEYS_MAX 8
|
||||||
|
#define ICLASS_AUTH_RETRY 10
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
@ -662,6 +663,10 @@ static int CmdHFiClassSim(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHFiClassInfo(const char *Cmd) {
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHFiClassReader(const char *Cmd) {
|
static int CmdHFiClassReader(const char *Cmd) {
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
if (cmdp == 'h') return usage_hf_iclass_reader();
|
if (cmdp == 'h') return usage_hf_iclass_reader();
|
||||||
|
@ -1563,36 +1568,62 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
|
static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
|
||||||
// block 0,1 should always be able to read, and block 5 on some cards.
|
|
||||||
if (auth || blockno >= 2) {
|
int numberAuthRetries = ICLASS_AUTH_RETRY;
|
||||||
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
|
// return data.
|
||||||
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
struct p {
|
||||||
if (!select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose))
|
bool isOK;
|
||||||
return 0;
|
uint8_t blockdata[8];
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
|
struct p *result = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// block 0,1 should always be able to read, and block 5 on some cards.
|
||||||
|
if (auth || blockno >= 2) {
|
||||||
|
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
|
||||||
|
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
if (!select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose)) {
|
||||||
|
numberAuthRetries--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
if (!select_only(CSN, CCNR, (keyType == 0x18), verbose)) {
|
||||||
|
numberAuthRetries--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketResponseNG resp;
|
||||||
|
clearCommandBuffer();
|
||||||
|
uint8_t payload[] = { blockno };
|
||||||
|
SendCommandNG(CMD_HF_ICLASS_READBL, payload, sizeof(payload));
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == 0) {
|
||||||
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( resp.status != PM3_SUCCESS ) {
|
||||||
|
PrintAndLogEx(ERR, "failed to communicate with card");
|
||||||
|
return PM3_EWRONGANSVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = (struct p*)resp.data.asBytes;
|
||||||
|
if (result->isOK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
} while (numberAuthRetries);
|
||||||
|
|
||||||
|
if ( numberAuthRetries > 0 ) {
|
||||||
|
PrintAndLogEx(SUCCESS, "block %02X: %s\n", blockno, sprint_hex(result->blockdata, sizeof(result->blockdata)));
|
||||||
} else {
|
} else {
|
||||||
uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
PrintAndLogEx(ERR,"failed to authenticate and read block");
|
||||||
uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
return PM3_ESOFT;
|
||||||
if (!select_only(CSN, CCNR, (keyType == 0x18), verbose))
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
PacketResponseNG resp;
|
|
||||||
clearCommandBuffer();
|
|
||||||
SendCommandMIX(CMD_HF_ICLASS_READBL, blockno, 0, 0, NULL, 0);
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
|
||||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
|
||||||
if (!isOK) {
|
|
||||||
PrintAndLogEx(WARNING, "read block failed");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//data read is stored in: resp.data.asBytes[0-15]
|
|
||||||
PrintAndLogEx(NORMAL, "block %02X: %s\n", blockno, sprint_hex(resp.data.asBytes, 8));
|
|
||||||
// should decrypt it if file is accessable.
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
||||||
|
@ -1613,14 +1644,16 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
||||||
case 'h':
|
case 'h':
|
||||||
return usage_hf_iclass_readblock();
|
return usage_hf_iclass_readblock();
|
||||||
case 'b':
|
case 'b':
|
||||||
blockno = param_get8ex(Cmd, cmdp + 1, 06, 16);
|
blockno = param_get8ex(Cmd, cmdp + 1, 7, 16);
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT"));
|
||||||
keyType = 0x18;
|
keyType = 0x18;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo"));
|
||||||
elite = true;
|
elite = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
@ -1632,6 +1665,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
||||||
} else if (dataLen == 1) {
|
} else if (dataLen == 1) {
|
||||||
keyNbr = param_get8(Cmd, cmdp + 1);
|
keyNbr = param_get8(Cmd, cmdp + 1);
|
||||||
if (keyNbr < ICLASS_KEYS_MAX) {
|
if (keyNbr < ICLASS_KEYS_MAX) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8 ));
|
||||||
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
memcpy(KEY, iClass_Key_Table[keyNbr], 8);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
|
||||||
|
@ -1644,6 +1678,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode"));
|
||||||
rawkey = true;
|
rawkey = true;
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
@ -2127,7 +2162,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
|
||||||
|
|
||||||
// Get CSN / UID and CCNR
|
// Get CSN / UID and CCNR
|
||||||
PrintAndLogEx(SUCCESS, "Reading tag CSN");
|
PrintAndLogEx(SUCCESS, "Reading tag CSN");
|
||||||
for (uint8_t i = 0; i < 10 && !got_csn; i++) {
|
for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) {
|
||||||
got_csn = select_only(CSN, CCNR, false, false);
|
got_csn = select_only(CSN, CCNR, false, false);
|
||||||
if (got_csn == false)
|
if (got_csn == false)
|
||||||
PrintAndLogEx(WARNING, "one more try\n");
|
PrintAndLogEx(WARNING, "one more try\n");
|
||||||
|
@ -2611,18 +2646,19 @@ static command_t CommandTable[] = {
|
||||||
{"dump", CmdHFiClassReader_Dump, IfPm3Iclass, "[options..] Authenticate and Dump iClass tag's AA1"},
|
{"dump", CmdHFiClassReader_Dump, IfPm3Iclass, "[options..] Authenticate and Dump iClass tag's AA1"},
|
||||||
{"eload", CmdHFiClassELoad, IfPm3Iclass, "[f <fname>] (experimental) Load data into iClass emulator memory"},
|
{"eload", CmdHFiClassELoad, IfPm3Iclass, "[f <fname>] (experimental) Load data into iClass emulator memory"},
|
||||||
{"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "[options..] Encrypt given block data"},
|
{"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "[options..] Encrypt given block data"},
|
||||||
|
{"info", CmdHFiClassInfo, AlwaysAvailable, " Tag information"},
|
||||||
{"list", CmdHFiClassList, AlwaysAvailable, " List iClass history"},
|
{"list", CmdHFiClassList, AlwaysAvailable, " List iClass history"},
|
||||||
{"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce of reader attack dump"},
|
{"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce of reader attack dump"},
|
||||||
{"lookup", CmdHFiClassLookUp, AlwaysAvailable, "[options..] Uses authentication trace to check for key in dictionary file"},
|
{"lookup", CmdHFiClassLookUp, AlwaysAvailable, "[options..] Uses authentication trace to check for key in dictionary file"},
|
||||||
{"managekeys", CmdHFiClassManageKeys, AlwaysAvailable, "[options..] Manage the keys to use with iClass"},
|
{"managekeys", CmdHFiClassManageKeys, AlwaysAvailable, "[options..] Manage the keys to use with iClass"},
|
||||||
{"permutekey", CmdHFiClassPermuteKey, IfPm3Iclass, " Permute function from 'heart of darkness' paper"},
|
{"permutekey", CmdHFiClassPermuteKey, IfPm3Iclass, " Permute function from 'heart of darkness' paper"},
|
||||||
{"readblk", CmdHFiClass_ReadBlock, IfPm3Iclass, "[options..] Read iClass block"},
|
{"rdbl", CmdHFiClass_ReadBlock, IfPm3Iclass, "[options..] Read iClass block"},
|
||||||
{"reader", CmdHFiClassReader, IfPm3Iclass, " Act like an iClass reader"},
|
{"reader", CmdHFiClassReader, IfPm3Iclass, " Act like an iClass reader"},
|
||||||
{"readtagfile", CmdHFiClassReadTagFile, AlwaysAvailable, "[options..] Display Content from tagfile"},
|
{"readtagfile", CmdHFiClassReadTagFile, AlwaysAvailable, "[options..] Display Content from tagfile"},
|
||||||
{"replay", CmdHFiClassReader_Replay, IfPm3Iclass, "<mac> Read an iClass tag via Replay Attack"},
|
{"replay", CmdHFiClassReader_Replay, IfPm3Iclass, "<mac> Read an iClass tag via Replay Attack"},
|
||||||
{"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iClass tag"},
|
{"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iClass tag"},
|
||||||
{"sniff", CmdHFiClassSniff, IfPm3Iclass, " Eavesdrop iClass communication"},
|
{"sniff", CmdHFiClassSniff, IfPm3Iclass, " Eavesdrop iClass communication"},
|
||||||
{"writeblk", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Write iClass block"},
|
{"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Write iClass block"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue