Merge branch 'master' into reason

Signed-off-by: Iceman <iceman@iuse.se>
This commit is contained in:
Iceman 2024-10-04 11:12:49 +03:00 committed by GitHub
commit e431d33fd5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 406 additions and 179 deletions

View file

@ -4,6 +4,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased] ## [unreleased][unreleased]
- Changed split PacketResponseNG status into status and reason(@douniwan5788) - Changed split PacketResponseNG status into status and reason(@douniwan5788)
- add a helper script to decode JEDEC data `script run spi_flash_decode` (@ANTodorov)
- show SPI flash JEDEC Manufacturer ID and Device ID in `hw status` output (@ANTodorov)
- Improved `hf iclass configcards` to support generating config cards using a different key than the default k0 as the card's key (@antiklesys)
- Added maur keys (@iceman1001) - Added maur keys (@iceman1001)
- Fixed `hf mfu pwdgen` for the 7 byte UID (@ANTodorov) - Fixed `hf mfu pwdgen` for the 7 byte UID (@ANTodorov)
- Added `hf iclass unhash` command to reverse an iclass diversified key to hash0 pre-images (@antiklesys) - Added `hf iclass unhash` command to reverse an iclass diversified key to hash0 pre-images (@antiklesys)

View file

@ -2593,13 +2593,13 @@ static void SendForward(uint8_t fwd_bit_count, bool fast) {
// 32FC * 8us == 256us / 21.3 == 12.018 steps. ok // 32FC * 8us == 256us / 21.3 == 12.018 steps. ok
// 16FC * 8us == 128us / 21.3 == 6.009 steps. ok // 16FC * 8us == 128us / 21.3 == 6.009 steps. ok
#ifndef EM_START_GAP #ifndef EM_START_GAP
#define EM_START_GAP 55*8 #define EM_START_GAP (55 * 8)
#endif #endif
fwd_write_ptr = forwardLink_data; fwd_write_ptr = forwardLink_data;
fwd_bit_sz = fwd_bit_count; fwd_bit_sz = fwd_bit_count;
if (! fast) { if (fast == false) {
// Set up FPGA, 125kHz or 95 divisor // Set up FPGA, 125kHz or 95 divisor
LFSetupFPGAForADC(LF_DIVISOR_125, true); LFSetupFPGAForADC(LF_DIVISOR_125, true);
} }
@ -2639,16 +2639,21 @@ void EM4xBruteforce(uint32_t start_pwd, uint32_t n, bool ledcontrol) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitMS(20); WaitMS(20);
if (ledcontrol) LED_A_ON(); if (ledcontrol) LED_A_ON();
LFSetupFPGAForADC(LF_DIVISOR_125, true); LFSetupFPGAForADC(LF_DIVISOR_125, true);
uint32_t candidates_found = 0; uint32_t candidates_found = 0;
for (uint32_t pwd = start_pwd; pwd < 0xFFFFFFFF; pwd++) { for (uint32_t pwd = start_pwd; pwd < 0xFFFFFFFF; pwd++) {
if (((pwd - start_pwd) & 0x3F) == 0x00) { if (((pwd - start_pwd) & 0x3F) == 0x00) {
WDT_HIT(); WDT_HIT();
if (BUTTON_PRESS() || data_available()) { if (BUTTON_PRESS() || data_available()) {
Dbprintf("EM4x05 Bruteforce Interrupted"); Dbprintf("EM4x05 Bruteforce Interrupted");
break; break;
} }
} }
// Report progress every 256 attempts // Report progress every 256 attempts
if (((pwd - start_pwd) & 0xFF) == 0x00) { if (((pwd - start_pwd) & 0xFF) == 0x00) {
Dbprintf("Trying: %06Xxx", pwd >> 8); Dbprintf("Trying: %06Xxx", pwd >> 8);
@ -2662,7 +2667,9 @@ void EM4xBruteforce(uint32_t start_pwd, uint32_t n, bool ledcontrol) {
WaitUS(400); WaitUS(400);
DoPartialAcquisition(0, false, 350, 1000, ledcontrol); DoPartialAcquisition(0, false, 350, 1000, ledcontrol);
uint8_t *mem = BigBuf_get_addr(); uint8_t *mem = BigBuf_get_addr();
if (mem[334] < 128) { if (mem[334] < 128) {
candidates_found++; candidates_found++;
Dbprintf("Password candidate: " _GREEN_("%08X"), pwd); Dbprintf("Password candidate: " _GREEN_("%08X"), pwd);
@ -2671,6 +2678,7 @@ void EM4xBruteforce(uint32_t start_pwd, uint32_t n, bool ledcontrol) {
break; break;
} }
} }
// Beware: if smaller, tag might not have time to be back in listening state yet // Beware: if smaller, tag might not have time to be back in listening state yet
WaitMS(1); WaitMS(1);
} }
@ -2719,7 +2727,9 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd, bool ledcontrol) {
* 0000 1010 ok * 0000 1010 ok
* 0000 0001 fail * 0000 0001 fail
**/ **/
if (usepwd) EM4xLoginEx(pwd); if (usepwd) {
EM4xLoginEx(pwd);
}
forward_ptr = forwardLink_data; forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_READ); uint8_t len = Prepare_Cmd(FWD_CMD_READ);
@ -2754,7 +2764,9 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd, bo
* 0000 1010 ok. * 0000 1010 ok.
* 0000 0001 fail * 0000 0001 fail
**/ **/
if (usepwd) EM4xLoginEx(pwd); if (usepwd) {
EM4xLoginEx(pwd);
}
forward_ptr = forwardLink_data; forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE); uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
@ -2797,7 +2809,9 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd, bool ledcontro
* 0000 1010 ok. * 0000 1010 ok.
* 0000 0001 fail * 0000 0001 fail
**/ **/
if (usepwd) EM4xLoginEx(pwd); if (usepwd) {
EM4xLoginEx(pwd);
}
forward_ptr = forwardLink_data; forward_ptr = forwardLink_data;
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT); uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);

View file

@ -0,0 +1,86 @@
#!/usr/bin/env python3
import re
import pm3
# optional color support
try:
# pip install ansicolors
from colors import color
except ModuleNotFoundError:
def color(s, fg=None):
_ = fg
return str(s)
spi = {
0x85:{
"manufacturer": "Puya",
0x60: {
0x15: {
"part": "P25Q16H",
"size": "16mbits",
"sizeB": "2MB",
},
},
},
0xEF:{
"manufacturer": "Winbond",
0x30: {
0x11: {
"part": "W25X10BV",
"size": "1mbits",
"sizeB": "128KB",
},
0x12: {
"part": "W25X20BV",
"size": "2mbits",
"sizeB": "256KB",
},
0x13: {
"part": "W25X40BV",
"size": "4mbits",
"sizeB": "512KB",
},
},
0x70: {
0x22: {
"part": "W25Q02JV-IM",
"size": "2mbits",
"sizeB": "256KB",
},
},
},
}
p = pm3.pm3()
p.console("hw status")
rex = re.compile("...\s([0-9a-fA-F]{2})\s/\s([0-9a-fA-F]{4})")
for line in p.grabbed_output.split('\n'):
# [#] JEDEC Mfr ID / Dev ID... 85 / 6015
if " JEDEC " not in line:
continue
match = re.findall(rex, line)
mid = int(match[0][0], 16)
did = int(match[0][1], 16)
did_h = did >> 8
did_l = did & 0xff
t = None
if mid in spi:
mfr = spi[mid]['manufacturer']
if did_h in spi[mid]:
if did_l in spi[mid][did_h]:
t = spi[mid][did_h][did_l]
print("\n Manufacturer... " + color(f"{mfr}", fg="green") +
"\n Device......... " + color(f"{t['part']}", fg="green") +
"\n Size........... " + color(f"{t['size']} ({t['sizeB']})", fg="yellow")
)
else:
print("\n Manufacturer... " + color(f"{mfr}", fg="green") +
"\n Device ID...... " + color(f"{did:04X}h (unknown)", fg="red"))
else:
print("\n Manufacturer... " + color(f"{mfr}", fg="green") +
"\n Device ID...... " + color(f"{did:04X}h (unknown)", fg="red"))
else:
print("\n Manufacturer... " + color(f"{mid:02X}h (unknown)", fg="red") +
"\n Device ID...... " + color(f"{did:04X}h (unknown)", fg="red"))

