adapting hf mf cget* commands to longer timeouts. Same with the quick eload used in autopwn among others.\nAlso adapted the return codes, so its more accurate in its reporting back to the client. Also added some more informative messages

This commit is contained in:
iceman1001 2023-07-25 21:29:31 +02:00
parent cb9ee94ed6
commit 1cb15c84c1
3 changed files with 70 additions and 26 deletions

View file

@ -2365,9 +2365,10 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
}
// timeout already in ms + 100ms guard time
if (GetTickCountDelta(receive_timer) > timeout + 100)
if (GetTickCountDelta(receive_timer) > timeout + 100) {
break;
}
}
return false;
}
@ -2401,15 +2402,17 @@ void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing) {
}
static uint16_t ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, offset))
if (GetIso14443aAnswerFromTag(receivedAnswer, par, offset) == false) {
return 0;
}
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
return Demod.len;
}
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, par, 0))
if (GetIso14443aAnswerFromTag(receivedAnswer, par, 0) == false) {
return 0;
}
LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false);
return Demod.len;
}

View file

@ -73,10 +73,11 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
struct Crypto1State *pcs = &mpcs;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(true);
uint32_t timeout = iso14a_get_timeout();
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
@ -95,6 +96,10 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
goto OUT;
};
// frame waiting time (FWT) in 1/fc
uint32_t fwt = 256 * 16 * (1 << 6);
iso14a_set_timeout(fwt / (8 * 16));
for (uint8_t i = 0; i < count; i++) {
if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block error");
@ -112,11 +117,11 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c
OUT:
crypto1_deinit(pcs);
iso14a_set_timeout(timeout);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
set_tracing(false);
BigBuf_free();
return retval;
}
@ -2072,6 +2077,12 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
int retval = PM3_SUCCESS;
// increase time-out. Magic card etc are slow
uint32_t timeout = iso14a_get_timeout();
// frame waiting time (FWT) in 1/fc
uint32_t fwt = 256 * 16 * (1 << 7);
iso14a_set_timeout(fwt / (8 * 16));
for (uint8_t s = 0; s < sectorcnt; s++) {
uint64_t ui64Key = emlGetKey(s, keytype);
@ -2110,7 +2121,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
// Auth
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) {
retval = PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) {
if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Sector %2d - Auth error", s);
}
continue;
@ -2122,31 +2133,43 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
memset(data, 0x00, sizeof(data));
uint8_t tb = FirstBlockOfSector(s) + b;
uint8_t r = 0;
for (; r < MAX_RETRIES; r++) {
for (uint8_t r = 0; r < MAX_RETRIES; r++) {
if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + b, data)) {
int res = mifare_classic_readblock(pcs, tb, data);
if (res == 1) {
retval |= PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) {
Dbprintf("Error reading sector %2d block %2d", s, b);
if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Error No rights reading sector %2d block %2d", s, b);
}
break;
}
// retry if wrong len.
if (res != 0) {
continue;
}
// No need to copy empty
if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
continue;
break;
}
if (b < NumBlocksPerSector(s) - 1) {
emlSetMem(data, FirstBlockOfSector(s) + b, 1);
} else {
if (IsSectorTrailer(b)) {
// sector trailer, keep the keys, set only the AC
uint8_t st[16] = {0x00};
emlGetMem(st, FirstBlockOfSector(s) + b, 1);
emlGetMem(st, tb, 1);
memcpy(st + 6, data + 6, 4);
emlSetMem(st, FirstBlockOfSector(s) + b, 1);
emlSetMem(st, tb, 1);
} else {
emlSetMem(data, tb, 1);
}
break;
}
// if we failed all retries, notify client
if (r == MAX_RETRIES) {
retval |= PM3_EPARTIAL;
}
}
}
@ -2154,6 +2177,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
int res = mifare_classic_halt(pcs);
(void)res;
iso14a_set_timeout(timeout);
crypto1_deinit(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
@ -2322,6 +2346,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
set_tracing(true);
}
// increase time-out. Magic card etc are slow
uint32_t timeout = iso14a_get_timeout();
// frame waiting time (FWT) in 1/fc
uint32_t fwt = 256 * 16 * (1 << 7);
iso14a_set_timeout(fwt / (8 * 16));
//loop doesn't loop just breaks out if error or done
while (true) {
if (workFlags & MAGIC_WUPC) {
@ -2343,7 +2373,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
}
// read block
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != MAX_MIFARE_FRAME_SIZE)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("read block send command error");
errormsg = 0;
break;
@ -2371,6 +2401,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
if (workFlags & MAGIC_OFF)
OnSuccessMagic();
iso14a_set_timeout(timeout);
}
void MifareCIdent(bool is_mfc) {

View file

@ -116,7 +116,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
uint16_t len = ReaderReceive(answer, par);
if (answer_parity) *answer_parity = par[0];
if (answer_parity) {
*answer_parity = par[0];
}
if (pcs && (crypted == CRYPT_ALL)) {
if (len == 1) {
@ -127,10 +129,11 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3;
answer[0] = res;
} else {
for (pos = 0; pos < len; pos++)
for (pos = 0; pos < len; pos++) {
answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos];
}
}
}
return len;
}
@ -238,11 +241,15 @@ int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8
uint16_t len = mifare_sendcmd_short(pcs, 1, iso_byte, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]);
if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Cmd Error %02x", blockNo, iso_byte, receivedAnswer[0]);
}
return 1;
}
if (len != 18) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("wrong response len %d (expected 18)", len);
if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Wrong response len, expected 18 got " _RED_("%d"), blockNo, iso_byte, len);
}
return 2;
}
@ -701,13 +708,15 @@ void emlClearMem(void) {
uint8_t SectorTrailer(uint8_t blockNo) {
if (blockNo <= MIFARE_2K_MAXBLOCK) {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
}
return (blockNo | 0x03);
} else {
if (g_dbglevel >= DBG_EXTENDED)
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));
return (blockNo | 0x0f);
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0F));
}
return (blockNo | 0x0F);
}
}