Merge pull request #2886 from Antiklesys/master

Updated hf iclass legrec to optionally use shorter delays
This commit is contained in:
Iceman 2025-06-06 11:47:29 +02:00 committed by GitHub
commit 27ce314051
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 22 additions and 9 deletions

View file

@ -1795,7 +1795,7 @@ static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac,
return true;
}
static bool iclass_writeblock_sp(uint8_t blockno, uint8_t *data, uint8_t *mac, bool shallow_mod, uint32_t *start_time, uint32_t *eof_time) {
static bool iclass_writeblock_sp(uint8_t blockno, uint8_t *data, uint8_t *mac, bool shallow_mod, uint32_t *start_time, uint32_t *eof_time, bool short_delay) {
// write command: cmd, 1 blockno, 8 data, 4 mac
uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
@ -1804,7 +1804,12 @@ static bool iclass_writeblock_sp(uint8_t blockno, uint8_t *data, uint8_t *mac, b
memcpy(write + 10, mac, 4);
uint8_t resp[10] = {0};
bool isOK = iclass_send_cmd_with_retries(write, write_len, resp, sizeof(resp), 10, 3, start_time, ICLASS_READER_TIMEOUT_UPDATE, eof_time, shallow_mod);
bool isOK = false;
if(short_delay){
isOK = iclass_send_cmd_with_retries(write, write_len, resp, sizeof(resp), 10, 3, start_time, ICLASS_READER_TIMEOUT_UPDATE_FAST, eof_time, shallow_mod);
}else{
isOK = iclass_send_cmd_with_retries(write, write_len, resp, sizeof(resp), 10, 3, start_time, ICLASS_READER_TIMEOUT_UPDATE, eof_time, shallow_mod);
}
if (isOK == false) {
return false;
}
@ -2642,6 +2647,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
uint8_t fast_previous_key[PICOPASS_BLOCK_SIZE] = {0};
uint8_t fast_current_key[PICOPASS_BLOCK_SIZE] = {0};
uint32_t index = msg->index;
bool short_delay = msg->short_delay;
int bits_found = -1;
bool recovered = false;
bool completed = false;
@ -2841,7 +2847,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
bool write_error = false;
while (written == false && write_error == false) {
//Step5 Perform Write
if (iclass_writeblock_sp(blockno, genkeyblock, mac2, shallow_mod, &start_time, &eof_time)) {
if (iclass_writeblock_sp(blockno, genkeyblock, mac2, shallow_mod, &start_time, &eof_time, short_delay)) {
status_message = 4; //wrote new key on the card - unverified
}
if(!msg->fast){ //if we're going slow we check at every write that the write actually happened
@ -2905,7 +2911,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
if (iclass_writeblock_sp(blockno, genkeyblock, mac2, shallow_mod, &start_time, &eof_time)) {
if (iclass_writeblock_sp(blockno, genkeyblock, mac2, shallow_mod, &start_time, &eof_time, short_delay)) {
status_message = 6; //restore of original key successful but unverified
}
//Do a readcheck first to reset the cypher state
@ -2991,7 +2997,7 @@ fast_restore:
memcpy(wb + 1, fast_restore_key, 8);
doMAC_N(wb, sizeof(wb), div_key2, mac2);
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
if (iclass_writeblock_sp(blockno, fast_restore_key, mac2, shallow_mod, &start_time, &eof_time)) {
if (iclass_writeblock_sp(blockno, fast_restore_key, mac2, shallow_mod, &start_time, &eof_time, short_delay)) {
status_message = 6; //restore of original key successful but unverified
}
//Do a readcheck first to reset the cypher state

View file

@ -34,6 +34,7 @@
// times in samples @ 212kHz when acting as reader
#define ICLASS_READER_TIMEOUT_ACTALL 330 // 1558us, nominal 330us + 7slots*160us = 1450us
#define ICLASS_READER_TIMEOUT_UPDATE 3390 // 16000us, nominal 4-15ms
#define ICLASS_READER_TIMEOUT_UPDATE_FAST 1500 // A copy of ICLASS_READER_TIMEOUT_UPDATE with reduced timeout values
#define ICLASS_READER_TIMEOUT_OTHERS 80 // 380us, nominal 330us
// The length of a received command will in most cases be no more than 18 bytes.

View file

@ -4524,7 +4524,7 @@ void picopass_elite_nextKey(uint8_t *key) {
memcpy(key, key_state, 8);
}
static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, uint8_t no_first_auth[8], bool debug, bool test, bool fast, bool allnight) {
static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, uint8_t no_first_auth[8], bool debug, bool test, bool fast, bool short_delay, bool allnight) {
int runs = 1;
int cycle = 1;
@ -4557,6 +4557,7 @@ static int iclass_recover(uint8_t key[8], uint32_t index_start, uint32_t loop, u
payload->debug = debug;
payload->test = test;
payload->fast = fast;
payload->short_delay = short_delay;
memcpy(payload->nfa, no_first_auth, PICOPASS_BLOCK_SIZE);
memcpy(payload->req.key, key, PICOPASS_BLOCK_SIZE);
memcpy(payload->req2.key, aa2_standard_key, PICOPASS_BLOCK_SIZE);
@ -4859,9 +4860,11 @@ static int CmdHFiClassLegacyRecSim(void) {
bits_found = index;
PrintAndLogEx(SUCCESS, "Original Key: " _GREEN_("%s"), sprint_hex(original_key, sizeof(original_key)));
PrintAndLogEx(SUCCESS, "Weak Key: " _GREEN_("%s"), sprint_hex(key, sizeof(key)));
PrintAndLogEx(SUCCESS, "Key Updates Required to Weak Key :" _GREEN_("%d"), index);
PrintAndLogEx(SUCCESS, "Key Updates Required to Weak Key: " _GREEN_("%d"), index);
PrintAndLogEx(SUCCESS, "Estimated Time (default mode) : ~" _GREEN_("%d")" hours", index / 17800);
PrintAndLogEx(SUCCESS, "Estimated Time (default + --sl) : ~" _GREEN_("%d")" hours", index / 19450);
PrintAndLogEx(SUCCESS, "Estimated Time (--fast mode) : ~" _GREEN_("%d")" hours", index / 26860);
PrintAndLogEx(SUCCESS, "Estimated Time (--fast + --sl) : ~" _GREEN_("%d")" hours", index / 29750);
}
index++;
@ -4890,6 +4893,7 @@ static int CmdHFiClassLegacyRecover(const char *Cmd) {
arg_lit0(NULL, "notest", "Perform real writes on the card!"),
arg_lit0(NULL, "allnight", "Loops the loop for 10 times, recommended loop value of 5000."),
arg_lit0(NULL, "fast", "Increases the speed (4.6->7.4 key updates/second), higher risk to brick the card."),
arg_lit0(NULL, "sl", "Lower card comms delay times, further speeds increases, may cause more errors."),
arg_lit0(NULL, "est", "Estimates the key updates based on the card's CSN assuming standard key."),
arg_param_end
};
@ -4906,7 +4910,8 @@ static int CmdHFiClassLegacyRecover(const char *Cmd) {
bool no_test = arg_get_lit(ctx, 5);
bool allnight = arg_get_lit(ctx, 6);
bool fast = arg_get_lit(ctx, 7);
bool sim = arg_get_lit(ctx, 8);
bool short_delay = arg_get_lit(ctx, 8);
bool sim = arg_get_lit(ctx, 9);
if (sim) {
CmdHFiClassLegacyRecSim();
@ -4948,8 +4953,8 @@ static int CmdHFiClassLegacyRecover(const char *Cmd) {
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort");
PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------\n");
iclass_recover(macs, index, loop, no_first_auth, debug, test, fast, allnight);
iclass_recover(macs, index, loop, no_first_auth, debug, test, fast, short_delay, allnight);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, _YELLOW_("If the process completed successfully, you can now run 'hf iclass legbrute' with the partial key found."));

View file

@ -125,6 +125,7 @@ typedef struct {
bool debug;
bool test;
bool fast;
bool short_delay;
} PACKED iclass_recover_req_t;
typedef struct iclass_premac {