mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 18:48:13 -07:00
WIP - hitag sniff, eload, sim
This commit is contained in:
parent
48012061a6
commit
d012a879f2
3 changed files with 318 additions and 66 deletions
364
armsrc/hitag2.c
364
armsrc/hitag2.c
|
@ -106,15 +106,13 @@ static int16_t blocknr;
|
|||
static size_t flipped_bit = 0;
|
||||
static uint32_t byte_value = 0;
|
||||
|
||||
static int hitag2_reset(void) {
|
||||
static void hitag2_reset(void) {
|
||||
tag.state = TAG_STATE_RESET;
|
||||
tag.crypto_active = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hitag2_init(void) {
|
||||
static void hitag2_init(void) {
|
||||
hitag2_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||
|
@ -126,14 +124,14 @@ static int hitag2_init(void) {
|
|||
#endif
|
||||
|
||||
#define HITAG_FRAME_LEN 20
|
||||
#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
|
||||
#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
|
||||
#define HITAG_T_STOP 37 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_LOW 4 /* T_LOW should be 4..10 */
|
||||
#define HITAG_T_0_MIN 17 /* 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 */
|
||||
#define HITAG_T_1 30 /* T[1] should be 26..30 */
|
||||
//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_EOF 80 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_WAIT_1_MIN 199 /* T_wresp should be 199..206 */
|
||||
#define HITAG_T_WAIT_2_MIN 90 /* T_wait2 should be at least 90 */
|
||||
#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
|
||||
|
@ -987,84 +985,330 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
|
|||
return true;
|
||||
}
|
||||
|
||||
void EloadHitag(uint8_t *data, uint16_t len) {
|
||||
memcpy(tag.sectors, data, sizeof(tag.sectors));
|
||||
}
|
||||
|
||||
// Hitag2 Sniffing
|
||||
|
||||
// T0 18-22 fc (total time ZERO)
|
||||
// T1 26-32 fc (total time ONE)
|
||||
// Tstop 36 > fc (high field stop limit)
|
||||
// Tlow 4-10 fc (reader field low time)
|
||||
void SniffHitag2(void) {
|
||||
DbpString("Starting Hitag2 sniffing");
|
||||
LED_D_ON();
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
auth_table_len = 0;
|
||||
auth_table_pos = 0;
|
||||
|
||||
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
|
||||
DbpString("Starting Hitag2 sniffing");
|
||||
LED_D_ON();
|
||||
|
||||
/*
|
||||
lf_init(false, false);
|
||||
|
||||
g_logging = false;
|
||||
// no logging of the raw signal
|
||||
g_logging = lf_get_reader_modulation();
|
||||
uint32_t total_count = 0;
|
||||
|
||||
uint8_t periods_bytes[4];
|
||||
|
||||
// int16_t checked = 0;
|
||||
|
||||
/*bool waiting_for_first_edge = true;*/
|
||||
LED_C_ON();
|
||||
|
||||
uint32_t signal_size = 10000;
|
||||
uint8_t rx[20 * 8 * 2];
|
||||
while (BUTTON_PRESS() == false) {
|
||||
|
||||
// use malloc
|
||||
initSampleBufferEx(&signal_size, false);
|
||||
lf_reset_counter();
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
/*
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 1000) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
*/
|
||||
size_t periods = 0;
|
||||
uint16_t rxlen = 0;
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
|
||||
// Use the current modulation state as starting point
|
||||
uint8_t mod_state = lf_get_reader_modulation();
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
// lf_reset_counter();
|
||||
|
||||
// Wait "infinite" for reader modulation
|
||||
size_t periods = lf_detect_gap(10000);
|
||||
|
||||
// Test if we detected the first reader modulation edge
|
||||
if (periods != 0) {
|
||||
if (g_logging == false) {
|
||||
g_logging = true;
|
||||
LED_D_ON();
|
||||
while (rxlen < sizeof(rx)) {
|
||||
periods = lf_count_edge_periods(64);
|
||||
// Evaluate the number of periods before the next edge
|
||||
if (periods >= 24 && periods < 64) {
|
||||
// Detected two sequential equal bits and a modulation switch
|
||||
// NRZ modulation: (11 => --|) or (11 __|)
|
||||
rx[rxlen++] = mod_state;
|
||||
rx[rxlen++] = mod_state;
|
||||
// toggle tag modulation state
|
||||
mod_state ^= 1;
|
||||
} else if (periods > 0 && periods < 24) {
|
||||
// Detected one bit and a modulation switch
|
||||
// NRZ modulation: (1 => -|) or (0 _|)
|
||||
rx[rxlen++] = mod_state;
|
||||
mod_state ^= 1;
|
||||
} else {
|
||||
mod_state ^= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rxlen == 0)
|
||||
continue;
|
||||
|
||||
/*lf_count_edge_periods(10000);*/
|
||||
while ((periods = lf_detect_gap(64)) != 0) {
|
||||
num_to_bytes(periods, 4, periods_bytes);
|
||||
LogTrace(periods_bytes, 4, 0, 0, NULL, true);
|
||||
// tag sends 11111 + uid,
|
||||
bool got_tag = ((memcmp(rx, "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00", 10) == 0));
|
||||
|
||||
if (got_tag) {
|
||||
// mqnchester decode
|
||||
bool bad_man = false;
|
||||
uint16_t bitnum = 0;
|
||||
for (uint16_t i = 0; i < rxlen; i += 2) {
|
||||
if (rx[i] == 1 && (rx[i + 1] == 0)) {
|
||||
rx[bitnum++] = 0;
|
||||
} else if ((rx[i] == 0) && rx[i + 1] == 1) {
|
||||
rx[bitnum++] = 1;
|
||||
} else {
|
||||
bad_man = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bad_man) {
|
||||
DBG DbpString("bad manchester");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bitnum < 5) {
|
||||
DBG DbpString("too few bits");
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip header 11111
|
||||
uint16_t i = 0;
|
||||
if (got_tag) {
|
||||
i = 5;
|
||||
}
|
||||
|
||||
// Pack the response into a byte array
|
||||
rxlen = 0;
|
||||
for (; i < bitnum; i++) {
|
||||
uint8_t b = rx[i];
|
||||
rx[rxlen >> 3] |= b << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
|
||||
// skip spurious bit
|
||||
if (rxlen % 8 == 1) {
|
||||
rxlen--;
|
||||
}
|
||||
|
||||
// nothing to log
|
||||
if (rxlen == 0)
|
||||
continue;
|
||||
|
||||
LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
|
||||
total_count += nbytes(rxlen);
|
||||
} else {
|
||||
// decode reader comms
|
||||
LogTrace(rx, rxlen, 0, 0, NULL, true);
|
||||
total_count += rxlen;
|
||||
// Pack the response into a byte array
|
||||
|
||||
// LogTrace(rx, nbytes(rdr), 0, 0, NULL, true);
|
||||
// total_count += nbytes(rdr);
|
||||
}
|
||||
LED_A_INV();
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
|
||||
DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations");
|
||||
Dbprintf("Collected %u bytes", total_count);
|
||||
|
||||
*/
|
||||
|
||||
// Set up eavesdropping mode, frequency divisor which will drive the FPGA
|
||||
// and analog mux selection.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); // 125Khz
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
RELAY_OFF();
|
||||
|
||||
// Configure output pin that is connected to the FPGA (for modulating)
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
|
||||
// Disable modulation, we are going to eavesdrop, not modulate ;)
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
||||
// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
|
||||
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
|
||||
|
||||
// Disable timer during configuration
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
||||
// external trigger rising edge, load RA on rising edge of TIOA.
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH;
|
||||
|
||||
// Enable and reset counter
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
int frame_count = 0, response = 0, overflow = 0, lastbit = 1, tag_sof = 4;
|
||||
bool rising_edge = false, reader_frame = false, bSkip = true;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
|
||||
auth_table_len = 0;
|
||||
auth_table_pos = 0;
|
||||
|
||||
// Reset the received frame, frame count and timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
|
||||
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
|
||||
while(BUTTON_PRESS() == false) {
|
||||
|
||||
WDT_HIT();
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
|
||||
// Receive frame, watch for at most T0 * EOF periods
|
||||
while (AT91C_BASE_TC1->TC_CV < (HITAG_T0 * HITAG_T_EOF) ) {
|
||||
// Check if rising edge in modulation is detected
|
||||
if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
|
||||
// Retrieve the new timing values
|
||||
int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0);
|
||||
|
||||
// Find out if we are dealing with a rising or falling edge
|
||||
rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0;
|
||||
|
||||
// Shorter periods will only happen with reader frames
|
||||
if (reader_frame == false && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) {
|
||||
// Switch from tag to reader capture
|
||||
LED_C_OFF();
|
||||
reader_frame = true;
|
||||
rxlen = 0;
|
||||
}
|
||||
|
||||
// Only handle if reader frame and rising edge, or tag frame and falling edge
|
||||
if (reader_frame == rising_edge) {
|
||||
overflow += ra;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the buffered timing values of earlier captured edges which were skipped
|
||||
ra += overflow;
|
||||
overflow = 0;
|
||||
|
||||
if (reader_frame) {
|
||||
LED_B_ON();
|
||||
// Capture reader frame
|
||||
if(ra >= HITAG_T_STOP) {
|
||||
// if (rxlen != 0) {
|
||||
//DbpString("wierd0?");
|
||||
// }
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
response = (ra - HITAG_T_LOW);
|
||||
} else if(ra >= HITAG_T_1_MIN ) {
|
||||
// '1' bit
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
} else if(ra >= HITAG_T_0_MIN) {
|
||||
// '0' bit
|
||||
rx[rxlen / 8] |= 0 << (7-(rxlen%8));
|
||||
rxlen++;
|
||||
}
|
||||
|
||||
} else {
|
||||
LED_C_ON();
|
||||
// Capture tag frame (manchester decoding using only falling edges)
|
||||
if(ra >= HITAG_T_EOF) {
|
||||
// if (rxlen != 0) {
|
||||
//DbpString("wierd1?");
|
||||
// }
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
|
||||
response = ra - HITAG_T_TAG_HALF_PERIOD;
|
||||
|
||||
} else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
|
||||
// Manchester coding example |-_|_-|-_| (101)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
|
||||
} else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
|
||||
// Manchester coding example |_-|...|_-|-_| (0...01)
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
// We have to skip this half period at start and add the 'one' the second time
|
||||
if (bSkip == false) {
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
lastbit = !lastbit;
|
||||
bSkip = !bSkip;
|
||||
|
||||
} else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
|
||||
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
|
||||
if (tag_sof) {
|
||||
// Ignore bits that are transmitted during SOF
|
||||
tag_sof--;
|
||||
} else {
|
||||
// bit is same as last bit
|
||||
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if frame was captured
|
||||
if(rxlen) {
|
||||
frame_count++;
|
||||
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
|
||||
|
||||
// Check if we recognize a valid authentication attempt
|
||||
if (nbytes(rxlen) == 8) {
|
||||
// Store the authentication attempt
|
||||
if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) {
|
||||
memcpy(auth_table + auth_table_len, rx, 8);
|
||||
auth_table_len += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the received frame and response timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
response = 0;
|
||||
reader_frame = false;
|
||||
lastbit = 1;
|
||||
bSkip = true;
|
||||
tag_sof = 4;
|
||||
overflow = 0;
|
||||
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
} else {
|
||||
// Save the timer overflow, will be 0 when frame was received
|
||||
overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0);
|
||||
}
|
||||
// Reset the frame length
|
||||
rxlen = 0;
|
||||
// Reset the timer to restart while-loop that receives frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
}
|
||||
|
||||
LEDsoff();
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
|
||||
Dbprintf("frame received: %d",frame_count);
|
||||
Dbprintf("Authentication Attempts: %d",(auth_table_len / 8));
|
||||
|
||||
}
|
||||
|
||||
// Hitag2 simulation
|
||||
void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
||||
void SimulateHitag2() {
|
||||
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
|
@ -1092,12 +1336,6 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
|||
// hitag2 state machine?
|
||||
hitag2_init();
|
||||
|
||||
// copy user supplied emulation data
|
||||
if (tag_mem_supplied) {
|
||||
DbpString("Loading hitag2 memory...");
|
||||
memcpy((uint8_t *)tag.sectors, data, 48);
|
||||
}
|
||||
|
||||
// printing
|
||||
uint32_t block = 0;
|
||||
for (size_t i = 0; i < 12; i++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue