Merge remote-tracking branch 'remotes/origin/master' into standalone-mfc-rewrite

This commit is contained in:
Michael Roland
2024-07-25 12:50:34 +02:00
59 changed files with 3683 additions and 1083 deletions
+22
View File
@@ -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)
+19 -9
View File
@@ -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;
}
}
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+20
View File
@@ -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);
}
}
+2
View File
@@ -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);
+119 -9
View File
@@ -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
+5 -1
View File
@@ -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