Add partial byte annotation in Hitag traces

Example:
[usb] pm3 --> trace load -f traces/lf_HitagS256_dump.trace
[+] loaded 287 bytes from binary file traces/lf_HitagS256_dump.trace
[+] Recorded Activity (TraceLen = 287 bytes)
[?] try `trace list -1 -t ...` to view trace.  Remember the `-1` param
[usb] pm3 --> trace list -1 -t hitags -c
[+] Recorded activity (trace len = 287 bytes)
[=] start = start of start frame end = end of frame. src = source of transfer
[=] Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)

      Start |        End | Src | Data (! denotes parity error)
------------+------------+-----+-----------------------------------------
          0 |          0 | Rdr |18(5)
        117 |        117 | Tag |0f(4) 2c  ab  cc  b3  cf  32  bf [2f]
          0 |          0 | Rdr |00(5) 21  a5  b4  73 [8c]
        117 |        117 | Tag |0f(4) c9  00  00  aa [75]
          0 |          0 | Rdr |0c(4) 00 [ab]
        117 |        117 | Tag |0f(4) 21  a5  b4  73 [53]
          0 |          0 | Rdr |0c(4) 01 [b6]
        117 |        117 | Tag |0f(4) c9  00  00  aa [75]
          0 |          0 | Rdr |0c(4) 02 [91]
        117 |        117 | Tag |0f(4) 48  54  4f  4e [2c]
          0 |          0 | Rdr |0c(4) 03 [8c]
        117 |        117 | Tag |0f(4) 4d  49  4b  52 [1e]
          0 |          0 | Rdr |0c(4) 04 [df]
        117 |        117 | Tag |0f(4) 00  00  00  00 [a6]
          0 |          0 | Rdr |0c(4) 05 [c2]
        117 |        117 | Tag |0f(4) 00  00  00  00 [a6]
          0 |          0 | Rdr |0c(4) 06 [e5]
        117 |        117 | Tag |0f(4) 00  00  00  00 [a6]
          0 |          0 | Rdr |0c(4) 07 [f8]
        117 |        117 | Tag |0f(4) 57  5f  4f  4b [88]
          0 |          0 | Rdr |0c(4) 08 [43]
This commit is contained in:
Philippe Teuwen 2021-12-29 23:40:18 +01:00
commit 323f70ff7a
6 changed files with 57 additions and 23 deletions

View file

@ -13,6 +13,7 @@
#include "string.h"
#include "dbprint.h"
#include "pm3_cmd.h"
#include "util.h" // nbytes
extern uint32_t _stack_start[], __bss_end__[];
@ -289,6 +290,13 @@ bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, ui
return LogTrace(bytes, len, ts_start, ts_end, parity, reader2tag);
}
// specific LogTrace function for bitstreams: the partial byte size is stored in first parity byte. E.g. bitstream "1100 00100010" -> partial byte: 4 bits
bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t timestamp_start, uint32_t timestamp_end, bool readerToTag) {
uint8_t parity[(nbytes(bitLen) - 1) / 8 + 1];
memset(parity, 0x00, sizeof(parity));
parity[0] = ((bitLen - 1) % 8) + 1;
return LogTrace(btBytes, nbytes(bitLen), timestamp_start, timestamp_end, parity, readerToTag);
}
// Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) {

View file

@ -45,6 +45,7 @@ void set_tracelen(uint32_t value);
bool get_tracing(void);
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t timestamp_start, uint32_t timestamp_end, bool readerToTag);
bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, uint8_t *parity, bool reader2tag);
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);

View file