View file

@ -262,9 +262,9 @@ static int CmdFlashMemSpiFFSRemove(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_REMOVE, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_SPIFFS_REMOVE, (uint8_t *)&payload, sizeof(payload));
WaitForResponse(CMD_SPIFFS_REMOVE, &resp); WaitForResponse(CMD_SPIFFS_REMOVE, &resp);
if (resp.status == PM3_SUCCESS) if (resp.status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Done!"); PrintAndLogEx(INFO, "Done!");
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -310,8 +310,9 @@ static int CmdFlashMemSpiFFSRename(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_RENAME, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_SPIFFS_RENAME, (uint8_t *)&payload, sizeof(payload));
WaitForResponse(CMD_SPIFFS_RENAME, &resp); WaitForResponse(CMD_SPIFFS_RENAME, &resp);
if (resp.status == PM3_SUCCESS) if (resp.status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Done!"); PrintAndLogEx(INFO, "Done!");
}
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
@ -358,8 +359,9 @@ static int CmdFlashMemSpiFFSCopy(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_COPY, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_SPIFFS_COPY, (uint8_t *)&payload, sizeof(payload));
WaitForResponse(CMD_SPIFFS_COPY, &resp); WaitForResponse(CMD_SPIFFS_COPY, &resp);
if (resp.status == PM3_SUCCESS) if (resp.status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Done!"); PrintAndLogEx(INFO, "Done!");
}
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
@ -474,8 +476,9 @@ static int CmdFlashMemSpiFFSWipe(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0); SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0);
WaitForResponse(CMD_SPIFFS_WIPE, &resp); WaitForResponse(CMD_SPIFFS_WIPE, &resp);
if (resp.status == PM3_SUCCESS) if (resp.status == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Done!"); PrintAndLogEx(INFO, "Done!");
}
PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -516,7 +516,7 @@ int CmdHFSniff(const char *Cmd) {
} }
} }
} }
PrintAndLogEx(INFO, "Done."); PrintAndLogEx(INFO, "Done!");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -457,23 +457,27 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
memcpy(card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if (select_status == 0) { if (select_status == 0) {
PrintAndLogEx(ERR, "E->iso14443a card select failed"); PrintAndLogEx(ERR, "iso14443a card select failed");
return PM3_EFAILED; return PM3_EFAILED;
} }
if (select_status == 2) { if (select_status == 2) {
PrintAndLogEx(ERR, "E->Card doesn't support iso14443-4 mode"); PrintAndLogEx(ERR, "Card doesn't support iso14443-4 mode");
return PM3_EFAILED; return PM3_EFAILED;
} }
if (select_status == 3) { if (select_status == 3) {
PrintAndLogEx(INFO, "E->Card doesn't support standard iso14443-3 anticollision"); PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
// identify TOPAZ // identify TOPAZ
if (card->atqa[1] == 0x0C && card->atqa[0] == 0x00) { if (card->atqa[1] == 0x0C && card->atqa[0] == 0x00) {
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`")); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`"));
@ -489,7 +493,7 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
// a valid ATS consists of at least the length byte (TL) and 2 CRC bytes // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
if (card->ats_len < 3) { if (card->ats_len < 3) {
PrintAndLogEx(INFO, "E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); PrintAndLogEx(INFO, "Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len));
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
@ -754,9 +758,12 @@ static int CmdHF14ACUIDs(const char *Cmd) {
// execute anticollision procedure // execute anticollision procedure
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp);
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
iso14a_card_select_t *card = (iso14a_card_select_t *) resp.data.asBytes; iso14a_card_select_t *card = (iso14a_card_select_t *) resp.data.asBytes;
@ -773,7 +780,7 @@ static int CmdHF14ACUIDs(const char *Cmd) {
} }
} }
PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock() - t1) / 1000); PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock() - t1) / 1000);
return 1; return PM3_SUCCESS;
} }
// ## simulate iso14443a tag // ## simulate iso14443a tag
@ -1051,7 +1058,7 @@ int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
} }
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "command execution time out"); PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
@ -2217,7 +2224,11 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
// reconnect for further tests // reconnect for further tests
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
DropField();
return PM3_ETIMEOUT;
}
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
@ -2273,7 +2284,10 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats)); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats));
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
memcpy(card.ats, resp.data.asBytes, resp.oldarg[0]); memcpy(card.ats, resp.data.asBytes, resp.oldarg[0]);
card.ats_len = resp.oldarg[0]; // note: ats_len includes CRC Bytes card.ats_len = resp.oldarg[0]; // note: ats_len includes CRC Bytes

View file

