mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 18:48:13 -07:00
Merge branch 'RfidResearchGroup:master' into master
This commit is contained in:
commit
66c57e8652
45 changed files with 1156 additions and 384 deletions
|
@ -3,10 +3,17 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Changed `hf iclass dump` - now uses default AA1 key when called without a key or key index (@iceman1001)
|
||||
- Renamed `hf iclass trbl` to `hf iclass tear` (@iceman1001)
|
||||
- Changed `hw tearoff` - the device side message is now debug log controlled (@iceman1001)
|
||||
- Changed `pm3.sh` - Serial ports enumeration on Proxspace3.xx / MINGW environments, now using powershell.exe since wmic is deprecated (@iceman1001)
|
||||
- Fixed and updated `hf iclass trbl` to correctly use the credit key when passed and show partial tearoff results (@antiklesys)
|
||||
- Fixed `hf iclass legbrute` was not correctly parsin the index value
|
||||
- Fixed `hf mf ekeyprn` - failed to download emulator memory due to wrong size calculation (@iceman1001)
|
||||
- Fixed `hf mf fchk --mem` to actually use flash dict (@doegox)
|
||||
- Fixed `make install` on OSX thanks DaveItsLong (@doegox)
|
||||
- Added new standalone mode `HF_ST25_TEAROFF` to store/restore ST25TB tags with tearoff for counters (@seclabz)
|
||||
- Added `hf_mfu_ultra.lua` script enables restoring dump to ULTRA/UL-5 tags and clearing previously written ULTRA tags (@mak-42)
|
||||
|
||||
## [Blue Ice.4.20142][2025-03-25]
|
||||
- Added `des_talk.py` script for easier MIFARE DESFire handling (@trigat)
|
||||
|
@ -44,7 +51,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Changed `hf mf cload` - now accepts MFC Ev1 sized dumps (@iceman1001)
|
||||
- Changed `hf mfu info` - now properly identify ULEv1 AES 50pF (@iceman1001)
|
||||
- Changed `hf mf info` - now differentiates between full USCUID and cut down ZUID chips (@nvx)
|
||||
- Changed `lf hitag chk` - added key counter, client side abort and minor delay (@iceman1001)
|
||||
- Changed `lf hitag chk` - added key counter, client side abort and minor delay (@iceman1001)
|
||||
- Added `hf seos sam` - Added support for HID SAM SEOS communications (@jkramarz)
|
||||
- Changed (extended) area accessible by spiffs into last page of FLASH (@piotrva)
|
||||
- Changed flash-stored key dictionaries (Mifare, iClass, T55XX) and T55XX configurations to SPIFFS files (@piotrva)
|
||||
|
|
|
@ -27,6 +27,10 @@ PLATFORM=PM3RDV4
|
|||
# Only available with PLATFORM=PM3GENERIC
|
||||
#LED_ORDER=PM3EASY
|
||||
|
||||
# Uncomment a line below to change default USART baud rate
|
||||
# defaults to 115200 used by HC-05 in Blueshark
|
||||
#USART_BAUD_RATE=19200
|
||||
|
||||
# Uncomment the lines below in order to make a 256KB image
|
||||
# and comment out the lines above
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ void BigBuf_Clear_ext(bool verbose) {
|
|||
memset(BigBuf, 0, s_bigbuf_size);
|
||||
clear_trace();
|
||||
if (verbose) {
|
||||
Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size);
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ static void update_leds_mode(standalone_mode_t mode) {
|
|||
*/
|
||||
static void indicate_success(void) {
|
||||
// Blink Green LED (A) 3 times quickly for success
|
||||
for(int i=0; i<3; ++i) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
LED_A_ON();
|
||||
SpinDelay(150);
|
||||
LED_A_OFF();
|
||||
|
@ -265,7 +265,7 @@ static void indicate_success(void) {
|
|||
*/
|
||||
static void indicate_failure(void) {
|
||||
// Blink Red LED (B) 3 times quickly for failure
|
||||
for(int i=0; i<3; ++i) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
LED_B_ON();
|
||||
SpinDelay(150);
|
||||
LED_B_OFF();
|
||||
|
@ -291,7 +291,7 @@ static bool load_tags_from_flash(st25tb_data_t collection[MAX_SAVED_TAGS]) {
|
|||
// Verify file size
|
||||
uint32_t size = size_in_spiffs(HF_ST25TB_MULTI_SR_FILE);
|
||||
if (size != sizeof(g_stored_tags)) {
|
||||
Dbprintf(_RED_("Flash file size mismatch (expected %zu, got %u). Wiping old file."),
|
||||
Dbprintf(_RED_("Flash file size mismatch (expected %zu, got %u). Wiping old file."),
|
||||
sizeof(g_stored_tags), size);
|
||||
// Remove corrupted file
|
||||
rdv40_spiffs_remove(HF_ST25TB_MULTI_SR_FILE, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
@ -299,8 +299,8 @@ static bool load_tags_from_flash(st25tb_data_t collection[MAX_SAVED_TAGS]) {
|
|||
}
|
||||
|
||||
// Read file contents
|
||||
int res = rdv40_spiffs_read(HF_ST25TB_MULTI_SR_FILE, (uint8_t *)collection,
|
||||
size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
int res = rdv40_spiffs_read(HF_ST25TB_MULTI_SR_FILE, (uint8_t *)collection,
|
||||
size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
if (res != SPIFFS_OK) {
|
||||
Dbprintf(_RED_("Failed to read tag collection from flash (err %d)"), res);
|
||||
|
@ -319,8 +319,8 @@ static bool load_tags_from_flash(st25tb_data_t collection[MAX_SAVED_TAGS]) {
|
|||
* @return true if successful, false otherwise
|
||||
*/
|
||||
static bool save_tags_to_flash(const st25tb_data_t collection[MAX_SAVED_TAGS]) {
|
||||
int res = rdv40_spiffs_write(HF_ST25TB_MULTI_SR_FILE, (uint8_t *)collection,
|
||||
sizeof(g_stored_tags), RDV40_SPIFFS_SAFETY_SAFE);
|
||||
int res = rdv40_spiffs_write(HF_ST25TB_MULTI_SR_FILE, (uint8_t *)collection,
|
||||
sizeof(g_stored_tags), RDV40_SPIFFS_SAFETY_SAFE);
|
||||
return (res == SPIFFS_OK);
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,7 @@ static int find_free_tag_slot(void) {
|
|||
//=============================================================================
|
||||
|
||||
/**
|
||||
* @brief Stripped version of "iso14443b_setup" that avoids unnecessary LED
|
||||
* @brief Stripped version of "iso14443b_setup" that avoids unnecessary LED
|
||||
* operations and uses shorter delays
|
||||
*/
|
||||
static void iso14443b_setup_light(void) {
|
||||
|
@ -417,7 +417,7 @@ static bool st25tb_tag_read(st25tb_data_t *tag_data_slot) {
|
|||
|
||||
Dbprintf("Found ST tag. Reading %d blocks...", ST25TB_BLOCK_COUNT);
|
||||
tag_data_slot->uid = bytes_to_num_le(card_info.uid, sizeof(tag_data_slot->uid));
|
||||
|
||||
|
||||
// Read all data blocks
|
||||
for (uint8_t block_address = 0; block_address < ST25TB_BLOCK_COUNT; block_address++) {
|
||||
WDT_HIT();
|
||||
|
@ -507,7 +507,7 @@ static bool st25tb_tag_restore(const st25tb_data_t *stored_data_slot) {
|
|||
}
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
Dbprintf("Counter Block %d: Stored=0x%08X, Current=0x%08X",
|
||||
Dbprintf("Counter Block %d: Stored=0x%08X, Current=0x%08X",
|
||||
block_address, stored_value, current_value);
|
||||
}
|
||||
|
||||
|
@ -528,7 +528,7 @@ static bool st25tb_tag_restore(const st25tb_data_t *stored_data_slot) {
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
Dbprintf("Counter block %d already has the target value (0x%08X). Skipping write.",
|
||||
Dbprintf("Counter block %d already has the target value (0x%08X). Skipping write.",
|
||||
block_address, stored_value);
|
||||
}
|
||||
} else {
|
||||
|
@ -658,7 +658,7 @@ static void st25tb_tear_off_write_block(uint8_t block_address, uint32_t data, ui
|
|||
block[0] = (data & 0xFF);
|
||||
block[1] = (data >> 8) & 0xFF;
|
||||
block[2] = (data >> 16) & 0xFF;
|
||||
block[3] = (data >> 24) & 0xFF;
|
||||
block[3] = (data >> 24) & 0xFF;
|
||||
|
||||
iso14b_card_select_t card;
|
||||
int res = iso14443b_select_srx_card(&card);
|
||||
|
@ -667,7 +667,7 @@ static void st25tb_tear_off_write_block(uint8_t block_address, uint32_t data, ui
|
|||
}
|
||||
|
||||
res = st25tb_cmd_write_block(block_address, block);
|
||||
|
||||
|
||||
// Tear off the communication at precise timing
|
||||
SpinDelayUsPrecision(tearoff_delay_us);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -685,9 +685,9 @@ out:
|
|||
* @param read_back_value Pointer to store read-back value
|
||||
* @return 0 for success, -1 for failure
|
||||
*/
|
||||
static int8_t st25tb_tear_off_retry_write_verify(uint8_t block_address, uint32_t target_value,
|
||||
uint32_t max_try_count, int sleep_time_ms,
|
||||
uint32_t *read_back_value) {
|
||||
static int8_t st25tb_tear_off_retry_write_verify(uint8_t block_address, uint32_t target_value,
|
||||
uint32_t max_try_count, int sleep_time_ms,
|
||||
uint32_t *read_back_value) {
|
||||
int i = 0;
|
||||
*read_back_value = ~target_value; // Initialize to ensure the loop runs at least once
|
||||
|
||||
|
@ -711,9 +711,9 @@ static int8_t st25tb_tear_off_retry_write_verify(uint8_t block_address, uint32_t
|
|||
* @param read_value Pointer to store read value
|
||||
* @return 0 if consolidated, -1 otherwise
|
||||
*/
|
||||
static int8_t st25tb_tear_off_is_consolidated(const uint8_t block_address, uint32_t value,
|
||||
int repeat_read, int sleep_time_ms,
|
||||
uint32_t *read_value) {
|
||||
static int8_t st25tb_tear_off_is_consolidated(const uint8_t block_address, uint32_t value,
|
||||
int repeat_read, int sleep_time_ms,
|
||||
uint32_t *read_value) {
|
||||
int result;
|
||||
for (int i = 0; i < repeat_read; i++) {
|
||||
if (sleep_time_ms > 0) SpinDelayUsPrecision(sleep_time_ms * 1000);
|
||||
|
@ -733,8 +733,8 @@ static int8_t st25tb_tear_off_is_consolidated(const uint8_t block_address, uint3
|
|||
* @param read_back_value Pointer to store read-back value
|
||||
* @return 0 for success, -1 for failure
|
||||
*/
|
||||
static int8_t st25tb_tear_off_consolidate_block(const uint8_t block_address, uint32_t current_value,
|
||||
uint32_t target_value, uint32_t *read_back_value) {
|
||||
static int8_t st25tb_tear_off_consolidate_block(const uint8_t block_address, uint32_t current_value,
|
||||
uint32_t target_value, uint32_t *read_back_value) {
|
||||
int8_t result;
|
||||
uint32_t consolidation_value;
|
||||
|
||||
|
@ -746,8 +746,8 @@ static int8_t st25tb_tear_off_consolidate_block(const uint8_t block_address, uin
|
|||
}
|
||||
|
||||
// Try writing value - 1
|
||||
result = st25tb_tear_off_retry_write_verify(block_address, consolidation_value - 1,
|
||||
TEAR_OFF_WRITE_RETRY_COUNT, 0, read_back_value);
|
||||
result = st25tb_tear_off_retry_write_verify(block_address, consolidation_value - 1,
|
||||
TEAR_OFF_WRITE_RETRY_COUNT, 0, read_back_value);
|
||||
if (result != 0) {
|
||||
Dbprintf("Consolidation failed at step 1 (write 0x%08X)", consolidation_value - 1);
|
||||
return -1;
|
||||
|
@ -755,8 +755,8 @@ static int8_t st25tb_tear_off_consolidate_block(const uint8_t block_address, uin
|
|||
|
||||
// If value is not FE or target is not FD, try writing value - 2
|
||||
if (*read_back_value != 0xFFFFFFFE || (*read_back_value == 0xFFFFFFFE && target_value == 0xFFFFFFFD)) {
|
||||
result = st25tb_tear_off_retry_write_verify(block_address, consolidation_value - 2,
|
||||
TEAR_OFF_WRITE_RETRY_COUNT, 0, read_back_value);
|
||||
result = st25tb_tear_off_retry_write_verify(block_address, consolidation_value - 2,
|
||||
TEAR_OFF_WRITE_RETRY_COUNT, 0, read_back_value);
|
||||
if (result != 0) {
|
||||
Dbprintf("Consolidation failed at step 2 (write 0x%08X)", consolidation_value - 2);
|
||||
return -1;
|
||||
|
@ -765,12 +765,12 @@ static int8_t st25tb_tear_off_consolidate_block(const uint8_t block_address, uin
|
|||
|
||||
// Final checks for stability of unstable high values (due to internal dual counters)
|
||||
if (result == 0 && target_value > 0xFFFFFFFD && *read_back_value > 0xFFFFFFFD) {
|
||||
result = st25tb_tear_off_is_consolidated(block_address, *read_back_value,
|
||||
TEAR_OFF_CONSOLIDATE_READ_COUNT, 0, read_back_value);
|
||||
result = st25tb_tear_off_is_consolidated(block_address, *read_back_value,
|
||||
TEAR_OFF_CONSOLIDATE_READ_COUNT, 0, read_back_value);
|
||||
if (result == 0) {
|
||||
result = st25tb_tear_off_is_consolidated(block_address, *read_back_value,
|
||||
TEAR_OFF_CONSOLIDATE_WAIT_READ_COUNT,
|
||||
TEAR_OFF_CONSOLIDATE_WAIT_MS, read_back_value);
|
||||
result = st25tb_tear_off_is_consolidated(block_address, *read_back_value,
|
||||
TEAR_OFF_CONSOLIDATE_WAIT_READ_COUNT,
|
||||
TEAR_OFF_CONSOLIDATE_WAIT_MS, read_back_value);
|
||||
if (result != 0) {
|
||||
Dbprintf("Consolidation failed stability check (long wait)");
|
||||
return -1;
|
||||
|
@ -861,8 +861,8 @@ static void st25tb_tear_off_log(int tear_off_us, char *color, uint32_t value) {
|
|||
* @param safety_value Safety threshold to prevent going below
|
||||
* @return 0 for success, non-zero for failure
|
||||
*/
|
||||
static int8_t st25tb_tear_off_write_counter(uint8_t block_address, uint32_t target_value,
|
||||
uint32_t tear_off_adjustment_us, uint32_t safety_value) {
|
||||
static int8_t st25tb_tear_off_write_counter(uint8_t block_address, uint32_t target_value,
|
||||
uint32_t tear_off_adjustment_us, uint32_t safety_value) {
|
||||
int result;
|
||||
bool trigger = true;
|
||||
|
||||
|
@ -906,7 +906,7 @@ static int8_t st25tb_tear_off_write_counter(uint8_t block_address, uint32_t targ
|
|||
for (;;) {
|
||||
// Safety check: ensure we don't go below the safety threshold
|
||||
if (tear_off_value < safety_value) {
|
||||
Dbprintf("Stopped. Safety threshold reached (next value 0x%08X < safety 0x%08X)",
|
||||
Dbprintf("Stopped. Safety threshold reached (next value 0x%08X < safety 0x%08X)",
|
||||
tear_off_value, safety_value);
|
||||
return -1;
|
||||
}
|
||||
|
@ -921,15 +921,15 @@ static int8_t st25tb_tear_off_write_counter(uint8_t block_address, uint32_t targ
|
|||
}
|
||||
|
||||
// Analyze the result and decide next action
|
||||
if (read_value > current_value) {
|
||||
if (read_value > current_value) {
|
||||
// Partial write succeeded (successful tear-off)
|
||||
if (read_value >= 0xFFFFFFFE ||
|
||||
(read_value - 2) > target_value ||
|
||||
read_value != last_consolidated_value ||
|
||||
((read_value & 0xF0000000) > (current_value & 0xF0000000))) { // Major bit flip
|
||||
|
||||
result = st25tb_tear_off_consolidate_block(block_address, read_value,
|
||||
target_value, ¤t_value);
|
||||
(read_value - 2) > target_value ||
|
||||
read_value != last_consolidated_value ||
|
||||
((read_value & 0xF0000000) > (current_value & 0xF0000000))) { // Major bit flip
|
||||
|
||||
result = st25tb_tear_off_consolidate_block(block_address, read_value,
|
||||
target_value, ¤t_value);
|
||||
if (result == 0 && current_value == target_value) {
|
||||
st25tb_tear_off_log(tear_off_us, GREEN, read_value);
|
||||
Dbprintf("Target value 0x%08X reached successfully!", target_value);
|
||||
|
@ -1004,11 +1004,11 @@ static void run_learn_function(void) {
|
|||
} else {
|
||||
// Only increment if we are adding to a new slot, not overwriting
|
||||
if (!g_stored_tags[slot_index].data_valid) {
|
||||
g_valid_tag_count++;
|
||||
g_valid_tag_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Store tag data in collection
|
||||
memcpy(&g_stored_tags[slot_index], &temp_tag_data, sizeof(st25tb_data_t));
|
||||
g_stored_tags[slot_index].data_valid = true;
|
||||
|
@ -1020,7 +1020,7 @@ static void run_learn_function(void) {
|
|||
} else {
|
||||
DbpString(_RED_("Failed to save collection to flash!"));
|
||||
}
|
||||
|
||||
|
||||
current_state = STATE_DONE; // Indicate success
|
||||
}
|
||||
}
|
||||
|
@ -1052,8 +1052,8 @@ static void run_restore_function(void) {
|
|||
current_state = STATE_ERROR;
|
||||
}
|
||||
} else {
|
||||
// Tag found but not in collection, remain busy to scan again
|
||||
current_state = STATE_BUSY;
|
||||
// Tag found but not in collection, remain busy to scan again
|
||||
current_state = STATE_BUSY;
|
||||
}
|
||||
} else {
|
||||
// No tag found, remain busy to scan again
|
||||
|
@ -1131,10 +1131,10 @@ void RunMod(void) {
|
|||
// --- Update Display (only if mode changed) ---
|
||||
if (mode_display_update) {
|
||||
if (g_current_mode == MODE_LEARN) {
|
||||
Dbprintf("Mode: " _YELLOW_("Learn") ". (Cnt: %d/%d)",
|
||||
Dbprintf("Mode: " _YELLOW_("Learn") ". (Cnt: %d/%d)",
|
||||
g_valid_tag_count, MAX_SAVED_TAGS);
|
||||
} else {
|
||||
Dbprintf("Mode: " _BLUE_("Restore") ". (Cnt: %d/%d)",
|
||||
Dbprintf("Mode: " _BLUE_("Restore") ". (Cnt: %d/%d)",
|
||||
g_valid_tag_count, MAX_SAVED_TAGS);
|
||||
}
|
||||
mode_display_update = false;
|
||||
|
@ -1142,14 +1142,14 @@ void RunMod(void) {
|
|||
update_leds_mode(g_current_mode);
|
||||
|
||||
// Process according to current state
|
||||
if(current_state == STATE_BUSY) {
|
||||
if (current_state == STATE_BUSY) {
|
||||
// Run appropriate function based on mode
|
||||
if (g_current_mode == MODE_LEARN) {
|
||||
run_learn_function();
|
||||
} else { // MODE_RESTORE
|
||||
run_restore_function();
|
||||
}
|
||||
} else if(current_state == STATE_DONE) {
|
||||
} else if (current_state == STATE_DONE) {
|
||||
indicate_success();
|
||||
} else {
|
||||
indicate_failure();
|
||||
|
|
|
@ -104,7 +104,7 @@ int tearoff_hook(void) {
|
|||
SpinDelayUsPrecision(g_tearoff_delay_us);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
g_tearoff_enabled = false;
|
||||
Dbprintf(_YELLOW_("Tear-off triggered!"));
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf(_YELLOW_("Tear-off triggered!"));
|
||||
return PM3_ETEAROFF;
|
||||
} else {
|
||||
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
|
||||
|
@ -254,7 +254,7 @@ static uint32_t MeasureAntennaTuningLfData(void) {
|
|||
void print_stack_usage(void) {
|
||||
for (uint32_t *p = _stack_start; ; ++p) {
|
||||
if (*p != 0xdeadbeef) {
|
||||
Dbprintf(" Max stack usage......... %d / %d bytes", (uint32_t)_stack_end - (uint32_t)p, (uint32_t)_stack_end - (uint32_t)_stack_start);
|
||||
Dbprintf(" Max stack usage..... %d / %d bytes", (uint32_t)_stack_end - (uint32_t)p, (uint32_t)_stack_end - (uint32_t)_stack_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ static void print_debug_level(void) {
|
|||
sprintf(dbglvlstr, "extended");
|
||||
break;
|
||||
}
|
||||
Dbprintf(" Debug log level......... %d ( " _YELLOW_("%s")" )", g_dbglevel, dbglvlstr);
|
||||
Dbprintf(" Debug log level..... %d ( " _YELLOW_("%s")" )", g_dbglevel, dbglvlstr);
|
||||
}
|
||||
|
||||
// measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
|
||||
|
@ -421,11 +421,11 @@ static void SendStatus(uint32_t wait) {
|
|||
print_debug_level();
|
||||
|
||||
tosend_t *ts = get_tosend();
|
||||
Dbprintf(" ToSendMax............... %d", ts->max);
|
||||
Dbprintf(" ToSend BUFFERSIZE....... %d", TOSEND_BUFFER_SIZE);
|
||||
Dbprintf(" ToSendMax........... %d", ts->max);
|
||||
Dbprintf(" ToSend BUFFERSIZE... %d", TOSEND_BUFFER_SIZE);
|
||||
while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
|
||||
uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks
|
||||
Dbprintf(" Slow clock.............. %d Hz", (16 * MAINCK) / mainf);
|
||||
Dbprintf(" Slow clock.......... %d Hz", (16 * MAINCK) / mainf);
|
||||
uint32_t delta_time = 0;
|
||||
uint32_t start_time = GetTickCount();
|
||||
#define SLCK_CHECK_MS 50
|
||||
|
@ -449,10 +449,11 @@ static void SendStatus(uint32_t wait) {
|
|||
} else {
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if (num > 0) {
|
||||
Dbprintf(" Mifare.................. "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, MF_KEYS_FILE);
|
||||
Dbprintf(" Mifare... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, MF_KEYS_FILE);
|
||||
} else {
|
||||
Dbprintf(" Mifare.................. "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, MF_KEYS_FILE);
|
||||
Dbprintf(" Mifare... "_RED_("%u")" keys - "_RED_("%s"), num, MF_KEYS_FILE);
|
||||
}
|
||||
|
||||
if (exists_in_spiffs(T55XX_KEYS_FILE)) {
|
||||
|
@ -460,10 +461,11 @@ static void SendStatus(uint32_t wait) {
|
|||
} else {
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if (num > 0) {
|
||||
Dbprintf(" T55xx................... "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, T55XX_KEYS_FILE);
|
||||
Dbprintf(" T55xx.... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, T55XX_KEYS_FILE);
|
||||
} else {
|
||||
Dbprintf(" T55xx................... "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, T55XX_KEYS_FILE);
|
||||
Dbprintf(" T55xx.... "_RED_("%u")" keys - "_RED_("%s"), num, T55XX_KEYS_FILE);
|
||||
}
|
||||
|
||||
if (exists_in_spiffs(ICLASS_KEYS_FILE)) {
|
||||
|
@ -471,10 +473,11 @@ static void SendStatus(uint32_t wait) {
|
|||
} else {
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if (num > 0) {
|
||||
Dbprintf(" iClass.................. "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, ICLASS_KEYS_FILE);
|
||||
Dbprintf(" iClass... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, ICLASS_KEYS_FILE);
|
||||
} else {
|
||||
Dbprintf(" iClass.................. "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, ICLASS_KEYS_FILE);
|
||||
Dbprintf(" iClass... "_RED_("%u")" keys - "_RED_("%s"), num, ICLASS_KEYS_FILE);
|
||||
}
|
||||
#endif
|
||||
DbpString("");
|
||||
|
@ -2354,7 +2357,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
|
||||
uint16_t available;
|
||||
uint16_t pre_available = 0;
|
||||
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
|
||||
uint8_t *dest = BigBuf_calloc(USART_FIFOLEN);
|
||||
uint32_t wait = payload->waittime;
|
||||
|
||||
StartTicks();
|
||||
|
@ -2398,7 +2401,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
|
||||
uint16_t available;
|
||||
uint16_t pre_available = 0;
|
||||
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
|
||||
uint8_t *dest = BigBuf_calloc(USART_FIFOLEN);
|
||||
uint32_t wait = payload->waittime;
|
||||
|
||||
StartTicks();
|
||||
|
@ -2694,7 +2697,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
|
||||
uint32_t size = packet->oldarg[1];
|
||||
|
||||
uint8_t *buff = BigBuf_malloc(size);
|
||||
uint8_t *buff = BigBuf_calloc(size);
|
||||
if (buff == NULL) {
|
||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Failed to allocate memory");
|
||||
// Trigger a finish downloading signal with an PM3_EMALLOC
|
||||
|
@ -2899,7 +2902,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
case CMD_FLASHMEM_DOWNLOAD: {
|
||||
|
||||
LED_B_ON();
|
||||
uint8_t *mem = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
||||
uint8_t *mem = BigBuf_calloc(PM3_CMD_DATA_SIZE);
|
||||
uint32_t startidx = packet->oldarg[0];
|
||||
uint32_t numofbytes = packet->oldarg[1];
|
||||
// arg0 = startindex
|
||||
|
@ -2931,7 +2934,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
case CMD_FLASHMEM_INFO: {
|
||||
|
||||
LED_B_ON();
|
||||
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_malloc(sizeof(rdv40_validation_t));
|
||||
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_calloc(sizeof(rdv40_validation_t));
|
||||
|
||||
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET_P(spi_flash_pages64k), info->signature, FLASH_MEM_SIGNATURE_LEN);
|
||||
|
||||
|
|
|
@ -748,7 +748,7 @@ void em4x50_chk(const char *filename, bool ledcontrol) {
|
|||
uint16_t pwd_count = 0;
|
||||
uint32_t size = size_in_spiffs(filename);
|
||||
pwd_count = size / 4;
|
||||
uint8_t *pwds = BigBuf_malloc(size);
|
||||
uint8_t *pwds = BigBuf_calloc(size);
|
||||
|
||||
rdv40_spiffs_read_as_filetype(filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE);
|
||||
|
||||
|
|
|
@ -857,7 +857,7 @@ void SmartCardRaw(const smart_card_raw_t *p) {
|
|||
LED_D_ON();
|
||||
|
||||
uint16_t len = 0;
|
||||
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *resp = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
// check if alloacted...
|
||||
smartcard_command_t flags = p->flags;
|
||||
|
||||
|
@ -937,7 +937,7 @@ void SmartCardUpgrade(uint64_t arg0) {
|
|||
bool isOK = true;
|
||||
uint16_t length = arg0, pos = 0;
|
||||
const uint8_t *fwdata = BigBuf_get_addr();
|
||||
uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE);
|
||||
uint8_t *verfiydata = BigBuf_calloc(I2C_BLOCK_SIZE);
|
||||
|
||||
while (length) {
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
|
|||
LED_D_ON();
|
||||
|
||||
uint16_t len = 0;
|
||||
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *resp = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
resp[0] = prepend;
|
||||
// check if alloacted...
|
||||
smartcard_command_t flags = p->flags;
|
||||
|
|
|
@ -399,40 +399,40 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
int trace_data_size;
|
||||
|
||||
// Respond SOF -- takes 1 bytes
|
||||
uint8_t *resp_sof = BigBuf_malloc(1);
|
||||
uint8_t resp_sof[1] = {0};
|
||||
int resp_sof_len;
|
||||
|
||||
// Anticollision CSN (rotated CSN)
|
||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||
uint8_t *resp_anticoll = BigBuf_malloc(22);
|
||||
uint8_t *resp_anticoll = BigBuf_calloc(22);
|
||||
int resp_anticoll_len;
|
||||
|
||||
// CSN (block 0)
|
||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||
uint8_t *resp_csn = BigBuf_malloc(22);
|
||||
uint8_t *resp_csn = BigBuf_calloc(22);
|
||||
int resp_csn_len;
|
||||
|
||||
// configuration (blk 1) PICOPASS 2ks
|
||||
uint8_t *resp_conf = BigBuf_malloc(22);
|
||||
uint8_t *resp_conf = BigBuf_calloc(22);
|
||||
int resp_conf_len;
|
||||
|
||||
// e-Purse (blk 2)
|
||||
// 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
|
||||
uint8_t *resp_cc = BigBuf_malloc(18);
|
||||
uint8_t *resp_cc = BigBuf_calloc(18);
|
||||
int resp_cc_len;
|
||||
|
||||
// Kd, Kc (blocks 3 and 4). Cannot be read. Always respond with 0xff bytes only
|
||||
uint8_t *resp_ff = BigBuf_malloc(22);
|
||||
uint8_t *resp_ff = BigBuf_calloc(22);
|
||||
int resp_ff_len;
|
||||
uint8_t ff_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
|
||||
AddCrc(ff_data, 8);
|
||||
|
||||
// Application Issuer Area (blk 5)
|
||||
uint8_t *resp_aia = BigBuf_malloc(22);
|
||||
uint8_t *resp_aia = BigBuf_calloc(22);
|
||||
int resp_aia_len;
|
||||
|
||||
// receive command
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE);
|
||||
|
||||
// Prepare card messages
|
||||
tosend_t *ts = get_tosend();
|
||||
|
@ -474,11 +474,11 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
|
||||
//This is used for responding to READ-block commands or other data which is dynamically generated
|
||||
//First the 'trace'-data, not encoded for FPGA
|
||||
uint8_t *data_generic_trace = BigBuf_malloc(34); // 32 bytes data + 2byte CRC is max tag answer
|
||||
uint8_t *data_generic_trace = BigBuf_calloc(34); // 32 bytes data + 2byte CRC is max tag answer
|
||||
|
||||
//Then storage for the modulated data
|
||||
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
|
||||
uint8_t *data_response = BigBuf_malloc((34 * 2) + 3);
|
||||
uint8_t *data_response = BigBuf_calloc((34 * 2) + 3);
|
||||
|
||||
enum { IDLE, ACTIVATED, SELECTED, HALTED } chip_state = IDLE;
|
||||
|
||||
|
@ -942,29 +942,29 @@ int do_iclass_simulation_nonsec(void) {
|
|||
int trace_data_size = 0;
|
||||
|
||||
// Respond SOF -- takes 1 bytes
|
||||
uint8_t *resp_sof = BigBuf_malloc(2);
|
||||
uint8_t resp_sof[2] = { 0 };
|
||||
int resp_sof_len;
|
||||
|
||||
// Anticollision CSN (rotated CSN)
|
||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||
uint8_t *resp_anticoll = BigBuf_malloc(28);
|
||||
uint8_t *resp_anticoll = BigBuf_calloc(28);
|
||||
int resp_anticoll_len;
|
||||
|
||||
// CSN
|
||||
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
|
||||
uint8_t *resp_csn = BigBuf_malloc(28);
|
||||
uint8_t *resp_csn = BigBuf_calloc(28);
|
||||
int resp_csn_len;
|
||||
|
||||
// configuration (blk 1) PICOPASS 2ks
|
||||
uint8_t *resp_conf = BigBuf_malloc(28);
|
||||
uint8_t *resp_conf = BigBuf_calloc(28);
|
||||
int resp_conf_len;
|
||||
|
||||
// Application Issuer Area (blk 5)
|
||||
uint8_t *resp_aia = BigBuf_malloc(28);
|
||||
uint8_t *resp_aia = BigBuf_calloc(28);
|
||||
int resp_aia_len;
|
||||
|
||||
// receive command
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE);
|
||||
|
||||
// Prepare card messages
|
||||
tosend_t *ts = get_tosend();
|
||||
|
@ -997,11 +997,11 @@ int do_iclass_simulation_nonsec(void) {
|
|||
|
||||
//This is used for responding to READ-block commands or other data which is dynamically generated
|
||||
//First the 'trace'-data, not encoded for FPGA
|
||||
uint8_t *data_generic_trace = BigBuf_malloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer
|
||||
uint8_t *data_generic_trace = BigBuf_calloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer
|
||||
|
||||
//Then storage for the modulated data
|
||||
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
|
||||
uint8_t *data_response = BigBuf_malloc((32 + 2) * 2 + 2);
|
||||
uint8_t *data_response = BigBuf_calloc((32 + 2) * 2 + 2);
|
||||
|
||||
enum { IDLE, ACTIVATED, SELECTED, HALTED } chip_state = IDLE;
|
||||
|
||||
|
|
|
@ -190,35 +190,35 @@ struct Crypto1State crypto1_state = {0, 0};
|
|||
|
||||
void printHf14aConfig(void) {
|
||||
DbpString(_CYAN_("HF 14a config"));
|
||||
Dbprintf(" [a] Anticol override.............. %s%s%s",
|
||||
Dbprintf(" [a] Anticol override........... %s%s%s",
|
||||
(hf14aconfig.forceanticol == 0) ? _GREEN_("std") " ( follow standard )" : "",
|
||||
(hf14aconfig.forceanticol == 1) ? _RED_("force") " ( always do anticol )" : "",
|
||||
(hf14aconfig.forceanticol == 2) ? _RED_("skip") " ( always skip anticol )" : ""
|
||||
);
|
||||
Dbprintf(" [b] BCC override.................. %s%s%s",
|
||||
Dbprintf(" [b] BCC override............... %s%s%s",
|
||||
(hf14aconfig.forcebcc == 0) ? _GREEN_("std") " ( follow standard )" : "",
|
||||
(hf14aconfig.forcebcc == 1) ? _RED_("fix") " ( fix bad BCC )" : "",
|
||||
(hf14aconfig.forcebcc == 2) ? _RED_("ignore") " ( ignore bad BCC, always use card BCC )" : ""
|
||||
);
|
||||
Dbprintf(" [2] CL2 override.................. %s%s%s",
|
||||
Dbprintf(" [2] CL2 override............... %s%s%s",
|
||||
(hf14aconfig.forcecl2 == 0) ? _GREEN_("std") " ( follow standard )" : "",
|
||||
(hf14aconfig.forcecl2 == 1) ? _RED_("force") " ( always do CL2 )" : "",
|
||||
(hf14aconfig.forcecl2 == 2) ? _RED_("skip") " ( always skip CL2 )" : ""
|
||||
);
|
||||
Dbprintf(" [3] CL3 override.................. %s%s%s",
|
||||
Dbprintf(" [3] CL3 override............... %s%s%s",
|
||||
(hf14aconfig.forcecl3 == 0) ? _GREEN_("std") " ( follow standard )" : "",
|
||||
(hf14aconfig.forcecl3 == 1) ? _RED_("force") " ( always do CL3 )" : "",
|
||||
(hf14aconfig.forcecl3 == 2) ? _RED_("skip") " ( always skip CL3 )" : ""
|
||||
);
|
||||
Dbprintf(" [r] RATS override................. %s%s%s",
|
||||
Dbprintf(" [r] RATS override.............. %s%s%s",
|
||||
(hf14aconfig.forcerats == 0) ? _GREEN_("std") " ( follow standard )" : "",
|
||||
(hf14aconfig.forcerats == 1) ? _RED_("force") " ( always do RATS )" : "",
|
||||
(hf14aconfig.forcerats == 2) ? _RED_("skip") " ( always skip RATS )" : ""
|
||||
);
|
||||
Dbprintf(" [m] Magsafe polling............... %s",
|
||||
Dbprintf(" [m] Magsafe polling............ %s",
|
||||
(hf14aconfig.magsafe == 1) ? _GREEN_("enabled") : _YELLOW_("disabled")
|
||||
);
|
||||
Dbprintf(" [p] Polling loop annotation....... %s %*D",
|
||||
Dbprintf(" [p] Polling loop annotation.... %s %*D",
|
||||
(hf14aconfig.polling_loop_annotation.frame_length <= 0) ? _YELLOW_("disabled") : _GREEN_("enabled"),
|
||||
hf14aconfig.polling_loop_annotation.frame_length,
|
||||
hf14aconfig.polling_loop_annotation.frame,
|
||||
|
@ -524,6 +524,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
|||
Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
|
||||
Uart.bitCount = 0;
|
||||
Uart.shiftReg = 0;
|
||||
|
||||
// Every 8 data bytes, store 8 parity bits into a parity byte
|
||||
if ((Uart.len & 0x0007) == 0) { // every 8 data bytes
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
|
||||
|
@ -804,12 +805,12 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
|
|||
set_tracing(true);
|
||||
|
||||
// The command (reader -> tag) that we're receiving.
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmdPar = BigBuf_calloc(MAX_PARITY_SIZE);
|
||||
|
||||
// The response (tag -> reader) that we're receiving.
|
||||
uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
uint8_t *receivedResp = BigBuf_calloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedRespPar = BigBuf_calloc(MAX_PARITY_SIZE);
|
||||
|
||||
uint8_t previous_data = 0;
|
||||
int maxDataLen = 0, dataLen;
|
||||
|
@ -1496,6 +1497,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
|
|||
// "precompiled" responses.
|
||||
// These exist for speed reasons. There are no time in the anti collision phase to calculate responses.
|
||||
// There are 12 predefined responses with a total of 84 bytes data to transmit.
|
||||
//
|
||||
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
|
||||
// 85 * 8 data bits, 85 * 1 parity bits, 12 start bits, 12 stop bits, 12 correction bits
|
||||
// 85 * 8 + 85 + 12 + 12 + 12 == 801
|
||||
|
@ -2681,9 +2683,9 @@ void iso14443a_antifuzz(uint32_t flags) {
|
|||
int len = 0;
|
||||
|
||||
// allocate buffers:
|
||||
uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
uint8_t *resp = BigBuf_malloc(20);
|
||||
uint8_t *received = BigBuf_calloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedPar = BigBuf_calloc(MAX_PARITY_SIZE);
|
||||
uint8_t *resp = BigBuf_calloc(20);
|
||||
|
||||
memset(received, 0x00, MAX_FRAME_SIZE);
|
||||
memset(received, 0x00, MAX_PARITY_SIZE);
|
||||
|
@ -2771,19 +2773,19 @@ static void iso14a_set_ATS_times(const uint8_t *ats) {
|
|||
|
||||
|
||||
static int GetATQA(uint8_t *resp, uint16_t resp_len, uint8_t *resp_par, const iso14a_polling_parameters_t *polling_parameters) {
|
||||
#define RETRY_TIMEOUT 10
|
||||
#define RETRY_TIMEOUT 10
|
||||
|
||||
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
||||
iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
|
||||
|
||||
// refactored to use local pointer, now no modification of polling_parameters pointer is done
|
||||
// I don't think the intention was to modify polling_parameters when sending in WUPA_POLLING_PARAMETERS etc.
|
||||
// I don't think the intention was to modify polling_parameters when sending in WUPA_POLLING_PARAMETERS etc.
|
||||
// Modify polling_params, if null use default values.
|
||||
iso14a_polling_parameters_t p;
|
||||
memcpy(&p, (uint8_t*)polling_parameters, sizeof(iso14a_polling_parameters_t));
|
||||
memcpy(&p, (uint8_t *)polling_parameters, sizeof(iso14a_polling_parameters_t));
|
||||
|
||||
if (polling_parameters == NULL) {
|
||||
memcpy(&p, (uint8_t*)&hf14a_polling_parameters, sizeof(iso14a_polling_parameters_t));
|
||||
memcpy(&p, (uint8_t *)&hf14a_polling_parameters, sizeof(iso14a_polling_parameters_t));
|
||||
}
|
||||
|
||||
bool first_try = true;
|
||||
|
@ -4068,9 +4070,7 @@ void DetectNACKbug(void) {
|
|||
// i = number of authentications sent. Not always 256, since we are trying to sync but close to it.
|
||||
FpgaDisableTracing();
|
||||
|
||||
uint8_t *data = BigBuf_malloc(4);
|
||||
data[0] = isOK;
|
||||
data[1] = num_nacks;
|
||||
uint8_t data[4] = {isOK, num_nacks, 0, 0};
|
||||
num_to_bytes(i, 2, data + 2);
|
||||
reply_ng(CMD_HF_MIFARE_NACK_DETECT, status, data, 4);
|
||||
|
||||
|
|
|
@ -221,10 +221,11 @@ out:
|
|||
int sam_get_version(void) {
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("start sam_get_version");
|
||||
}
|
||||
|
||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||
|
||||
uint8_t payload[] = {
|
||||
|
@ -252,8 +253,9 @@ int sam_get_version(void) {
|
|||
// 82 01
|
||||
// 01
|
||||
// 90 00
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("end sam_get_version");
|
||||
}
|
||||
|
||||
if (response[5] != 0xbd) {
|
||||
Dbprintf("Invalid SAM response");
|
||||
|
@ -289,8 +291,9 @@ error:
|
|||
out:
|
||||
BigBuf_free();
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("end sam_get_version");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -350,12 +353,10 @@ void sam_append_asn1_node(const uint8_t *root, const uint8_t *node, uint8_t type
|
|||
}
|
||||
|
||||
void sam_send_ack(void) {
|
||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||
|
||||
uint8_t payload[] = {
|
||||
0xa0, 0
|
||||
};
|
||||
uint8_t payload[] = { 0xa0, 0 };
|
||||
uint16_t payload_len = sizeof(payload);
|
||||
|
||||
sam_send_payload(
|
||||
|
|
|
@ -46,11 +46,12 @@
|
|||
*/
|
||||
static int sam_send_request_iso15(const uint8_t *const request, const uint8_t request_len, uint8_t *response, uint8_t *response_len, const bool shallow_mod, const bool break_on_nr_mac, const bool prevent_epurse_update) {
|
||||
int res = PM3_SUCCESS;
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("start sam_send_request_iso14a");
|
||||
}
|
||||
|
||||
uint8_t *buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *buf1 = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *buf2 = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
if (buf1 == NULL || buf2 == NULL) {
|
||||
res = PM3_EMALLOC;
|
||||
goto out;
|
||||
|
@ -255,10 +256,10 @@ out:
|
|||
*/
|
||||
static int sam_set_card_detected_picopass(const picopass_hdr_t *card_select) {
|
||||
int res = PM3_SUCCESS;
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("start sam_set_card_detected");
|
||||
|
||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
}
|
||||
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||
|
||||
// a0 12
|
||||
|
@ -314,8 +315,9 @@ error:
|
|||
out:
|
||||
BigBuf_free();
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("end sam_set_card_detected");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,13 +51,14 @@
|
|||
*/
|
||||
static int sam_set_card_detected_seos(iso14a_card_select_t *card_select) {
|
||||
int res = PM3_SUCCESS;
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("start sam_set_card_detected");
|
||||
}
|
||||
|
||||
uint8_t *request = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *request = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
uint16_t request_len = ISO7816_MAX_FRAME;
|
||||
|
||||
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||
|
||||
const uint8_t payload[] = {
|
||||
|
@ -107,8 +108,9 @@ error:
|
|||
out:
|
||||
BigBuf_free();
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
DbpString("end sam_set_card_detected");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -312,7 +312,7 @@ static int is_valid_filename(const char *filename) {
|
|||
*/
|
||||
static void copy_in_spiffs(const char *src, const char *dst) {
|
||||
uint32_t size = size_in_spiffs(src);
|
||||
uint8_t *mem = BigBuf_malloc(size);
|
||||
uint8_t *mem = BigBuf_calloc(size);
|
||||
read_from_spiffs(src, (uint8_t *)mem, size);
|
||||
write_to_spiffs(dst, (uint8_t *)mem, size);
|
||||
}
|
||||
|
|
|
@ -3107,3 +3107,55 @@ AB921CF0752C
|
|||
265A5F32DE73
|
||||
567D734C403C
|
||||
2426217B3B3B
|
||||
#
|
||||
# Card keys from Andalusian public transport system (Consorcio de Transportes)
|
||||
1848A8D1E4C5
|
||||
16EE1FE134E4
|
||||
5246B8F4ACFC
|
||||
515A8209843C
|
||||
0EF7636AA829
|
||||
E59D0F78C413
|
||||
5AF68604DD6B
|
||||
B0BCB22DCBA3
|
||||
51B3EF60BF56
|
||||
99100225D83B
|
||||
63C88F562B97
|
||||
B30B6A5AD434
|
||||
D33E4A4A0041
|
||||
9C0A4CC89D61
|
||||
5204D83D8CD3
|
||||
A662F9DC0D3D
|
||||
#
|
||||
# Card keys from EMT Malaga (Spain) bus system
|
||||
41534E354936
|
||||
454D41343253
|
||||
4541444C4130
|
||||
46305234324E
|
||||
505444505232
|
||||
5239425A3546
|
||||
454449434631
|
||||
414F4544384C
|
||||
344E4F4E4937
|
||||
45444E413254
|
||||
3255534D3033
|
||||
4F554D523935
|
||||
3141544D3735
|
||||
494E47463539
|
||||
32414F4E3341
|
||||
41534C473637
|
||||
534E41395430
|
||||
41364C38364F
|
||||
525241414D39
|
||||
41304532334F
|
||||
4D4545494F35
|
||||
4E324C453045
|
||||
394143494E32
|
||||
5352554E3245
|
||||
324553553036
|
||||
444D414E3539
|
||||
324745413232
|
||||
4E4E41455236
|
||||
394C52493639
|
||||
4D4941413236
|
||||
414D504F3243
|
||||
434C414E3639
|
||||
|
|
357
client/luascripts/hf_mfu_ultra.lua
Normal file
357
client/luascripts/hf_mfu_ultra.lua
Normal file
|
@ -0,0 +1,357 @@
|
|||
local ansicolors = require('ansicolors')
|
||||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local lib14a = require('read14a')
|
||||
local utils = require('utils')
|
||||
|
||||
-- globals
|
||||
copyright = ''
|
||||
author = 'Dmitry Malenok'
|
||||
version = 'v1.0.0'
|
||||
desc = [[
|
||||
The script provides functionality for writing Mifare Ultralight Ultra/UL-5 tags.
|
||||
]]
|
||||
example = [[
|
||||
-- restpre (write) dump to tag
|
||||
]]..ansicolors.yellow..[[script run hf_mfu_ultra -f hf-mfu-3476FF1514D866-dump.bin -k ffffffff -r]]..ansicolors.reset..[[
|
||||
|
||||
-- wipe tag (]]..ansicolors.red..[[Do not use it with UL-5!]]..ansicolors.reset..[[)
|
||||
]]..ansicolors.yellow..[[script run hf_mfu_ultra -k 1d237f76 -w ]]..ansicolors.reset..[[
|
||||
]]
|
||||
usage = [[
|
||||
script run hf_mfu_ultra -h -f <dump filename> -k <passwd> -w -r
|
||||
]]
|
||||
arguments = [[
|
||||
-h this help
|
||||
-f filename for the datadump to read (bin)
|
||||
-k pwd to use with the restore and wipe operations
|
||||
-r restore a binary dump to tag
|
||||
-w wipe tag (]]..ansicolors.red..[[Do not use it with UL-5!]]..ansicolors.reset..[[)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
local _password = nil
|
||||
local _defaultPassword = 'FFFFFFFF'
|
||||
local _dumpstart = 0x38*2 + 1
|
||||
---
|
||||
|
||||
--- Handles errors
|
||||
local function error(err)
|
||||
print(ansicolors.red.."ERROR:"..ansicolors.reset, err)
|
||||
core.clearCommandBuffer()
|
||||
return nil, err
|
||||
end
|
||||
---
|
||||
|
||||
-- sets the global password variable
|
||||
local function setPassword(password)
|
||||
if password == nil or #password == 0 then
|
||||
_password = nil;
|
||||
elseif #password ~= 8 then
|
||||
return false, 'Password must be 4 hex bytes'
|
||||
else
|
||||
_password = password
|
||||
end
|
||||
return true, 'Sets'
|
||||
end
|
||||
|
||||
|
||||
--- Parses response data
|
||||
local function parseResponse(rawResponse)
|
||||
local resp = Command.parse(rawResponse)
|
||||
local len = tonumber(resp.arg1) * 2
|
||||
return string.sub(tostring(resp.data), 0, len);
|
||||
end
|
||||
---
|
||||
|
||||
--- Sends raw data to PM3 and returns raw response if any
|
||||
local function sendRaw(rawdata, options)
|
||||
|
||||
local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW
|
||||
|
||||
if options.keep_signal then
|
||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT
|
||||
end
|
||||
|
||||
if options.connect then
|
||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_CONNECT
|
||||
end
|
||||
|
||||
if options.no_select then
|
||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_SELECT
|
||||
end
|
||||
|
||||
if options.append_crc then
|
||||
flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC
|
||||
end
|
||||
|
||||
local arg2 = #rawdata / 2
|
||||
if options.bits7 then
|
||||
arg2 = arg2 | tonumber(bit32.lshift(7, 16))
|
||||
end
|
||||
|
||||
local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER,
|
||||
arg1 = flags,
|
||||
arg2 = arg2,
|
||||
data = rawdata}
|
||||
return command:sendMIX(options.ignore_response)
|
||||
end
|
||||
---
|
||||
|
||||
--- Sends raw data to PM3 and returns parsed response
|
||||
local function sendWithResponse(payload, options)
|
||||
local opts;
|
||||
if options then
|
||||
opts = options
|
||||
else
|
||||
opts = {ignore_response = false, keep_signal = true, append_crc = true}
|
||||
end
|
||||
local rawResp, err = sendRaw(payload, opts)
|
||||
if err then return err end
|
||||
return parseResponse(rawResp)
|
||||
end
|
||||
---
|
||||
|
||||
-- Authenticates if password is provided
|
||||
local function authenticate(password)
|
||||
if password then
|
||||
local resp, err = sendWithResponse('1B'..password)
|
||||
if err then return err end
|
||||
-- looking for 2 bytes (4 symbols) of PACK and 2 bytes (4 symbols) of CRC
|
||||
if not resp or #resp ~=8 then return false, 'It seems that password is wrong' end
|
||||
return true
|
||||
end
|
||||
return true
|
||||
end
|
||||
--
|
||||
|
||||
-- selects tag and authenticates if password is provided
|
||||
local function connect()
|
||||
core.clearCommandBuffer()
|
||||
local info, err = lib14a.read(true, true)
|
||||
if err then
|
||||
lib14a.disconnect()
|
||||
return false, err
|
||||
end
|
||||
core.clearCommandBuffer()
|
||||
|
||||
return authenticate(_password)
|
||||
end
|
||||
--
|
||||
|
||||
-- reconnects and selects tag again
|
||||
local function reconnect()
|
||||
lib14a.disconnect()
|
||||
utils.Sleep(1)
|
||||
local info, err = connect()
|
||||
if not info then return false, "Unable to select tag: "..err end
|
||||
return true
|
||||
end
|
||||
--
|
||||
|
||||
-- checks tag version
|
||||
local function checkTagVersion()
|
||||
local resp, err = sendWithResponse('60');
|
||||
if err or resp == nil then return false, err end
|
||||
if string.find(resp, '0034210101000E03') ~= 1 then return false, 'Wrong tag version: '..string.sub(resp,1,-5) end
|
||||
return true
|
||||
end
|
||||
--
|
||||
|
||||
-- sends magic wakeup command
|
||||
local function magicWakeup()
|
||||
io.write('Sending magic wakeup command...')
|
||||
local resp, err = sendRaw('5000', {ignore_response = false, append_crc = true})
|
||||
if err or resp == nil then return false, "Unable to send first magic wakeup command: "..err end
|
||||
resp, err = sendRaw('40', {connect = true, no_select = true, ignore_response = false, keep_signal = true, append_crc = false, bits7 = true})
|
||||
if err or resp == nil then return false, "Unable to send first magic wakeup command: "..err end
|
||||
resp, err = sendRaw('43', {ignore_response = false, keep_signal = true, append_crc = false})
|
||||
if err or resp == nil then return false, "Unable to send second magic wakeup command: "..err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
return true
|
||||
end
|
||||
--
|
||||
|
||||
-- Writes dump to tag
|
||||
local function writeDump(filename)
|
||||
print(string.rep('--',20))
|
||||
local info, err = connect()
|
||||
if not info then return false, "Unable to select tag: "..err end
|
||||
info, err = checkTagVersion()
|
||||
if not info then return info, err end
|
||||
|
||||
-- load dump from file
|
||||
if not filename then return false, 'No dump filename provided' end
|
||||
io.write('Loading dump from file '..filename..'...')
|
||||
local dump
|
||||
dump, err = utils.ReadDumpFile(filename)
|
||||
if not dump then return false, err end
|
||||
if #dump ~= _dumpstart - 1 + 0xa4*2 then return false, 'Invalid dump file' end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
|
||||
local resp
|
||||
for i = 3, 0x23 do
|
||||
local blockStart = i * 8 + _dumpstart
|
||||
local block = string.sub(dump, blockStart, blockStart + 7)
|
||||
local cblock = string.format('%02x',i)
|
||||
io.write('Writing block 0x'..cblock..'...')
|
||||
resp, err = sendWithResponse('A2'..cblock..block)
|
||||
if err ~= nil then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
end
|
||||
|
||||
-- set password
|
||||
io.write('Setting password and pack ')
|
||||
info, err = reconnect()
|
||||
if not info then return false, err end
|
||||
local passwordStart = 0x27*8 + _dumpstart
|
||||
local password = string.sub(dump, passwordStart, passwordStart + 7)
|
||||
local packBlock = string.sub(dump, passwordStart+8, passwordStart + 15)
|
||||
io.write('(password: '..password..') (pack block: '..packBlock..')...')
|
||||
resp, err = sendWithResponse('A227'..password)
|
||||
if err ~= nil then return false, err end
|
||||
resp, err = sendWithResponse('A228'..packBlock)
|
||||
if err ~= nil then return false, err end
|
||||
if not setPassword(password) then return false, 'Unable to set password' end
|
||||
info, err = reconnect()
|
||||
if not info then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
|
||||
-- set configs and locks
|
||||
for i = 0x24, 0x26 do
|
||||
local blockStart = i * 8 + _dumpstart
|
||||
local block = string.sub(dump, blockStart, blockStart + 7)
|
||||
local cblock = string.format('%02x',i)
|
||||
io.write('Writing block 0x'..cblock..'...')
|
||||
resp, err = sendWithResponse('A2'..cblock..block)
|
||||
if err ~= nil then return false, err end
|
||||
info, err = reconnect()
|
||||
if not info then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
end
|
||||
|
||||
info, err = magicWakeup()
|
||||
if not info then return false, err end
|
||||
-- set uid and locks
|
||||
for i = 0x2, 0x0, -1 do
|
||||
local blockStart = i * 8 + _dumpstart
|
||||
local block = string.sub(dump, blockStart, blockStart + 7)
|
||||
local cblock = string.format('%02x',i)
|
||||
io.write('Writing block 0x'..cblock..'...')
|
||||
resp, err = sendWithResponse('A2'..cblock..block, {connect = i == 0x2, ignore_response = false, keep_signal = i ~= 0, append_crc = true})
|
||||
if err ~= nil then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
end
|
||||
|
||||
print(ansicolors.green..'The dump has been written to the tag.'..ansicolors.reset)
|
||||
return true
|
||||
end
|
||||
--
|
||||
|
||||
-- Wipes tag
|
||||
local function wipe()
|
||||
print(string.rep('--',20))
|
||||
print('Wiping tag')
|
||||
|
||||
local info, err = connect()
|
||||
if not info then return false, "Unable to select tag: "..err end
|
||||
info, err = checkTagVersion()
|
||||
if not info then return info, err end
|
||||
|
||||
|
||||
local resp
|
||||
-- clear lock bytes on page 0x02
|
||||
resp, err = sendWithResponse('3000')
|
||||
if err or resp == nil then return false, err end
|
||||
local currentLowLockPage = string.sub(resp,17,24)
|
||||
if(string.sub(currentLowLockPage,5,8) ~= '0000') then
|
||||
info, err = magicWakeup()
|
||||
if not info then return false, err end
|
||||
local newLowLockPage = string.sub(currentLowLockPage,1,4)..'0000'
|
||||
io.write('Clearing lock bytes on page 0x02...')
|
||||
resp, err = sendWithResponse('A202'..newLowLockPage, {connect = true, ignore_response = false, keep_signal = true, append_crc = true})
|
||||
if err ~= nil then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
end
|
||||
|
||||
-- clear lock bytes on page 0x24
|
||||
io.write('Clearing lock bytes on page 0x24...')
|
||||
info, err = reconnect()
|
||||
if not info then return false, err end
|
||||
resp, err = sendWithResponse('A224000000BD')
|
||||
if err ~= nil then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
|
||||
-- clear configs
|
||||
io.write('Clearing cfg0 and cfg1...')
|
||||
resp, err = sendWithResponse('A225000000FF')
|
||||
if err ~= nil then return false, err end
|
||||
resp, err = sendWithResponse('A22600050000')
|
||||
if err ~= nil then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
|
||||
-- clear password
|
||||
io.write('Reseting password (and pack) to default ('.._defaultPassword..') and 0000...')
|
||||
info, err = reconnect()
|
||||
if not info then return false, err end
|
||||
resp, err = sendWithResponse('A227'.._defaultPassword)
|
||||
if err ~= nil then return false, err end
|
||||
resp, err = sendWithResponse('A22800000000')
|
||||
if err ~= nil then return false, err end
|
||||
if not setPassword(_defaultPassword) then return false, 'Unable to set password' end
|
||||
info, err = reconnect()
|
||||
if not info then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
|
||||
-- clear other blocks
|
||||
for i = 3, 0x23 do
|
||||
local cblock = string.format('%02x',i)
|
||||
io.write('Clearing block 0x'..cblock..'...')
|
||||
resp, err = sendWithResponse('A2'..cblock..'00000000')
|
||||
if err ~= nil then return false, err end
|
||||
print(ansicolors.green..'done'..ansicolors.reset..'.')
|
||||
end
|
||||
|
||||
print(ansicolors.green..'The tag has been wiped.'..ansicolors.reset)
|
||||
|
||||
lib14a.disconnect()
|
||||
return true
|
||||
end
|
||||
--
|
||||
|
||||
-- Prints help
|
||||
local function help()
|
||||
print(copyright)
|
||||
print(author)
|
||||
print(version)
|
||||
print(desc)
|
||||
print(ansicolors.cyan..'Usage'..ansicolors.reset)
|
||||
print(usage)
|
||||
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
|
||||
print(arguments)
|
||||
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
|
||||
print(example)
|
||||
end
|
||||
---
|
||||
|
||||
-- The main entry point
|
||||
local function main(args)
|
||||
if #args == 0 then return help() end
|
||||
|
||||
local dumpFilename = nil
|
||||
|
||||
for opt, value in getopt.getopt(args, 'hf:k:rw') do
|
||||
local res, err
|
||||
res = true
|
||||
if opt == "h" then return help() end
|
||||
if opt == "f" then dumpFilename = value end
|
||||
if opt == 'k' then res, err = setPassword(value) end
|
||||
if opt == 'r' then res, err = writeDump(dumpFilename) end
|
||||
if opt == 'w' then res, err = wipe() end
|
||||
if not res then return error(err) end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
main(args)
|
|
@ -90,13 +90,14 @@ def lprint(s='', end='\n', flush=False, prompt="[" + color("=", fg="yellow") +
|
|||
- logfile (R)
|
||||
"""
|
||||
s = f"{prompt}" + f"\n{prompt}".join(s.split('\n'))
|
||||
print(s, end=end, flush=flush)
|
||||
safe_s = s.encode('utf-8', errors='ignore').decode('utf-8')
|
||||
print(safe_s, end=end, flush=flush)
|
||||
|
||||
if log is True:
|
||||
global logbuffer
|
||||
if logfile is not None:
|
||||
with open(logfile, 'a', encoding='utf-8') as f:
|
||||
f.write(s + end)
|
||||
f.write(safe_s + end)
|
||||
else:
|
||||
# buffering
|
||||
logbuffer += s + end
|
||||
|
|
|
@ -600,7 +600,7 @@ static command_t CommandTable[] = {
|
|||
{"texkom", CmdHFTexkom, AlwaysAvailable, "{ Texkom RFIDs... }"},
|
||||
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
|
||||
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
|
||||
{"vas", CmdHFVAS, AlwaysAvailable, "{ Apple Value Added Service }"},
|
||||
{"vas", CmdHFVAS, AlwaysAvailable, "{ Apple Value Added Service... }"},
|
||||
#ifdef HAVE_GD
|
||||
{"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"},
|
||||
#endif
|
||||
|
|
|
@ -914,7 +914,7 @@ int CmdHF14ASim(const char *Cmd) {
|
|||
bool keypress = kbd_enter_pressed();
|
||||
while (keypress == false) {
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == false)
|
||||
continue;
|
||||
|
||||
if (resp.status != PM3_SUCCESS)
|
||||
|
@ -1403,10 +1403,10 @@ static int CmdHF14AAPDU(const char *Cmd) {
|
|||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
||||
bool extendedAPDU = arg_get_lit(ctx, 6);
|
||||
int le = arg_get_int_def(ctx, 7, 0);
|
||||
|
||||
|
||||
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||
int datalen = 0;
|
||||
|
||||
|
@ -4037,7 +4037,7 @@ int CmdHF14AAIDSim(const char *Cmd) {
|
|||
bool keypress = kbd_enter_pressed();
|
||||
while (keypress == false) {
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) {
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -3029,7 +3029,9 @@ int infoHF14B(bool verbose, bool do_aid_search) {
|
|||
|
||||
// try unknown 14b read commands (to be identified later)
|
||||
// could be read of calypso, CEPAS, moneo, or pico pass.
|
||||
if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found");
|
||||
if (verbose) {
|
||||
PrintAndLogEx(FAILED, "no 14443-B tag found");
|
||||
}
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -584,14 +584,14 @@ static void fuse_config(const picopass_hdr_t *hdr) {
|
|||
|
||||
uint16_t otp = (hdr->conf.otp[1] << 8 | hdr->conf.otp[0]);
|
||||
|
||||
PrintAndLogEx(INFO, " Raw... " _YELLOW_("%s"), sprint_hex((uint8_t *)&hdr->conf, 8));
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " ( %3u )............. app limit", hdr->conf.app_limit, hdr->conf.app_limit);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ block write lock", hdr->conf.block_writelock);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... chip", hdr->conf.chip_config);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... mem", hdr->conf.mem_config);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " fuses", hdr->conf.fuses);
|
||||
PrintAndLogEx(INFO, " Raw: " _YELLOW_("%s"), sprint_hex((uint8_t *)&hdr->conf, 8));
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " ( %3u )............. app limit", hdr->conf.app_limit, hdr->conf.app_limit);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ block write lock", hdr->conf.block_writelock);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... chip", hdr->conf.chip_config);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... mem", hdr->conf.mem_config);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas);
|
||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " fuses", hdr->conf.fuses);
|
||||
|
||||
uint8_t fuses = hdr->conf.fuses;
|
||||
|
||||
|
@ -1467,8 +1467,9 @@ static void iclass_decode_credentials(uint8_t *data) {
|
|||
bool has_values = (memcmp(b7, empty, PICOPASS_BLOCK_SIZE) != 0) && (memcmp(b7, zeros, PICOPASS_BLOCK_SIZE) != 0);
|
||||
if (has_values && encryption == None) {
|
||||
|
||||
// todo: remove preamble/sentinel
|
||||
PrintAndLogEx(INFO, "------------------------ " _CYAN_("Block 7 decoder") " --------------------------");
|
||||
|
||||
// todo: remove preamble/sentinel
|
||||
if (has_new_pacs) {
|
||||
iclass_decode_credentials_new_pacs(b7);
|
||||
} else {
|
||||
|
@ -1487,9 +1488,6 @@ static void iclass_decode_credentials(uint8_t *data) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
decode_wiegand(top, mid, bot, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "No unencrypted legacy credential found");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1903,15 +1901,32 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
|
||||
int key_len = 0;
|
||||
uint8_t key[8] = {0};
|
||||
bool auth = false;
|
||||
|
||||
CLIGetHexWithReturn(ctx, 2, key, &key_len);
|
||||
|
||||
int deb_key_nr = arg_get_int_def(ctx, 3, -1);
|
||||
|
||||
int credit_key_len = 0;
|
||||
uint8_t credit_key[8] = {0};
|
||||
CLIGetHexWithReturn(ctx, 4, credit_key, &credit_key_len);
|
||||
|
||||
int credit_key_nr = arg_get_int_def(ctx, 5, -1);
|
||||
bool elite = arg_get_lit(ctx, 6);
|
||||
bool rawkey = arg_get_lit(ctx, 7);
|
||||
bool use_replay = arg_get_lit(ctx, 8);
|
||||
bool dense_output = g_session.dense_output || arg_get_lit(ctx, 9);
|
||||
bool force = arg_get_lit(ctx, 10);
|
||||
bool shallow_mod = arg_get_lit(ctx, 11);
|
||||
bool nosave = arg_get_lit(ctx, 12);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
bool auth = false;
|
||||
bool have_credit_key = false;
|
||||
|
||||
// Sanity checks
|
||||
|
||||
if (key_len > 0 && deb_key_nr >= 0) {
|
||||
PrintAndLogEx(ERR, "Please specify debit key or index, not both");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -1919,7 +1934,6 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
auth = true;
|
||||
if (key_len != 8) {
|
||||
PrintAndLogEx(ERR, "Debit key is incorrect length");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
@ -1931,22 +1945,12 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, "Using AA1 (debit) key[%d] " _GREEN_("%s"), deb_key_nr, sprint_hex(iClass_Key_Table[deb_key_nr], 8));
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Key number is invalid");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
int credit_key_len = 0;
|
||||
uint8_t credit_key[8] = {0};
|
||||
bool have_credit_key = false;
|
||||
|
||||
CLIGetHexWithReturn(ctx, 4, credit_key, &credit_key_len);
|
||||
|
||||
int credit_key_nr = arg_get_int_def(ctx, 5, -1);
|
||||
|
||||
if (credit_key_len > 0 && credit_key_nr >= 0) {
|
||||
PrintAndLogEx(ERR, "Please specify credit key or index, not both");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -1955,7 +1959,6 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
have_credit_key = true;
|
||||
if (credit_key_len != 8) {
|
||||
PrintAndLogEx(ERR, "Credit key is incorrect length");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
@ -1968,21 +1971,10 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, "Using AA2 (credit) key[%d] " _GREEN_("%s"), credit_key_nr, sprint_hex(iClass_Key_Table[credit_key_nr], 8));
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Key number is invalid");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
bool elite = arg_get_lit(ctx, 6);
|
||||
bool rawkey = arg_get_lit(ctx, 7);
|
||||
bool use_replay = arg_get_lit(ctx, 8);
|
||||
bool dense_output = g_session.dense_output || arg_get_lit(ctx, 9);
|
||||
bool force = arg_get_lit(ctx, 10);
|
||||
bool shallow_mod = arg_get_lit(ctx, 11);
|
||||
bool nosave = arg_get_lit(ctx, 12);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if ((use_replay + rawkey + elite) > 1) {
|
||||
PrintAndLogEx(ERR, "Can not use a combo of 'elite', 'raw', 'nr'");
|
||||
return PM3_EINVARG;
|
||||
|
@ -2005,7 +1997,6 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t *)&payload_rdr, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
DropField();
|
||||
|
@ -2062,9 +2053,11 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "No keys needed, ignoring user supplied key");
|
||||
}
|
||||
} else {
|
||||
|
||||
if (auth == false) {
|
||||
PrintAndLogEx(FAILED, "Run command with keys");
|
||||
return PM3_ESOFT;
|
||||
auth = true;
|
||||
memcpy(key, iClass_Key_Table[0], 8);
|
||||
PrintAndLogEx(SUCCESS, "Default to AA1 (debit) " _GREEN_("%s"), sprint_hex(key, sizeof(key)));
|
||||
}
|
||||
|
||||
if (app_limit2 != 0) {
|
||||
|
@ -2134,7 +2127,7 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
uint8_t tempbuf[0x100 * 8];
|
||||
|
||||
// response ok - now get bigbuf content of the dump
|
||||
if (!GetFromDevice(BIG_BUF, tempbuf, sizeof(tempbuf), startindex, NULL, 0, NULL, 2500, false)) {
|
||||
if (GetFromDevice(BIG_BUF, tempbuf, sizeof(tempbuf), startindex, NULL, 0, NULL, 2500, false) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -2199,7 +2192,7 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
}
|
||||
|
||||
// get dumped data from bigbuf
|
||||
if (!GetFromDevice(BIG_BUF, tempbuf, sizeof(tempbuf), startindex, NULL, 0, NULL, 2500, false)) {
|
||||
if (GetFromDevice(BIG_BUF, tempbuf, sizeof(tempbuf), startindex, NULL, 0, NULL, 2500, false) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
goto write_dump;
|
||||
}
|
||||
|
@ -2272,7 +2265,7 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *macdata
|
|||
SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 2000) == 0) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 2000) == false) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -2406,14 +2399,13 @@ static int CmdHFiClassCreditEpurse(const char *Cmd) {
|
|||
"Credit the epurse on an iCLASS tag. The provided key must be the credit key.\n"
|
||||
"The first two bytes of the epurse are the debit value (big endian) and may be any value except FFFF.\n"
|
||||
"The remaining two bytes of the epurse are the credit value and must be smaller than the previous value.",
|
||||
"hf iclass creditepurse -d FEFFFFFF -k 001122334455667B\n"
|
||||
"hf iclass creditepurse -d FEFFFFFF --ki 0");
|
||||
"hf iclass creditepurse --ki 0 -d FEFFFEFF");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("k", "key", "<hex>", "Credit key as 8 hex bytes"),
|
||||
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
|
||||
arg_str1("d", "data", "<hex>", "data to write as 8 hex bytes"),
|
||||
arg_str1("d", "data", "<hex>", "data to write as 4 hex bytes"),
|
||||
arg_lit0(NULL, "elite", "elite computations applied to key"),
|
||||
arg_lit0(NULL, "raw", "no computations applied to key"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
|
@ -2498,7 +2490,7 @@ static int CmdHFiClassCreditEpurse(const char *Cmd) {
|
|||
PacketResponseNG resp;
|
||||
|
||||
int isok;
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_CREDIT_EPURSE, &resp, 2000) == 0) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_CREDIT_EPURSE, &resp, 2000) == false) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "command execution time out");
|
||||
isok = PM3_ETIMEOUT;
|
||||
} else if (resp.status != PM3_SUCCESS) {
|
||||
|
@ -2680,7 +2672,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_ICLASS_RESTORE, (uint8_t *)payload, payload_size);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_RESTORE, &resp, 2500) == 0) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_RESTORE, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
DropField();
|
||||
free(payload);
|
||||
|
@ -2917,12 +2909,60 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void iclass_cmp_print(uint8_t *b1, uint8_t *b2, const char *header1, const char *header2) {
|
||||
|
||||
char line1[240] = {0};
|
||||
char line2[240] = {0};
|
||||
|
||||
strcat(line1, header1);
|
||||
strcat(line2, header2);
|
||||
|
||||
for (uint8_t i = 0; i < PICOPASS_BLOCK_SIZE; i++) {
|
||||
|
||||
int l1 = strlen(line1);
|
||||
int l2 = strlen(line2);
|
||||
|
||||
uint8_t hi1 = NIBBLE_HIGH(b1[i]);
|
||||
uint8_t low1 = NIBBLE_LOW(b1[i]);
|
||||
|
||||
uint8_t hi2 = NIBBLE_HIGH(b2[i]);
|
||||
uint8_t low2 = NIBBLE_LOW(b2[i]);
|
||||
|
||||
if (hi1 != hi2) {
|
||||
snprintf(line1 + l1, sizeof(line1) - l1, _RED_("%1X"), hi1);
|
||||
snprintf(line2 + l2, sizeof(line2) - l2, _GREEN_("%1X"), hi2);
|
||||
} else {
|
||||
snprintf(line1 + l1, sizeof(line1) - l1, "%1X", hi1);
|
||||
snprintf(line2 + l2, sizeof(line2) - l2, "%1X", hi2);
|
||||
}
|
||||
|
||||
l1 = strlen(line1);
|
||||
l2 = strlen(line2);
|
||||
|
||||
if (low1 != low2) {
|
||||
snprintf(line1 + l1, sizeof(line1) - l1, _RED_("%1X"), low1);
|
||||
snprintf(line2 + l2, sizeof(line2) - l2, _GREEN_("%1X"), low2);
|
||||
} else {
|
||||
snprintf(line1 + l1, sizeof(line1) - l1, "%1X", low1);
|
||||
snprintf(line2 + l2, sizeof(line2) - l2, "%1X", low2);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "%s", line1);
|
||||
PrintAndLogEx(INFO, "%s", line2);
|
||||
}
|
||||
|
||||
static int CmdHFiClass_TearBlock(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf iclass trbl",
|
||||
"Tear off an iCLASS tag block",
|
||||
"hf iclass trbl --blk 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B --tdb 100 --tde 150\n"
|
||||
"hf iclass trbl --blk 10 -d AAAAAAAAAAAAAAAA --ki 0 --tdb 100 --tde 150");
|
||||
CLIParserInit(&ctx, "hf iclass tear",
|
||||
"Tear off an iCLASS tag block\n"
|
||||
"e-purse usually 300-500us to trigger the erase phase\n"
|
||||
"also seen 1800-2100us on some cards\n",
|
||||
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B -s 300 -e 600\n"
|
||||
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA --ki 0 -s 300 -e 600\n"
|
||||
"hf iclass tear --blk 2 -d fdffffffffffffff --ki 1 --credit -s 400 -e 500"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -2937,83 +2977,30 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
|
|||
arg_lit0(NULL, "nr", "replay of NR/MAC"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"),
|
||||
arg_int1(NULL, "tdb", "<dec>", "tearoff delay start in ms"),
|
||||
arg_int1(NULL, "tde", "<dec>", "tearoff delay end in ms"),
|
||||
arg_int1("s", NULL, "<dec>", "tearoff delay start (in us) must be between 1 and 43000 (43ms). Precision is about 1/3 us"),
|
||||
arg_int0("i", NULL, "<dec>", "tearoff delay increment (in us) - default 10"),
|
||||
arg_int0("e", NULL, "<dec>", "tearoff delay end (in us) must be a higher value than the start delay"),
|
||||
arg_int0(NULL, "loop", "<dec>", "number of times to loop per tearoff time"),
|
||||
arg_int0(NULL, "sleep", "<ms>", "Sleep between each tear"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int key_len = 0;
|
||||
uint8_t key[8] = {0};
|
||||
|
||||
CLIGetHexWithReturn(ctx, 1, key, &key_len);
|
||||
|
||||
int key_nr = arg_get_int_def(ctx, 2, -1);
|
||||
|
||||
if (key_len > 0 && key_nr >= 0) {
|
||||
PrintAndLogEx(ERR, "Please specify key or index, not both");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool auth = false;
|
||||
|
||||
if (key_len > 0) {
|
||||
auth = true;
|
||||
if (key_len != 8) {
|
||||
PrintAndLogEx(ERR, "Key is incorrect length");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
} else if (key_nr >= 0) {
|
||||
if (key_nr < ICLASS_KEYS_MAX) {
|
||||
auth = true;
|
||||
memcpy(key, iClass_Key_Table[key_nr], 8);
|
||||
PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8));
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Key number is invalid");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
int blockno = arg_get_int_def(ctx, 3, 0);
|
||||
|
||||
int data_len = 0;
|
||||
uint8_t data[8] = {0};
|
||||
CLIGetHexWithReturn(ctx, 4, data, &data_len);
|
||||
|
||||
if (data_len != 8) {
|
||||
PrintAndLogEx(ERR, "Data must be 8 hex bytes (16 hex symbols)");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
int mac_len = 0;
|
||||
uint8_t mac[4] = {0};
|
||||
CLIGetHexWithReturn(ctx, 5, mac, &mac_len);
|
||||
|
||||
if (mac_len) {
|
||||
if (mac_len != 4) {
|
||||
PrintAndLogEx(ERR, "MAC must be 4 hex bytes (8 hex symbols)");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
int tearoff_start = arg_get_int_def(ctx, 12, 100);
|
||||
int tearoff_end = arg_get_int_def(ctx, 13, 200);
|
||||
|
||||
if (tearoff_end <= tearoff_start) {
|
||||
PrintAndLogEx(ERR, "Tearoff end delay must be bigger than the start delay.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (tearoff_start < 0 || tearoff_end <= 0) {
|
||||
PrintAndLogEx(ERR, "Tearoff start/end delays should be bigger than 0.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool use_credit_key = arg_get_lit(ctx, 6);
|
||||
bool elite = arg_get_lit(ctx, 7);
|
||||
bool rawkey = arg_get_lit(ctx, 8);
|
||||
|
@ -3021,58 +3008,231 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
|
|||
bool verbose = arg_get_lit(ctx, 10);
|
||||
bool shallow_mod = arg_get_lit(ctx, 11);
|
||||
|
||||
int tearoff_start = arg_get_int_def(ctx, 12, 100);
|
||||
int tearoff_original_start = tearoff_start; // save original start value for later use
|
||||
int tearoff_increment = arg_get_int_def(ctx, 13, 10);
|
||||
int tearoff_end = arg_get_int_def(ctx, 14, tearoff_start + tearoff_increment + 500);
|
||||
int tearoff_loop = arg_get_int_def(ctx, 15, 1);
|
||||
int tearoff_sleep = arg_get_int_def(ctx, 16, 0);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if ((use_replay + rawkey + elite) > 1) {
|
||||
PrintAndLogEx(ERR, "Can not use a combo of 'elite', 'raw', 'nr'");
|
||||
// Sanity checks
|
||||
if (key_len > 0 && key_nr >= 0) {
|
||||
PrintAndLogEx(ERR, "Please specify key or index, not both");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool auth = false;
|
||||
|
||||
if (key_len > 0) {
|
||||
|
||||
auth = true;
|
||||
if (key_len != 8) {
|
||||
PrintAndLogEx(ERR, "Key is incorrect length");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
if (key_nr >= 0) {
|
||||
if (key_nr < ICLASS_KEYS_MAX) {
|
||||
auth = true;
|
||||
memcpy(key, iClass_Key_Table[key_nr], 8);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex_inrow(iClass_Key_Table[key_nr], 8));
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Key number is invalid");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (data_len != 8) {
|
||||
PrintAndLogEx(ERR, "Data must be 8 hex bytes (16 hex symbols), got " _RED_("%u"), data_len);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (mac_len && mac_len != 4) {
|
||||
PrintAndLogEx(ERR, "MAC must be 4 hex bytes (8 hex symbols)");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (tearoff_end <= tearoff_start) {
|
||||
PrintAndLogEx(ERR, "Tearoff end delay must be larger than the start delay");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (tearoff_start <= 0) {
|
||||
PrintAndLogEx(ERR, "Tearoff_start delays must be larger than 0");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (tearoff_end <= 0) {
|
||||
PrintAndLogEx(ERR, "Tearoff_end delays must be larger than 0");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if ((use_replay + rawkey + elite) > 1) {
|
||||
PrintAndLogEx(ERR, "Can not use a combo of `--elite`, `--raw`, `--nr`");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
int loop_count = 0;
|
||||
int isok = 0;
|
||||
tearoff_params_t params;
|
||||
bool read_ok = false;
|
||||
while (tearoff_start < tearoff_end && !read_ok) {
|
||||
//perform read here, repeat if failed or 00s
|
||||
uint8_t keyType = 0x88; // debit key
|
||||
|
||||
uint8_t data_read_orig[8] = {0};
|
||||
bool first_read = false;
|
||||
bool reread = false;
|
||||
while (!first_read) {
|
||||
int res_orig = iclass_read_block_ex(key, blockno, 0x88, elite, rawkey, use_replay, verbose, auth, shallow_mod, data_read_orig, false);
|
||||
if (res_orig == PM3_SUCCESS && !reread) {
|
||||
if (memcmp(data_read_orig, zeros, 8) == 0) {
|
||||
reread = true;
|
||||
} else {
|
||||
first_read = true;
|
||||
reread = false;
|
||||
}
|
||||
} else if (res_orig == PM3_SUCCESS && reread) {
|
||||
first_read = true;
|
||||
reread = false;
|
||||
}
|
||||
if (use_credit_key) {
|
||||
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("credit") " key");
|
||||
keyType = 0x18; // credit key
|
||||
}
|
||||
|
||||
if (auth == false) {
|
||||
PrintAndLogEx(SUCCESS, "No key supplied. Trying no authentication read/writes");
|
||||
}
|
||||
|
||||
if (tearoff_loop > 1) {
|
||||
PrintAndLogEx(SUCCESS, _YELLOW_("%u") " attempts / tearoff", tearoff_loop);
|
||||
}
|
||||
|
||||
if (tearoff_sleep) {
|
||||
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("%u") " ms delay between attempts", tearoff_sleep);
|
||||
}
|
||||
|
||||
//check if the card is in secure mode or not
|
||||
iclass_card_select_t payload_rdr = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
|
||||
if (shallow_mod) {
|
||||
payload_rdr.flags |= FLAG_ICLASS_READER_SHALLOW_MOD;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t *)&payload_rdr, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
DropField();
|
||||
|
||||
if (resp.status == PM3_ERFTRANS) {
|
||||
PrintAndLogEx(FAILED, "no tag found");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t *)resp.data.asBytes;
|
||||
if (r->status == FLAG_ICLASS_NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to read block 0,1,2");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = &r->header.hdr;
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
PrintAndLogEx(INFO, "Card in non-secure page mode detected");
|
||||
auth = false;
|
||||
}
|
||||
|
||||
if (pagemap == 0x0) {
|
||||
PrintAndLogEx(WARNING, _RED_("No auth possible. Read only if RA is enabled"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
bool read_auth = auth;
|
||||
|
||||
// perform initial read here, repeat if failed or 00s
|
||||
uint8_t data_read_orig[8] = {0};
|
||||
uint8_t ff_data[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
bool first_read = false;
|
||||
bool reread = false;
|
||||
bool erase_phase = false;
|
||||
|
||||
int res_orig = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, data_read_orig, false);
|
||||
if (res_orig == PM3_SUCCESS && !reread) {
|
||||
if (memcmp(data_read_orig, zeros, 8) == 0) {
|
||||
reread = true;
|
||||
} else {
|
||||
first_read = true;
|
||||
reread = false;
|
||||
}
|
||||
} else if (res_orig == PM3_SUCCESS && reread) {
|
||||
first_read = true;
|
||||
reread = false;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Original block data... " _CYAN_("%s"), sprint_hex_inrow(data_read_orig, sizeof(data_read_orig)));
|
||||
PrintAndLogEx(SUCCESS, "New data to write..... " _YELLOW_("%s"), sprint_hex_inrow(data, sizeof(data)));
|
||||
PrintAndLogEx(SUCCESS, "Target block.......... " _YELLOW_("%u") " / " _YELLOW_("0x%02x"), blockno, blockno);
|
||||
// turn off Device side debug messages
|
||||
uint8_t dbg_curr = DBG_NONE;
|
||||
if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
// clear trace log
|
||||
SendCommandNG(CMD_BUFF_CLEAR, NULL, 0);
|
||||
|
||||
PrintAndLogEx(INFO, "---------------------------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------\n");
|
||||
// Main loop
|
||||
while ((tearoff_start <= tearoff_end) && (read_ok == false)) {
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
PrintAndLogEx(WARNING, "\naborted via keyboard.");
|
||||
isok = PM3_EOPABORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
params.on = true;
|
||||
params.delay_us = tearoff_start;
|
||||
handle_tearoff(¶ms, false);
|
||||
PrintAndLogEx(INFO, "Tear off delay: "_YELLOW_("%d")" ms", tearoff_start);
|
||||
isok = iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, verbose, auth, shallow_mod);
|
||||
switch (isok) {
|
||||
case PM3_SUCCESS:
|
||||
PrintAndLogEx(SUCCESS, "Wrote block " _YELLOW_("%d") " / " _YELLOW_("0x%02X") " ( " _GREEN_("ok") " )", blockno, blockno);
|
||||
break;
|
||||
case PM3_ETEAROFF:
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(FAILED, "Writing failed");
|
||||
break;
|
||||
// set tear off trigger
|
||||
clearCommandBuffer();
|
||||
tearoff_params_t params = {
|
||||
.delay_us = (tearoff_start & 0xFFFF),
|
||||
.on = true,
|
||||
.off = false
|
||||
};
|
||||
|
||||
int res = handle_tearoff(¶ms, verbose);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Failed to configure tear off");
|
||||
isok = PM3_ESOFT;
|
||||
goto out;
|
||||
}
|
||||
//read the data back
|
||||
|
||||
PrintAndLogEx(INPLACE, " Tear off delay "_YELLOW_("%u")" / "_YELLOW_("%d")" us - "_YELLOW_("%u")" / "_YELLOW_("%d")" loops", params.delay_us, (tearoff_end & 0xFFFF), loop_count+1, tearoff_loop);
|
||||
|
||||
// write block - don't check the return value. As a tear-off occurred, the write failed.
|
||||
iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, verbose, auth, shallow_mod);
|
||||
|
||||
// read the data back
|
||||
uint8_t data_read[8] = {0};
|
||||
first_read = false;
|
||||
reread = false;
|
||||
bool decrease = false;
|
||||
while (!first_read) {
|
||||
int res = iclass_read_block_ex(key, blockno, 0x88, elite, rawkey, use_replay, verbose, auth, shallow_mod, data_read, false);
|
||||
|
||||
while (first_read == false) {
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
PrintAndLogEx(WARNING, "\naborted via keyboard.");
|
||||
isok = PM3_EOPABORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (blockno == 1) {
|
||||
read_auth = false;
|
||||
}
|
||||
|
||||
res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false);
|
||||
if (res == PM3_SUCCESS && !reread) {
|
||||
if (memcmp(data_read, zeros, 8) == 0) {
|
||||
reread = true;
|
||||
|
@ -3087,26 +3247,103 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
|
|||
decrease = true;
|
||||
}
|
||||
}
|
||||
if (decrease && tearoff_start > 0) { //if there was an error reading repeat the tearoff with the same delay
|
||||
tearoff_start--;
|
||||
|
||||
// if there was an error reading repeat the tearoff with the same delay
|
||||
if (decrease && (tearoff_start > tearoff_increment) && (tearoff_start >= tearoff_original_start)) {
|
||||
tearoff_start -= tearoff_increment;
|
||||
}
|
||||
|
||||
bool tear_success = true;
|
||||
for (int i = 0; i < PICOPASS_BLOCK_SIZE; i++) {
|
||||
if (data[i] != data_read[i]) {
|
||||
tear_success = false;
|
||||
bool expected_values = true;
|
||||
|
||||
if (memcmp(data_read, data, 8) != 0) {
|
||||
tear_success = false;
|
||||
}
|
||||
|
||||
if ((tear_success == false) && (memcmp(data_read, zeros, 8) != 0) && (memcmp(data_read, data_read_orig, 8) != 0)) {
|
||||
|
||||
// tearoff succeeded (partially)
|
||||
|
||||
expected_values = false;
|
||||
|
||||
if (memcmp(data_read, ff_data, 8) == 0 && memcmp(data_read_orig, ff_data, 8) != 0) {
|
||||
erase_phase = true;
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, _CYAN_("Erase phase hit... ALL ONES"));
|
||||
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
|
||||
} else {
|
||||
|
||||
if (erase_phase) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, _MAGENTA_("Tearing! Write phase (post erase)"));
|
||||
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, _CYAN_("Tearing! unknown phase"));
|
||||
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
|
||||
}
|
||||
}
|
||||
|
||||
if (blockno == 1) {
|
||||
if (data_read[0] != data_read_orig[0]) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "Application limit changed, from %u to %u", data_read_orig[0], data_read[0]);
|
||||
isok = PM3_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (data_read[7] != data_read_orig[7]) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "Fuse changed, from %02x to %02x", data_read_orig[7], data_read[7]);
|
||||
isok = PM3_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tear_success) { //tearoff succeeded
|
||||
|
||||
if (tear_success) { // tearoff succeeded with expected values
|
||||
|
||||
read_ok = true;
|
||||
PrintAndLogEx(SUCCESS, _GREEN_("Tear-off Success!"));
|
||||
PrintAndLogEx(INFO, "Read: %s", sprint_hex(data_read, sizeof(data_read)));
|
||||
} else { //tearoff did not succeed
|
||||
PrintAndLogEx(FAILED, _RED_("Tear-off Failed!"));
|
||||
tearoff_start++;
|
||||
tear_success = true;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Read: " _GREEN_("%s") " %s"
|
||||
, sprint_hex_inrow(data_read, sizeof(data_read)),
|
||||
(expected_values) ? _GREEN_(" -> Expected values!") : ""
|
||||
);
|
||||
}
|
||||
|
||||
loop_count++;
|
||||
|
||||
if (loop_count == tearoff_loop) {
|
||||
tearoff_start += tearoff_increment;
|
||||
loop_count = 0;
|
||||
}
|
||||
|
||||
if (tearoff_sleep) {
|
||||
msleep(tearoff_sleep);
|
||||
}
|
||||
PrintAndLogEx(INFO, "---------------");
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
DropField();
|
||||
|
||||
if (setDeviceDebugLevel(verbose ? MAX(dbg_curr, DBG_INFO) : DBG_NONE, false) != PM3_SUCCESS) {
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
// disable tearoff in case of keyboard abort, or it'll trigger on next operation
|
||||
clearCommandBuffer();
|
||||
tearoff_params_t params = {
|
||||
.delay_us = tearoff_start,
|
||||
.on = false,
|
||||
.off = true
|
||||
};
|
||||
handle_tearoff(¶ms, false);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
clearCommandBuffer();
|
||||
return isok;
|
||||
}
|
||||
|
||||
|
@ -3502,7 +3739,6 @@ static int CmdHFiClassView(const char *Cmd) {
|
|||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
|
||||
PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, (uint16_t)(bytes_read >> 3), (uint16_t)(bytes_read >> 3));
|
||||
PrintAndLogEx(INFO, "Printing blocks from: " _YELLOW_("%02d") " to: " _YELLOW_("%02d"), (startblock == 0) ? 6 : startblock, endblock);
|
||||
}
|
||||
|
@ -4255,7 +4491,7 @@ static int CmdHFiClassLegRecLookUp(const char *Cmd) {
|
|||
uint8_t startingKey[PICOPASS_BLOCK_SIZE] = {0};
|
||||
CLIGetHexWithReturn(ctx, 4, startingKey, &startingkey_len);
|
||||
|
||||
uint64_t index = arg_get_int_def(ctx, 6, 0); //has to be 64 as we're bruteforcing 40 bits
|
||||
uint64_t index = arg_get_int_def(ctx, 5, 0); //has to be 64 as we're bruteforcing 40 bits
|
||||
index = index * 1000000;
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
@ -5530,7 +5766,7 @@ static command_t CommandTable[] = {
|
|||
{"view", CmdHFiClassView, AlwaysAvailable, "Display content from tag dump file"},
|
||||
{"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "Write Picopass / iCLASS block"},
|
||||
{"creditepurse", CmdHFiClassCreditEpurse, IfPm3Iclass, "Credit epurse value"},
|
||||
{"trbl", CmdHFiClass_TearBlock, IfPm3Iclass, "Performs tearoff attack on iClass block"},
|
||||
{"tear", CmdHFiClass_TearBlock, IfPm3Iclass, "Performs tearoff attack on iClass block"},
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("Recovery") " --------------------"},
|
||||
// {"autopwn", CmdHFiClassAutopwn, IfPm3Iclass, "Automatic key recovery tool for iCLASS"},
|
||||
{"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "Check keys"},
|
||||
|
@ -5634,7 +5870,7 @@ int info_iclass(bool shallow_mod) {
|
|||
} else {
|
||||
|
||||
if ((r->status & FLAG_ICLASS_CC) == FLAG_ICLASS_CC) {
|
||||
PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
|
||||
PrintAndLogEx(SUCCESS, "E-purse: %s card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
|
||||
}
|
||||
|
||||
if (memcmp(hdr->key_d, zeros, sizeof(zeros))) {
|
||||
|
@ -5733,5 +5969,6 @@ int info_iclass(bool shallow_mod) {
|
|||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16
|
|||
SendCommandMIX(CMD_HF_ISO14443A_READER, arg0, arg1, 0, cmd, len);
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
|
|
@ -1915,9 +1915,13 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't
|
|||
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) continue;
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
key64 = bytes_to_num(data + 10, 6);
|
||||
|
@ -4005,9 +4009,13 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
|||
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) continue;
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE);
|
||||
|
@ -4070,7 +4078,7 @@ out:
|
|||
// Disable fast mode and send a dummy command to make it effective
|
||||
g_conn.block_after_ACK = false;
|
||||
SendCommandNG(CMD_PING, NULL, 0);
|
||||
if (!WaitForResponseTimeout(CMD_PING, NULL, 1000)) {
|
||||
if (WaitForResponseTimeout(CMD_PING, NULL, 1000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -6176,7 +6184,9 @@ static int CmdHF14AMfice(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, NULL, 0);
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 3000) == false) {
|
||||
goto out;
|
||||
}
|
||||
if (resp.oldarg[0]) goto out;
|
||||
|
||||
uint32_t items = resp.oldarg[2];
|
||||
|
|
|
@ -1684,7 +1684,7 @@ typedef struct {
|
|||
} mfu_otp_identify_t;
|
||||
|
||||
static mfu_otp_identify_t mfu_otp_ident_table[] = {
|
||||
{ "SALTO Systems card", 12, 4, "534C544F", ul_c_otpgenA, NULL },
|
||||
{ "SALTO Systems card", 12, 4, "534C544F", ul_c_otpgenA, "report to iceman!" },
|
||||
{ NULL, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1963,7 +1963,7 @@ static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, const uint8_t *aut
|
|||
// OTP checks
|
||||
mfu_otp_identify_t *item = mfu_match_otp_fingerprint(uid, data);
|
||||
if (item) {
|
||||
PrintAndLogEx(SUCCESS, _GREEN_("%s"), item->desc);
|
||||
PrintAndLogEx(SUCCESS, _BACK_GREEN_(" %s "), item->desc);
|
||||
res = PM3_SUCCESS;
|
||||
|
||||
if (item->hint) {
|
||||
|
@ -4628,7 +4628,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
|
||||
// we be getting ACK that we are silently ignoring here..
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "Failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -4649,11 +4649,13 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
got_post = true;
|
||||
}
|
||||
}
|
||||
if (! got_post) {
|
||||
|
||||
if (!got_post) {
|
||||
PrintAndLogEx(FAILED, "Failed to read block BEFORE");
|
||||
error_retries++;
|
||||
continue; // try again
|
||||
}
|
||||
|
||||
error_retries = 0;
|
||||
char prestr[20] = {0};
|
||||
snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
|
||||
|
@ -4936,7 +4938,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
|
||||
if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "\ntear off command failed");
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -562,7 +562,7 @@ static int select_DF_verify(uint8_t *response, uint8_t response_length, uint8_t
|
|||
}
|
||||
|
||||
// ----------------- MAC Key Generation -----------------
|
||||
uint8_t cmac[8];
|
||||
uint8_t cmac[16];
|
||||
uint8_t MAC_key[24] = {0x00};
|
||||
memcpy(MAC_key, keys[key_index].privMacKey, 16);
|
||||
create_cmac(MAC_key, input, cmac, sizeof(input), encryption_algorithm);
|
||||
|
@ -1351,7 +1351,7 @@ static int CmdHfSeosGDF(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
int key_index = arg_get_int_def(ctx, 1, -1);
|
||||
int key_index = arg_get_int_def(ctx, 1, 0);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
return seos_global_df(key_index);
|
||||
|
|
|
@ -664,7 +664,7 @@ static int CmdHFTexkomReader(const char *Cmd) {
|
|||
SendCommandNG(CMD_HF_ACQ_RAW_ADC, (uint8_t *)&samplesCount, sizeof(uint32_t));
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_HF_ACQ_RAW_ADC, &resp, 2500)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ACQ_RAW_ADC, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ int CmdHfThinFilmSim(const char *Cmd) {
|
|||
int ret;
|
||||
while (!(ret = kbd_enter_pressed())) {
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_THINFILM_SIMULATE, &resp, 500) == 0) {
|
||||
if (WaitForResponseTimeout(CMD_HF_THINFILM_SIMULATE, &resp, 500) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -928,15 +928,19 @@ static int CmdTune(const char *Cmd) {
|
|||
SendCommandNG(CMD_MEASURE_ANTENNA_TUNING, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
PrintAndLogEx(INPLACE, "% 3i", timeout_max - timeout);
|
||||
while (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING, &resp, 500)) {
|
||||
|
||||
while (WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING, &resp, 500) == false) {
|
||||
|
||||
fflush(stdout);
|
||||
if (timeout >= timeout_max) {
|
||||
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
timeout++;
|
||||
PrintAndLogEx(INPLACE, "% 3i", timeout_max - timeout);
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
|
@ -1607,7 +1611,7 @@ void pm3_version_short(void) {
|
|||
if (ptr != NULL) {
|
||||
char *ptr_end = strstr(ptr, "\n");
|
||||
if (ptr_end != NULL) {
|
||||
uint8_t len = ptr_end - 19 - ptr;
|
||||
uint8_t len = ptr_end - 12 - ptr;
|
||||
PrintAndLogEx(NORMAL, " Bootrom... %.*s", len, ptr + 12);
|
||||
}
|
||||
}
|
||||
|
@ -1617,7 +1621,7 @@ void pm3_version_short(void) {
|
|||
if (ptr != NULL) {
|
||||
char *ptr_end = strstr(ptr, "\n");
|
||||
if (ptr_end != NULL) {
|
||||
uint8_t len = ptr_end - 14 - ptr;
|
||||
uint8_t len = ptr_end - 12 - ptr;
|
||||
PrintAndLogEx(NORMAL, " OS........ %.*s", len, ptr + 12);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,15 +435,17 @@ int CmdLFCommandRead(const char *Cmd) {
|
|||
|
||||
i = 10;
|
||||
// 20sec wait loop
|
||||
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
|
||||
while (WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) == false && i != 0) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(NORMAL, "." NOLF);
|
||||
}
|
||||
i--;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "command failed.");
|
||||
return PM3_ESOFT;
|
||||
|
@ -595,7 +597,7 @@ int lf_getconfig(sample_config *config) {
|
|||
|
||||
SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_LF_SAMPLING_GET_CONFIG, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_LF_SAMPLING_GET_CONFIG, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -797,10 +799,12 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) {
|
|||
payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples;
|
||||
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (is_trigger_threshold_set) {
|
||||
WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
|
||||
} else {
|
||||
if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) {
|
||||
|
||||
if (WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "(lf_read) command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
|
|
@ -2013,7 +2013,7 @@ int CmdEM4x05Unlock(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "----------------------------------------------------------------------------\n");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>'") " to exit");
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------------\n");
|
||||
|
||||
|
|
|
@ -466,7 +466,7 @@ int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks) {
|
|||
ng.flags = 0;
|
||||
|
||||
SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng));
|
||||
if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) {
|
||||
if (WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT) == false) {
|
||||
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -664,7 +664,7 @@ int t55xxWrite(uint8_t block, bool page1, bool usepwd, bool testMode, uint32_t p
|
|||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng));
|
||||
if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, 2000) == false) {
|
||||
PrintAndLogEx(ERR, "Error occurred, device did not ACK write operation.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -1992,7 +1992,7 @@ static int CmdT55xxDangerousRaw(const char *Cmd) {
|
|||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_T55XX_DANGERRAW, (uint8_t *)&ng, sizeof(ng));
|
||||
if (!WaitForResponseTimeout(CMD_LF_T55XX_DANGERRAW, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_LF_T55XX_DANGERRAW, &resp, 2000) == false) {
|
||||
PrintAndLogEx(ERR, "Error occurred, device did not ACK write operation.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -2840,7 +2840,7 @@ bool AcquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, u
|
|||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_T55XX_READBL, (uint8_t *)&payload, sizeof(payload));
|
||||
if (!WaitForResponseTimeout(CMD_LF_T55XX_READBL, NULL, 2500)) {
|
||||
if (WaitForResponseTimeout(CMD_LF_T55XX_READBL, NULL, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return false;
|
||||
}
|
||||
|
@ -3435,7 +3435,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
PacketResponseNG resp;
|
||||
|
||||
uint8_t timeout = 0;
|
||||
while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000)) {
|
||||
while (WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000) == false) {
|
||||
timeout++;
|
||||
PrintAndLogEx(NORMAL, "." NOLF);
|
||||
if (timeout > 180) {
|
||||
|
|
|
@ -172,7 +172,7 @@ static int CmdVikingClone(const char *Cmd) {
|
|||
|
||||
SendCommandNG(CMD_LF_VIKING_CLONE, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_LF_VIKING_CLONE, &resp, T55XX_WRITE_TIMEOUT)) {
|
||||
if (WaitForResponseTimeout(CMD_LF_VIKING_CLONE, &resp, T55XX_WRITE_TIMEOUT) == false) {
|
||||
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
|
|
@ -663,7 +663,7 @@ static int CmdSmartUpgrade(const char *Cmd) {
|
|||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_UPLOAD, (uint8_t *)&upload, sizeof(upload));
|
||||
if (!WaitForResponseTimeout(CMD_SMART_UPLOAD, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_SMART_UPLOAD, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
free(firmware);
|
||||
return PM3_ETIMEOUT;
|
||||
|
@ -695,7 +695,7 @@ static int CmdSmartUpgrade(const char *Cmd) {
|
|||
|
||||
free(firmware);
|
||||
SendCommandNG(CMD_SMART_UPGRADE, (uint8_t *)&payload, sizeof(payload));
|
||||
if (!WaitForResponseTimeout(CMD_SMART_UPGRADE, &resp, 2500)) {
|
||||
if (WaitForResponseTimeout(CMD_SMART_UPGRADE, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
@ -876,7 +876,7 @@ static int CmdSmartSetClock(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_SETCLOCK, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_SMART_SETCLOCK, &resp, 2500)) {
|
||||
if (WaitForResponseTimeout(CMD_SMART_SETCLOCK, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "smart card select failed");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ static int usart_tx(uint8_t *data, size_t len) {
|
|||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_USART_TX, data, len);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_USART_TX, &resp, 1000)) {
|
||||
if (WaitForResponseTimeout(CMD_USART_TX, &resp, 1000) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
return resp.status;
|
||||
|
@ -49,7 +49,7 @@ static int usart_rx(uint8_t *data, size_t *len, uint32_t waittime) {
|
|||
payload.waittime = waittime;
|
||||
SendCommandNG(CMD_USART_RX, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_USART_RX, &resp, waittime + 500)) {
|
||||
if (WaitForResponseTimeout(CMD_USART_RX, &resp, waittime + 500) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
|
@ -99,7 +99,7 @@ static int set_usart_config(uint32_t baudrate, uint8_t parity) {
|
|||
payload.parity = parity;
|
||||
SendCommandNG(CMD_USART_CONFIG, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_USART_CONFIG, &resp, 1000)) {
|
||||
if (WaitForResponseTimeout(CMD_USART_CONFIG, &resp, 1000) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
return resp.status;
|
||||
|
|
|
@ -871,7 +871,7 @@ int TestProxmark(pm3_device_t *dev) {
|
|||
#endif
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == 0) {
|
||||
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
|
@ -881,7 +881,7 @@ int TestProxmark(pm3_device_t *dev) {
|
|||
}
|
||||
|
||||
SendCommandNG(CMD_CAPABILITIES, NULL, 0);
|
||||
if (WaitForResponseTimeoutW(CMD_CAPABILITIES, &resp, 1000, false) == 0) {
|
||||
if (WaitForResponseTimeoutW(CMD_CAPABILITIES, &resp, 1000, false) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,6 +165,7 @@ static char *filenamemcopy(const char *preferredName, const char *suffix) {
|
|||
|
||||
char *fileName = (char *) calloc(strlen(preferredName) + strlen(suffix) + 1, sizeof(uint8_t));
|
||||
if (fileName == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -993,8 +994,8 @@ int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata,
|
|||
}
|
||||
|
||||
*pdata = calloc(fsize, sizeof(uint8_t));
|
||||
if (!*pdata) {
|
||||
PrintAndLogEx(FAILED, "error, cannot allocate memory");
|
||||
if (*pdata == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
fclose(f);
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
@ -1044,8 +1045,8 @@ int loadFileEML_safe(const char *preferredName, void **pdata, size_t *datalen) {
|
|||
}
|
||||
|
||||
*pdata = calloc(fsize, sizeof(uint8_t));
|
||||
if (!*pdata) {
|
||||
PrintAndLogEx(FAILED, "error, cannot allocate memory");
|
||||
if (*pdata == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
fclose(f);
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
@ -1091,6 +1092,7 @@ int loadFileEML_safe(const char *preferredName, void **pdata, size_t *datalen) {
|
|||
|
||||
uint8_t *newdump = realloc(*pdata, counter);
|
||||
if (newdump == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
free(*pdata);
|
||||
return PM3_EMALLOC;
|
||||
} else {
|
||||
|
@ -1366,8 +1368,8 @@ int loadFileMCT_safe(const char *preferredName, void **pdata, size_t *datalen) {
|
|||
}
|
||||
|
||||
*pdata = calloc(fsize, sizeof(uint8_t));
|
||||
if (!*pdata) {
|
||||
PrintAndLogEx(FAILED, "error, cannot allocate memory");
|
||||
if (*pdata == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
fclose(f);
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
@ -1414,6 +1416,7 @@ int loadFileMCT_safe(const char *preferredName, void **pdata, size_t *datalen) {
|
|||
|
||||
uint8_t *newdump = realloc(*pdata, counter);
|
||||
if (newdump == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
free(*pdata);
|
||||
return PM3_EMALLOC;
|
||||
} else {
|
||||
|
@ -2358,6 +2361,7 @@ int loadFileDICTIONARY_safe_ex(const char *preferredName, const char *suffix, vo
|
|||
// allocate some space for the dictionary
|
||||
*pdata = calloc(block_size, sizeof(uint8_t));
|
||||
if (*pdata == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
free(path);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
@ -2377,9 +2381,10 @@ int loadFileDICTIONARY_safe_ex(const char *preferredName, const char *suffix, vo
|
|||
if ((*keycnt * (keylen >> 1)) >= mem_size) {
|
||||
|
||||
mem_size += block_size;
|
||||
*pdata = realloc(*pdata, mem_size);
|
||||
|
||||
*pdata = realloc(*pdata, mem_size);
|
||||
if (*pdata == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
retval = PM3_EFILE;
|
||||
fclose(f);
|
||||
goto out;
|
||||
|
@ -2473,7 +2478,7 @@ int loadFileBinaryKey(const char *preferredName, const char *suffix, void **keya
|
|||
|
||||
*keya = calloc(fsize, sizeof(uint8_t));
|
||||
if (*keya == NULL) {
|
||||
PrintAndLogEx(FAILED, "error, cannot allocate memory");
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
fclose(f);
|
||||
free(path);
|
||||
return PM3_EMALLOC;
|
||||
|
@ -2483,7 +2488,7 @@ int loadFileBinaryKey(const char *preferredName, const char *suffix, void **keya
|
|||
|
||||
*keyb = calloc(fsize, sizeof(uint8_t));
|
||||
if (*keyb == NULL) {
|
||||
PrintAndLogEx(FAILED, "error, cannot allocate memory");
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
fclose(f);
|
||||
free(*keya);
|
||||
free(path);
|
||||
|
@ -2663,6 +2668,7 @@ static int convert_plain_mfu_dump(uint8_t **dump, size_t *dumplen, bool verbose)
|
|||
|
||||
mfu_dump_t *mfu = (mfu_dump_t *) calloc(sizeof(mfu_dump_t), sizeof(uint8_t));
|
||||
if (mfu == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
|
@ -2700,6 +2706,7 @@ static int convert_old_mfu_dump(uint8_t **dump, size_t *dumplen, bool verbose) {
|
|||
|
||||
mfu_dump_t *mfu_dump = (mfu_dump_t *) calloc(sizeof(mfu_dump_t), sizeof(uint8_t));
|
||||
if (mfu_dump == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
|
@ -2846,6 +2853,7 @@ static int searchFinalFile(char **foundpath, const char *pm3dir, const char *sea
|
|||
// explicit absolute (/) or relative path (./) => try only to match it directly
|
||||
char *filename = calloc(strlen(searchname) + 1, sizeof(char));
|
||||
if (filename == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
|
@ -3081,7 +3089,7 @@ int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumpl
|
|||
case JSON: {
|
||||
*pdump = calloc(maxdumplen, sizeof(uint8_t));
|
||||
if (*pdump == NULL) {
|
||||
PrintAndLogEx(WARNING, "fail, cannot allocate memory");
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
|
@ -3121,7 +3129,7 @@ int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumpl
|
|||
|
||||
*pdump = calloc(maxdumplen, sizeof(uint8_t));
|
||||
if (*pdump == NULL) {
|
||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
res = loadFileNFC_safe(fn, *pdump, maxdumplen, dumplen, dumptype);
|
||||
|
|
|
@ -281,7 +281,7 @@ const static vocabulary_t vocabulary[] = {
|
|||
{ 1, "hf iclass view" },
|
||||
{ 0, "hf iclass wrbl" },
|
||||
{ 0, "hf iclass creditepurse" },
|
||||
{ 0, "hf iclass trbl" },
|
||||
{ 0, "hf iclass tear" },
|
||||
{ 0, "hf iclass chk" },
|
||||
{ 1, "hf iclass loclass" },
|
||||
{ 1, "hf iclass lookup" },
|
||||
|
|
|
@ -303,7 +303,7 @@ static int l_GetFromFlashMemSpiffs(lua_State *L) {
|
|||
// get size from spiffs itself !
|
||||
SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)destfilename, 32);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000))
|
||||
if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false)
|
||||
return returnToLuaWithError(L, "No response from the device");
|
||||
|
||||
len = resp.data.asDwords[0];
|
||||
|
|
|
@ -252,6 +252,10 @@ endif
|
|||
# WITH_FPC_USART_* needs WITH_FPC_USART :
|
||||
ifneq (,$(findstring WITH_FPC_USART_,$(PLATFORM_DEFS)))
|
||||
PLATFORM_DEFS += -DWITH_FPC_USART
|
||||
ifeq ($(USART_BAUD_RATE),)
|
||||
USART_BAUD_RATE=115200
|
||||
endif
|
||||
PLATFORM_DEFS += -DUSART_BAUD_RATE=$(USART_BAUD_RATE)
|
||||
endif
|
||||
|
||||
PLATFORM_DEFS_INFO = $(strip $(filter-out STANDALONE%, $(subst -DWITH_,,$(PLATFORM_DEFS))))
|
||||
|
|
|
@ -1342,7 +1342,6 @@
|
|||
"-t, --timeout <ms> Timeout in milliseconds",
|
||||
"-b <dec> Number of bits to send. Useful for send partial byte",
|
||||
"-v, --verbose Verbose output",
|
||||
"--mag Use Apple magsafe polling",
|
||||
"--topaz Use Topaz protocol to send command",
|
||||
"--crypto1 Use crypto1 session",
|
||||
"<hex> Raw bytes to send"
|
||||
|
@ -1354,8 +1353,7 @@
|
|||
"description": "Act as a ISO-14443a reader to identify tag. Look for ISO-14443a tags until Enter or the pm3 button is pressed",
|
||||
"notes": [
|
||||
"hf 14a reader",
|
||||
"hf 14a reader -@ -> Continuous mode",
|
||||
"hf 14a reader --mag -> trigger apple magsafe polling"
|
||||
"hf 14a reader -@ -> Continuous mode"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
|
@ -1364,7 +1362,6 @@
|
|||
"-s, --silent silent (no messages)",
|
||||
"--drop just drop the signal field",
|
||||
"--skip ISO14443-3 select only (skip RATS)",
|
||||
"--mag Use Apple magsafe polling",
|
||||
"-@ continuous reader mode",
|
||||
"-w, --wait wait for card"
|
||||
],
|
||||
|
@ -3204,7 +3201,7 @@
|
|||
},
|
||||
"hf help": {
|
||||
"command": "hf help",
|
||||
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service } waveshare { Waveshare NFC ePaper... } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
|
||||
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service... } waveshare { Waveshare NFC ePaper... } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
|
||||
"notes": [
|
||||
"hf list --frame -> show frame delay times",
|
||||
"hf list -1 -> use trace buffer"
|
||||
|
@ -3288,15 +3285,14 @@
|
|||
"command": "hf iclass creditepurse",
|
||||
"description": "Credit the epurse on an iCLASS tag. The provided key must be the credit key. The first two bytes of the epurse are the debit value (big endian) and may be any value except FFFF. The remaining two bytes of the epurse are the credit value and must be smaller than the previous value.",
|
||||
"notes": [
|
||||
"hf iclass creditepurse -d FEFFFFFF -k 001122334455667B",
|
||||
"hf iclass creditepurse -d FEFFFFFF --ki 0"
|
||||
"hf iclass creditepurse --ki 0 -d FEFFFEFF"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-k, --key <hex> Credit key as 8 hex bytes",
|
||||
"--ki <dec> Key index to select key from memory 'hf iclass managekeys'",
|
||||
"-d, --data <hex> data to write as 8 hex bytes",
|
||||
"-d, --data <hex> data to write as 4 hex bytes",
|
||||
"--elite elite computations applied to key",
|
||||
"--raw no computations applied to key",
|
||||
"-v, --verbose verbose output",
|
||||
|
@ -3720,12 +3716,13 @@
|
|||
],
|
||||
"usage": "hf iclass sniff [-hj]"
|
||||
},
|
||||
"hf iclass trbl": {
|
||||
"command": "hf iclass trbl",
|
||||
"description": "Tear off an iCLASS tag block",
|
||||
"hf iclass tear": {
|
||||
"command": "hf iclass tear",
|
||||
"description": "Tear off an iCLASS tag block e-purse usually 300-500us to trigger the erase phase also seen 1800-2100us on some cards",
|
||||
"notes": [
|
||||
"hf iclass trbl --blk 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B --tdb 100 --tde 150",
|
||||
"hf iclass trbl --blk 10 -d AAAAAAAAAAAAAAAA --ki 0 --tdb 100 --tde 150"
|
||||
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B -s 300 -e 600",
|
||||
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA --ki 0 -s 300 -e 600",
|
||||
"hf iclass tear --blk 2 -d fdffffffffffffff --ki 1 --credit -s 400 -e 500"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
|
@ -3741,10 +3738,13 @@
|
|||
"--nr replay of NR/MAC",
|
||||
"-v, --verbose verbose output",
|
||||
"--shallow use shallow (ASK) reader modulation instead of OOK",
|
||||
"--tdb <dec> tearoff delay start in ms",
|
||||
"--tde <dec> tearoff delay end in ms"
|
||||
"-s <dec> tearoff delay start (in us) must be between 1 and 43000 (43ms). Precision is about 1/3 us",
|
||||
"-i <dec> tearoff delay increment (in us) - default 10",
|
||||
"-e <dec> tearoff delay end (in us) must be a higher value than the start delay",
|
||||
"--loop <dec> number of times to loop per tearoff time",
|
||||
"--sleep <ms> Sleep between each tear"
|
||||
],
|
||||
"usage": "hf iclass trbl [-hv] [-k <hex>] [--ki <dec>] --blk <dec> -d <hex> [-m <hex>] [--credit] [--elite] [--raw] [--nr] [--shallow] --tdb <dec> --tde <dec>"
|
||||
"usage": "hf iclass tear [-hv] [-k <hex>] [--ki <dec>] --blk <dec> -d <hex> [-m <hex>] [--credit] [--elite] [--raw] [--nr] [--shallow] -s <dec> [-i <dec>] [-e <dec>] [--loop <dec>] [--sleep <ms>]"
|
||||
},
|
||||
"hf iclass unhash": {
|
||||
"command": "hf iclass unhash",
|
||||
|
@ -13354,6 +13354,6 @@
|
|||
"metadata": {
|
||||
"commands_extracted": 767,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2025-04-20T09:18:59"
|
||||
"extracted_on": "2025-05-25T12:38:36"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -404,7 +404,7 @@ Check column "offline" for their availability.
|
|||
|`hf iclass view `|Y |`Display content from tag dump file`
|
||||
|`hf iclass wrbl `|N |`Write Picopass / iCLASS block`
|
||||
|`hf iclass creditepurse `|N |`Credit epurse value`
|
||||
|`hf iclass trbl `|N |`Performs tearoff attack on iClass block`
|
||||
|`hf iclass tear `|N |`Performs tearoff attack on iClass block`
|
||||
|`hf iclass chk `|N |`Check keys`
|
||||
|`hf iclass loclass `|Y |`Use loclass to perform bruteforce reader attack`
|
||||
|`hf iclass lookup `|Y |`Uses authentication trace to check for key in dictionary file`
|
||||
|
@ -786,7 +786,7 @@ Check column "offline" for their availability.
|
|||
|
||||
### hf vas
|
||||
|
||||
{ Apple Value Added Service }
|
||||
{ Apple Value Added Service... }
|
||||
|
||||
|command |offline |description
|
||||
|------- |------- |-----------
|
||||
|
|
|
@ -73,9 +73,9 @@ There is a docker image with webpack installed which has been built which you ca
|
|||
|
||||
```
|
||||
docker pull nhutton/prox-container:webp_image_complete
|
||||
docker run -v <LOCAL_PATH>/proxmark3:/tmp --rm -it nhutton/prox-container:webp_image_complete bash
|
||||
$ cd /tmp/proxmark/fpga
|
||||
$ make all
|
||||
docker run -v <LOCAL_PATH>/proxmark3:/tmp/proxmark3 --rm -it nhutton/prox-container:1.0 bash
|
||||
$ cd /tmp/proxmark3/fpga
|
||||
$ make all -j
|
||||
```
|
||||
|
||||
In order to save space, these fpga images are LZ4 compressed and included in the fullimage.elf file when compiling the ARM SRC. `make armsrc`
|
||||
|
|
|
@ -2356,6 +2356,36 @@ After communication to iKey LLC (importer of those tags to Russian market), new
|
|||
[+] ATS: 85 00 00 A0 00 00 0A 3C 00 04 03 01 01 00 0E 03 [ C8 1D ]
|
||||
```
|
||||
|
||||
### Magic commands
|
||||
|
||||
^[Top](#top)
|
||||
|
||||
Use the script `hf_mfu_ultra.lua` to restore (write) dump to tag or clear previously written tag.
|
||||
|
||||
Usage:
|
||||
1. Restore dump to tag:
|
||||
```
|
||||
script run hf_mfu_ultra -f <dump filename> -k <passwd> -r
|
||||
```
|
||||
2. Wipe tag (use it to prepare tag for restoring another dump):
|
||||
```
|
||||
script run hf_mfu_ultra -k <passwd> -w
|
||||
```
|
||||
3. Show help:
|
||||
```
|
||||
script run hf_mfu_ultra -h
|
||||
```
|
||||
|
||||
Examples:
|
||||
1. Restore dump to tag:
|
||||
```
|
||||
script run hf_mfu_ultra -f hf-mfu-3476FF1514D866-dump.bin -k ffffffff -r
|
||||
```
|
||||
2. Wipe tag:
|
||||
```
|
||||
script run hf_mfu_ultra -k 1d237f76 -w
|
||||
```
|
||||
|
||||
## UL-5
|
||||
|
||||
^[Top](#top)
|
||||
|
@ -2389,6 +2419,28 @@ The manufacturer confirmed unpersonalized tags could be identified by first 2 by
|
|||
|
||||
* `AA 55...`
|
||||
|
||||
### Magic commands
|
||||
|
||||
^[Top](#top)
|
||||
|
||||
Use the script `hf_mfu_ultra.lua` to restore (write) dump to tag.
|
||||
|
||||
Usage:
|
||||
1. Restore dump to tag:
|
||||
```
|
||||
script run hf_mfu_ultra -f <dump filename> -k <passwd> -r
|
||||
```
|
||||
3. Show help:
|
||||
```
|
||||
script run hf_mfu_ultra -h
|
||||
```
|
||||
|
||||
Examples:
|
||||
1. Restore dump to tag:
|
||||
```
|
||||
script run hf_mfu_ultra -f hf-mfu-3476FF1514D866-dump.bin -k ffffffff -r
|
||||
```
|
||||
|
||||
## UL, other chips
|
||||
|
||||
** TODO **
|
||||
|
|
|
@ -16,8 +16,9 @@
|
|||
#ifndef __USART_DEFS_H
|
||||
#define __USART_DEFS_H
|
||||
|
||||
//#define USART_BAUD_RATE 9600
|
||||
#ifndef USART_BAUD_RATE
|
||||
#define USART_BAUD_RATE 115200
|
||||
#endif
|
||||
// BT HC-06 physical layer runs at 128kbps
|
||||
// so it's possible to gain a little bit by using 230400
|
||||
// with some risk to overflow its internal buffers:
|
||||
|
|
33
pm3
33
pm3
|
@ -136,11 +136,15 @@ function get_pm3_list_Windows {
|
|||
PM3LIST=()
|
||||
|
||||
# Normal SERIAL PORTS (COM)
|
||||
for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_9AC4&PID_4B8F%' Or PNPDeviceID LIKE '%VID_2D2D&PID_504D%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do
|
||||
DEV=${DEV/ */}
|
||||
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.PNPDeviceID -like '*VID_9AC4&PID_4B8F*' -or \$_.PNPDeviceID -like '*VID_2D2D&PID_504D*'} | Select -expandproperty DeviceID" 2>/dev/null); do
|
||||
|
||||
_comport=$DEV
|
||||
|
||||
#prevent soft bricking when using pm3-flash-all on an outdated bootloader
|
||||
if [ $(basename -- "$0") = "pm3-flash-all" ]; then
|
||||
line=$(wmic /locale:ms_409 path Win32_SerialPort Where "DeviceID='$DEV'" Get PNPDeviceID 2>/dev/null | awk -b '/^USB/{print $1}');
|
||||
|
||||
line=$($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$_comport'} | Select -expandproperty PNPDeviceID" 2>/dev/null);
|
||||
|
||||
if [[ ! $line =~ ^"USB\VID_9AC4&PID_4B8F\ICEMAN" ]]; then
|
||||
echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!"
|
||||
exit 1
|
||||
|
@ -154,8 +158,8 @@ function get_pm3_list_Windows {
|
|||
|
||||
#BT direct SERIAL PORTS (COM)
|
||||
if $FINDBTRFCOMM; then
|
||||
for DEV in $(wmic /locale:ms_409 path Win32_PnPEntity Where "Caption LIKE '%Bluetooth%(COM%'" Get Name 2> /dev/null | awk -b 'match($0,/(COM[0-9]+)/,m){print m[1]}'); do
|
||||
DEV=${DEV/ */}
|
||||
|
||||
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_PnPEntity | Where-Object Caption -like 'Standard Serial over Bluetooth link (COM*' | Select Name" 2>/dev/null); do
|
||||
PM3LIST+=("$DEV")
|
||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
||||
return
|
||||
|
@ -165,8 +169,8 @@ function get_pm3_list_Windows {
|
|||
|
||||
#white BT dongle SERIAL PORTS (COM)
|
||||
if $FINDBTDONGLE; then
|
||||
for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_10C4&PID_EA60%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do
|
||||
DEV=${DEV/ */}
|
||||
|
||||
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object PNPDeviceID -like '*VID_10C4&PID_EA60*' | Select -expandproperty DeviceID" 2>/dev/null); do
|
||||
PM3LIST+=("$DEV")
|
||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
||||
return
|
||||
|
@ -497,6 +501,21 @@ if [ "$HOSTOS" = "LINUX" ]; then
|
|||
elif [ "$HOSTOS" = "DARWIN" ]; then
|
||||
GETPM3LIST=get_pm3_list_macOS
|
||||
elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then
|
||||
|
||||
# First try finding it using the PATH environment variable
|
||||
PSHEXE=$(command -v powershell.exe 2>/dev/null)
|
||||
|
||||
# If it fails (such as if WSLENV is not set), try using the default installation path
|
||||
if [ -z "$PSHEXE" ]; then
|
||||
PSHEXE=/cygdrive/c/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe
|
||||
fi
|
||||
|
||||
# Finally test if PowerShell is working
|
||||
if ! "$PSHEXE" exit >/dev/null 2>&1; then
|
||||
echo >&2 "[!!] Cannot run powershell.exe in your MINGW environment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GETPM3LIST=get_pm3_list_Windows
|
||||
else
|
||||
echo >&2 "[!!] Host OS not recognized, abort: $HOSTOS"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue