From 9aafc094b6426b7e590037727147a0ba0f348476 Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:43:13 +0200 Subject: [PATCH] deleted nearly all EM4x50 code; new EM4x50 code is in 'cmdlfem4x50.c' (device side instead GraphBuffer) --- client/src/cmdlfem4x.c | 369 +---------------------------------------- 1 file changed, 4 insertions(+), 365 deletions(-) diff --git a/client/src/cmdlfem4x.c b/client/src/cmdlfem4x.c index ef8cbdc13..27de68519 100644 --- a/client/src/cmdlfem4x.c +++ b/client/src/cmdlfem4x.c @@ -116,41 +116,6 @@ static int usage_lf_em410x_brute(void) { return PM3_SUCCESS; } -//////////////// 4050 / 4450 commands -static int usage_lf_em4x50_demod(void) { - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_demod [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x50_demod"); - return PM3_SUCCESS; -} -static int usage_lf_em4x50_dump(void) { - PrintAndLogEx(NORMAL, "Dump EM4x50/EM4x69. Tag must be on antenna. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_dump [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x50_dump"); - PrintAndLogEx(NORMAL, " lf em 4x50_dump 11223344"); - return PM3_SUCCESS; -} -static int usage_lf_em4x50_read(void) { - PrintAndLogEx(NORMAL, "Read EM 4x50/EM4x69. Tag must be on antenna. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_read [h]
"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " address - memory address to read. (0-15)"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x50_read 1"); - PrintAndLogEx(NORMAL, " lf em 4x50_read 1 11223344"); - return PM3_SUCCESS; -} - //////////////// 4205 / 4305 commands static int usage_lf_em4x05_dump(void) { PrintAndLogEx(NORMAL, "Dump EM4x05/EM4x69. Tag must be on antenna. "); @@ -723,329 +688,6 @@ static bool EM_ColParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t col return true; } -// even parity ROW -static bool EM_RowParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { - if (rows * cols > size) return false; - uint8_t rowP = 0; - - for (uint8_t r = 0; r < rows - 1; r++) { - for (uint8_t c = 0; c < cols; c++) { - rowP ^= bs[(r * cols) + c]; - } - if (rowP != pType) return false; - rowP = 0; - } - return true; -} - -// EM word parity test. -// 9*5 = 45 bits in total -// 012345678|r0 -// 012345678|r1 -// 012345678|r2 -// 012345678|r3 -// ------------ -//c012345678| 0 -// |- must be zero - -/* -static int EMwordparitytest(uint8_t *bits) { - - // last row/col parity must be 0 - if (bits[44] != 0) return PM3_ESOFT; - - // col parity check - uint8_t c1 = bytebits_to_byte(bits, 8) ^ bytebits_to_byte(bits + 9, 8) ^ bytebits_to_byte(bits + 18, 8) ^ bytebits_to_byte(bits + 27, 8); - uint8_t c2 = bytebits_to_byte(bits + 36, 8); - if (c1 != c2) return PM3_ESOFT; - - // row parity check - uint8_t rowP = 0; - for (uint8_t i = 0; i < 36; ++i) { - - rowP ^= bits[i]; - if (i > 0 && (i % 9) == 0) { - - if (rowP != EVEN) - return PM3_ESOFT; - - rowP = 0; - } - } - // all checks ok. - return PM3_SUCCESS; -} -*/ - -//////////////// 4050 / 4450 commands - -static uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest) { - if (size < 45) return 0; - - uint32_t code = bytebits_to_byte(BitStream, 8); - code = code << 8 | bytebits_to_byte(BitStream + 9, 8); - code = code << 8 | bytebits_to_byte(BitStream + 18, 8); - code = code << 8 | bytebits_to_byte(BitStream + 27, 8); - - if (verbose || g_debugMode) { - for (uint8_t i = 0; i < 5; i++) { - if (i == 4) PrintAndLogEx(NORMAL, ""); //parity byte spacer - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d -> 0x%02x", - BitStream[i * 9], - BitStream[i * 9 + 1], - BitStream[i * 9 + 2], - BitStream[i * 9 + 3], - BitStream[i * 9 + 4], - BitStream[i * 9 + 5], - BitStream[i * 9 + 6], - BitStream[i * 9 + 7], - BitStream[i * 9 + 8], - bytebits_to_byte(BitStream + i * 9, 8) - ); - } - - PrintAndLogEx(SUCCESS, "Parity checks | %s", (pTest) ? _GREEN_("Passed") : _RED_("Fail")); - } - return code; -} - -/* Read the transmitted data of an EM4x50 tag from the graphbuffer - * Format: - * - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * CCCCCCC0 <- column parity bits - * 0 <- stop bit - * LW <- Listen Window - * - * This pattern repeats for every block of data being transmitted. - * Transmission starts with two Listen Windows (LW - a modulated - * pattern of 320 cycles each (32/32/128/64/64)). - * - * Note that this data may or may not be the UID. It is whatever data - * is stored in the blocks defined in the control word First and Last - * Word Read values. UID is stored in block 32. - */ -//completed by Marshmellow -int EM4x50Read(const char *Cmd, bool verbose) { - int clk = 0, invert = 0, tol = 0, phaseoff; - int i = 0, j = 0, startblock, skip, block, start, end, low = 0, high = 0; - uint32_t Code[6]; - char tmp[6]; - char tmp2[20]; - bool complete = false; - - int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; - memset(tmpbuff, 0, sizeof(tmpbuff)); - - // get user entry if any - sscanf(Cmd, "%i %i", &clk, &invert); - - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - size_t size = getFromGraphBuf(bits); - - if (size < 4000) { - if (verbose || g_debugMode) PrintAndLogEx(ERR, "Error: EM4x50 - Too little data in Graphbuffer"); - return PM3_ESOFT; - } - - computeSignalProperties(bits, size); - - // get fuzzed HI / LOW limits in signal - getHiLo(&high, &low, 75, 75); - - // get to first full low to prime loop and skip incomplete first pulse - size_t offset = 0; - getNextHigh(bits, size, high, &offset); - getNextLow(bits, size, low, &offset); - - i = (int)offset; - skip = offset; - - // set clock - if (clk == 0) { - DetectASKClock(bits, size, &clk, 0); - if (clk == 0) { - if (verbose || g_debugMode) PrintAndLogEx(ERR, "Error: EM4x50 - didn't find a clock"); - return PM3_ESOFT; - } - } - // tolerance - tol = clk / 8; - - // populate tmpbuff buffer with pulse lengths - while (i < size) { - // measure from low to low - while ((i < size) && (bits[i] > low)) - ++i; - start = i; - - while ((i < size) && (bits[i] < high)) - ++i; - - while ((i < size) && (bits[i] > low)) - ++i; - - if (j >= (MAX_GRAPH_TRACE_LEN / 64)) { - break; - } - tmpbuff[j++] = i - start; - } - - // look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2) - start = -1; - for (i = 0; i < j - 4 ; ++i) { - skip += tmpbuff[i]; - if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 1] >= clk * 2 - tol && tmpbuff[i + 1] <= clk * 2 + tol) //2 clocks - if (tmpbuff[i + 2] >= clk * 3 - tol && tmpbuff[i + 2] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 3] >= clk - tol) { //1.5 to 2 clocks - depends on bit following - start = i + 4; - break; - } - } - startblock = i + 4; - - // skip over the remainder of LW - skip += (tmpbuff[i + 1] + tmpbuff[i + 2] + clk); - - if (tmpbuff[i + 3] > clk) - phaseoff = tmpbuff[i + 3] - clk; - else - phaseoff = 0; - - // now do it again to find the end - for (i += 3; i < j - 4 ; ++i) { - if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 1] >= clk * 2 - tol && tmpbuff[i + 1] <= clk * 2 + tol) //2 clocks - if (tmpbuff[i + 2] >= clk * 3 - tol && tmpbuff[i + 2] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 3] >= clk - tol) { //1.5 to 2 clocks - depends on bit following - complete = true; - break; - } - } - end = i; - - // report back - if (verbose || g_debugMode) { - if (start >= 0) { - PrintAndLogEx(INFO, "\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)"); - } else { - PrintAndLogEx(INFO, "No data found!, clock tried: " _YELLOW_("%d"), clk); - PrintAndLogEx(HINT, "Try again with more samples"); - PrintAndLogEx(HINT, " or after a " _YELLOW_("'data askedge'") " command to clean up the read"); - return PM3_ESOFT; - } - } else if (start < 0) { - return PM3_ESOFT; - } - - start = skip; - - snprintf(tmp2, sizeof(tmp2), "%d %d 1000 %d", clk, invert, clk * 47); - - // save GraphBuffer - to restore it later - save_restoreGB(GRAPH_SAVE); - - // get rid of leading crap - snprintf(tmp, sizeof(tmp), "%i", skip); - CmdLtrim(tmp); - - bool AllPTest = true; - - // now work through remaining buffer printing out data blocks - block = 0; - i = startblock; - while (block < 6) { - if (verbose || g_debugMode) PrintAndLogEx(NORMAL, "\nBlock %i:", block); - skip = phaseoff; - - // look for LW before start of next block - for (; i < j - 4 ; ++i) { - skip += tmpbuff[i]; - if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) - if (tmpbuff[i + 1] >= clk - tol) - break; - } - if (i >= j - 4) break; //next LW not found - skip += clk; - if (tmpbuff[i + 1] > clk) - phaseoff = tmpbuff[i + 1] - clk; - else - phaseoff = 0; - - i += 2; - - if (ASKDemod(tmp2, false, false, 1) != PM3_SUCCESS) { - save_restoreGB(GRAPH_RESTORE); - return PM3_ESOFT; - } - - //set DemodBufferLen to just one block - DemodBufferLen = skip / clk; - //test parities - bool pTest = EM_RowParityTest(DemodBuffer, DemodBufferLen, 5, 9, 0); - pTest &= EM_ColParityTest(DemodBuffer, DemodBufferLen, 5, 9, 0); - AllPTest &= pTest; - //get output - Code[block] = OutputEM4x50_Block(DemodBuffer, DemodBufferLen, verbose, pTest); - PrintAndLogEx(DEBUG, "\nskipping %d samples, bits:%d", skip, skip / clk); - //skip to start of next block - snprintf(tmp, sizeof(tmp), "%i", skip); - CmdLtrim(tmp); - block++; - if (i >= end) break; //in case chip doesn't output 6 blocks - } - - //print full code: - if (verbose || g_debugMode || AllPTest) { - if (!complete) { - PrintAndLogEx(WARNING, _RED_("* **Warning!")); - PrintAndLogEx(INFO, "Partial data - no end found!"); - PrintAndLogEx(HINT, "Try again with more samples."); - } - PrintAndLogEx(INFO, "Found data at sample: %i - using clock: %i", start, clk); - end = block; - PrintAndLogEx(INFO, "blk | data"); - PrintAndLogEx(INFO, "----+--------------"); - for (block = 0; block < end; block++) { - PrintAndLogEx(INFO, "%03d | %08x", block, Code[block]); - } - PrintAndLogEx(INFO, "----+--------------"); - PrintAndLogEx((AllPTest) ? SUCCESS : WARNING, "Parities checks | %s", (AllPTest) ? _GREEN_("Passed") : _RED_("Fail")); - - if (AllPTest == false) { - PrintAndLogEx(HINT, "Try cleaning the read samples with " _YELLOW_("'data askedge'")); - } - } - - //restore GraphBuffer - save_restoreGB(GRAPH_RESTORE); - return AllPTest ? PM3_SUCCESS : PM3_ESOFT; -} - -static int CmdEM4x50Demod(const char *Cmd) { - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_lf_em4x50_demod(); - return EM4x50Read(Cmd, true); -} - -static int CmdEM4x50Read(const char *Cmd) { - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_lf_em4x50_read(); - lf_read(false, 24000); - return EM4x50Read(Cmd, true); -} - -static int CmdEM4x50Dump(const char *Cmd) { - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_lf_em4x50_dump(); - PrintAndLogEx(NORMAL, "no implemented yet"); - return PM3_SUCCESS; -} - #define EM_PREAMBLE_LEN 6 // download samples from device and copy to Graphbuffer static bool downloadSamplesEM(void) { @@ -1753,13 +1395,10 @@ static command_t CommandTable[] = { {"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"}, {"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"}, {"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"}, - {"4x50_demod", CmdEM4x50Demod, AlwaysAvailable, "demodulate a EM4x50 tag from the GraphBuffer"}, - {"4x50_dump", CmdEM4x50Dump, IfPm3Lf, "dump EM4x50 tag"}, - {"4x50_read", CmdEM4x50Read, IfPm3Lf, "read word data from EM4x50"}, - {"4x50_info", CmdEM4x50Info, IfPm3Lf, "read complete data from EM4x50"}, - {"4x50_write", CmdEM4x50Write, IfPm3Lf, "write word data to EM4x50"}, - {"4x50_write_password", CmdEM4x50WritePassword, IfPm3Lf, "change passwword of EM4x50 tag"}, - {"4x50_sread", CmdEM4x50SRead, IfPm3Lf, "read word data from EM4x50 on device"}, + {"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "read complete data from EM4x50"}, + {"4x50_write", CmdEM4x50Write, IfPm3EM4x50, "write word data to EM4x50"}, + {"4x50_write_password", CmdEM4x50WritePassword, IfPm3EM4x50, "change passwword of EM4x50 tag"}, + {"4x50_read", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"}, {NULL, NULL, NULL, NULL} };