@ -1179,7 +1179,9 @@ static void hf15EmlClear(void) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_EML_CLEAR, NULL, 0); SendCommandNG(CMD_HF_ISO15693_EML_CLEAR, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_HF_ISO15693_EML_CLEAR, &resp); if (WaitForResponseTimeout(CMD_HF_ISO15693_EML_CLEAR, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
}
} }
static int hf15EmlSetMem(const uint8_t *data, uint16_t count, size_t offset) { static int hf15EmlSetMem(const uint8_t *data, uint16_t count, size_t offset) {

View file

@ -647,6 +647,17 @@ static int CmdHFCipurseReadFile(const char *Cmd) {
PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " offset " _YELLOW_("%zu") " key id " _YELLOW_("%d") " key " _YELLOW_("%s"), fileId, offset, keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)); PrintAndLogEx(INFO, "File id " _YELLOW_("%x") " offset " _YELLOW_("%zu") " key id " _YELLOW_("%d") " key " _YELLOW_("%s"), fileId, offset, keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH));
} }
res = CIPURSESelectFile(fileId, buf, sizeof(buf), &len, &sw);
if (res != 0 || sw != ISO7816_OK) {
if (verbose == false)
PrintAndLogEx(ERR, "File select ( " _RED_("error") " ). Card returns 0x%04x", sw);
DropField();
return PM3_ESOFT;
}
if (verbose)
PrintAndLogEx(INFO, "Select file 0x%x ( %s )", fileId, _GREEN_("ok"));
if (noAuth == false) { if (noAuth == false) {
bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose);
if (bres == false) { if (bres == false) {
@ -660,17 +671,6 @@ static int CmdHFCipurseReadFile(const char *Cmd) {
CIPURSECSetActChannelSecurityLevels(sreq, sresp); CIPURSECSetActChannelSecurityLevels(sreq, sresp);
} }
res = CIPURSESelectFile(fileId, buf, sizeof(buf), &len, &sw);
if (res != 0 || sw != ISO7816_OK) {
if (verbose == false)
PrintAndLogEx(ERR, "File select ( " _RED_("error") " ). Card returns 0x%04x", sw);
DropField();
return PM3_ESOFT;
}
if (verbose)
PrintAndLogEx(INFO, "Select file 0x%x ( %s )", fileId, _GREEN_("ok"));
res = CIPURSEReadBinary(offset, buf, sizeof(buf), &len, &sw); res = CIPURSEReadBinary(offset, buf, sizeof(buf), &len, &sw);
if (res != 0 || sw != ISO7816_OK) { if (res != 0 || sw != ISO7816_OK) {
if (verbose == false) if (verbose == false)
@ -776,6 +776,17 @@ static int CmdHFCipurseWriteFile(const char *Cmd) {
PrintAndLogEx(INFO, "Data [%d]: %s", hdatalen, sprint_hex(hdata, hdatalen)); PrintAndLogEx(INFO, "Data [%d]: %s", hdatalen, sprint_hex(hdata, hdatalen));
} }
res = CIPURSESelectFile(fileId, buf, sizeof(buf), &len, &sw);
if (res != 0 || sw != ISO7816_OK) {
if (verbose == false)
PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw);
DropField();
return PM3_ESOFT;
}
if (verbose)
PrintAndLogEx(INFO, "Select file 0x%x ( %s )", fileId, _GREEN_("ok"));
if (noAuth == false) { if (noAuth == false) {
bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose); bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose);
if (bres == false) { if (bres == false) {
@ -789,17 +800,6 @@ static int CmdHFCipurseWriteFile(const char *Cmd) {
CIPURSECSetActChannelSecurityLevels(sreq, sresp); CIPURSECSetActChannelSecurityLevels(sreq, sresp);
} }
res = CIPURSESelectFile(fileId, buf, sizeof(buf), &len, &sw);
if (res != 0 || sw != ISO7816_OK) {
if (verbose == false)
PrintAndLogEx(ERR, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw);
DropField();
return PM3_ESOFT;
}
if (verbose)
PrintAndLogEx(INFO, "Select file 0x%x ( %s )", fileId, _GREEN_("ok"));
res = CIPURSEUpdateBinary(offset, hdata, hdatalen, buf, sizeof(buf), &len, &sw); res = CIPURSEUpdateBinary(offset, hdata, hdatalen, buf, sizeof(buf), &len, &sw);
if (res != 0 || sw != ISO7816_OK) { if (res != 0 || sw != ISO7816_OK) {
if (verbose == false) if (verbose == false)

View file

@ -73,7 +73,6 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) {
PacketResponseNG resp; PacketResponseNG resp;
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_EPA_COLLECT_NONCE, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_HF_EPA_COLLECT_NONCE, (uint8_t *)&payload, sizeof(payload));
WaitForResponse(CMD_HF_EPA_COLLECT_NONCE, &resp); WaitForResponse(CMD_HF_EPA_COLLECT_NONCE, &resp);
// check if command failed // check if command failed
@ -241,7 +240,6 @@ static int CmdHFEPAPACESimulate(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_EPA_PACE_SIMULATE, 0, 0, 0, pwd, plen); SendCommandMIX(CMD_HF_EPA_PACE_SIMULATE, 0, 0, 0, pwd, plen);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); WaitForResponse(CMD_ACK, &resp);

View file

@ -1088,7 +1088,7 @@ static int CmdGallagherClone(const char *cmd) {
PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating Gallagher credential file"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating Gallagher credential file");
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1169,7 +1169,7 @@ static int CmdGallagherDelete(const char *cmd) {
PM3_RET_IF_ERR_WITH_MSG(res, "Failed deleting Gallagher application"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed deleting Gallagher application");
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -283,7 +283,7 @@ static void iclass_encrypt_block_data(uint8_t *blk_data, uint8_t *key) {
mbedtls_des3_free(&ctx); mbedtls_des3_free(&ctx);
} }
static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *key, bool got_kr) { static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *key, bool got_kr, uint8_t *card_key, bool got_krki, bool use_elite) {
if (check_config_card(o) == false) { if (check_config_card(o) == false) {
return PM3_EINVARG; return PM3_EINVARG;
} }
@ -294,8 +294,13 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
memcpy(configcard.csn, "\x41\x87\x66\x00\xFB\xFF\x12\xE0", 8); memcpy(configcard.csn, "\x41\x87\x66\x00\xFB\xFF\x12\xE0", 8);
memcpy(&configcard.conf, "\xFF\xFF\xFF\xFF\xF9\xFF\xFF\xBC", 8); memcpy(&configcard.conf, "\xFF\xFF\xFF\xFF\xF9\xFF\xFF\xBC", 8);
memcpy(&configcard.epurse, "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8); memcpy(&configcard.epurse, "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8);
// defaulting to known AA1 key
HFiClassCalcDivKey(configcard.csn, iClass_Key_Table[0], configcard.key_d, false); if (got_krki) {
HFiClassCalcDivKey(configcard.csn, card_key, configcard.key_d, use_elite);
} else {
// defaulting to AA1 ki 0
HFiClassCalcDivKey(configcard.csn, iClass_Key_Table[0], configcard.key_d, use_elite);
}
// reference // reference
picopass_hdr_t *cc = &configcard; picopass_hdr_t *cc = &configcard;
@ -306,7 +311,12 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
cc = &iclass_last_known_card; cc = &iclass_last_known_card;
// calc diversified key for selected card // calc diversified key for selected card
HFiClassCalcDivKey(cc->csn, iClass_Key_Table[0], cc->key_d, false); if (got_krki) {
HFiClassCalcDivKey(cc->csn, card_key, cc->key_d, use_elite);
} else {
// defaulting to AA1 ki 0
HFiClassCalcDivKey(cc->csn, iClass_Key_Table[0], cc->key_d, use_elite);
}
} else { } else {
PrintAndLogEx(FAILED, "failed to read a card"); PrintAndLogEx(FAILED, "failed to read a card");
PrintAndLogEx(INFO, "falling back to default config card"); PrintAndLogEx(INFO, "falling back to default config card");
@ -3890,7 +3900,6 @@ static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, u
PacketResponseNG resp; PacketResponseNG resp;
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_RECOVER, (uint8_t *)payload, payload_size); SendCommandNG(CMD_HF_ICLASS_RECOVER, (uint8_t *)payload, payload_size);
WaitForResponse(CMD_HF_ICLASS_RECOVER, &resp); WaitForResponse(CMD_HF_ICLASS_RECOVER, &resp);
if (resp.status == PM3_SUCCESS) { if (resp.status == PM3_SUCCESS) {
@ -4146,13 +4155,14 @@ static int CmdHFiClassUnhash(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass unhash", CLIParserInit(&ctx, "hf iclass unhash",
"Reverses the hash0 function used generate iclass diversified keys after DES encryption, returning the DES crypted CSN.", "Reverses the hash0 function used generate iclass diversified keys after DES encryption,\n"
"hf iclass unhash --divkey B4F12AADC5301A2D" "Function returns the DES crypted CSN. Next step bruteforcing.",
"hf iclass unhash -k B4F12AADC5301A2D"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str1(NULL, "divkey", "<hex>", "The card's Diversified Key value"), arg_str1("k", "divkey", "<hex>", "Card diversified key"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -4164,14 +4174,17 @@ static int CmdHFiClassUnhash(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
if (dk_len && dk_len != PICOPASS_BLOCK_SIZE) { if (dk_len && dk_len != PICOPASS_BLOCK_SIZE) {
PrintAndLogEx(ERR, "Diversified Key is incorrect length"); PrintAndLogEx(ERR, "Diversified key is incorrect length");
return PM3_EINVARG; return PM3_EINVARG;
} }
PrintAndLogEx(INFO, _YELLOW_("Div Key: ")"%s", sprint_hex(div_key, sizeof(div_key))); PrintAndLogEx(INFO, "Diversified key... %s", sprint_hex_inrow(div_key, sizeof(div_key)));
invert_hash0(div_key); invert_hash0(div_key);
PrintAndLogEx(SUCCESS, "You can now retrieve the master key by cracking DES with hashcat!");
PrintAndLogEx(SUCCESS, "hashcat.exe -a 3 -m 14000 preimage:csn -1 charsets/DES_full.hcchr --hex-charset ?1?1?1?1?1?1?1?1");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -4907,7 +4920,9 @@ static int CmdHFiClassConfigCard(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_int0(NULL, "ci", "<dec>", "use config slot at index"), arg_int0(NULL, "ci", "<dec>", "use config slot at index"),
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"), arg_int0(NULL, "ki", "<dec>", "Card Key - index to select key from memory 'hf iclass managekeys'"),
arg_int0(NULL, "krki", "<dec>", "Elite Keyroll Key - index to select key from memory 'hf iclass managekeys'"),
arg_lit0(NULL, "elite", "Use elite key for the the Card Key ki"),
arg_lit0("g", NULL, "generate card dump file"), arg_lit0("g", NULL, "generate card dump file"),
arg_lit0("l", NULL, "load available cards"), arg_lit0("l", NULL, "load available cards"),
arg_lit0("p", NULL, "print available cards"), arg_lit0("p", NULL, "print available cards"),
@ -4916,19 +4931,34 @@ static int CmdHFiClassConfigCard(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int ccidx = arg_get_int_def(ctx, 1, -1); int ccidx = arg_get_int_def(ctx, 1, -1);
int kidx = arg_get_int_def(ctx, 2, -1); int card_kidx = arg_get_int_def(ctx, 2, -1);
bool do_generate = arg_get_lit(ctx, 3); int kidx = arg_get_int_def(ctx, 3, -1);
bool do_load = arg_get_lit(ctx, 4); bool elite = arg_get_lit(ctx, 4);
bool do_print = arg_get_lit(ctx, 5); bool do_generate = arg_get_lit(ctx, 5);
bool do_load = arg_get_lit(ctx, 6);
bool do_print = arg_get_lit(ctx, 7);
CLIParserFree(ctx); CLIParserFree(ctx);
bool got_krki = false;
uint8_t card_key[8] = {0};
if (card_kidx >= 0) {
if (card_kidx < ICLASS_KEYS_MAX) {
got_krki = true;
memcpy(card_key, iClass_Key_Table[card_kidx], 8);
PrintAndLogEx(SUCCESS, "Using card key[%d] " _GREEN_("%s"), card_kidx, sprint_hex(iClass_Key_Table[card_kidx], 8));
} else {
PrintAndLogEx(ERR, "--krki number is invalid");
return PM3_EINVARG;
}
}
bool got_kr = false; bool got_kr = false;
uint8_t key[8] = {0}; uint8_t keyroll_key[8] = {0};
if (kidx >= 0) { if (kidx >= 0) {
if (kidx < ICLASS_KEYS_MAX) { if (kidx < ICLASS_KEYS_MAX) {
got_kr = true; got_kr = true;
memcpy(key, iClass_Key_Table[kidx], 8); memcpy(keyroll_key, iClass_Key_Table[kidx], 8);
PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), kidx, sprint_hex(iClass_Key_Table[kidx], 8)); PrintAndLogEx(SUCCESS, "Using keyroll key[%d] " _GREEN_("%s"), kidx, sprint_hex(iClass_Key_Table[kidx], 8));
} else { } else {
PrintAndLogEx(ERR, "--ki number is invalid"); PrintAndLogEx(ERR, "--ki number is invalid");
return PM3_EINVARG; return PM3_EINVARG;
@ -4960,7 +4990,7 @@ static int CmdHFiClassConfigCard(const char *Cmd) {
return PM3_EINVARG; return PM3_EINVARG;
} }
} }
generate_config_card(item, key, got_kr); generate_config_card(item, keyroll_key, got_kr, card_key, got_krki, elite);
} }
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -1465,9 +1465,11 @@ static int CmdHF14aDesChk(const char *Cmd) {
DropField(); DropField();
// MIFARE DESFire info // MIFARE DESFire info
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
iso14a_card_select_t card; iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
@ -2173,7 +2175,7 @@ static int CmdHF14ADesBruteApps(const char *Cmd) {
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _GREEN_("Done")); PrintAndLogEx(SUCCESS, _GREEN_("Done!"));
DropField(); DropField();
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -2923,7 +2925,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(SUCCESS, "Desfire format: " _GREEN_("done")); PrintAndLogEx(SUCCESS, "Desfire format: " _GREEN_("done!"));
DropField(); DropField();
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -260,7 +260,7 @@ static void init_bitflip_bitarrays(void) {
#endif #endif
uint64_t init_bitflip_bitarrays_starttime = msclock(); uint64_t init_bitflip_bitarrays_starttime = msclock();
char state_file_name[MAX(strlen(STATE_FILE_TEMPLATE_RAW), MAX(strlen(STATE_FILE_TEMPLATE_LZ4), strlen(STATE_FILE_TEMPLATE_BZ2))) + 1]; char state_file_name[MAX(sizeof(STATE_FILE_TEMPLATE_RAW), MAX(sizeof(STATE_FILE_TEMPLATE_LZ4), sizeof(STATE_FILE_TEMPLATE_BZ2)))];
char state_files_path[strlen(get_my_executable_directory()) + strlen(STATE_FILES_DIRECTORY) + sizeof(state_file_name)]; char state_files_path[strlen(get_my_executable_directory()) + strlen(STATE_FILES_DIRECTORY) + sizeof(state_file_name)];
uint16_t nraw = 0, nlz4 = 0, nbz2 = 0; uint16_t nraw = 0, nlz4 = 0, nbz2 = 0;
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {

View file

@ -317,7 +317,11 @@ static int CmdHFMFPInfo(const char *Cmd) {
// Mifare Plus info // Mifare Plus info
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
PrintAndLogEx(DEBUG, "iso14443a card select timeout");
DropField();
return false;
}
iso14a_card_select_t card; iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
@ -1673,7 +1677,10 @@ static int CmdHFMFPChk(const char *Cmd) {
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
iso14a_card_select_t card; iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));

View file

@ -307,7 +307,10 @@ int ul_read_uid(uint8_t *uid) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
iso14a_card_select_t card; iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
@ -356,7 +359,7 @@ static bool ul_select(iso14a_card_select_t *card) {
ul_switch_on_field(); ul_switch_on_field();
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
PrintAndLogEx(DEBUG, "iso14443a card select timeout"); PrintAndLogEx(DEBUG, "iso14443a card select timeout");
DropField(); DropField();
return false; return false;
@ -4213,7 +4216,11 @@ static int CmdHF14AMfUKeyGen(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
iso14a_card_select_t card; iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));

View file

@ -1673,21 +1673,21 @@ void pm3_version(bool verbose, bool oneliner) {
PrintAndLogEx(NORMAL, " native BT support......... " _YELLOW_("absent")); PrintAndLogEx(NORMAL, " native BT support......... " _YELLOW_("absent"));
#endif #endif
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
PrintAndLogEx(NORMAL, " Python script support..... " _GREEN_("present") " (" _YELLOW_(PY_VERSION) ")"); PrintAndLogEx(NORMAL, " Python script support..... " _GREEN_("present") " ( " _YELLOW_(PY_VERSION) " )");
#else #else
PrintAndLogEx(NORMAL, " Python script support..... " _YELLOW_("absent")); PrintAndLogEx(NORMAL, " Python script support..... " _YELLOW_("absent"));
#endif #endif
#ifdef HAVE_LUA_SWIG
PrintAndLogEx(NORMAL, " Lua SWIG support.......... " _GREEN_("present"));
#else
PrintAndLogEx(NORMAL, " Lua SWIG support.......... " _YELLOW_("absent"));
#endif
PrintAndLogEx(NORMAL, " Lua runtime version....... " _GREEN_(LUA_RELEASE));
#ifdef HAVE_PYTHON_SWIG #ifdef HAVE_PYTHON_SWIG
PrintAndLogEx(NORMAL, " Python SWIG support....... " _GREEN_("present")); PrintAndLogEx(NORMAL, " Python SWIG support....... " _GREEN_("present"));
#else #else
PrintAndLogEx(NORMAL, " Python SWIG support....... " _YELLOW_("absent")); PrintAndLogEx(NORMAL, " Python SWIG support....... " _YELLOW_("absent"));
#endif #endif
PrintAndLogEx(NORMAL, " Lua script support........ " _GREEN_("present") " ( " _YELLOW_("%s.%s.%s") " )", LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
#ifdef HAVE_LUA_SWIG
PrintAndLogEx(NORMAL, " Lua SWIG support.......... " _GREEN_("present"));
#else
PrintAndLogEx(NORMAL, " Lua SWIG support.......... " _YELLOW_("absent"));
#endif
if (g_session.pm3_present) { if (g_session.pm3_present) {
PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Proxmark3") " ]"); PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Proxmark3") " ]");

View file

@ -433,7 +433,7 @@ static int CmdAWIDClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf awid reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf awid reader`") " to verify");
return res; return res;
} }

View file

@ -212,7 +212,7 @@ static int CmdDestronClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf destron reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf destron reader`") " to verify");
return res; return res;
} }

View file

@ -799,12 +799,15 @@ static int CmdEM410xClone(const char *Cmd) {
payload.low = (uint32_t)id; payload.low = (uint32_t)id;
SendCommandNG(CMD_LF_EM410X_CLONE, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_LF_EM410X_CLONE, (uint8_t *)&payload, sizeof(payload));
WaitForResponse(CMD_LF_EM410X_CLONE, &resp); if (WaitForResponseTimeout(CMD_LF_EM410X_CLONE, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
} }
switch (resp.status) { switch (resp.status) {
case PM3_SUCCESS: { case PM3_SUCCESS: {
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify");
break; break;
} }

View file

@ -340,7 +340,10 @@ static int CmdEM4x50Login(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
PacketResponseNG resp; PacketResponseNG resp;
SendCommandNG(CMD_LF_EM4X50_LOGIN, (uint8_t *)&password, sizeof(password)); SendCommandNG(CMD_LF_EM4X50_LOGIN, (uint8_t *)&password, sizeof(password));
WaitForResponse(CMD_LF_EM4X50_LOGIN, &resp); if (WaitForResponseTimeout(CMD_LF_EM4X50_LOGIN, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
// print response // print response
if (resp.status == PM3_SUCCESS) if (resp.status == PM3_SUCCESS)

View file

@ -802,7 +802,7 @@ static int CmdFdxBClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf fdxb reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf fdxb reader`") " to verify");
return res; return res;
} }

View file

@ -276,7 +276,7 @@ static int CmdGallagherClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gallagher reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gallagher reader`") " to verify");
return res; return res;
} }

View file

@ -331,7 +331,7 @@ static int CmdGuardClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gproxii reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gproxii reader`") " to verify");
return res; return res;
} }

View file

@ -58,8 +58,9 @@ static int sendPing(void) {
SendCommandNG(CMD_PING, NULL, 0); SendCommandNG(CMD_PING, NULL, 0);
clearCommandBuffer(); clearCommandBuffer();
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_PING, &resp, 1000)) if (WaitForResponseTimeout(CMD_PING, &resp, 1000) == false) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, bool verbose) { static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, bool verbose) {
@ -470,15 +471,17 @@ static int CmdHIDClone(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_LF_HID_CLONE, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_LF_HID_CLONE, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_LF_HID_CLONE, &resp); if (WaitForResponseTimeout(CMD_LF_HID_CLONE, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
if (resp.status == PM3_SUCCESS) { if (resp.status == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf hid reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf hid reader`") " to verify");
PrintAndLogEx(INFO, "Done!");
} else { } else {
PrintAndLogEx(FAILED, "cloning ( " _RED_("fail") " )"); PrintAndLogEx(FAILED, "cloning ( " _RED_("fail") " )");
} }
return resp.status; return resp.status;
} }

View file

@ -226,7 +226,7 @@ static int CmdIdteckClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf idteck reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf idteck reader`") " to verify");
return res; return res;
} }

View file

@ -945,7 +945,7 @@ static int CmdIndalaClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf indala reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf indala reader`") " to verify");
return res; return res;
} }

View file

@ -358,7 +358,7 @@ static int CmdIOProxClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf io reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf io reader`") " to verify");
return res; return res;
} }

View file

@ -240,7 +240,7 @@ static int CmdJablotronClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf jablotron reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf jablotron reader`") " to verify");
return res; return res;
} }

View file

@ -309,7 +309,7 @@ static int CmdKeriClone(const char *Cmd) {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf keri read`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf keri read`") " to verify");
return res; return res;
} }

View file

@ -253,7 +253,7 @@ static int CmdMotorolaClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf motorola reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf motorola reader`") " to verify");
return res; return res;
} }

View file

@ -472,7 +472,7 @@ static int CmdLFNedapClone(const char *Cmd) {
} else { } else {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nedap reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nedap reader`") " to verify");
return res; return res;
} }

View file

@ -447,7 +447,7 @@ static int CmdNexWatchClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nexwatch reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nexwatch reader`") " to verify");
return res; return res;
} }

View file

@ -220,7 +220,7 @@ static int CmdNoralsyClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf noralsy reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf noralsy reader`") " to verify");
return res; return res;
} }