@ -314,8 +314,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
break;
}
// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
// LogTraceBits(rx, rxlen, 0, 0, false);
// LogTraceBits(tx, txlen, 0, 0, true);
if (tag.crypto_active) {
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
@ -1100,7 +1100,7 @@ void SniffHitag2(bool ledcontrol) {
if (rxlen == 0)
continue;
LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
LogTraceBits(rx, rxlen, 0, 0, false);
total_count += nbytes(rxlen);
} else {
// decode reader comms
@ -1108,7 +1108,7 @@ void SniffHitag2(bool ledcontrol) {
total_count += rxlen;
// Pack the response into a byte array
// LogTrace(rx, nbytes(rdr), 0, 0, NULL, true);
// LogTraceBits(rx, rdr, 0, 0, true);
// total_count += nbytes(rdr);
}
if (ledcontrol) LED_A_INV();
@ -1265,7 +1265,7 @@ void SniffHitag2(bool ledcontrol) {
// Check if frame was captured
if (rxlen) {
frame_count++;
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
LogTraceBits(rx, rxlen, response, 0, reader_frame);
// Check if we recognize a valid authentication attempt
if (nbytes(rxlen) == 8) {
@ -1495,7 +1495,7 @@ void SimulateHitag2(bool ledcontrol) {
// Check if frame was captured
if (rxlen > 4) {
LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
LogTraceBits(rx, rxlen, response, response, true);
// Process the incoming frame (rx) and prepare the outgoing frame (tx)
hitag2_handle_reader_command(rx, rxlen, tx, &txlen);
@ -1514,7 +1514,7 @@ void SimulateHitag2(bool ledcontrol) {
lf_manchester_send_bytes(tx, txlen, ledcontrol);
// Store the frame in the trace
LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
LogTraceBits(tx, txlen, 0, 0, false);
}
// Reset the received frame and response timing info
@ -1844,7 +1844,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd, bool ledcontrol) {
// and to be able to overwrite the first samples with the trace (since they currently
// still use the same memory space)
if (txlen > 0) {
LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true);
LogTraceBits(tx, txlen, command_start, command_start + command_duration, true);
}
// Reset values for receiving frames
@ -1904,7 +1904,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd, bool ledcontrol) {
// Check if frame was captured and store it
if (rxlen > 0) {
LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false);
LogTraceBits(rx, rxlen, response_start, response_start + response_duration, false);
// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag reader --23 -k 4F4E4D494B52
// Use delta time?
@ -2167,7 +2167,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page, bool ledcontrol)
// and to be able to overwrite the first samples with the trace (since they currently
// still use the same memory space)
if (txlen > 0) {
LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true);
LogTraceBits(tx, txlen, command_start, command_start + command_duration, true);
}
// Reset values for receiving frames
@ -2225,7 +2225,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page, bool ledcontrol)
// Check if frame was captured and store it
if (rxlen > 0) {
LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false);
LogTraceBits(rx, rxlen, response_start, response_start + response_duration, false);
command_start = 0;
}
}

View file

@ -1036,7 +1036,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) {
// Check if frame was captured
if (rxlen > 0) {
// frame_count++;
LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
LogTraceBits(rx, rxlen, response, response, true);
// Disable timer 1 with external trigger to avoid triggers during our own modulation
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
@ -1055,7 +1055,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) {
if (txlen > 0) {
// Transmit the tag frame
hitag_send_frame(tx, txlen, ledcontrol);
LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
LogTraceBits(tx, txlen, 0, 0, false);
}
// Enable and reset external trigger in timer for capturing future frames
@ -1278,7 +1278,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) {
// Check if frame was captured and store it
if (rxlen > 0) {
// frame_count++;
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
LogTraceBits(rx, rxlen, response, response, false);
}
// By default reset the transmission buffer
@ -1407,7 +1407,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) {
// Add transmitted frame to total count
if (txlen > 0) {
// frame_count++;
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
LogTraceBits(tx, txlen, HITAG_T_WAIT_2, HITAG_T_WAIT_2, true);
}
hitagS_receive_frame(rx, &rxlen, &response, ledcontrol);
@ -1535,7 +1535,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcont
// Check if frame was captured and store it
if (rxlen > 0) {
// frame_count++;
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
LogTraceBits(rx, rxlen, response, response, false);
}
//check for valid input
@ -1622,7 +1622,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcont
// Add transmitted frame to total count
if (txlen > 0) {
// frame_count++;
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
LogTraceBits(tx, txlen, HITAG_T_WAIT_2, HITAG_T_WAIT_2, true);
}
hitagS_receive_frame(rx, &rxlen, &response, ledcontrol);
@ -1729,7 +1729,7 @@ void check_challenges(bool file_given, uint8_t *data, bool ledcontrol) {
// Check if frame was captured and store it
if (rxlen > 0) {
// frame_count++;
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
LogTraceBits(rx, rxlen, response, response, false);
}
uint8_t *tx = txbuf;
@ -1861,7 +1861,7 @@ void check_challenges(bool file_given, uint8_t *data, bool ledcontrol) {
// Add transmitted frame to total count
if (txlen > 0) {
// frame_count++;
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
LogTraceBits(tx, txlen, HITAG_T_WAIT_2, HITAG_T_WAIT_2, true);
}
hitagS_receive_frame(rx, &rxlen, &response, ledcontrol);

View file

@ -240,7 +240,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
sprintf(line[0], "<empty trace - possible error>");
}
}
uint8_t partialbytebuff = 0;
uint8_t offset = 0;
for (int j = 0; j < data_len && j / 18 < 18; j++) {
uint8_t parityBits = parityBytes[j >> 3];
if (protocol != LEGIC
@ -270,6 +271,18 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x! ", frame[j]);
}
} else if (((protocol == PROTO_HITAG1) || (protocol == PROTO_HITAG2) || (protocol == PROTO_HITAGS)) && (parityBytes[0] > 0)){
// handle partial bytes
uint8_t nbits = parityBytes[0];
if (j==0) {
partialbytebuff = frame[0] << nbits;
snprintf(line[0], 120, "%02x(%i) ", frame[0] >> (8 - nbits), nbits);
offset = 2;
} else {
uint8_t byte = partialbytebuff | (frame[j] >> (8 - nbits));
partialbytebuff = frame[j] << nbits;
snprintf(line[j / 18] + ((j % 18) * 4) + offset, 120, "%02x ", byte);
}
} else {
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x ", frame[j]);
}
@ -278,11 +291,23 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
if (markCRCBytes) {
//CRC-command
if (crcStatus == 0 || crcStatus == 1) {
char *pos1 = line[(data_len - 2) / 18] + (((data_len - 2) % 18) * 4) - 1;
if (((protocol == PROTO_HITAG1) || (protocol == PROTO_HITAGS)) && (data_len > 1)) {
// notes hitag S:
// pm3 is using UID REQUEST Adv -> SOF is 111(AC) then 111111(MC)
// first tag response is AC encoded Currently, recorded trace is garbage
// for unknown reason, recorded SOF in trace is 1111 instead of 111111 (or should be even skipped)
// CRC on tag response is SOF excluded
char *pos1 = line[(data_len - 1) / 18] + (((data_len - 1) % 18) * 4) + offset - 1;
(*pos1) = '[';
char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) - 1;
char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) + offset - 2;
sprintf(pos2, "%c", ']');
} else {
if (crcStatus == 0 || crcStatus == 1) {
char *pos1 = line[(data_len - 2) / 18] + (((data_len - 2) % 18) * 4) - 1;
(*pos1) = '[';
char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) - 1;
sprintf(pos2, "%c", ']');
}
}
}

Binary file not shown.