From 323f70ff7ab2fbada666749311b28d5fd97df32c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 29 Dec 2021 23:40:18 +0100 Subject: [PATCH] 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] --- armsrc/BigBuf.c | 8 ++++++++ armsrc/BigBuf.h | 1 + armsrc/hitag2.c | 22 +++++++++++----------- armsrc/hitagS.c | 16 ++++++++-------- client/src/cmdtrace.c | 33 +++++++++++++++++++++++++++++---- traces/lf_HitagS256_dump.trace | Bin 287 -> 287 bytes 6 files changed, 57 insertions(+), 23 deletions(-) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 97c2ef5c4..9ba400ff9 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -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) { diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 6bdf4e331..435aeb80d 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -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); diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 693a5f9d2..70f048bab 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -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; } } diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 5ff3d9589..462a18277 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -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); diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 1e49ca64c..17ddacfdd 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -240,7 +240,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr sprintf(line[0], ""); } } - + 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", ']'); + } } } diff --git a/traces/lf_HitagS256_dump.trace b/traces/lf_HitagS256_dump.trace index 255abb56db0239736e8089e4de1eb3fefb54718a..b1036b1c4ffaeb314770d8c7cfee7e8462fd8bc0 100644 GIT binary patch literal 287 zcma!I00BmZ1FYx4EY5~cr}mt-`KYv0~xpy e5K=J;IHmFea7xuTz@@&He)+Pa0byW^0RsS;E