View file

@ -304,7 +304,7 @@ static int CmdPacClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pac reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pac reader`") " to verify");
return res; return res;
} }

View file

@ -383,7 +383,7 @@ static int CmdParadoxClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf paradox read`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf paradox read`") " to verify");
return res; return res;
} }

View file

@ -193,7 +193,7 @@ static int CmdLFPCF7931Write(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_LF_PCF7931_WRITE, block, idx, data[0], buf, sizeof(buf)); SendCommandMIX(CMD_LF_PCF7931_WRITE, block, idx, data[0], buf, sizeof(buf));
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 reader`") " to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -264,7 +264,7 @@ static int CmdPrescoClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf presco reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf presco reader`") " to verify");
return res; return res;
} }

View file

@ -355,7 +355,7 @@ static int CmdPyramidClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pyramid reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pyramid reader`") " to verify");
return res; return res;
} }

View file

@ -232,7 +232,7 @@ static int CmdSecurakeyClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf securakey reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf securakey reader`") " to verify");
return res; return res;
} }

View file

@ -369,7 +369,7 @@ static int CmdTIWrite(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_LF_TI_WRITE, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_LF_TI_WRITE, (uint8_t *)&payload, sizeof(payload));
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf ti reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf ti reader`") " to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -137,7 +137,7 @@ static int CmdVerichipClone(const char *Cmd) {
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf verichip read`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf verichip read`") " to verify");
return res; return res;
} }

View file

@ -176,7 +176,7 @@ static int CmdVikingClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf viking reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf viking reader`") " to verify");
return resp.status; return resp.status;
} }

View file

@ -244,7 +244,7 @@ static int CmdVisa2kClone(const char *Cmd) {
} else { } else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf visa2000 reader`") " to verify");
return res; return res;
} }

View file

@ -424,21 +424,25 @@ void invert_hash0(uint8_t k[8]) {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
y |= ((k[i] & 0x80) >> (7 - i)); // Recover the bit of y from the leftmost bit of k[i] y |= ((k[i] & 0x80) >> (7 - i)); // Recover the bit of y from the leftmost bit of k[i]
pushbackSixBitByte(&zTilde, (k[i] & 0x7E) >> 1, i); // Recover the six bits of zTilde from the middle of k[i] pushbackSixBitByte(&zTilde, (k[i] & 0x7E) >> 1, i); // Recover the six bits of zTilde from the middle of k[i]
if (g_debugMode > 0)printState("z~", zTilde);
if (g_debugMode > 0) printState("z~", zTilde);
p |= ((k[i] & 0x01) << i); p |= ((k[i] & 0x01) << i);
} }
if (g_debugMode > 0)PrintAndLogEx(INFO, " y : %02x", y); //value of y (recovered 1 byte of the pre-image)
//check if p is part of the array pi, if not invert it if (g_debugMode > 0) PrintAndLogEx(INFO, " y : %02x", y); // value of y (recovered 1 byte of the pre-image)
if (g_debugMode > 0)PrintAndLogEx(INFO, " p : %02x", p); //value of p (at some point in the original hash0) // check if p is part of the array pi, if not invert it
if (g_debugMode > 0) PrintAndLogEx(INFO, " p : %02x", p); // value of p (at some point in the original hash0)
int remainder = find_p_in_pi(p); int remainder = find_p_in_pi(p);
if (remainder < 0) { if (remainder < 0) {
p = ~p; p = ~p;
remainder = find_p_in_pi(p); remainder = find_p_in_pi(p);
} }
if (g_debugMode > 0)PrintAndLogEx(INFO, " p or ~p : %02x", p); //value of p (at some point in the original hash0) if (g_debugMode > 0) PrintAndLogEx(INFO, " p or ~p : %02x", p); // value of p (at some point in the original hash0)
//find possible values of x that can return the same remainder // find possible values of x that can return the same remainder
uint8_t x_count = 0; uint8_t x_count = 0;
uint8_t x_array[8]; uint8_t x_array[8];
for (int x = 0x00; x <= 0xFF; x++) { for (int x = 0x00; x <= 0xFF; x++) {
@ -450,24 +454,31 @@ void invert_hash0(uint8_t k[8]) {
uint8_t pre_image_base[8] = {0}; uint8_t pre_image_base[8] = {0};
pre_image_base[1] = y; pre_image_base[1] = y;
//calculate pre-images based on the potential values of x (should we use pre-flip p and post flip p just in case?)
uint64_t zTil_img[8] = {0}; //8 is the max size it'll have as per max number of X pre-images // calculate pre-images based on the potential values of x. Sshould we use pre-flip p and post flip p just in case?
for (int img = 0; img < x_count; img++) { //for each potential value of x calculate a pre-image uint64_t zTil_img[8] = {0}; // 8 is the max size it'll have as per max number of X pre-images
for (int img = 0; img < x_count; img++) { // for each potential value of x calculate a pre-image
zTil_img[img] = zTilde; zTil_img[img] = zTilde;
pre_image_base[0] = x_array[img]; pre_image_base[0] = x_array[img];
uint8_t pc = p; //redefine and reassociate it here or it'll keep changing through the loops
if (x_array[img] & 1) { //Check if potential x7 is 1, if it is then invert p uint8_t pc = p; // redefine and reassociate it here or it'll keep changing through the loops
if (x_array[img] & 1) { // Check if potential x7 is 1, if it is then invert p
pc = ~p; pc = ~p;
} }
//calculate zTilde for the x preimage
// calculate zTilde for the x preimage
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
uint8_t p_i = (pc >> i) & 0x1; //this is correct!
uint8_t p_i = (pc >> i) & 0x1; // this is correct!
uint8_t zTilde_i = getSixBitByte(zTilde, i) << 1; uint8_t zTilde_i = getSixBitByte(zTilde, i) << 1;
if (k[i] & 0x80) { //this checks the value of the first bit of the byte (value of y_i)
if (k[i] & 0x80) { // this checks the value of the first bit of the byte (value of y_i)
if (p_i) { if (p_i) {
zTilde_i--; zTilde_i--;
} }
zTilde_i = ~zTilde_i; //flip the 6 bit string zTilde_i = ~zTilde_i; // flip the 6 bit string
} else { } else {
zTilde_i |= p_i & 0x1; zTilde_i |= p_i & 0x1;
} }
@ -478,18 +489,19 @@ void invert_hash0(uint8_t k[8]) {
if (g_debugMode > 0) { if (g_debugMode > 0) {
PrintAndLogEx(INFO, _YELLOW_("Testing Pre-Image Base: %s"), sprint_hex(pre_image_base, sizeof(pre_image_base))); PrintAndLogEx(INFO, _YELLOW_("Testing Pre-Image Base: %s"), sprint_hex(pre_image_base, sizeof(pre_image_base)));
PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|"); PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|");
printState("0|0|z~", zTil_img[img]); //we retrieve the values of z~ printState("0|0|z~", zTil_img[img]); // we retrieve the values of z~
PrintAndLogEx(INFO, " p or ~p : %02x", pc); //value of p (at some point in the original hash0) PrintAndLogEx(INFO, " p or ~p : %02x", pc); // value of p (at some point in the original hash0)
} }
//reverse permute
// reverse permute
BitstreamIn_t p_in = { &pc, 8, 0 }; BitstreamIn_t p_in = { &pc, 8, 0 };
uint8_t outbuffer_1[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t outbuffer_1[] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t outbuffer_2[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t outbuffer_2[] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamOut_t out_1 = {outbuffer_1, 0, 0}; BitstreamOut_t out_1 = {outbuffer_1, 0, 0};
BitstreamOut_t out_2 = {outbuffer_2, 0, 0}; BitstreamOut_t out_2 = {outbuffer_2, 0, 0};
reverse_permute(&p_in, zTil_img[img], 0, &out_1, &out_2, false); //sort the bits reverse_permute(&p_in, zTil_img[img], 0, &out_1, &out_2, false); // sort the bits
//Shift z-values down onto the lower segment // Shift z-values down onto the lower segment
uint64_t zCaret_1 = x_bytes_to_num(outbuffer_1, sizeof(outbuffer_1)); uint64_t zCaret_1 = x_bytes_to_num(outbuffer_1, sizeof(outbuffer_1));
zCaret_1 >>= 16; zCaret_1 >>= 16;
uint64_t zCaret_2 = x_bytes_to_num(outbuffer_2, sizeof(outbuffer_2)); uint64_t zCaret_2 = x_bytes_to_num(outbuffer_2, sizeof(outbuffer_2));
@ -497,16 +509,16 @@ void invert_hash0(uint8_t k[8]) {
uint64_t zCaret = zCaret_1 | zCaret_2; uint64_t zCaret = zCaret_1 | zCaret_2;
if (g_debugMode > 0) printState("0|0|z^", zCaret); if (g_debugMode > 0) printState("0|0|z^", zCaret);
//fix the bits values // fix the bits values
uint8_t p_fix = 0x0F; //fix bits mask as the bits will be in 11110000 order uint8_t p_fix = 0x0F; // fix bits mask as the bits will be in 11110000 order
BitstreamIn_t p_in_f = { &p_fix, 8, 0 }; BitstreamIn_t p_in_f = { &p_fix, 8, 0 };
uint8_t outbuffer_f1[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t outbuffer_f1[] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t outbuffer_f2[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t outbuffer_f2[] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamOut_t out_f1 = {outbuffer_f1, 0, 0}; BitstreamOut_t out_f1 = {outbuffer_f1, 0, 0};
BitstreamOut_t out_f2 = {outbuffer_f2, 0, 0}; BitstreamOut_t out_f2 = {outbuffer_f2, 0, 0};
reverse_permute(&p_in_f, zCaret, 0, &out_f1, &out_f2, true); //fixes the bits accordingly reverse_permute(&p_in_f, zCaret, 0, &out_f1, &out_f2, true); // fixes the bits accordingly
//Shift z-values down onto the lower segment // Shift z-values down onto the lower segment
uint64_t zCaret_fixed1 = x_bytes_to_num(outbuffer_f1, sizeof(outbuffer_f1)); uint64_t zCaret_fixed1 = x_bytes_to_num(outbuffer_f1, sizeof(outbuffer_f1));
zCaret_fixed1 >>= 16; zCaret_fixed1 >>= 16;
uint64_t zCaret_fixed2 = x_bytes_to_num(outbuffer_f2, sizeof(outbuffer_f2)); uint64_t zCaret_fixed2 = x_bytes_to_num(outbuffer_f2, sizeof(outbuffer_f2));
@ -518,7 +530,7 @@ void invert_hash0(uint8_t k[8]) {
uint64_t zP = reverse_check(zCaret_fixed); uint64_t zP = reverse_check(zCaret_fixed);
if (g_debugMode > 0) printState("0|0|z'", zP); if (g_debugMode > 0) printState("0|0|z'", zP);
//reverse the modulo transformation in the hash0 function for the six-bit chunks // reverse the modulo transformation in the hash0 function for the six-bit chunks
uint64_t c = 0; uint64_t c = 0;
@ -533,39 +545,48 @@ void invert_hash0(uint8_t k[8]) {
pushbackSixBitByte(&c, zn4, n + 4); pushbackSixBitByte(&c, zn4, n + 4);
} }
//The Hydra: depending on their positions, values 0x00, 0x01, 0x02, 0x03, 0x3c, 0x3d, 0x3e, 0x3f can lead to additional pre-images. // The Hydra: depending on their positions, values 0x00, 0x01, 0x02, 0x03, 0x3c, 0x3d, 0x3e, 0x3f can lead to additional pre-images.
//When these values are present we need to generate additional pre-images if they have the same modulo as other values // When these values are present we need to generate additional pre-images if they have the same modulo as other values
// Initialize an array of pointers to uint64_t (start with one value, initialized to 0) // Initialize an array of pointers to uint64_t (start with one value, initialized to 0)
uint64_t *hydra_heads = (uint64_t *)malloc(sizeof(uint64_t)); // Start with one uint64_t uint64_t *hydra_heads = (uint64_t *)calloc(sizeof(uint64_t), 1); // Start with one uint64_t
hydra_heads[0] = 0; // Initialize first value to 0 hydra_heads[0] = 0; // Initialize first value to 0
int heads_count = 1; // Track number of forks int heads_count = 1; // Track number of forks
// Iterate 4 times as per the original loop // Iterate 4 times as per the original loop
for (int n = 0; n < 8; n++) { for (int n = 0; n < 8; n++) {
uint8_t hydra_head = getSixBitByte(c, n); uint8_t hydra_head = getSixBitByte(c, n);
if (hydra_head <= (n % 4) || hydra_head >= 63 - (n % 4)) { if (hydra_head <= (n % 4) || hydra_head >= 63 - (n % 4)) {
// Create new forks by duplicating existing uint64_t values // Create new forks by duplicating existing uint64_t values
int new_head = heads_count * 2; int new_head = heads_count * 2;
hydra_heads = (uint64_t *)realloc(hydra_heads, new_head * sizeof(uint64_t)); hydra_heads = (uint64_t *)realloc(hydra_heads, new_head * sizeof(uint64_t));
// Duplicate all current values and add the value to both original and new ones // Duplicate all current values and add the value to both original and new ones
for (int i = 0; i < heads_count; i++) { for (int i = 0; i < heads_count; i++) {
// Duplicate current value // Duplicate current value
hydra_heads[heads_count + i] = hydra_heads[i]; hydra_heads[heads_count + i] = hydra_heads[i];
uint8_t small_hydra_head = 0; uint8_t small_hydra_head = 0;
uint8_t big_hydra_head = 0; uint8_t big_hydra_head = 0;
uint8_t hydra_lil_spawns[4] = {0x00, 0x01, 0x02, 0x03}; uint8_t hydra_lil_spawns[4] = {0x00, 0x01, 0x02, 0x03};
uint8_t hydra_big_spawns[4] = {0x3f, 0x3e, 0x3d, 0x3c}; uint8_t hydra_big_spawns[4] = {0x3f, 0x3e, 0x3d, 0x3c};
if (hydra_head <= n % 4) { //check if is in the lower range
//replace with big spawn in one hydra and keep small in another if (hydra_head <= n % 4) { // check if is in the lower range
// replace with big spawn in one hydra and keep small in another
small_hydra_head = hydra_head; small_hydra_head = hydra_head;
for (int fh = 0; fh < 4; fh++) { for (int fh = 0; fh < 4; fh++) {
if (hydra_lil_spawns[fh] == hydra_head) { if (hydra_lil_spawns[fh] == hydra_head) {
big_hydra_head = hydra_big_spawns[fh]; big_hydra_head = hydra_big_spawns[fh];
} }
} }
} else if (hydra_head >= 63 - (n % 4)) { //or the higher range
//replace with small in one hydra and keep big in another } else if (hydra_head >= 63 - (n % 4)) { // or the higher range
// replace with small in one hydra and keep big in another
big_hydra_head = hydra_head; big_hydra_head = hydra_head;
for (int fh = 0; fh < 4; fh++) { for (int fh = 0; fh < 4; fh++) {
if (hydra_big_spawns[fh] == hydra_head) { if (hydra_big_spawns[fh] == hydra_head) {
@ -579,7 +600,8 @@ void invert_hash0(uint8_t k[8]) {
} }
// Update the count of total values // Update the count of total values
heads_count = new_head; heads_count = new_head;
} else { //no hydra head spawns } else {
// no hydra head spawns
for (int i = 0; i < heads_count; i++) { for (int i = 0; i < heads_count; i++) {
pushbackSixBitByte(&hydra_heads[i], hydra_head, n);; pushbackSixBitByte(&hydra_heads[i], hydra_head, n);;
} }
@ -587,14 +609,16 @@ void invert_hash0(uint8_t k[8]) {
} }
for (int i = 0; i < heads_count; i++) { for (int i = 0; i < heads_count; i++) {
//restore the two most significant bytes (x and y)
// restore the two most significant bytes (x and y)
hydra_heads[i] |= ((uint64_t)x_array[img] << 56); hydra_heads[i] |= ((uint64_t)x_array[img] << 56);
hydra_heads[i] |= ((uint64_t)y << 48); hydra_heads[i] |= ((uint64_t)y << 48);
if (g_debugMode > 0) { if (g_debugMode > 0) {
PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|"); PrintAndLogEx(DEBUG, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|");
printState("origin_r1", hydra_heads[i]); printState("origin_r1", hydra_heads[i]);
} }
//reverse the swapZbalues function to get the original six-bit byte order // reverse the swapZbalues function to get the original six-bit byte order
uint64_t original_z = swapZvalues(hydra_heads[i]); uint64_t original_z = swapZvalues(hydra_heads[i]);
if (g_debugMode > 0) { if (g_debugMode > 0) {
@ -602,24 +626,31 @@ void invert_hash0(uint8_t k[8]) {
printState("origin_r2", original_z); printState("origin_r2", original_z);
PrintAndLogEx(INFO, "--------------------------"); PrintAndLogEx(INFO, "--------------------------");
} }
//run pre-image through hash0 // run pre-image through hash0
uint8_t img_div_key[8] = {0}; uint8_t img_div_key[8] = {0};
hash0(original_z, img_div_key); //commented to avoid log spam hash0(original_z, img_div_key); // commented to avoid log spam
//verify result, if it matches add it to the list as a valid pre-image // verify result, if it matches add it to the list as a valid pre-image
bool image_match = true; bool image_match = true;
for (int v = 0; v < 8; v++) { for (int v = 0; v < 8; v++) {
if (img_div_key[v] != k[v]) { //compare against input key k
// compare against input key k
if (img_div_key[v] != k[v]) {
image_match = false; image_match = false;
} }
} }
uint8_t des_pre_image[8] = {0}; uint8_t des_pre_image[8] = {0};
x_num_to_bytes(original_z, sizeof(original_z), des_pre_image); x_num_to_bytes(original_z, sizeof(original_z), des_pre_image);
if (image_match) { if (image_match) {
PrintAndLogEx(INFO, _GREEN_("Valid pre-image: ")_YELLOW_("%s"), sprint_hex(des_pre_image, sizeof(des_pre_image))); PrintAndLogEx(INFO, "Pre-image......... " _YELLOW_("%s") " ( "_GREEN_("valid") " )", sprint_hex_inrow(des_pre_image, sizeof(des_pre_image)));
} else if (!image_match && g_debugMode > 0) { } else {
PrintAndLogEx(INFO, _RED_("Invalid pre-image: %s"), sprint_hex(des_pre_image, sizeof(des_pre_image)));
if (g_debugMode > 0) {
PrintAndLogEx(INFO, "Pre-image......... " _YELLOW_("%s") " ( "_RED_("invalid") " )", sprint_hex_inrow(des_pre_image, sizeof(des_pre_image)));
}
} }
} }
// Free allocated memory // Free allocated memory

View file

@ -3052,7 +3052,10 @@ int DesfireGetCardUID(DesfireContext_t *ctx) {
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
WaitForResponse(CMD_ACK, &resp); if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.oldarg[0]; uint64_t select_status = resp.oldarg[0];

View file

@ -529,7 +529,7 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len) {
while (i < max_len) { while (i < max_len) {
unsigned char c = (unsigned char)data[i]; unsigned char c = (unsigned char)data[i];
tmp[pos + i] = isprint(c) ? c : '.'; tmp[pos + i] = (isprint(c) && c != 0xff) ? c : '.';
++i; ++i;
} }
out: out:
@ -546,7 +546,7 @@ char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_st
while (i < max_len) { while (i < max_len) {
unsigned char c = (unsigned char)data[i]; unsigned char c = (unsigned char)data[i];
tmp[i] = isprint(c) ? c : '.'; tmp[i] = (isprint(c) && c != 0xff) ? c : '.';
++i; ++i;
} }

View file

@ -49,18 +49,28 @@ void FlashmemSetSpiBaudrate(uint32_t baudrate) {
} }
// read ID out // read ID out
bool Flash_ReadID_90(flash_device_type_90_t *result) { bool Flash_ReadID(flash_device_type_t *result, bool read_jedec) {
if (Flash_CheckBusy(BUSY_TIMEOUT)) return false; if (Flash_CheckBusy(BUSY_TIMEOUT)) return false;
// Manufacture ID / device ID
FlashSendByte(ID);
FlashSendByte(0x00);
FlashSendByte(0x00);
FlashSendByte(0x00);
result->manufacturer_id = FlashSendByte(0xFF); if (read_jedec) {
result->device_id = FlashSendLastByte(0xFF); // 0x9F JEDEC
FlashSendByte(JEDECID);
result->manufacturer_id = FlashSendByte(0xFF);
result->device_id = FlashSendByte(0xFF);
result->device_id2 = FlashSendLastByte(0xFF);
} else {
// 0x90 Manufacture ID / device ID
FlashSendByte(ID);
FlashSendByte(0x00);
FlashSendByte(0x00);
FlashSendByte(0x00);
result->manufacturer_id = FlashSendByte(0xFF);
result->device_id = FlashSendLastByte(0xFF);
}
return true; return true;
} }
@ -346,8 +356,8 @@ void Flashmem_print_status(void) {
// NOTE: It would likely be more useful to use JDEC ID command 9F, // NOTE: It would likely be more useful to use JDEC ID command 9F,
// as it provides a third byte indicative of capacity. // as it provides a third byte indicative of capacity.
flash_device_type_90_t device_type = {0}; flash_device_type_t device_type = {0};
if (!Flash_ReadID_90(&device_type)) { if (!Flash_ReadID(&device_type, false)) {
DbpString(" Device ID............... " _RED_(" --> Not Found <--")); DbpString(" Device ID............... " _RED_(" --> Not Found <--"));
} else { } else {
if (device_type.manufacturer_id == WINBOND_MANID) { if (device_type.manufacturer_id == WINBOND_MANID) {
@ -370,6 +380,13 @@ void Flashmem_print_status(void) {
device_type.device_id device_type.device_id
); );
} }
if (Flash_ReadID(&device_type, true)) {
Dbprintf(" JEDEC Mfr ID / Dev ID... " _YELLOW_("%02X / %02X%02X"),
device_type.manufacturer_id,
device_type.device_id,
device_type.device_id2
);
}
} }
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};

View file

@ -129,8 +129,9 @@ bool Flash_Erase64k(uint8_t block);
typedef struct { typedef struct {
uint8_t manufacturer_id; uint8_t manufacturer_id;
uint8_t device_id; uint8_t device_id;
} flash_device_type_90_t; // to differentiate from JDEC ID via cmd 9F uint8_t device_id2;
bool Flash_ReadID_90(flash_device_type_90_t *result); } flash_device_type_t; // extra device_id used for the JEDEC ID read via cmd 9F
bool Flash_ReadID(flash_device_type_t *result, bool read_jedec);
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len); uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len); uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);

View file

@ -3656,16 +3656,16 @@
}, },
"hf iclass unhash": { "hf iclass unhash": {
"command": "hf iclass unhash", "command": "hf iclass unhash",
"description": "Reverses the hash0 function used generate iclass diversified keys after DES encryption, returning the DES crypted CSN.", "description": "Reverses the hash0 function used generate iclass diversified keys after DES encryption, Function returns the DES crypted CSN. Next step bruteforcing.",
"notes": [ "notes": [
"hf iclass unhash --divkey B4F12AADC5301A2D" "hf iclass unhash -k B4F12AADC5301A2D"
], ],
"offline": true, "offline": true,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"--divkey <hex> The card's Diversified Key value" "-k, --divkey <hex> Card diversified key"
], ],
"usage": "hf iclass unhash [-h] --divkey <hex>" "usage": "hf iclass unhash [-h] -k <hex>"
}, },
"hf iclass view": { "hf iclass view": {
"command": "hf iclass view", "command": "hf iclass view",
@ -12956,6 +12956,6 @@
"metadata": { "metadata": {
"commands_extracted": 747, "commands_extracted": 747,
"extracted_by": "PM3Help2JSON v1.00", "extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2024-09-30T08:35:18" "extracted_on": "2024-10-04T07:43:15"
} }
} }