mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-05 04:26:05 -07:00
text & style
This commit is contained in:
parent
911d4f9df2
commit
2d610b8dc0
11 changed files with 124 additions and 99 deletions
|
@ -3,6 +3,8 @@ 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]
|
||||
- Added the `PM3ULTIMATE` platform in the build / docs. *untested* (@iceman1001)
|
||||
- Added fpga compilation for PM3ULTIMATE device (@n-hutton)
|
||||
- Updated the ATR list (@iceman1001)
|
||||
- Fixed fpga binary images to use fixed seed 2 (@n-hutton)
|
||||
- Changed `hf iclass sim -t 7` - implemented simulation that glitches key block responses (@antiklesys)
|
||||
|
|
|
@ -14,6 +14,9 @@ PLATFORM=PM3RDV4
|
|||
#PLATFORM=PM3ICOPYX
|
||||
#PLATFORM_EXTRAS=FLASH
|
||||
|
||||
# For PM3 Ultimate:
|
||||
# uncomment the line below
|
||||
#PLATFORM=PM3ULTIMATE
|
||||
|
||||
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
|
||||
#PLATFORM_EXTRAS=BTADDON
|
||||
|
|
|
@ -667,7 +667,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
|
||||
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
|
||||
|
||||
if(glitch_key_read){
|
||||
if (glitch_key_read) {
|
||||
goto send;
|
||||
}
|
||||
|
||||
|
@ -792,7 +792,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
|
|||
cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
|
||||
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
|
||||
memcpy(emulator + (current_page * page_size) + (8 * 3), diversified_kd, 8);
|
||||
if(simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY){
|
||||
if (simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
|
||||
glitch_key_read = true;
|
||||
goto send;
|
||||
}
|
||||
|
|
|
@ -2250,7 +2250,8 @@ write_dump:
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *macdata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose, bool use_secure_pagemode, bool shallow_mod) {
|
||||
static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *macdata, uint8_t *KEY, bool use_credit_key,
|
||||
bool elite, bool rawkey, bool replay, bool verbose, bool use_secure_pagemode, bool shallow_mod) {
|
||||
|
||||
iclass_writeblock_req_t payload = {
|
||||
.req.use_raw = rawkey,
|
||||
|
@ -5067,56 +5068,49 @@ static int CmdHFiClassLookUp(const char *Cmd) {
|
|||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool use_vb6kdf = arg_get_lit(ctx, 7);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
|
||||
bool use_elite = arg_get_lit(ctx, 5);
|
||||
bool use_raw = arg_get_lit(ctx, 6);
|
||||
if (use_vb6kdf) {
|
||||
use_elite = true;
|
||||
} else {
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
}
|
||||
|
||||
int csn_len = 0;
|
||||
uint8_t csn[8] = {0};
|
||||
CLIGetHexWithReturn(ctx, 2, csn, &csn_len);
|
||||
|
||||
if (csn_len > 0) {
|
||||
if (csn_len != 8) {
|
||||
PrintAndLogEx(ERR, "CSN is incorrect length");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
int epurse_len = 0;
|
||||
uint8_t epurse[8] = {0};
|
||||
CLIGetHexWithReturn(ctx, 3, epurse, &epurse_len);
|
||||
|
||||
if (epurse_len > 0) {
|
||||
if (epurse_len != 8) {
|
||||
PrintAndLogEx(ERR, "ePurse is incorrect length");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
int macs_len = 0;
|
||||
uint8_t macs[8] = {0};
|
||||
CLIGetHexWithReturn(ctx, 4, macs, &macs_len);
|
||||
|
||||
if (macs_len > 0) {
|
||||
if (macs_len != 8) {
|
||||
PrintAndLogEx(ERR, "MAC is incorrect length");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
bool use_elite = arg_get_lit(ctx, 5);
|
||||
bool use_raw = arg_get_lit(ctx, 6);
|
||||
bool use_vb6kdf = arg_get_lit(ctx, 7);
|
||||
|
||||
if (use_vb6kdf == false) {
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
}
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// santity checks
|
||||
|
||||
if (csn_len > 0 && csn_len != 8) {
|
||||
PrintAndLogEx(ERR, "CSN is incorrect length");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (epurse_len > 0 && epurse_len != 8) {
|
||||
PrintAndLogEx(ERR, "ePurse is incorrect length");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (macs_len > 0 && macs_len != 8) {
|
||||
PrintAndLogEx(ERR, "MAC is incorrect length");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
||||
uint8_t CCNR[12];
|
||||
uint8_t MAC_TAG[4] = { 0, 0, 0, 0 };
|
||||
|
||||
|
@ -5161,7 +5155,8 @@ static int CmdHFiClassLookUp(const char *Cmd) {
|
|||
|
||||
// Iclass_prekey_t
|
||||
iclass_prekey_t *prekey = calloc(keycount, sizeof(iclass_prekey_t));
|
||||
if (!prekey) {
|
||||
if (prekey == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
free(keyBlock);
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
@ -5182,13 +5177,14 @@ static int CmdHFiClassLookUp(const char *Cmd) {
|
|||
// Sort mac list
|
||||
qsort(prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") " key...", "DEBIT");
|
||||
PrintAndLogEx(SUCCESS, "Searching for %s key...", _YELLOW_("DEBIT"));
|
||||
iclass_prekey_t *item;
|
||||
iclass_prekey_t lookup;
|
||||
memcpy(lookup.mac, MAC_TAG, 4);
|
||||
|
||||
// Binsearch
|
||||
item = (iclass_prekey_t *) bsearch(&lookup, prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32);
|
||||
|
||||
if (item != NULL) {
|
||||
PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s"), sprint_hex(item->key, 8));
|
||||
add_key(item->key);
|
||||
|
|
|
@ -48,21 +48,15 @@
|
|||
#include "mifare/mifarehost.h"
|
||||
#include "crypto/originality.h"
|
||||
|
||||
|
||||
// Defines for Saflok parsing
|
||||
#define SAFLOK_YEAR_OFFSET 1980
|
||||
#define SAFLOK_BASIC_ACCESS_BYTE_NUM 17
|
||||
#define SAFLOK_KEY_LENGTH 6
|
||||
#define SAFLOK_UID_LENGTH 4 // Matches Mifare 4-byte UID
|
||||
#define SAFLOK_MAGIC_TABLE_SIZE 192
|
||||
#define SAFLOK_CHECK_SECTOR 1
|
||||
|
||||
typedef struct {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
} MfClassicKeyPair;
|
||||
|
||||
|
||||
// Structure for Saflok key levels
|
||||
typedef struct {
|
||||
uint8_t level_num;
|
||||
|
@ -114,8 +108,8 @@ static const uint8_t saflok_c_aDecode[256] = {
|
|||
// Function to decrypt Saflok card data
|
||||
static void DecryptSaflokCardData(
|
||||
const uint8_t strCard[SAFLOK_BASIC_ACCESS_BYTE_NUM],
|
||||
// int length, // length is always SAFLOK_BASIC_ACCESS_BYTE_NUM
|
||||
uint8_t decryptedCard[SAFLOK_BASIC_ACCESS_BYTE_NUM]) {
|
||||
uint8_t decryptedCard[SAFLOK_BASIC_ACCESS_BYTE_NUM]
|
||||
) {
|
||||
int i;
|
||||
int num;
|
||||
int num2;
|
||||
|
@ -163,8 +157,8 @@ static uint8_t CalculateCheckSum(uint8_t data[SAFLOK_BASIC_ACCESS_BYTE_NUM]) {
|
|||
static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t *sector1_info) {
|
||||
(void)sector1_info; // Not directly used for payload parsing currently
|
||||
|
||||
if (!sector0_info) {
|
||||
PrintAndLogEx(WARNING, "Saflok: Sector 0 information not available for parsing.");
|
||||
if (sector0_info == NULL) {
|
||||
PrintAndLogEx(WARNING, "Saflok: Sector 0 information not available for parsing");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -177,16 +171,16 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t
|
|||
num_to_bytes(sector0_info->Key[MF_KEY_A], MIFARE_KEY_SIZE, key_bytes_for_s0);
|
||||
key_type_for_s0 = MF_KEY_A; // MF_KEY_A is typically #define'd as 0x60
|
||||
s0_key_found = true;
|
||||
PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key A for reading blocks.");
|
||||
PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key A for reading blocks");
|
||||
} else if (sector0_info->foundKey[MF_KEY_B]) { // Fallback to Key B for Sector 0
|
||||
num_to_bytes(sector0_info->Key[MF_KEY_B], MIFARE_KEY_SIZE, key_bytes_for_s0);
|
||||
key_type_for_s0 = MF_KEY_B; // MF_KEY_B is typically #define'd as 0x61
|
||||
s0_key_found = true;
|
||||
PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key B for reading blocks.");
|
||||
PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key B for reading blocks");
|
||||
}
|
||||
|
||||
if (!s0_key_found) {
|
||||
PrintAndLogEx(WARNING, "Saflok: No known keys for Sector 0. Cannot read blocks 1 & 2 for parsing.");
|
||||
if (s0_key_found == false) {
|
||||
PrintAndLogEx(WARNING, "Saflok: No known keys for Sector 0. Cannot read blocks 1 & 2 for parsing");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -195,23 +189,23 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t
|
|||
|
||||
// Read absolute block 1 (data block within sector 0)
|
||||
if (mf_read_block(1, key_type_for_s0, key_bytes_for_s0, block1_content) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 1 using Sector 0 %s key.", (key_type_for_s0 == MF_KEY_A) ? "A" : "B");
|
||||
PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 1 using Sector 0 %s key", (key_type_for_s0 == MF_KEY_A) ? "A" : "B");
|
||||
return;
|
||||
}
|
||||
PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 1.");
|
||||
PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 1");
|
||||
|
||||
// Read absolute block 2 (data block within sector 0)
|
||||
if (mf_read_block(2, key_type_for_s0, key_bytes_for_s0, block2_content) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 2 using Sector 0 %s key.", (key_type_for_s0 == MF_KEY_A) ? "A" : "B");
|
||||
PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 2 using Sector 0 %s key", (key_type_for_s0 == MF_KEY_A) ? "A" : "B");
|
||||
return;
|
||||
}
|
||||
PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 2.");
|
||||
PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 2");
|
||||
|
||||
uint8_t basicAccess[SAFLOK_BASIC_ACCESS_BYTE_NUM];
|
||||
uint8_t decodedBA[SAFLOK_BASIC_ACCESS_BYTE_NUM];
|
||||
|
||||
memcpy(basicAccess, block1_content, 16); // 16 bytes from Block 1
|
||||
memcpy(basicAccess + 16, block2_content, 1); // 1 byte from Block 2
|
||||
memcpy(basicAccess, block1_content, MFBLOCK_SIZE); // 16 bytes from Block 1
|
||||
memcpy(basicAccess + MFBLOCK_SIZE, block2_content, 1); // 1 byte from Block 2
|
||||
|
||||
DecryptSaflokCardData(basicAccess, decodedBA);
|
||||
|
||||
|
@ -298,18 +292,25 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t
|
|||
// Handle day rollover for expiration
|
||||
static const uint8_t days_in_month_lookup[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 1-indexed month
|
||||
if (expire_month > 0 && expire_month <= 12) {
|
||||
|
||||
while (true) {
|
||||
|
||||
uint8_t max_days = days_in_month_lookup[expire_month];
|
||||
if (expire_month == 2 && (expire_year % 4 == 0 && (expire_year % 100 != 0 || expire_year % 400 == 0))) {
|
||||
if (expire_month == 2 &&
|
||||
(expire_year % 4 == 0 &&
|
||||
(expire_year % 100 != 0 || expire_year % 400 == 0))) {
|
||||
max_days = 29; // Leap year
|
||||
}
|
||||
|
||||
if (expire_day <= max_days) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (max_days == 0) { // Should not happen with valid month
|
||||
PrintAndLogEx(WARNING, "Saflok: Invalid day/month for expiration rollover calculation.");
|
||||
PrintAndLogEx(WARNING, "Saflok: Invalid day/month for expiration rollover calculation");
|
||||
break;
|
||||
}
|
||||
|
||||
expire_day -= max_days;
|
||||
expire_month++;
|
||||
if (expire_month > 12) {
|
||||
|
@ -317,8 +318,9 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t
|
|||
expire_year++;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (expire_month != 0) { // Allow 0 if it signifies no expiration or error
|
||||
PrintAndLogEx(WARNING, "Saflok: Invalid expiration month (%u) before day rollover.", expire_month);
|
||||
PrintAndLogEx(WARNING, "Saflok: Invalid expiration month (%u) before day rollover", expire_month);
|
||||
}
|
||||
|
||||
uint8_t checksum = decodedBA[16];
|
||||
|
@ -326,19 +328,19 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t
|
|||
bool checksum_valid = (checksum_calculated == checksum);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Saflok Details"));
|
||||
PrintAndLogEx(SUCCESS, "Key Level: %u (%s)", saflok_key_levels[key_level].level_num, saflok_key_levels[key_level].level_name);
|
||||
PrintAndLogEx(SUCCESS, "LED Warning: %s", led_warning ? "Yes" : "No");
|
||||
PrintAndLogEx(SUCCESS, "Key ID: %u (0x%02X)", key_id, key_id);
|
||||
PrintAndLogEx(SUCCESS, "Key Record: %u (0x%04X)", key_record, key_record);
|
||||
PrintAndLogEx(SUCCESS, "Opening Key: %s", opening_key ? "Yes" : "No");
|
||||
PrintAndLogEx(SUCCESS, "Sequence Number & Combination: %u (0x%02X)", sequence_combination_number, sequence_combination_number);
|
||||
PrintAndLogEx(SUCCESS, "Override Deadbolt: %s", override_deadbolt ? "Yes" : "No");
|
||||
PrintAndLogEx(SUCCESS, "Restricted Weekdays: %s", restricted_weekday_string);
|
||||
PrintAndLogEx(SUCCESS, "Property ID: %u (0x%04X)", property_id, property_id);
|
||||
PrintAndLogEx(SUCCESS, "Creation Date: %04u-%02u-%02u %02u:%02u", creation_year, creation_month, creation_day, creation_hour, creation_minute);
|
||||
PrintAndLogEx(SUCCESS, "Expiration Date: %04u-%02u-%02u %02u:%02u", expire_year, expire_month, expire_day, expiry_hour, expiry_minute);
|
||||
PrintAndLogEx(SUCCESS, "Checksum Valid: %s", checksum_valid ? "Yes" : "No");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("SAFLOK details"));
|
||||
PrintAndLogEx(SUCCESS, "Key Level............. %u (%s)", saflok_key_levels[key_level].level_num, saflok_key_levels[key_level].level_name);
|
||||
PrintAndLogEx(SUCCESS, "LED Warning........... %s", led_warning ? "Yes" : "No");
|
||||
PrintAndLogEx(SUCCESS, "Key ID................ %u (0x%02X)", key_id, key_id);
|
||||
PrintAndLogEx(SUCCESS, "Key Record............ %u (0x%04X)", key_record, key_record);
|
||||
PrintAndLogEx(SUCCESS, "Opening Key........... %s", opening_key ? "Yes" : "No");
|
||||
PrintAndLogEx(SUCCESS, "Sequence & Combination: %u (0x%02X)", sequence_combination_number, sequence_combination_number);
|
||||
PrintAndLogEx(SUCCESS, "Override Deadbolt..... %s", override_deadbolt ? "Yes" : "No");
|
||||
PrintAndLogEx(SUCCESS, "Restricted Weekdays... %s", restricted_weekday_string);
|
||||
PrintAndLogEx(SUCCESS, "Property ID........... %u (0x%04X)", property_id, property_id);
|
||||
PrintAndLogEx(SUCCESS, "Creation Date......... %04u-%02u-%02u %02u:%02u", creation_year, creation_month, creation_day, creation_hour, creation_minute);
|
||||
PrintAndLogEx(SUCCESS, "Expiration Date....... %04u-%02u-%02u %02u:%02u", expire_year, expire_month, expire_day, expiry_hour, expiry_minute);
|
||||
PrintAndLogEx(SUCCESS, "Checksum Valid........ ( %s )", checksum_valid ? _GREEN_("ok") : _RED_("fail"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -434,20 +436,19 @@ static int initSectorTable(sector_t **src, size_t items) {
|
|||
static void decode_print_st(uint16_t blockno, uint8_t *data) {
|
||||
if (mfIsSectorTrailer(blockno)) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Sector trailer decoder") " --------------------------");
|
||||
PrintAndLogEx(INFO, "key A........ " _GREEN_("%s"), sprint_hex_inrow(data, 6));
|
||||
PrintAndLogEx(INFO, "acr.......... " _GREEN_("%s"), sprint_hex_inrow(data + 6, 3));
|
||||
PrintAndLogEx(INFO, "user / gpb... " _GREEN_("%02x"), data[9]);
|
||||
PrintAndLogEx(INFO, "key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6));
|
||||
PrintAndLogEx(INFO, "------------------------ " _CYAN_("Sector trailer decoder") " ------------------------");
|
||||
PrintAndLogEx(INFO, " Key A........ " _BRIGHT_GREEN_("%s"), sprint_hex_inrow(data, 6));
|
||||
PrintAndLogEx(INFO, " ACR.......... " _MAGENTA_("%s"), sprint_hex_inrow(data + 6, 3));
|
||||
PrintAndLogEx(INFO, " User / gpb... %02x", data[9]);
|
||||
PrintAndLogEx(INFO, " Key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6));
|
||||
PrintAndLogEx(INFO, "");
|
||||
PrintAndLogEx(INFO, " # | access rights");
|
||||
PrintAndLogEx(INFO, "----+-----------------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "----+-------------------------------------------------------------------");
|
||||
|
||||
if (mfValidateAccessConditions(&data[6]) == false) {
|
||||
PrintAndLogEx(WARNING, _RED_("Invalid Access Conditions"));
|
||||
PrintAndLogEx(WARNING, _RED_("Invalid access conditions"));
|
||||
}
|
||||
|
||||
|
||||
int bln = mfFirstBlockOfSector(mfSectorNum(blockno));
|
||||
int blinc = (mfNumBlocksPerSector(mfSectorNum(blockno)) > 4) ? 5 : 1;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
@ -458,13 +459,13 @@ static void decode_print_st(uint16_t blockno, uint8_t *data) {
|
|||
uint8_t cond = mf_get_accesscondition(i, &data[6]);
|
||||
if (cond == 0 || cond == 1 || cond == 2) {
|
||||
PrintAndLogEx(INFO, "");
|
||||
PrintAndLogEx(INFO, "OBS! Key B is readable, it SHALL NOT be able to authenticate on original MFC");
|
||||
PrintAndLogEx(INFO, "OBS!");
|
||||
PrintAndLogEx(INFO, "Key B is readable, it SHALL NOT be able to authenticate on original MFC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PrintAndLogEx(INFO, "----------------------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "------------------------------------------------------------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
}
|
||||
|
@ -541,7 +542,7 @@ void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose) {
|
|||
char ascii[24] = {0};
|
||||
ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
|
||||
|
||||
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
||||
PrintAndLogEx(INFO, "%3d | " _BRIGHT_GREEN_("%s") _MAGENTA_("%s") "%02X " _GREEN_("%s") "| " _YELLOW_("%s"),
|
||||
blockno,
|
||||
keya,
|
||||
acl,
|
||||
|
@ -1428,7 +1429,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
|
|||
}
|
||||
|
||||
int keylen = 0;
|
||||
uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t key[MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
CLIGetHexWithReturn(ctx, 4, key, &keylen);
|
||||
|
||||
int s = arg_get_int_def(ctx, 5, 0);
|
||||
|
|
|
@ -29,15 +29,17 @@ define KNOWN_PLATFORM_DEFINITIONS
|
|||
|
||||
Known definitions:
|
||||
|
||||
+============================================+
|
||||
+==================================================+
|
||||
| PLATFORM | DESCRIPTION |
|
||||
+============================================+
|
||||
+==================================================+
|
||||
| PM3RDV4 (def) | Proxmark3 RDV4 |
|
||||
+--------------------------------------------+
|
||||
+--------------------------------------------------+
|
||||
| PM3GENERIC | Proxmark3 generic target |
|
||||
+--------------------------------------------+
|
||||
+--------------------------------------------------+
|
||||
| PM3ICOPYX | iCopy-X with XC3S100E |
|
||||
+--------------------------------------------+
|
||||
+--------------------------------------------------+
|
||||
| PM3ULTIMATE | Proxmark3 Ultimate with XC2S50 |
|
||||
+--------------------------------------------------+
|
||||
|
||||
+============================================+
|
||||
| PLATFORM_EXTRAS | DESCRIPTION |
|
||||
|
@ -153,7 +155,21 @@ else ifeq ($(PLATFORM),PM3ICOPYX)
|
|||
PLATFORM_DEFS = -DWITH_FLASH -DICOPYX -DXC3
|
||||
PLTNAME = iCopy-X with XC3S100E
|
||||
PLATFORM_FPGA = xc3s100e
|
||||
|
||||
else ifeq ($(PLATFORM),PM3ULTIMATE)
|
||||
# FPGA bitstream files, the order doesn't matter anymore - only hf has a bitstream
|
||||
FPGA_BITSTREAMS = fpga_pm3_ult_hf.bit
|
||||
ifneq ($(SKIP_LF),1)
|
||||
FPGA_BITSTREAMS += fpga_pm3_ult_lf.bit
|
||||
endif
|
||||
ifneq ($(SKIP_FELICA),1)
|
||||
FPGA_BITSTREAMS += fpga_pm3_ult_felica.bit
|
||||
endif
|
||||
ifneq ($(SKIP_ISO15693),1)
|
||||
FPGA_BITSTREAMS += fpga_pm3_ult_hf_15.bit
|
||||
endif
|
||||
PLATFORM_DEFS = -DWITH_FLASH -DXC2S50
|
||||
PLTNAME = Proxmark3 Ultimate with XC2S50
|
||||
PLATFORM_FPGA = xc2s50
|
||||
else
|
||||
$(error Invalid or empty PLATFORM: $(PLATFORM). $(KNOWN_DEFINITIONS))
|
||||
endif
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#if defined XC3
|
||||
#define FPGA_TYPE "3s100evq100"
|
||||
#define FPGA_CONFIG_SIZE 72864L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE
|
||||
#elif defined XC2S50
|
||||
#define FPGA_TYPE "2s50vq144"
|
||||
#define FPGA_CONFIG_SIZE 69984L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE
|
||||
#else
|
||||
#define FPGA_TYPE "2s30vq100"
|
||||
#define FPGA_CONFIG_SIZE 42336L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE
|
||||
|
|
|
@ -3695,7 +3695,8 @@
|
|||
"hf iclass sim -t 2 -> execute loclass attack online part",
|
||||
"hf iclass sim -t 3 -> simulate full iCLASS 2k tag",
|
||||
"hf iclass sim -t 4 -> Reader-attack, adapted for KeyRoll mode, gather reader responses to extract elite key",
|
||||
"hf iclass sim -t 6 -> simulate full iCLASS 2k tag that doesn't respond to r/w requests to the last SIO block"
|
||||
"hf iclass sim -t 6 -> simulate full iCLASS 2k tag that doesn't respond to r/w requests to the last SIO block",
|
||||
"hf iclass sim -t 7 -> simulate full iCLASS 2k tag that doesn't XOR or respond to r/w requests on block 3"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
|
@ -13375,6 +13376,6 @@
|
|||
"metadata": {
|
||||
"commands_extracted": 768,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2025-06-07T09:11:06"
|
||||
"extracted_on": "2025-06-08T07:56:09"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ At the moment both are maintained because they don't perfectly overlap yet.
|
|||
|
||||
| Feature | Makefile | Remarks |
|
||||
|-----|---|---|
|
||||
| Platform choice | `PLATFORM=` | values: `PM3RDV4`, `PM3GENERIC`, `PM3ICOPYX` |
|
||||
| Platform choice | `PLATFORM=` | values: `PM3RDV4`, `PM3GENERIC`, `PM3ICOPYX`, `PM3ULTIMATE` |
|
||||
| Platform size | `PLATFORM_SIZE=` | values: `256`, `512` |
|
||||
| Platform extras | `PLATFORM_EXTRAS=` | values: `BTADDON`, `FPC_USART_DEV` |
|
||||
| Skip LF/HF techs in the firmware | `SKIP_`*`=1` | see `common_arm/Makefile.hal` for a list |
|
||||
|
|
|
@ -61,11 +61,12 @@ For an up-to-date exhaustive list of options, you can run `make PLATFORM=`.
|
|||
|
||||
Here are the supported values you can assign to `PLATFORM` in `Makefile.platform`:
|
||||
|
||||
| PLATFORM | DESCRIPTION |
|
||||
|-----------------|--------------------------|
|
||||
| PM3RDV4 (def) | Proxmark3 RDV4 |
|
||||
| PM3GENERIC | Proxmark3 generic target |
|
||||
| PM3ICOPYX | iCopy-X with XC3S100E |
|
||||
| PLATFORM | DESCRIPTION |
|
||||
|-----------------|-------------------------------|
|
||||
| PM3RDV4 (def) | Proxmark3 RDV4 |
|
||||
| PM3GENERIC | Proxmark3 generic target |
|
||||
| PM3ICOPYX | iCopy-X with XC3S100E |
|
||||
| PM3ULTIMATE | Proxmar3 Ultimate with XC2S50 |
|
||||
|
||||
By default `PLATFORM=PM3RDV4`.
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
//`define PM3GENERIC
|
||||
// iCopy-X with XC3S100E
|
||||
//`define PM3ICOPYX
|
||||
// Proxmark3 Ultimate with XC2S50
|
||||
//`define PM3ULTIMATE
|
||||
|
||||
// Pass desired defines to compiler to enable required modules
|
||||
// WITH_LF enables Low Frequency mode when defined else HF is enabled
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue