From 305c54f3cfcd9acf9e394cdd68fbc60728a59dc1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 8 Sep 2019 17:37:14 +0200 Subject: [PATCH] chg: 'hf iclass rdbl' - now retries 10 ten times and uses NG --- armsrc/appmain.c | 6 ++- armsrc/iclass.c | 19 +++++--- client/cmdhficlass.c | 100 +++++++++++++++++++++++++++++-------------- 3 files changed, 85 insertions(+), 40 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c789f6aac..e673c078a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1237,7 +1237,11 @@ static void PacketReceived(PacketCommandNG *packet) { break; } 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; } case CMD_HF_ICLASS_AUTH: { //check diff --git a/armsrc/iclass.c b/armsrc/iclass.c index b63c696d6..940d0157a 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -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) { int c = 0; - volatile uint32_t b; +// volatile uint32_t b; bool firstpart = true; 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 + /* if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = AT91C_BASE_SSC->SSC_RHR; (void)b; } + */ } time_rdr = GetCountSspClk(); @@ -1949,12 +1951,11 @@ void setupIclassReader() { 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) { ReaderTransmitIClass(command, cmdsize); - //iceman - if received size is bigger than expected, we smash the stack here // 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.. if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { //try again - SpinDelayUs(400); + SpinDelayUs(360); continue; } @@ -2456,10 +2457,14 @@ bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len) { // turn off afterwards // readblock 8 + 2. only want 8. void iClass_ReadBlk(uint8_t blockno) { - uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - bool isOK = iClass_ReadBlock(blockno, data, sizeof(data)); - reply_mix(CMD_ACK, isOK, 0, 0, data, sizeof(data)); + struct p { + bool isOK; + uint8_t blockdata[8]; + } PACKED result; + + result.isOK = iClass_ReadBlock(blockno, result.blockdata, sizeof(result.blockdata)); switch_off(); + reply_ng(CMD_HF_ICLASS_READBL, PM3_SUCCESS, (uint8_t *)&result, sizeof(result)); } // turn off afterwards diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index a096137ee..2f8d3b56d 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -32,6 +32,7 @@ #define NUM_CSNS 9 #define ICLASS_KEYS_MAX 8 +#define ICLASS_AUTH_RETRY 10 static int CmdHelp(const char *Cmd); @@ -662,6 +663,10 @@ static int CmdHFiClassSim(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHFiClassInfo(const char *Cmd) { + return PM3_SUCCESS; +} + static int CmdHFiClassReader(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); 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) { - // 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)) - return 0; + + int numberAuthRetries = ICLASS_AUTH_RETRY; + // return data. + struct p { + bool isOK; + 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 { - 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)) - return 0; + PrintAndLogEx(ERR,"failed to authenticate and read block"); + return PM3_ESOFT; } - - 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; + return PM3_SUCCESS; } static int CmdHFiClass_ReadBlock(const char *Cmd) { @@ -1613,14 +1644,16 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { case 'h': return usage_hf_iclass_readblock(); case 'b': - blockno = param_get8ex(Cmd, cmdp + 1, 06, 16); + blockno = param_get8ex(Cmd, cmdp + 1, 7, 16); cmdp += 2; break; case 'c': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); keyType = 0x18; cmdp++; break; case 'e': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); elite = true; cmdp++; break; @@ -1632,6 +1665,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp + 1); 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); } else { PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); @@ -1644,6 +1678,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { cmdp += 2; break; case 'r': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); rawkey = true; cmdp++; break; @@ -2127,7 +2162,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { // Get CSN / UID and CCNR 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); if (got_csn == false) 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"}, {"eload", CmdHFiClassELoad, IfPm3Iclass, "[f ] (experimental) Load data into iClass emulator memory"}, {"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "[options..] Encrypt given block data"}, + {"info", CmdHFiClassInfo, AlwaysAvailable, " Tag information"}, {"list", CmdHFiClassList, AlwaysAvailable, " List iClass history"}, {"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"}, {"managekeys", CmdHFiClassManageKeys, AlwaysAvailable, "[options..] Manage the keys to use with iClass"}, {"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"}, {"readtagfile", CmdHFiClassReadTagFile, AlwaysAvailable, "[options..] Display Content from tagfile"}, {"replay", CmdHFiClassReader_Replay, IfPm3Iclass, " Read an iClass tag via Replay Attack"}, {"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iClass tag"}, {"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} };