mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Merge remote-tracking branch 'remotes/origin/master' into standalone-mfc-rewrite
This commit is contained in:
@@ -4,6 +4,28 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Changed standalone mode HF_MATTYRUN - support more card sizes, user dictionaries, improved emulation (@michaelroland)
|
||||
- Changed `hf iclass dump --ns` - now supports the nosave flag (@iceman1001)
|
||||
- Fixed write check in hitag2crack2 buildtables (@mwalker33)
|
||||
- Fixed breaking of client when trying to load a non-supported .picopass file (@iceman100) Thanks to Jump for suggested fixes!
|
||||
- Changed `mf_nonce_brute` tool to handle the odd case of multiple key candidates (@iceman1001)
|
||||
- Fixed a bad memory erase (@iceman1001)
|
||||
- Fixed BT serial comms (@iceman1001)
|
||||
- Changed `intertic.py` - updated and code clean up (@gentilkiwi)
|
||||
- Added `pm3_tears_for_fears.py` - a ISO14443b tear off script by Pierre Granier
|
||||
- Added new t55xx password (002BCFCF) sniffed from cheap cloner (@davidbeauchamp)
|
||||
- Fixed 'hf 14b sim' - now works (@michi-jung)
|
||||
- Added VB6 Rng for iclass elite keys `hf iclass lookup` and `hf iclass chk` functions by porting @bettse work in the Flipper Zero Picopass App (@antiklesys)
|
||||
- Added MFC Key for swimming pool cards in Reykjavík Iceland (@dandri)
|
||||
- Added key for Orkan keyfobs (@dandri)
|
||||
- Added key for Atlantsolía keyfobs (@dandri)
|
||||
- Added `hf iclass legbrute` this function allows to bruteforce 40/64 k1 bits of an iclass card to recover the raw key used(@antiklesys).
|
||||
- Added `hf iclass legrec` this function allows to recover 24/64 k1 bits of an iclass card (@antiklesys).
|
||||
## [Aurora.4.18589][2024-05-28]
|
||||
- Fixed the pm3 regressiontests for Hitag2Crack (@iceman1001)
|
||||
- Changed `mem spiffs tree` - adapted to bigbuff and show if empty (@iceman1001)
|
||||
- Changed `lf hitag info` - now tries to identify different key fob emulators (@iceman1001)
|
||||
- Added `lf hitag reader` - act as a Hitag2 reader (@iceman1001)
|
||||
- Fixed `lf hitag crack2` - now works. (@iceman1001)
|
||||
- Fixed wrong use of free() in desfire crypto on arm src, thanks @jlitewski! (@iceman1001)
|
||||
- Added `lf em 4x70 calc` - calculate `frn`/`grn` for a given `key` + `rnd`
|
||||
- Fixed `hf 15 dump` memory leaks (@jlitewski)
|
||||
|
||||
@@ -41,7 +41,7 @@ void ModInfo(void) {
|
||||
DbpString(" LF EM4100 simulator standalone mode");
|
||||
}
|
||||
|
||||
static uint64_t rev_quads(uint64_t bits) {
|
||||
static uint64_t em4100emul_rev_quads(uint64_t bits) {
|
||||
uint64_t result = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
|
||||
@@ -49,7 +49,7 @@ static uint64_t rev_quads(uint64_t bits) {
|
||||
return result >> 24;
|
||||
}
|
||||
|
||||
static void fill_buff(uint8_t bit) {
|
||||
static void em4100emul_fill_buff(uint8_t bit) {
|
||||
uint8_t *bba = BigBuf_get_addr();
|
||||
memset(bba + em4100emul_buflen, bit, LF_CLOCK / 2);
|
||||
em4100emul_buflen += (LF_CLOCK / 2);
|
||||
@@ -57,7 +57,7 @@ static void fill_buff(uint8_t bit) {
|
||||
em4100emul_buflen += (LF_CLOCK / 2);
|
||||
}
|
||||
|
||||
static void construct_EM410x_emul(uint64_t id) {
|
||||
static void em4100emul_construct_EM410x_emul(uint64_t id) {
|
||||
|
||||
int i, j;
|
||||
int binary[4] = {0, 0, 0, 0};
|
||||
@@ -65,24 +65,24 @@ static void construct_EM410x_emul(uint64_t id) {
|
||||
em4100emul_buflen = 0;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
fill_buff(1);
|
||||
em4100emul_fill_buff(1);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 3; j >= 0; j--, id /= 2)
|
||||
binary[j] = id % 2;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
fill_buff(binary[j]);
|
||||
em4100emul_fill_buff(binary[j]);
|
||||
|
||||
fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||
em4100emul_fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||
for (j = 0; j < 4; j++)
|
||||
parity[j] ^= binary[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
fill_buff(parity[j]);
|
||||
em4100emul_fill_buff(parity[j]);
|
||||
|
||||
fill_buff(0);
|
||||
em4100emul_fill_buff(0);
|
||||
}
|
||||
|
||||
static void LED_Slot(int i) {
|
||||
@@ -108,8 +108,18 @@ void RunMod(void) {
|
||||
SpinDelay(100);
|
||||
SpinUp(100);
|
||||
LED_Slot(selected);
|
||||
construct_EM410x_emul(rev_quads(em4100emul_low[selected]));
|
||||
Dbprintf("Emulating 0x%010llX", em4100emul_low[selected]);
|
||||
em4100emul_construct_EM410x_emul(em4100emul_rev_quads(em4100emul_low[selected]));
|
||||
SimulateTagLowFrequency(em4100emul_buflen, 0, true);
|
||||
|
||||
//Exit! Button hold break
|
||||
int button_pressed = BUTTON_HELD(500);
|
||||
if (button_pressed == BUTTON_HOLD) {
|
||||
Dbprintf("Button hold, Break!");
|
||||
LEDsoff();
|
||||
Dbprintf("[=] >> LF EM4100 simulator stopped due to button hold <<");
|
||||
return; // RunMod end
|
||||
}
|
||||
selected = (selected + 1) % em4100emul_slots_count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2061,6 +2061,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
iClass_Restore((iclass_restore_req_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_RECOVER: {
|
||||
iClass_Recover((iclass_recover_req_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_CREDIT_EPURSE: {
|
||||
iclass_credit_epurse((iclass_credit_epurse_t *)packet->data.asBytes);
|
||||
break;
|
||||
|
||||
+3
-2
@@ -101,9 +101,10 @@ void Dbhexdump(int len, const uint8_t *d, bool bAsci) {
|
||||
d += 16;
|
||||
}
|
||||
#endif
|
||||
}void print_result(const char *name, const uint8_t *d, size_t
|
||||
}
|
||||
void print_result(const char *name, const uint8_t *d, size_t
|
||||
|
||||
n) {
|
||||
n) {
|
||||
|
||||
const uint8_t *p = d;
|
||||
uint16_t tmp = n & 0xFFF0;
|
||||
|
||||
+1
-1
@@ -1257,7 +1257,7 @@ static int em4x50_sim_read_bit(void) {
|
||||
|
||||
// wait 16 cycles to make sure there is no field when reading a "0" bit
|
||||
uint32_t waitval = GetTicks();
|
||||
while(GetTicks() - waitval < EM4X50_T_TAG_QUARTER_PERIOD * CYCLES2TICKS);
|
||||
while (GetTicks() - waitval < EM4X50_T_TAG_QUARTER_PERIOD * CYCLES2TICKS);
|
||||
|
||||
while (cycles < EM4X50_T_TAG_THREE_QUARTER_PERIOD) {
|
||||
|
||||
|
||||
+38
-38
@@ -32,47 +32,47 @@ static bool command_parity = true;
|
||||
|
||||
|
||||
#if 1 // Calculation of ticks for timing functions
|
||||
// Conversion from Ticks to RF periods
|
||||
// 1 us = 1.5 ticks
|
||||
// 1RF Period = 8us = 12 Ticks
|
||||
#define TICKS_PER_FC 12
|
||||
// Conversion from Ticks to RF periods
|
||||
// 1 us = 1.5 ticks
|
||||
// 1RF Period = 8us = 12 Ticks
|
||||
#define TICKS_PER_FC 12
|
||||
|
||||
// Chip timing from datasheet
|
||||
// Converted into Ticks for timing functions
|
||||
#define EM4X70_T_TAG_QUARTER_PERIOD (8 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_HALF_PERIOD (16 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_THREE_QUARTER_PERIOD (24 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_FULL_PERIOD (32 * TICKS_PER_FC) // 1 Bit Period
|
||||
#define EM4X70_T_TAG_TWA (128 * TICKS_PER_FC) // Write Access Time
|
||||
#define EM4X70_T_TAG_DIV (224 * TICKS_PER_FC) // Divergency Time
|
||||
#define EM4X70_T_TAG_AUTH (4224 * TICKS_PER_FC) // Authentication Time
|
||||
#define EM4X70_T_TAG_WEE (3072 * TICKS_PER_FC) // EEPROM write Time
|
||||
#define EM4X70_T_TAG_TWALB (672 * TICKS_PER_FC) // Write Access Time of Lock Bits
|
||||
#define EM4X70_T_TAG_BITMOD (4 * TICKS_PER_FC) // Initial time to stop modulation when sending 0
|
||||
#define EM4X70_T_TAG_TOLERANCE (8 * TICKS_PER_FC) // Tolerance in RF periods for receive/LIW
|
||||
// Chip timing from datasheet
|
||||
// Converted into Ticks for timing functions
|
||||
#define EM4X70_T_TAG_QUARTER_PERIOD (8 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_HALF_PERIOD (16 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_THREE_QUARTER_PERIOD (24 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_FULL_PERIOD (32 * TICKS_PER_FC) // 1 Bit Period
|
||||
#define EM4X70_T_TAG_TWA (128 * TICKS_PER_FC) // Write Access Time
|
||||
#define EM4X70_T_TAG_DIV (224 * TICKS_PER_FC) // Divergency Time
|
||||
#define EM4X70_T_TAG_AUTH (4224 * TICKS_PER_FC) // Authentication Time
|
||||
#define EM4X70_T_TAG_WEE (3072 * TICKS_PER_FC) // EEPROM write Time
|
||||
#define EM4X70_T_TAG_TWALB (672 * TICKS_PER_FC) // Write Access Time of Lock Bits
|
||||
#define EM4X70_T_TAG_BITMOD (4 * TICKS_PER_FC) // Initial time to stop modulation when sending 0
|
||||
#define EM4X70_T_TAG_TOLERANCE (8 * TICKS_PER_FC) // Tolerance in RF periods for receive/LIW
|
||||
|
||||
#define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this
|
||||
#define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window
|
||||
#define EM4X70_T_READ_HEADER_LEN 16 // Read header length (16 bit periods)
|
||||
#define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this
|
||||
#define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window
|
||||
#define EM4X70_T_READ_HEADER_LEN 16 // Read header length (16 bit periods)
|
||||
|
||||
#define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command
|
||||
#define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command
|
||||
#define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command
|
||||
#define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command
|
||||
#endif // Calculation of ticks for timing functions
|
||||
|
||||
#if 1 // EM4x70 Command IDs
|
||||
/**
|
||||
* These IDs are from the EM4170 datasheet.
|
||||
* Some versions of the chip require a
|
||||
* (even) parity bit, others do not.
|
||||
* The command is thus stored only in the
|
||||
* three least significant bits (mask 0x07).
|
||||
*/
|
||||
#define EM4X70_COMMAND_ID 0x01
|
||||
#define EM4X70_COMMAND_UM1 0x02
|
||||
#define EM4X70_COMMAND_AUTH 0x03
|
||||
#define EM4X70_COMMAND_PIN 0x04
|
||||
#define EM4X70_COMMAND_WRITE 0x05
|
||||
#define EM4X70_COMMAND_UM2 0x07
|
||||
/**
|
||||
* These IDs are from the EM4170 datasheet.
|
||||
* Some versions of the chip require a
|
||||
* (even) parity bit, others do not.
|
||||
* The command is thus stored only in the
|
||||
* three least significant bits (mask 0x07).
|
||||
*/
|
||||
#define EM4X70_COMMAND_ID 0x01
|
||||
#define EM4X70_COMMAND_UM1 0x02
|
||||
#define EM4X70_COMMAND_AUTH 0x03
|
||||
#define EM4X70_COMMAND_PIN 0x04
|
||||
#define EM4X70_COMMAND_WRITE 0x05
|
||||
#define EM4X70_COMMAND_UM2 0x07
|
||||
#endif // EM4x70 Command IDs
|
||||
|
||||
// Constants used to determine high/low state of signal
|
||||
@@ -309,7 +309,7 @@ static bool check_ack(void) {
|
||||
// ACK 64 + 64
|
||||
// NAK 64 + 48
|
||||
if (check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) {
|
||||
check_pulse_length(get_pulse_length(FALLING_EDGE), 2 * EM4X70_T_TAG_FULL_PERIOD)) {
|
||||
// ACK
|
||||
return true;
|
||||
}
|
||||
@@ -549,8 +549,8 @@ static bool find_listen_window(bool command) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// *bits == array of bytes, each byte storing a single bit.
|
||||
// *out == array of bytes, storing converted bits --> bytes.
|
||||
// *bits == array of bytes, each byte storing a single bit.
|
||||
// *out == array of bytes, storing converted bits --> bytes.
|
||||
//
|
||||
// [in, bcount(count_of_bits) ] const uint8_t *bits
|
||||
// [out, bcount(count_of_bits/8)] uint8_t *out
|
||||
|
||||
+8
-8
@@ -120,7 +120,7 @@ static void hitag2_init(void) {
|
||||
#define HITAG_FRAME_LEN 20
|
||||
#define HITAG_FRAME_BIT_COUNT (8 * HITAG_FRAME_LEN)
|
||||
#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
|
||||
#define HITAG_T_LOW 6 /* T_LOW should be 4..10 */
|
||||
#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
|
||||
#define HITAG_T_0 20 /* T[0] should be 18..22 */
|
||||
#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */
|
||||
@@ -322,8 +322,6 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
||||
// reader/writer
|
||||
// returns how long it took
|
||||
static uint32_t hitag_reader_send_bit(int bit) {
|
||||
uint32_t wait = 0;
|
||||
|
||||
// Binary pulse length modulation (BPLM) is used to encode the data stream
|
||||
// This means that a transmission of a one takes longer than that of a zero
|
||||
|
||||
@@ -331,8 +329,8 @@ static uint32_t hitag_reader_send_bit(int bit) {
|
||||
lf_modulation(true);
|
||||
|
||||
// Wait for 4-10 times the carrier period
|
||||
lf_wait_periods(8); // wait for 4-10 times the carrier period
|
||||
wait += 8;
|
||||
lf_wait_periods(HITAG_T_LOW); // wait for 4-10 times the carrier period
|
||||
uint32_t wait = HITAG_T_LOW;
|
||||
|
||||
// Disable modulation, just activates the field again
|
||||
lf_modulation(false);
|
||||
@@ -353,6 +351,7 @@ static uint32_t hitag_reader_send_bit(int bit) {
|
||||
// reader / writer commands
|
||||
// frame_len is in number of bits?
|
||||
static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) {
|
||||
WDT_HIT();
|
||||
|
||||
uint32_t wait = 0;
|
||||
// Send the content of the frame
|
||||
@@ -360,6 +359,7 @@ static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len)
|
||||
wait += hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
|
||||
}
|
||||
|
||||
// Send EOF
|
||||
// Enable modulation, which means, drop the field
|
||||
lf_modulation(true);
|
||||
|
||||
@@ -373,6 +373,7 @@ static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len)
|
||||
// t_stop, high field for stop condition (> 36)
|
||||
lf_wait_periods(HITAG_T_STOP);
|
||||
wait += HITAG_T_STOP;
|
||||
WDT_HIT();
|
||||
return wait;
|
||||
}
|
||||
|
||||
@@ -388,7 +389,7 @@ static uint32_t hitag_reader_send_framebits(const uint8_t *frame, size_t frame_l
|
||||
wait += hitag_reader_send_bit(frame[i]);
|
||||
}
|
||||
|
||||
// EOF
|
||||
// Send EOF
|
||||
// Enable modulation, which means, drop the field
|
||||
// set GPIO_SSC_DOUT to HIGH
|
||||
lf_modulation(true);
|
||||
@@ -406,7 +407,6 @@ static uint32_t hitag_reader_send_framebits(const uint8_t *frame, size_t frame_l
|
||||
wait += HITAG_T_STOP;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
return wait;
|
||||
}
|
||||
|
||||
@@ -2418,7 +2418,7 @@ static void ht2_send(bool turn_on, uint32_t *cmd_start
|
||||
, uint8_t *tx, size_t txlen, bool send_bits) {
|
||||
|
||||
// Tag specific configuration settings (sof, timings, etc.) HITAG2 Settings
|
||||
#define T_WAIT_1_GUARD 8
|
||||
#define T_WAIT_1_GUARD 7
|
||||
|
||||
if (turn_on) {
|
||||
// Wait 50ms with field off to be sure the transponder gets reset
|
||||
|
||||
+71
-245
@@ -30,15 +30,13 @@
|
||||
#include "cmd.h"
|
||||
#include "lfadc.h"
|
||||
|
||||
const static uint8_t ERROR_RESPONSE[] = { 0xF4, 0x02, 0x88, 0x9C };
|
||||
|
||||
// #define READP0CMD "1100000111"
|
||||
const static uint8_t read_p0_cmd[] = {1, 1, 0, 0, 0, 0, 0, 1, 1, 1};
|
||||
|
||||
// hitag2crack_xor XORs the source with the pad to produce the target.
|
||||
// source, target and pad are binarrays of length len.
|
||||
static void hitag2crack_xor(uint8_t *target, const uint8_t *source, const uint8_t *pad, uint16_t len) {
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
static void hitag2crack_xor(uint8_t *target, const uint8_t *source, const uint8_t *pad, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
target[i] = source[i] ^ pad[i];
|
||||
}
|
||||
}
|
||||
@@ -113,22 +111,18 @@ static bool hitag2crack_read_page(uint8_t *resp, uint8_t pagenum, uint8_t *nrar,
|
||||
uint8_t e_resp[4];
|
||||
if (hitag2crack_send_e_cmd(e_resp, nrar, e_cmd, 10)) {
|
||||
|
||||
// check if it is valid OBS!
|
||||
if (memcmp(e_resp, ERROR_RESPONSE, 4)) {
|
||||
uint8_t e_response[32] = {0};
|
||||
uint8_t response[32] = {0};
|
||||
|
||||
uint8_t e_response[32];
|
||||
uint8_t response[32];
|
||||
// convert to binarray
|
||||
hex2binarray_n((char *)e_response, (char *)e_resp, 4);
|
||||
// decrypt response
|
||||
hitag2crack_xor(response, e_response, keybits + 10, 32);
|
||||
|
||||
// convert to binarray
|
||||
hex2binarray((char *)e_response, (char *)e_resp);
|
||||
// decrypt response
|
||||
hitag2crack_xor(response, e_response, keybits + 10, 32);
|
||||
// convert to hexstring
|
||||
binarray2hex(response, 32, resp);
|
||||
|
||||
// convert to hexstring
|
||||
binarray2hex(response, 32, resp);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -168,14 +162,7 @@ static bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e
|
||||
// send extended encrypted cmd
|
||||
uint8_t resp[4] = {0};
|
||||
if (hitag2crack_send_e_cmd(resp, nrar, e_ext_cmd, 40)) {
|
||||
|
||||
// test if it was valid
|
||||
if (memcmp(resp, ERROR_RESPONSE, 4)) {
|
||||
return true;
|
||||
} else {
|
||||
DbpString("test enc-page0 cmd. got error-response");
|
||||
Dbhexdump(4, resp, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -201,6 +188,7 @@ static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd,
|
||||
// encrypted command.
|
||||
uint8_t guess[10];
|
||||
memcpy(guess, e_firstcmd, 10);
|
||||
|
||||
if (a) {
|
||||
guess[5] = !guess[5];
|
||||
guess[0] = !guess[0];
|
||||
@@ -222,21 +210,17 @@ static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd,
|
||||
}
|
||||
|
||||
// try the guess
|
||||
uint8_t resp[4];
|
||||
uint8_t resp[4] = {0};
|
||||
if (hitag2crack_send_e_cmd(resp, nrar, guess, 10)) {
|
||||
|
||||
// check if it was valid
|
||||
if (memcmp(resp, ERROR_RESPONSE, 4)) {
|
||||
// convert response to binarray
|
||||
// response should been encrypted UID
|
||||
uint8_t e_uid[32] = {0};
|
||||
hex2binarray_n((char *)e_uid, (char *)resp, 4);
|
||||
|
||||
// convert response to binarray
|
||||
// response should been encrypted UID
|
||||
uint8_t e_uid[32];
|
||||
hex2binarray((char *)e_uid, (char *)resp);
|
||||
|
||||
// test if the guess was 'read page 0' command
|
||||
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
|
||||
return true;
|
||||
}
|
||||
// test if the guess was 'read page 0' command
|
||||
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,29 +247,15 @@ static bool hitag2crack_find_valid_e_cmd(uint8_t *e_cmd, uint8_t *nrar) {
|
||||
for (uint8_t g = 0; g < 2; g++) {
|
||||
|
||||
// build binarray
|
||||
//uint8_t guess[10] = { a, b, c, d, e, 0, g, 0, 0, 0 };
|
||||
uint8_t guess[10];
|
||||
guess[0] = a;
|
||||
guess[1] = b;
|
||||
guess[2] = c;
|
||||
guess[3] = d;
|
||||
guess[4] = e;
|
||||
guess[5] = 0;
|
||||
guess[6] = g;
|
||||
guess[7] = 0;
|
||||
guess[8] = 0;
|
||||
guess[9] = 0;
|
||||
uint8_t guess[10] = { a, b, c, d, e, 0, g, 0, 0, 0 };
|
||||
|
||||
// send guess
|
||||
uint8_t resp[4];
|
||||
uint8_t resp[4] = {0};
|
||||
if (hitag2crack_send_e_cmd(resp, nrar, guess, sizeof(guess))) {
|
||||
|
||||
// check if it was valid
|
||||
if (memcmp(resp, ERROR_RESPONSE, 4)) {
|
||||
// return the guess as the encrypted command
|
||||
memcpy(e_cmd, guess, 10);
|
||||
return true;
|
||||
}
|
||||
// return the guess as the encrypted command
|
||||
memcpy(e_cmd, guess, 10);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,114 +266,13 @@ static bool hitag2crack_find_valid_e_cmd(uint8_t *e_cmd, uint8_t *nrar) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t keybits[2080];
|
||||
uint8_t uid[32];
|
||||
uint8_t nrar[64];
|
||||
uint8_t e_ext_cmd[2080];
|
||||
uint8_t ext_cmd[2080];
|
||||
} PACKED lf_hitag_crack2_t;
|
||||
|
||||
// hitag2crack_consume_keystream sends an extended command (up to 510 bits in
|
||||
// length) to consume keystream.
|
||||
// keybits is the binarray of keystream bits;
|
||||
// kslen is the length of keystream;
|
||||
// ksoffset is a pointer to the current keystream offset (updated by this fn);
|
||||
// nrar is the 64 bit binarray of the nR aR pair.
|
||||
//static bool ht2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset) {
|
||||
/*
|
||||
static bool ht2crack_consume_keystream(lf_hitag_crack2_t *c2, int kslen, int *ksoffset) {
|
||||
|
||||
// calculate the length of keybits to consume with the extended command.
|
||||
// 42 = 32 bit response + 10 bit command reserved for next command. conlen
|
||||
// cannot be longer than 510 bits to fit into the small RWD buffer.
|
||||
int conlen = kslen - *ksoffset - 42;
|
||||
if (conlen < 10) {
|
||||
DbpString("ht2crack_consume_keystream: conlen < 10");
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate how many repeated commands to send in this extended command.
|
||||
int numcmds = conlen / 10;
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(c2->e_ext_cmd, c2->ext_cmd, c2->keybits + *ksoffset, (numcmds * 10));
|
||||
|
||||
// send encrypted command
|
||||
size_t n = 0;
|
||||
uint8_t resp[4];
|
||||
if (ht2_tx_rx(c2->e_ext_cmd, numcmds * 10, resp, &n, true, true) != PM3_SUCCESS) {
|
||||
Dbprintf("ht2crack_consume_keystream: tx/rx cmd failed, got %zu", n);
|
||||
return false;
|
||||
}
|
||||
|
||||
// test response
|
||||
if (memcmp(resp, ERROR_RESPONSE, 4) == 0) {
|
||||
DbpString("ht2crack_consume_keystream: got error response from card");
|
||||
return false;
|
||||
}
|
||||
|
||||
// dont bother decrypting the response - we already know the keybits
|
||||
|
||||
// update ksoffset with command length and response
|
||||
*ksoffset += (numcmds * 10) + 32;
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
// hitag2crack_extend_keystream sends an extended command to retrieve more keybits.
|
||||
// keybits is the binarray of the keystream bits;
|
||||
// kslen is a pointer to the current keybits length;
|
||||
// ksoffset is the offset into the keybits array;
|
||||
// nrar is the 64 bit binarray of the nR aR pair;
|
||||
// uid is the 32 bit binarray of the UID.
|
||||
//static bool ht2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid) {
|
||||
/*
|
||||
static bool ht2crack_extend_keystream(lf_hitag_crack2_t *c2, int *kslen, int ksoffset) {
|
||||
|
||||
// calc number of command iterations to send
|
||||
int cmdlen = *kslen - ksoffset;
|
||||
if (cmdlen < 10) {
|
||||
DbpString("extend_keystream: cmdlen < 10");
|
||||
return false;
|
||||
}
|
||||
|
||||
int numcmds = cmdlen / 10;
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(c2->e_ext_cmd, c2->ext_cmd, c2->keybits + ksoffset, numcmds * 10);
|
||||
|
||||
// send extended encrypted cmd
|
||||
size_t n = 0;
|
||||
uint8_t resp[4];
|
||||
if (ht2_tx_rx(c2->e_ext_cmd, numcmds * 10, resp, &n, true, true) != PM3_SUCCESS) {
|
||||
DbpString("extend_keystream: tx/rx cmd failed");
|
||||
Dbhexdump(numcmds * 10, c2->e_ext_cmd, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// test response
|
||||
if (memcmp(resp, ERROR_RESPONSE, 4) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert response to binarray
|
||||
uint8_t e_response[32];
|
||||
hex2binarray((char*)e_response, (char*)resp);
|
||||
|
||||
// recover keystream from encrypted response
|
||||
hitag2crack_xor(c2->keybits + ksoffset + (numcmds * 10), e_response, c2->uid, 32);
|
||||
|
||||
// update kslen
|
||||
*kslen = ksoffset + (numcmds * 10) + 32;
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
// hitag2_crack implements the first crack algorithm described in the paper,
|
||||
// Gone In 360 Seconds by Verdult, Garcia and Balasch.
|
||||
// response is a multi-line text response containing the 8 pages of the cracked tag
|
||||
@@ -468,148 +337,105 @@ out:
|
||||
// nrar_hex is the 32 bit nR and aR in hex
|
||||
void ht2_crack2(uint8_t *nrar_hex) {
|
||||
|
||||
BigBuf_free();
|
||||
|
||||
uint8_t *e_response = BigBuf_calloc(32);
|
||||
lf_hitag_crack2_t *c2 = (lf_hitag_crack2_t *)BigBuf_calloc(sizeof(lf_hitag_crack2_t));
|
||||
lf_hitag_crack_response_t *packet = (lf_hitag_crack_response_t *)BigBuf_calloc(sizeof(lf_hitag_crack_response_t));
|
||||
|
||||
g_logging = false;
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
clear_trace();
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
// find the 'read page 0' command and recover key stream
|
||||
|
||||
// get uid as hexstring
|
||||
uint8_t uid_hex[4];
|
||||
uint8_t uid_hex[4] = {0};
|
||||
if (ht2_read_uid(uid_hex, false, false, false) != PM3_SUCCESS) {
|
||||
res = PM3_EFAILED;
|
||||
goto out;
|
||||
BigBuf_free();
|
||||
reply_ng(CMD_LF_HITAG2_CRACK_2, PM3_EFAILED, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
hex2binarray_n((char *)c2->uid, (char *)uid_hex, 4);
|
||||
hex2binarray_n((char *)c2->nrar, (char *)nrar_hex, 8);
|
||||
|
||||
DbpString("looking for encrypted command");
|
||||
|
||||
// find a valid encrypted command
|
||||
uint8_t e_firstcmd[10];
|
||||
uint8_t e_firstcmd[10] = {0};
|
||||
if (hitag2crack_find_valid_e_cmd(e_firstcmd, c2->nrar) == false) {
|
||||
res = PM3_EFAILED;
|
||||
goto out;
|
||||
BigBuf_free();
|
||||
reply_ng(CMD_LF_HITAG2_CRACK_2, PM3_EFAILED, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
DbpString("looking for encrypted page 0");
|
||||
// find encrypted page0 commnd
|
||||
if (hitag2crack_find_e_page0_cmd(c2->keybits, e_firstcmd, c2->nrar, c2->uid) == false) {
|
||||
res = PM3_EFAILED;
|
||||
goto out;
|
||||
BigBuf_free();
|
||||
reply_ng(CMD_LF_HITAG2_CRACK_2, PM3_EFAILED, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we got 40 bits of keystream in c2->keybits.
|
||||
|
||||
// We got 42 bits of keystream in c2->keybits.
|
||||
// using the 40 bits of keystream in keybits, sending commands with ever
|
||||
// increasing lengths to acquire 2048 bits of key stream.
|
||||
int kslen = 40;
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
// build extended command
|
||||
for (int i = 0; i < 208 ; i++) {
|
||||
memcpy(c2->ext_cmd + (i * 10), read_p0_cmd, 10);
|
||||
}
|
||||
while (kslen < 2048 && BUTTON_PRESS() == false) {
|
||||
|
||||
DbpString("enter main keystream rec");
|
||||
Dbhexdump(160, c2->ext_cmd, false);
|
||||
hitag2crack_xor(c2->e_ext_cmd, read_p0_cmd, c2->keybits, 10);
|
||||
hitag2crack_xor(c2->e_ext_cmd + 10, read_p0_cmd, c2->keybits + 10, 10);
|
||||
hitag2crack_xor(c2->e_ext_cmd + 20, read_p0_cmd, c2->keybits + 20, 10);
|
||||
hitag2crack_xor(c2->e_ext_cmd + 30, read_p0_cmd, c2->keybits + 30, 10);
|
||||
|
||||
DbpString("enter main keystream recover loop");
|
||||
|
||||
while (kslen < 2048) {
|
||||
|
||||
//int ksoffset = 0;
|
||||
Dbprintf("Recovered " _YELLOW_("%4i") " bits of keystream", kslen);
|
||||
|
||||
// Get UID
|
||||
if (ht2_read_uid(NULL, true, false, true) != PM3_SUCCESS) {
|
||||
res = PM3_EFAILED;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
// send nrar and receive (useless) encrypted page 3 value
|
||||
size_t n = 0;
|
||||
if (ht2_tx_rx(c2->nrar, 64, NULL, &n, true, true) != PM3_SUCCESS) {
|
||||
res = PM3_EFAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// while we have at least 52 bits of keystream, consume it with
|
||||
// extended read page 0 commands.
|
||||
// 52 = 10 (min command len) + 32 (response) + 10 (min command len we'll send)
|
||||
/*
|
||||
while ((kslen - ksoffset) >= 52) {
|
||||
// consume the keystream, updating ksoffset as we go
|
||||
//if (ht2crack_consume_keystream(c2->keybits, kslen, &ksoffset, c2->nrar) == false) {
|
||||
if (ht2crack_consume_keystream(c2, kslen, &ksoffset) == false) {
|
||||
DbpString("ht2crack_consume_keystream failed");
|
||||
res = PM3_EFAILED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
// send an extended command to retrieve more keystream,
|
||||
// updating kslen as we go
|
||||
if (ht2crack_extend_keystream(c2, &kslen, ksoffset) == false) {
|
||||
DbpString("ht2crack_extend_keystream failed");
|
||||
res = PM3_EFAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// xor extended cmd with keybits
|
||||
hitag2crack_xor(c2->e_ext_cmd, c2->ext_cmd, c2->keybits, kslen);
|
||||
|
||||
// send extended encrypted cmd
|
||||
uint8_t resp[4];
|
||||
if (ht2_tx_rx(c2->e_ext_cmd, kslen, resp, &n, true, false) != PM3_SUCCESS) {
|
||||
DbpString("extend_keystream: tx/rx cmd failed");
|
||||
break;
|
||||
}
|
||||
|
||||
// test response
|
||||
if (memcmp(resp, ERROR_RESPONSE, 4) == 0) {
|
||||
uint8_t resp[4] = {0};
|
||||
res = ht2_tx_rx(c2->e_ext_cmd, kslen, resp, &n, true, false);
|
||||
if (res != PM3_SUCCESS) {
|
||||
Dbprintf("tx/rx failed, got %zu (res... %i)", n, res);
|
||||
break;
|
||||
}
|
||||
|
||||
// convert response to binarray
|
||||
uint8_t e_response[32];
|
||||
hex2binarray((char *)e_response, (char *)resp);
|
||||
hex2binarray_n((char *)e_response, (char *)resp, 4);
|
||||
|
||||
// recover keystream from encrypted response
|
||||
hitag2crack_xor(c2->keybits + kslen + 40, e_response, c2->uid, 32);
|
||||
hitag2crack_xor(c2->keybits + kslen, e_response, c2->uid, 32);
|
||||
|
||||
// update kslen
|
||||
kslen += (40 + 32);
|
||||
|
||||
Dbprintf("Recovered " _YELLOW_("%i") " bits of keystream", kslen);
|
||||
// extented with 30 bits or 3 * 10 read_p0_cmds
|
||||
hitag2crack_xor(c2->e_ext_cmd + kslen, read_p0_cmd, c2->keybits + kslen, 10);
|
||||
kslen += 10;
|
||||
hitag2crack_xor(c2->e_ext_cmd + kslen, read_p0_cmd, c2->keybits + kslen, 10);
|
||||
kslen += 10;
|
||||
hitag2crack_xor(c2->e_ext_cmd + kslen, read_p0_cmd, c2->keybits + kslen, 10);
|
||||
kslen += 10;
|
||||
}
|
||||
|
||||
/*
|
||||
uint8_t *keybitshex = BigBuf_calloc(64);
|
||||
for (int i = 0; i < 2048; i += 256) {
|
||||
binarray2hex(c2->keybits + i, 256, keybitshex);
|
||||
Dbhexdump(256, keybitshex, false);
|
||||
}
|
||||
*/
|
||||
BigBuf_free();
|
||||
Dbprintf("Recovered " _YELLOW_("%4i") " bits of keystream", kslen);
|
||||
|
||||
lf_hitag_crack_response_t *packet = (lf_hitag_crack_response_t *)BigBuf_calloc(sizeof(lf_hitag_crack_response_t));
|
||||
|
||||
// copy UID since we already have it...
|
||||
memcpy(packet->data, uid_hex, 4);
|
||||
packet->status = 1;
|
||||
|
||||
out:
|
||||
|
||||
/*
|
||||
DbpString("keybits:");
|
||||
Dbhexdump(2080, c2->keybits, false);
|
||||
DbpString("uid:");
|
||||
Dbhexdump(32, c2->uid, false);
|
||||
DbpString("nrar:");
|
||||
Dbhexdump(64, c2->nrar, false);
|
||||
*/
|
||||
binarray2hex(c2->keybits, kslen, packet->data);
|
||||
|
||||
reply_ng(CMD_LF_HITAG2_CRACK_2, res, (uint8_t *)packet, sizeof(lf_hitag_crack_response_t));
|
||||
BigBuf_free();
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1090,7 +1090,7 @@ static void hitagS_receive_frame(uint8_t *rx, size_t sizeofrx, size_t *rxlen, ui
|
||||
// Dbprintf("RX0 %i:%02X.. err:%i resptime:%i", *rxlen, rx[0], errorCount, *resptime);
|
||||
}
|
||||
|
||||
static void sendReceiveHitagS( const uint8_t *tx, size_t txlen, uint8_t *rx, size_t sizeofrx, size_t *prxbits, int t_wait, bool ledcontrol, bool ac_seq) {
|
||||
static void sendReceiveHitagS(const uint8_t *tx, size_t txlen, uint8_t *rx, size_t sizeofrx, size_t *prxbits, int t_wait, bool ledcontrol, bool ac_seq) {
|
||||
|
||||
LogTraceBits(tx, txlen, HITAG_T_WAIT_2, HITAG_T_WAIT_2, true);
|
||||
|
||||
|
||||
+198
@@ -2152,3 +2152,201 @@ out:
|
||||
reply_ng(CMD_HF_ICLASS_RESTORE, isOK, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void generate_single_key_block_inverted(const uint8_t *startingKey, uint32_t index, uint8_t *keyBlock) {
|
||||
uint32_t carry = index;
|
||||
memcpy(keyBlock, startingKey, PICOPASS_BLOCK_SIZE);
|
||||
|
||||
for (int j = PICOPASS_BLOCK_SIZE - 1; j >= 0; j--) {
|
||||
uint8_t increment_value = carry & 0x07; // Use only the last 3 bits of carry
|
||||
keyBlock[j] = increment_value; // Set the last 3 bits, assuming first 5 bits are always 0
|
||||
|
||||
carry >>= 3; // Shift right by 3 bits for the next byte
|
||||
if (carry == 0) {
|
||||
// If no more carry, break early to avoid unnecessary loops
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iClass_Recover(iclass_recover_req_t *msg) {
|
||||
|
||||
bool shallow_mod = false;
|
||||
|
||||
LED_A_ON();
|
||||
Dbprintf(_RED_("Interrupting this process will render the card unusable!"));
|
||||
|
||||
Iso15693InitReader();
|
||||
//Authenticate with AA2 with the standard key to get the AA2 mac
|
||||
//Step0 Card Select Routine
|
||||
|
||||
uint32_t eof_time = 0;
|
||||
picopass_hdr_t hdr = {0};
|
||||
bool res = select_iclass_tag(&hdr, true, &eof_time, shallow_mod);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
//Step1 Authenticate with AA2 using K2
|
||||
|
||||
uint8_t mac2[4] = {0};
|
||||
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
res = authenticate_iclass_tag(&msg->req2, &hdr, &start_time, &eof_time, mac2);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint8_t div_key2[8] = {0};
|
||||
memcpy(div_key2, hdr.key_c, 8);
|
||||
|
||||
//cycle reader to reset cypher state and be able to authenticate with k1 trace
|
||||
switch_off();
|
||||
Iso15693InitReader();
|
||||
|
||||
//Step0 Card Select Routine
|
||||
|
||||
eof_time = 0;
|
||||
//hdr = {0};
|
||||
res = select_iclass_tag(&hdr, false, &eof_time, shallow_mod);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
//Step1 Authenticate with AA1 using trace
|
||||
|
||||
uint8_t mac1[4] = {0};
|
||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
|
||||
if (res == false) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
//Step2 Privilege Escalation: attempt to read AA2 with credentials for AA1
|
||||
uint8_t blockno = 24;
|
||||
uint8_t cmd_read[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00};
|
||||
AddCrc(cmd_read + 1, 1);
|
||||
uint8_t resp[10];
|
||||
|
||||
res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
|
||||
|
||||
static uint8_t iclass_mac_table[8][8] = { //Reference weak macs table
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xBF, 0x5D, 0x67, 0x7F }, //Expected mac when last 3 bits of each byte are: 000
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x6F, 0x11 }, //Expected mac when last 3 bits of each byte are: 001
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x53, 0x35, 0x42, 0x0F }, //Expected mac when last 3 bits of each byte are: 010
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xAB, 0x47, 0x4D, 0xA0 }, //Expected mac when last 3 bits of each byte are: 011
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xF6, 0xCF, 0x43, 0x36 }, //Expected mac when last 3 bits of each byte are: 100
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x59, 0x7F, 0x4B, 0x58 }, //Expected mac when last 3 bits of each byte are: 101
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x1A, 0xA7, 0x66, 0x46 }, //Expected mac when last 3 bits of each byte are: 110
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0xE2, 0xD5, 0x69, 0xE9 } //Expected mac when last 3 bits of each byte are: 111
|
||||
};
|
||||
//Viewing the weak macs table card 24 bits (3x8) in the form of a 24 bit decimal number
|
||||
static uint32_t iclass_mac_table_bit_values[8] = {0, 2396745, 4793490, 7190235, 9586980, 11983725, 14380470, 16777215};
|
||||
|
||||
/* iclass_mac_table is a series of weak macs, those weak macs correspond to the different combinations of the last 3 bits of each key byte.
|
||||
If we concatenate the last three bits of each key byte, we have a 24 bits long binary string.
|
||||
If we convert that string to decimal we obtain the decimal numbers in iclass_mac_table_bit_values
|
||||
Xorring the index of iterations against those decimal numbers allows us to retrieve the what was the corresponding sequence of bits of the original key in decimal format. */
|
||||
|
||||
uint8_t zero_key[PICOPASS_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint32_t index = 1;
|
||||
int bits_found = -1;
|
||||
|
||||
//START LOOP
|
||||
while (bits_found == -1) {
|
||||
|
||||
//Step3 Calculate New Key
|
||||
uint8_t genkeyblock[PICOPASS_BLOCK_SIZE];
|
||||
uint8_t genkeyblock_old[PICOPASS_BLOCK_SIZE];
|
||||
uint8_t xorkeyblock[PICOPASS_BLOCK_SIZE];
|
||||
generate_single_key_block_inverted(zero_key, index, genkeyblock);
|
||||
|
||||
//NOTE BEFORE UPDATING THE KEY WE NEED TO KEEP IN MIND KEYS ARE XORRED
|
||||
//xor the new key against the previously generated key so that we only update the difference
|
||||
if (index != 0) {
|
||||
generate_single_key_block_inverted(zero_key, index - 1, genkeyblock_old);
|
||||
for (int i = 0; i < 8 ; i++) {
|
||||
xorkeyblock[i] = genkeyblock[i] ^ genkeyblock_old[i];
|
||||
}
|
||||
} else {
|
||||
memcpy(xorkeyblock, genkeyblock, PICOPASS_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
//Step4 Calculate New Mac
|
||||
|
||||
bool use_mac = true;
|
||||
uint8_t wb[9] = {0};
|
||||
blockno = 3;
|
||||
wb[0] = blockno;
|
||||
memcpy(wb + 1, xorkeyblock, 8);
|
||||
doMAC_N(wb, sizeof(wb), div_key2, mac2);
|
||||
|
||||
//Step5 Perform Write
|
||||
|
||||
DbpString("Generated XOR Key: ");
|
||||
Dbhexdump(8, xorkeyblock, false);
|
||||
|
||||
if (iclass_writeblock_ext(blockno, xorkeyblock, mac2, use_mac, shallow_mod)) {
|
||||
Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), blockno, blockno);
|
||||
} else {
|
||||
Dbprintf("Write block [%3d/0x%02X] " _RED_("failed"), blockno, blockno);
|
||||
if (index > 1) {
|
||||
Dbprintf(_RED_("Card is likely to be unusable!"));
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
//Step6 Perform 8 authentication attempts
|
||||
|
||||
for (int i = 0; i < 8 ; ++i) {
|
||||
//need to craft the authentication payload accordingly
|
||||
memcpy(msg->req.key, iclass_mac_table[i], 8);
|
||||
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); //mac1 here shouldn't matter
|
||||
if (res == true) {
|
||||
bits_found = iclass_mac_table_bit_values[i] ^ index;
|
||||
Dbprintf("Found Card Bits Index: " _GREEN_("[%3d]"), index);
|
||||
Dbprintf("Mac Table Bit Values: " _GREEN_("[%3d]"), iclass_mac_table_bit_values[i]);
|
||||
Dbprintf("Decimal Value of Partial Key: " _GREEN_("[%3d]"), bits_found);
|
||||
goto restore;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}//end while
|
||||
|
||||
|
||||
restore:
|
||||
;//empty statement for compilation
|
||||
uint8_t partialkey[PICOPASS_BLOCK_SIZE];
|
||||
convertToHexArray(bits_found, partialkey);
|
||||
|
||||
uint8_t resetkey[PICOPASS_BLOCK_SIZE];
|
||||
convertToHexArray(index, resetkey);
|
||||
|
||||
//Calculate reset Mac
|
||||
|
||||
bool use_mac = true;
|
||||
uint8_t wb[9] = {0};
|
||||
blockno = 3;
|
||||
wb[0] = blockno;
|
||||
memcpy(wb + 1, resetkey, 8);
|
||||
doMAC_N(wb, sizeof(wb), div_key2, mac2);
|
||||
|
||||
//Write back the card to the original key
|
||||
DbpString(_YELLOW_("Restoring Card to the original key using Reset Key: "));
|
||||
Dbhexdump(8, resetkey, false);
|
||||
if (iclass_writeblock_ext(blockno, resetkey, mac2, use_mac, shallow_mod)) {
|
||||
Dbprintf("Restore of Original Key "_GREEN_("successful. Card is usable again."));
|
||||
} else {
|
||||
Dbprintf("Restore of Original Key " _RED_("failed. Card is likely unusable."));
|
||||
}
|
||||
//Print the 24 bits found from k1
|
||||
DbpString(_YELLOW_("Raw Key Partial Bytes: "));
|
||||
Dbhexdump(8, partialkey, false);
|
||||
switch_off();
|
||||
reply_ng(CMD_HF_ICLASS_RECOVER, PM3_SUCCESS, NULL, 0);
|
||||
|
||||
|
||||
out:
|
||||
|
||||
switch_off();
|
||||
reply_ng(CMD_HF_ICLASS_RECOVER, PM3_ESOFT, NULL, 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -70,4 +70,7 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, ui
|
||||
|
||||
uint8_t get_pagemap(const picopass_hdr_t *hdr);
|
||||
void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod);
|
||||
|
||||
void generate_single_key_block_inverted(const uint8_t *startingKey, uint32_t index, uint8_t *keyBlock);
|
||||
void iClass_Recover(iclass_recover_req_t *msg);
|
||||
#endif
|
||||
|
||||
+93
-73
@@ -186,7 +186,7 @@
|
||||
#endif
|
||||
|
||||
// 4sample
|
||||
#define SEND4STUFFBIT(x) tosend_stuffbit(x);tosend_stuffbit(x);tosend_stuffbit(x);tosend_stuffbit(x);
|
||||
#define SEND4STUFFBIT(x) tosend_stuffbit(!(x));tosend_stuffbit(!(x));tosend_stuffbit(!(x));tosend_stuffbit(!(x));
|
||||
|
||||
static void iso14b_set_timeout(uint32_t timeout_etu);
|
||||
static void iso14b_set_maxframesize(uint16_t size);
|
||||
@@ -702,10 +702,11 @@ static void TransmitFor14443b_AsTag(const uint8_t *response, uint16_t len) {
|
||||
// Signal field is off with the appropriate LED
|
||||
LED_D_OFF();
|
||||
|
||||
// TR0: min - 1024 cycles = 75.52 us - max 4096 cycles = 302.08 us
|
||||
SpinDelayUs(76);
|
||||
|
||||
// Modulate BPSK
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
|
||||
AT91C_BASE_SSC->SSC_THR = 0xFF;
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
|
||||
// Transmit the response.
|
||||
for (uint16_t i = 0; i < len;) {
|
||||
@@ -713,6 +714,11 @@ static void TransmitFor14443b_AsTag(const uint8_t *response, uint16_t len) {
|
||||
// Put byte into tx holding register as soon as it is ready
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
AT91C_BASE_SSC->SSC_THR = response[i++];
|
||||
|
||||
// Start-up SSC once first byte is in SSC_THR
|
||||
if (i == 1) {
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -771,7 +777,7 @@ void SimulateIso14443bTag(const uint8_t *pupi) {
|
||||
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
|
||||
|
||||
uint16_t len, cmdsReceived = 0;
|
||||
int cardSTATE = SIM_NOFIELD;
|
||||
int cardSTATE = SIM_POWER_OFF;
|
||||
int vHf = 0; // in mV
|
||||
|
||||
const tosend_t *ts = get_tosend();
|
||||
@@ -801,16 +807,18 @@ void SimulateIso14443bTag(const uint8_t *pupi) {
|
||||
}
|
||||
|
||||
// find reader field
|
||||
if (cardSTATE == SIM_NOFIELD) {
|
||||
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
if (cardSTATE == SIM_POWER_OFF) {
|
||||
cardSTATE = SIM_IDLE;
|
||||
LED_A_ON();
|
||||
}
|
||||
} else {
|
||||
cardSTATE = SIM_POWER_OFF;
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
if (cardSTATE == SIM_NOFIELD) {
|
||||
if (cardSTATE == SIM_POWER_OFF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -820,73 +828,85 @@ void SimulateIso14443bTag(const uint8_t *pupi) {
|
||||
break;
|
||||
}
|
||||
|
||||
// ISO14443-B protocol states:
|
||||
// REQ or WUP request in ANY state
|
||||
// WUP in HALTED state
|
||||
if (len == 5) {
|
||||
if (((receivedCmd[0] == ISO14443B_REQB) && ((receivedCmd[2] & 0x08) == 0x08) && (cardSTATE == SIM_HALTED)) ||
|
||||
(receivedCmd[0] == ISO14443B_REQB)) {
|
||||
LogTrace(receivedCmd, len, 0, 0, NULL, true);
|
||||
|
||||
LogTrace(receivedCmd, len, 0, 0, NULL, true);
|
||||
cardSTATE = SIM_SELECTING;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* How should this flow go?
|
||||
* REQB or WUPB
|
||||
* send response ( waiting for Attrib)
|
||||
* ATTRIB
|
||||
* send response ( waiting for commands 7816)
|
||||
* HALT
|
||||
send halt response ( waiting for wupb )
|
||||
*/
|
||||
|
||||
switch (cardSTATE) {
|
||||
//case SIM_NOFIELD:
|
||||
case SIM_HALTED:
|
||||
case SIM_IDLE: {
|
||||
LogTrace(receivedCmd, len, 0, 0, NULL, true);
|
||||
break;
|
||||
}
|
||||
case SIM_SELECTING: {
|
||||
TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
|
||||
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_WORK;
|
||||
break;
|
||||
}
|
||||
case SIM_HALTING: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_HALTED;
|
||||
break;
|
||||
}
|
||||
case SIM_ACKNOWLEDGE: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_IDLE;
|
||||
break;
|
||||
}
|
||||
case SIM_WORK: {
|
||||
if (len == 7 && receivedCmd[0] == ISO14443B_HALT) {
|
||||
cardSTATE = SIM_HALTED;
|
||||
} else if (len == 11 && receivedCmd[0] == ISO14443B_ATTRIB) {
|
||||
cardSTATE = SIM_ACKNOWLEDGE;
|
||||
} else {
|
||||
// Todo:
|
||||
// - SLOT MARKER
|
||||
// - ISO7816
|
||||
// - emulate with a memory dump
|
||||
if (g_dbglevel >= DBG_DEBUG) {
|
||||
Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived);
|
||||
}
|
||||
|
||||
cardSTATE = SIM_IDLE;
|
||||
if ((len == 5) && (receivedCmd[0] == ISO14443B_REQB) && (receivedCmd[2] & 0x08)) {
|
||||
// WUPB
|
||||
switch (cardSTATE) {
|
||||
case SIM_IDLE:
|
||||
case SIM_READY:
|
||||
case SIM_HALT: {
|
||||
TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
|
||||
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_READY;
|
||||
break;
|
||||
}
|
||||
case SIM_ACTIVE:
|
||||
default: {
|
||||
TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
|
||||
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
} else if ((len == 5) && (receivedCmd[0] == ISO14443B_REQB) && !(receivedCmd[2] & 0x08)) {
|
||||
// REQB
|
||||
switch (cardSTATE) {
|
||||
case SIM_IDLE:
|
||||
case SIM_READY: {
|
||||
TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
|
||||
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_READY;
|
||||
break;
|
||||
}
|
||||
case SIM_ACTIVE: {
|
||||
TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
|
||||
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
|
||||
break;
|
||||
}
|
||||
case SIM_HALT:
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((len == 7) && (receivedCmd[0] == ISO14443B_HALT)) {
|
||||
// HLTB
|
||||
switch (cardSTATE) {
|
||||
case SIM_READY: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_HALT;
|
||||
break;
|
||||
}
|
||||
case SIM_IDLE:
|
||||
case SIM_ACTIVE: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
break;
|
||||
}
|
||||
case SIM_HALT:
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (len == 11 && receivedCmd[0] == ISO14443B_ATTRIB) {
|
||||
// ATTRIB
|
||||
switch (cardSTATE) {
|
||||
case SIM_READY: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
cardSTATE = SIM_ACTIVE;
|
||||
break;
|
||||
}
|
||||
case SIM_IDLE:
|
||||
case SIM_ACTIVE: {
|
||||
TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
|
||||
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
|
||||
break;
|
||||
}
|
||||
case SIM_HALT:
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -49,12 +49,10 @@ void SniffIso14443b(void);
|
||||
void SendRawCommand14443B(iso14b_raw_cmd_t *p);
|
||||
|
||||
// States for 14B SIM command
|
||||
#define SIM_NOFIELD 0
|
||||
#define SIM_POWER_OFF 0
|
||||
#define SIM_IDLE 1
|
||||
#define SIM_HALTED 2
|
||||
#define SIM_SELECTING 3
|
||||
#define SIM_HALTING 4
|
||||
#define SIM_ACKNOWLEDGE 5
|
||||
#define SIM_WORK 6
|
||||
#define SIM_READY 2
|
||||
#define SIM_HALT 3
|
||||
#define SIM_ACTIVE 4
|
||||
|
||||
#endif /* __ISO14443B_H */
|
||||
|
||||
+23
-9
@@ -134,10 +134,11 @@ void initSampleBuffer(uint32_t *sample_size) {
|
||||
}
|
||||
|
||||
void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) {
|
||||
|
||||
if (sample_size == NULL) {
|
||||
Dbprintf("initSampleBufferEx, param NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
BigBuf_free_keep_EM();
|
||||
|
||||
// We can't erase the buffer now, it would drastically delay the acquisition
|
||||
@@ -181,14 +182,26 @@ void logSampleSimple(uint8_t sample) {
|
||||
|
||||
void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) {
|
||||
|
||||
if (!data.buffer) return;
|
||||
if (!data.buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// keep track of total gather samples regardless how many was discarded.
|
||||
if (samples.counter-- == 0) return;
|
||||
if (samples.counter-- == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bits_per_sample == 0) bits_per_sample = 1;
|
||||
if (bits_per_sample > 8) bits_per_sample = 8;
|
||||
if (decimation == 0) decimation = 1;
|
||||
if (bits_per_sample == 0) {
|
||||
bits_per_sample = 1;
|
||||
}
|
||||
|
||||
if (bits_per_sample > 8) {
|
||||
bits_per_sample = 8;
|
||||
}
|
||||
|
||||
if (decimation == 0) {
|
||||
decimation = 1;
|
||||
}
|
||||
|
||||
if (avg) {
|
||||
samples.sum += sample;
|
||||
@@ -198,7 +211,9 @@ void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool
|
||||
if (decimation > 1) {
|
||||
samples.dec_counter++;
|
||||
|
||||
if (samples.dec_counter < decimation) return;
|
||||
if (samples.dec_counter < decimation) {
|
||||
return;
|
||||
}
|
||||
|
||||
samples.dec_counter = 0;
|
||||
}
|
||||
@@ -538,11 +553,10 @@ int ReadLF_realtime(bool reader_field) {
|
||||
|
||||
return_value = async_usb_write_stop();
|
||||
|
||||
out:
|
||||
out:
|
||||
LED_D_OFF();
|
||||
|
||||
// DoAcquisition() end
|
||||
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return return_value;
|
||||
|
||||
+13
-5
@@ -639,24 +639,32 @@ void rdv40_spiffs_safe_print_tree(void) {
|
||||
struct spiffs_dirent e;
|
||||
struct spiffs_dirent *pe = &e;
|
||||
|
||||
char *resolvedlink = (char *)BigBuf_calloc(11 + SPIFFS_OBJ_NAME_LEN);
|
||||
char *linkdest = (char *)BigBuf_calloc(SPIFFS_OBJ_NAME_LEN);
|
||||
bool printed = false;
|
||||
|
||||
SPIFFS_opendir(&fs, "/", &d);
|
||||
while ((pe = SPIFFS_readdir(&d, pe))) {
|
||||
|
||||
char resolvedlink[11 + SPIFFS_OBJ_NAME_LEN];
|
||||
memset(resolvedlink, 0, 11 + SPIFFS_OBJ_NAME_LEN);
|
||||
|
||||
if (rdv40_spiffs_is_symlink((const char *)pe->name)) {
|
||||
char linkdest[SPIFFS_OBJ_NAME_LEN];
|
||||
|
||||
read_from_spiffs((char *)pe->name, (uint8_t *)linkdest, SPIFFS_OBJ_NAME_LEN);
|
||||
sprintf(resolvedlink, "(.lnk) --> %s", linkdest);
|
||||
// Kind of stripping the .lnk extension
|
||||
strtok((char *)pe->name, ".");
|
||||
} else {
|
||||
memset(resolvedlink, 0, sizeof(resolvedlink));
|
||||
}
|
||||
|
||||
Dbprintf("[%04x]\t " _YELLOW_("%i") " B |-- %s%s", pe->obj_id, pe->size, pe->name, resolvedlink);
|
||||
Dbprintf("[%04x] " _YELLOW_("%5i") " B |-- %s%s", pe->obj_id, pe->size, pe->name, resolvedlink);
|
||||
printed = true;
|
||||
}
|
||||
if (printed == false) {
|
||||
DbpString("<empty>");
|
||||
}
|
||||
SPIFFS_closedir(&d);
|
||||
rdv40_spiffs_lazy_mount_rollback(changed);
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
void rdv40_spiffs_safe_wipe(void) {
|
||||
|
||||
@@ -395,3 +395,23 @@ uint32_t flash_size_from_cidr(uint32_t cidr) {
|
||||
uint32_t get_flash_size(void) {
|
||||
return flash_size_from_cidr(*AT91C_DBGU_CIDR);
|
||||
}
|
||||
|
||||
// Combined function to convert an unsigned int to an array of hex values corresponding to the last three bits of k1
|
||||
void convertToHexArray(uint8_t num, uint8_t *partialkey) {
|
||||
char binaryStr[25]; // 24 bits for binary representation + 1 for null terminator
|
||||
binaryStr[24] = '\0'; // Null-terminate the string
|
||||
|
||||
// Convert the number to binary string
|
||||
for (int i = 23; i >= 0; i--) {
|
||||
binaryStr[i] = (num % 2) ? '1' : '0';
|
||||
num /= 2;
|
||||
}
|
||||
|
||||
// Split the binary string into groups of 3 and convert to hex
|
||||
for (int i = 0; i < 8 ; i++) {
|
||||
char group[4];
|
||||
strncpy(group, binaryStr + i * 3, 3);
|
||||
group[3] = '\0'; // Null-terminate the group string
|
||||
partialkey[i] = (uint8_t)strtoul(group, NULL, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,8 @@ int hex2binarray(char *target, char *source);
|
||||
int hex2binarray_n(char *target, const char *source, int sourcelen);
|
||||
int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex);
|
||||
|
||||
void convertToHexArray(uint8_t num, uint8_t *partialKey);
|
||||
|
||||
void LED(int led, int ms);
|
||||
void LEDsoff(void);
|
||||
void SpinOff(uint32_t pause);
|
||||
|
||||
@@ -307,7 +307,7 @@ E3429281EFC1
|
||||
# EPI Envisionte
|
||||
AAFB06045877
|
||||
#
|
||||
# gym
|
||||
# Gyms / Fitness Clubs / Health Clubs / Wellness Centres
|
||||
#
|
||||
# Fysiken A
|
||||
3E65E4FB65B3
|
||||
@@ -318,8 +318,8 @@ AAFB06045877
|
||||
#
|
||||
# https://mattionline.de/fitnessstudio-armband-reverse-engineering/
|
||||
# https://mattionline.de/milazycracker/
|
||||
# gym wistband A, same as Fysiken A
|
||||
# gym wistband B
|
||||
# Gym Wristband A - Same as Fysiken A
|
||||
# Gym Wristband B
|
||||
81CC25EBBB6A
|
||||
195DC63DB3A3
|
||||
#
|
||||
@@ -330,9 +330,13 @@ A05DBD98E0FC
|
||||
AA4DDA458EBB
|
||||
EAB8066C7479
|
||||
#
|
||||
# Nordic Wellness A, same as Fysiken A
|
||||
# Nordic Wellness A - Same as Fysiken A
|
||||
# Nordic Wellness B
|
||||
E5519E1CC92B
|
||||
#
|
||||
# Jett's 24 Hour Fitness S0 KA/B
|
||||
# 049979614077
|
||||
# 829338771705
|
||||
#
|
||||
# Hotel KeyCard
|
||||
D3B595E9DD63
|
||||
@@ -1110,6 +1114,14 @@ EA0FD73CB149
|
||||
FC0001877BF7
|
||||
FD8705E721B0
|
||||
00ADA2CD516D
|
||||
518108E061E2
|
||||
558AAD64EB5B
|
||||
001122334455
|
||||
6CA761AB6CA7
|
||||
B1C4A8F7F6E3
|
||||
FF75AFDA5A3C
|
||||
FCDDF7767C10
|
||||
A6B3F6C8F1D4
|
||||
#
|
||||
#
|
||||
237A4D0D9119
|
||||
@@ -2193,6 +2205,13 @@ C8382A233993
|
||||
7B304F2A12A6
|
||||
FC9418BF788B
|
||||
#
|
||||
# Guest Cashless Prepaid Arcade Payment Cards
|
||||
168168168168
|
||||
198407157610
|
||||
4E4F584D2101
|
||||
4E4F584D2105
|
||||
686B35333376
|
||||
861861861861
|
||||
# Data from "the more the marriott" mifare project (colonelborkmundus)
|
||||
# aka The Horde
|
||||
#
|
||||
@@ -2345,9 +2364,8 @@ EA0CA627FD06
|
||||
# Hotel key
|
||||
CE0F4F15E909
|
||||
D60DE9436219
|
||||
|
||||
#
|
||||
# ATM Area de Girona, spanish transport card
|
||||
|
||||
A01000000000
|
||||
A02000000000
|
||||
A03000000000
|
||||
@@ -2363,7 +2381,6 @@ A12000000000
|
||||
A13000000000
|
||||
A14000000000
|
||||
A15000000000
|
||||
|
||||
B01000000000
|
||||
B02000000000
|
||||
B03000000000
|
||||
@@ -2379,7 +2396,7 @@ B12000000000
|
||||
B13000000000
|
||||
B14000000000
|
||||
B15000000000
|
||||
|
||||
#
|
||||
# Pittsburgh, PA, USA - Pittsburgh Regional Transit ConnectCard
|
||||
A7AE4A5A33DC
|
||||
6B857B568C10
|
||||
@@ -2413,7 +2430,100 @@ CE8BFF3728EE
|
||||
09938D05DA78
|
||||
EACDA4DBE420
|
||||
EC2B9FD483CA
|
||||
|
||||
#
|
||||
# Hotel Intelier Orange - Benicasim, Spain
|
||||
# block 1 - key A
|
||||
04256CFE0425
|
||||
#
|
||||
# InsideWash Membership Card - Portugal
|
||||
C18063858BB9
|
||||
#
|
||||
# An apartment building in Sydney Olympic Park
|
||||
13254608D0AB
|
||||
24A2971BC0B2
|
||||
14264709D1AC
|
||||
25A3981CC1B3
|
||||
1527480AD2AD
|
||||
26A4991DC2B4
|
||||
1628490BD3AE
|
||||
27A59A1EC3B5
|
||||
17294A0CD4AF
|
||||
28A69B1FC4B6
|
||||
182A4B0DD5B0
|
||||
29A79C20C5B7
|
||||
192B4C0ED6B1
|
||||
2AA89D21C6B8
|
||||
1A2C4D0FD7B2
|
||||
2BA99E22C7B9
|
||||
1B2D4E10D8B3
|
||||
2CAA9F23C8BA
|
||||
1C2E4F11D9B4
|
||||
2DABA024C9BB
|
||||
1D2F5012DAB5
|
||||
2EACA125CABC
|
||||
1E305113DBB6
|
||||
2FADA226CBBD
|
||||
1F315214DCB7
|
||||
30AEA327CCBE
|
||||
20325315DDB8
|
||||
31AFA428CDBF
|
||||
21335416DEB9
|
||||
32B0A529CEC0
|
||||
22345517DFBA
|
||||
33B1A62ACFC1
|
||||
#
|
||||
# Universidade de São Paulo (USP) student card
|
||||
17B50E38F1B0
|
||||
24E311F594CE
|
||||
3794FBFB1A54
|
||||
43B229069F6A
|
||||
4531952F765F
|
||||
4943F2F35E0A
|
||||
4985E681EF88
|
||||
4F56C88E0337
|
||||
710070E92C79
|
||||
8A036C5C35D4
|
||||
A027BD830A06
|
||||
D33673C19243
|
||||
D89A506542F2
|
||||
E5813CD228F1
|
||||
FAB943906E9C
|
||||
#
|
||||
# R.A.T.T transport card key A/B
|
||||
AA034F342A55
|
||||
456776908C48
|
||||
|
||||
# BusFacil - Brazilian public transport card for some cities
|
||||
7b296f353c6b
|
||||
3fa7217ec575
|
||||
fae9b14365a9
|
||||
c567dd4a6004
|
||||
c567dd4a6005
|
||||
c567dd4a6006
|
||||
c567dd4a6007
|
||||
c567dd4a6008
|
||||
c567dd4a6009
|
||||
c567dd4a600a
|
||||
c567dd4a600d
|
||||
c567dd4a600e
|
||||
c567dd4a600f
|
||||
5ef014ec5d7f
|
||||
5086052022ac
|
||||
bd6af9754c18
|
||||
5d67d4732a7d
|
||||
17fe45604a04
|
||||
17fe45604a05
|
||||
17fe45604a06
|
||||
17fe45604a07
|
||||
17fe45604a08
|
||||
17fe45604a09
|
||||
17fe45604a0a
|
||||
17fe45604a0d
|
||||
17fe45604a0e
|
||||
17fe45604a0f
|
||||
# keys for swimming pool cards in Reykjavík Iceland
|
||||
28220F14BEF0
|
||||
# key for Orkan keyfobs
|
||||
300724070486
|
||||
# key for Atlantsolía keyfobs
|
||||
60FCB3C42ABF
|
||||
|
||||
@@ -3,4 +3,8 @@
|
||||
# -- iceman fork version --
|
||||
# -- contribute to this list, sharing is caring --
|
||||
#
|
||||
425245414B4D454946594F5543414E21 # Sample Key (BREAKMEIFYOUCAN!)
|
||||
12E4143455F495649454D4B414542524 # ( 4U d T T%$) Hexadecimal-Reversed Sample Key
|
||||
214E4143554F594649454D4B41455242 # (!NACUOYFIEMKAERB) Byte-Reversed Sample Key
|
||||
425245414B4D454946594F5543414E21 # (BREAKMEIFYOUCAN!) Sample Key
|
||||
49454D4B41455242214E4143554F5900 # (IEMKAERB!NACUOY ) Semnox Key
|
||||
49454D4B41455242214E4143554F5946 # (IEMKAERB!NACUOYF) Modified Semnox Key
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
51243648
|
||||
000D8787
|
||||
19920427
|
||||
# White Chinese cloner, circa 2019, firmware v5.04.16.0727 (eBay)
|
||||
002BCFCF
|
||||
# ZX-copy3 T55xx / EM4305
|
||||
# ref. http://www.proxmark.org/forum/viewtopic.php?pid=40662#p40662
|
||||
# default PROX
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user