Merge branch 'RfidResearchGroup:master' into master

This commit is contained in:
ry4000
2025-05-26 17:46:52 +10:00
committed by GitHub
45 changed files with 1156 additions and 384 deletions
+8 -1
View File
@@ -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)
+4
View File
@@ -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
+1 -1
View File
@@ -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);
}
}
+49 -49
View File
@@ -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, &current_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, &current_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();
+20 -17
View File
@@ -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);
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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) {
+1 -1
View File
@@ -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;
+18 -18
View File
@@ -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;
+21 -21
View File
@@ -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);
+9 -8
View File
@@ -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(
+9 -7
View File
@@ -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;
}
+6 -4
View File
@@ -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;
}
+1 -1
View File
@@ -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);
}
+52
View File
@@ -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
View 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)
+3 -2
View File
@@ -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
+1 -1
View File
@@ -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
+4 -4
View File
@@ -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;
}
+3 -1
View File
@@ -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;
}

Some files were not shown because too many files have changed in this diff Show More