mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Merge branch 'master' into reason
Signed-off-by: Iceman <iceman@iuse.se>
This commit is contained in:
commit
e431d33fd5
49 changed files with 406 additions and 179 deletions
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
86
client/pyscripts/spi_flash_decode.py
Normal file
86
client/pyscripts/spi_flash_decode.py
Normal 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"))
|
|
@ -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;
|
||||||
|
|
|
@ -516,7 +516,7 @@ int CmdHFSniff(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(INFO, "Done.");
|
PrintAndLogEx(INFO, "Done!");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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") " ]");
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue