From 7666f4608e8ade0ada08777d1cc33469c5d9471d Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sun, 12 Feb 2017 23:59:44 -0500 Subject: [PATCH 01/19] update em4x05/em4x69 cmds @iceman1001 s updates + some of my own. still more to do: -auto demod responses -figure out config block -figure out block 0 info / serial # in block 1 -figure out block 3 protection data -add dump all blocks cmd --- armsrc/appmain.c | 4 +- armsrc/apps.h | 2 +- armsrc/lfops.c | 57 +++++++--------- client/cmdlfem4x.c | 162 ++++++++++++++++++++++++++++++++------------- 4 files changed, 144 insertions(+), 81 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ec133c7a..03855172 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1017,10 +1017,10 @@ void UsbPacketReceived(uint8_t *packet, int len) WritePCF7931(c->d.asBytes[0],c->d.asBytes[1],c->d.asBytes[2],c->d.asBytes[3],c->d.asBytes[4],c->d.asBytes[5],c->d.asBytes[6], c->d.asBytes[9], c->d.asBytes[7]-128,c->d.asBytes[8]-128, c->arg[0], c->arg[1], c->arg[2]); break; case CMD_EM4X_READ_WORD: - EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]); + EM4xReadWord(c->arg[0], c->arg[1],c->arg[2]); break; case CMD_EM4X_WRITE_WORD: - EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); + EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2]); break; case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation CmdAWIDdemodFSK(c->arg[0], 0, 0, 1); diff --git a/armsrc/apps.h b/armsrc/apps.h index cbe3b239..8d51335b 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -88,7 +88,7 @@ void T55xxWakeUp(uint32_t Pwd); void TurnReadLFOn(); //void T55xxReadTrace(void); void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); -void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); +void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd); void Cotag(uint32_t arg0); /// iso14443.h diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 0a8ce3a9..1d18c709 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -684,7 +684,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) for (i=0; i>1)<>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; // Program the data blocks for supplied ID and the block 0 config WriteT55xx(data, 0, 3); LED_D_OFF(); @@ -1571,8 +1571,6 @@ void SendForward(uint8_t fwd_bit_count) { fwd_write_ptr = forwardLink_data; fwd_bit_sz = fwd_bit_count; - LED_D_ON(); - // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); @@ -1580,7 +1578,7 @@ void SendForward(uint8_t fwd_bit_count) { fwd_bit_sz--; //prepare next bit modulation fwd_write_ptr++; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - SpinDelayUs(55*8); //55 cycles off (8us each)for 4305 + SpinDelayUs(56*8); //55 cycles off (8us each)for 4305 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on SpinDelayUs(16*8); //16 cycles on (8us each) @@ -1591,9 +1589,9 @@ void SendForward(uint8_t fwd_bit_count) { else { //These timings work for 4469/4269/4305 (with the 55*8 above) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - SpinDelayUs(23*8); //16-4 cycles off (8us each) + SpinDelayUs(20*8); //16-4 cycles off (8us each) //23 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on - SpinDelayUs(9*8); //16 cycles on (8us each) + SpinDelayUs(12*8); //16 cycles on (8us each) //9 } } } @@ -1615,13 +1613,11 @@ void EM4xLogin(uint32_t Password) { void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { uint8_t fwd_bit_count; - uint8_t *dest = BigBuf_get_addr(); - uint16_t bufferlength = BigBuf_max_traceLen(); - uint32_t i = 0; // Clear destination buffer before sending the command BigBuf_Clear_ext(false); + LED_A_ON(); //If password mode do login if (PwdMode == 1) EM4xLogin(Pwd); @@ -1629,36 +1625,28 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { fwd_bit_count = Prepare_Cmd( FWD_CMD_READ ); fwd_bit_count += Prepare_Addr( Address ); - // Connect the A/D to the peak-detected low-frequency path. - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - // Now set up the SSC to get the ADC samples that are now streaming at us. - FpgaSetupSsc(); - SendForward(fwd_bit_count); // Now do the acquisition - i = 0; - for(;;) { - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - } - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - if (i >= bufferlength) break; - } - } + DoAcquisition_config(TRUE); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off + LED_A_OFF(); cmd_send(CMD_ACK,0,0,0,0,0); - LED_D_OFF(); } -void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { - +void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { + + bool PwdMode = (flag & 0xF); + uint8_t Address = (flag >> 8) & 0xFF; uint8_t fwd_bit_count; + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + + LED_A_ON(); //If password mode do login - if (PwdMode == 1) EM4xLogin(Pwd); + if (PwdMode) EM4xLogin(Pwd); forward_ptr = forwardLink_data; fwd_bit_count = Prepare_Cmd( FWD_CMD_WRITE ); @@ -1669,8 +1657,13 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode //Wait for write to complete SpinDelay(20); + + //Capture response if one exists + DoAcquisition_config(TRUE); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - LED_D_OFF(); + LED_A_OFF(); + cmd_send(CMD_ACK,0,0,0,0,0); } /* Reading a COTAG. diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index aa0fc856..aa568e9e 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -18,6 +18,7 @@ #include "cmdparser.h" #include "cmddata.h" #include "cmdlf.h" +#include "cmdmain.h" #include "cmdlfem4x.h" #include "lfdemod.h" @@ -285,7 +286,7 @@ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool } return code; } -/* Read the transmitted data of an EM4x50 tag +/* Read the transmitted data of an EM4x50 tag from the graphbuffer * Format: * * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity @@ -498,53 +499,122 @@ int CmdEM4x50Read(const char *Cmd) return EM4x50Read(Cmd, true); } -int CmdReadWord(const char *Cmd) -{ - int Word = -1; //default to invalid word - UsbCommand c; +int usage_lf_em_read(void) { + PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em readword [h]
"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" address - memory address to read. (0-15)"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em readword 1"); + PrintAndLog(" lf em readword 1 11223344"); + return 0; +} +int CmdReadWord(const char *Cmd) { + int addr, pwd; + bool usePwd = false; + uint8_t ctmp = param_getchar(Cmd, 0); + if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_read(); + + addr = param_get8ex(Cmd, 0, -1, 10); + pwd = param_get32ex(Cmd, 1, -1, 16); - sscanf(Cmd, "%d", &Word); - - if ( (Word > 15) | (Word < 0) ) { - PrintAndLog("Word must be between 0 and 15"); + if ( (addr > 15) || (addr < 0 ) || ( addr == -1) ) { + PrintAndLog("Address must be between 0 and 15"); return 1; } + if ( pwd == -1 ) + PrintAndLog("Reading address %d", addr); + else { + usePwd = true; + PrintAndLog("Reading address %d | password %08X", addr, pwd); + } - PrintAndLog("Reading word %d", Word); - - c.cmd = CMD_EM4X_READ_WORD; - c.d.asBytes[0] = 0x0; //Normal mode - c.arg[0] = 0; - c.arg[1] = Word; - c.arg[2] = 0; - SendCommand(&c); - return 0; -} - -int CmdReadWordPWD(const char *Cmd) -{ - int Word = -1; //default to invalid word - int Password = 0xFFFFFFFF; //default to blank password - UsbCommand c; - - sscanf(Cmd, "%d %x", &Word, &Password); - - if ( (Word > 15) | (Word < 0) ) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Reading word %d with password %08X", Word, Password); - - c.cmd = CMD_EM4X_READ_WORD; - c.d.asBytes[0] = 0x1; //Password mode - c.arg[0] = 0; - c.arg[1] = Word; - c.arg[2] = Password; + UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}}; + clearCommandBuffer(); SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)){ + PrintAndLog("Command timed out"); + return -1; + } + + uint8_t got[6000]; // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) + GetFromBigBuf(got, sizeof(got), 0); + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 8000) ) { + PrintAndLog("command execution time out"); + return 0; + } + setGraphBuf(got, sizeof(got)); + //todo: demodulate read data + return 1; +} + +int usage_lf_em_write(void) { + PrintAndLog("Write EM4x05/EM4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em writeword [h]
"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" address - memory address to write to. (0-15)"); + PrintAndLog(" data - data to write (hex)"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em writeword 1"); + PrintAndLog(" lf em writeword 1 deadc0de 11223344"); + return 0; +} +int CmdWriteWord(const char *Cmd) { + uint8_t ctmp = param_getchar(Cmd, 0); + if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write(); + + bool usePwd = false; + + int addr = 16; // default to invalid address + int data = 0xFFFFFFFF; // default to blank data + int pwd = 0xFFFFFFFF; // default to blank password + + addr = param_get8ex(Cmd, 0, -1, 10); + data = param_get32ex(Cmd, 1, -1, 16); + pwd = param_get32ex(Cmd, 2, -1, 16); + + + if ( (addr > 15) || (addr < 0 ) || ( addr == -1) ) { + PrintAndLog("Address must be between 0 and 15"); + return 1; + } + if ( pwd == -1 ) + PrintAndLog("Writing address %d data %08X", addr, data); + else { + usePwd = true; + PrintAndLog("Writing address %d data %08X using password %08X", addr, data, pwd); + } + + uint16_t flag = (addr << 8 ) | usePwd; + + UsbCommand c = {CMD_EM4X_WRITE_WORD, {flag, data, pwd}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){ + PrintAndLog("Error occurred, device did not respond during write operation."); + return -1; + } + //get response if there is one + uint8_t got[6000]; // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) + GetFromBigBuf(got, sizeof(got), 0); + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 8000) ) { + PrintAndLog("command execution time out"); + return 0; + } + setGraphBuf(got, sizeof(got)); + //todo: check response for 00001010 then write data for write confirmation! return 0; } +/* int CmdWriteWord(const char *Cmd) { int Word = 16; //default to invalid block @@ -593,7 +663,7 @@ int CmdWriteWordPWD(const char *Cmd) SendCommand(&c); return 0; } - +*/ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -603,11 +673,11 @@ static command_t CommandTable[] = {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, {"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, {"em410xwrite", CmdEM410xWrite, 0, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, - {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, - {"readword", CmdReadWord, 1, " -- Read EM4xxx word data"}, - {"readwordPWD", CmdReadWordPWD, 1, " -- Read EM4xxx word data in password mode"}, - {"writeword", CmdWriteWord, 1, " -- Write EM4xxx word data"}, - {"writewordPWD", CmdWriteWordPWD, 1, " -- Write EM4xxx word data in password mode"}, + {"em4x50read", CmdEM4x50Read, 1, "demod data from EM4x50 tag from the graph buffer"}, + {"readword", CmdReadWord, 1, " (pwd) -- Read EM4x05/EM4x69 word data"}, + //{"readwordPWD", CmdReadWordPWD, 1, " -- Read EM4xxx word data in password mode"}, + {"writeword", CmdWriteWord, 1, " (pwd) -- Write EM4x05/EM4x69 word data"}, + //{"writewordPWD", CmdWriteWordPWD, 1, " -- Write EM4xxx word data in password mode"}, {NULL, NULL, 0, NULL} }; From 6f1a597855d5ba70e0d37613ffe144e63690a058 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 14 Feb 2017 23:42:55 -0500 Subject: [PATCH 02/19] couple q5 fixes + continue with em4x05 em4x69.. .. readword demods (not tested) still a work in progress --- client/cmddata.h | 1 + client/cmdlfawid.c | 2 +- client/cmdlfem4x.c | 137 +++++++++++++++++++++++++++++++++++++++++-- client/cmdlfpresco.c | 2 +- 4 files changed, 135 insertions(+), 7 deletions(-) diff --git a/client/cmddata.h b/client/cmddata.h index 9b9f2da9..c45a162d 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -22,6 +22,7 @@ command_t * CmdDataCommands(); int CmdData(const char *Cmd); void printDemodBuff(void); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); +int CmdPrintDemodBuff(const char *Cmd); int CmdAskEM410xDemod(const char *Cmd); int CmdVikingDemod(const char *Cmd); int CmdG_Prox_II_Demod(const char *Cmd); diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 309f4118..1ace6bea 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -140,7 +140,7 @@ int CmdAWIDClone(const char *Cmd) { if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_awid_clone(); if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q') - blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<>1)< DemodBufferLen) ? DemodBufferLen : 10; + size_t startIdx = 0; + + if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); + + uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + if ( errChk == 0) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); + //return -1; + } else { + //can't test size because the preamble doesn't repeat :( + //meaning chances of false positives are high. + demodFound = true; + } + } + } + + ans = GetPskClock("", FALSE, FALSE); + if (ans>0) { + PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod"); + } + + if (!demodFound) { + DemodBufferLen = 0x00; + //try biphase + ans = ASKbiphaseDemod("0 0 1", FALSE); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); + //return -1; + } else { + // set size to 10 to only test first 4 positions for the preamble + size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; + size_t startIdx = 0; + + if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); + + uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + if ( errChk == 0) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); + //return -1; + } else { + //can't test size because the preamble doesn't repeat :( + //meaning chances of false positives are high. + demodFound = true; + } + } + } + + if (!demodFound) { + DemodBufferLen = 0x00; + // try manchester - NOTE: ST only applies to T55x7 tags. + ans = ASKDemod_ext("0,0,1", false, false, 1, false); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); + //return -1; + } else { + // set size to 10 to only test first 4 positions for the preamble + size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; + size_t startIdx = 0; + + if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); + + uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + if ( errChk == 0) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); + //return -1; + } else { + //can't test size because the preamble doesn't repeat :( + //meaning chances of false positives are high. + demodFound = true; + } + } + } + + if (demodFound && bitsNeeded < DemodBufferLen) { + setDemodBuf(DemodBuffer + ans + sizeof(preamble), bitsNeeded, 0); + CmdPrintDemodBuff("x"); + return 1; + } + return -1; +} + int CmdReadWord(const char *Cmd) { int addr, pwd; bool usePwd = false; @@ -540,15 +659,23 @@ int CmdReadWord(const char *Cmd) { PrintAndLog("Command timed out"); return -1; } - - uint8_t got[6000]; // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) + + uint8_t got[6000]; GetFromBigBuf(got, sizeof(got), 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 8000) ) { + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { PrintAndLog("command execution time out"); - return 0; + return -1; } setGraphBuf(got, sizeof(got)); - //todo: demodulate read data + int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000; + if (graphJustNoise(GraphBuffer, testLen)) { + PrintAndLog("no tag not found"); + return -1; + } + + //need 32 bits for read word + demodEM4x05resp(32); + return 1; } diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index abae165d..c6dbd756 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -178,7 +178,7 @@ int CmdPrescoClone(const char *Cmd) { if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone(); if (Q5) - blocks[0] = T5555_MODULATION_MANCHESTER | 32<>1)< Date: Wed, 15 Feb 2017 23:27:15 -0500 Subject: [PATCH 03/19] EM4x05/EM4x69 continued + a couple of icemans utils. --- client/cmdlfem4x.c | 73 ++++++++++++++++++++++++++++++++------------ client/util.c | 76 ++++++++++++++++++++++++++++++++++++++++++++-- client/util.h | 6 +++- common/lfdemod.c | 3 ++ 4 files changed, 134 insertions(+), 24 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 820b24e9..7d8d2931 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -533,6 +533,9 @@ uint8_t EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, siz return 0; } +// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE +// should cover 90% of known used configs +// the rest will need to be manually demoded for now... int demodEM4x05resp(uint8_t bitsNeeded) { int ans = 0; bool demodFound = false; @@ -546,7 +549,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) { ans = FSKrawDemod("0 0", false); if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed"); - //return -1; } else { // set size to 10 to only test first 4 positions for the preamble size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; @@ -557,7 +559,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) { uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); if ( errChk == 0) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); - //return -1; } else { //can't test size because the preamble doesn't repeat :( //meaning chances of false positives are high. @@ -565,10 +566,37 @@ int demodEM4x05resp(uint8_t bitsNeeded) { } } } + // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... ) + if (!demodFound) { + ans = GetPskClock("", FALSE, FALSE); + if (ans>0) { + PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod"); + } + } - ans = GetPskClock("", FALSE, FALSE); - if (ans>0) { - PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod"); + // more common than biphase + if (!demodFound) { + DemodBufferLen = 0x00; + // try manchester - NOTE: ST only applies to T55x7 tags. + ans = ASKDemod_ext("0,0,1", false, false, 1, false); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); + } else { + // set size to 10 to only test first 4 positions for the preamble + size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; + size_t startIdx = 0; + + if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); + + uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + if ( errChk == 0) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); + } else { + //can't test size because the preamble doesn't repeat :( + //meaning chances of false positives are high. + demodFound = true; + } + } } if (!demodFound) { @@ -577,7 +605,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) { ans = ASKbiphaseDemod("0 0 1", FALSE); if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); - //return -1; } else { // set size to 10 to only test first 4 positions for the preamble size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; @@ -588,7 +615,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) { uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); if ( errChk == 0) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); - //return -1; } else { //can't test size because the preamble doesn't repeat :( //meaning chances of false positives are high. @@ -599,11 +625,10 @@ int demodEM4x05resp(uint8_t bitsNeeded) { if (!demodFound) { DemodBufferLen = 0x00; - // try manchester - NOTE: ST only applies to T55x7 tags. - ans = ASKDemod_ext("0,0,1", false, false, 1, false); - if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); - //return -1; + //try diphase (differential biphase or inverted) + ans = ASKbiphaseDemod("0 1 1", FALSE); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); } else { // set size to 10 to only test first 4 positions for the preamble size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; @@ -614,7 +639,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) { uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); if ( errChk == 0) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); - //return -1; } else { //can't test size because the preamble doesn't repeat :( //meaning chances of false positives are high. @@ -624,8 +648,10 @@ int demodEM4x05resp(uint8_t bitsNeeded) { } if (demodFound && bitsNeeded < DemodBufferLen) { - setDemodBuf(DemodBuffer + ans + sizeof(preamble), bitsNeeded, 0); - CmdPrintDemodBuff("x"); + if (bitsNeeded > 0) { + setDemodBuf(DemodBuffer + ans + sizeof(preamble), bitsNeeded, 0); + CmdPrintDemodBuff("x"); + } return 1; } return -1; @@ -673,10 +699,9 @@ int CmdReadWord(const char *Cmd) { return -1; } - //need 32 bits for read word - demodEM4x05resp(32); - - return 1; + //attempt demod: + //need 32 bits from a read word + return demodEM4x05resp(32); } int usage_lf_em_write(void) { @@ -693,6 +718,7 @@ int usage_lf_em_write(void) { PrintAndLog(" lf em writeword 1 deadc0de 11223344"); return 0; } + int CmdWriteWord(const char *Cmd) { uint8_t ctmp = param_getchar(Cmd, 0); if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write(); @@ -738,7 +764,14 @@ int CmdWriteWord(const char *Cmd) { } setGraphBuf(got, sizeof(got)); //todo: check response for 00001010 then write data for write confirmation! - return 0; + + //attempt demod: + //need 0 bits demoded (after preamble) to verify write cmd + int result = demodEM4x05resp(0); + if (result == 1) { + PrintAndLog("Write Verified"); + } + return result; } /* diff --git a/client/util.c b/client/util.c index e4add6c0..374ae397 100644 --- a/client/util.c +++ b/client/util.c @@ -110,6 +110,23 @@ void print_hex(const uint8_t * data, const size_t len) printf("\n"); } +void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { + + int rownum = 0; + printf("[%02d] | ", rownum); + for (int i = 0; i < len; ++i) { + + printf("%02X ", data[i]); + + // check if a line break is needed + if ( breaks > 0 && !((i+1) % breaks) && (i+1 < len) ) { + ++rownum; + printf("\n[%02d] | ", rownum); + } + } + printf("\n"); +} + char *sprint_hex(const uint8_t *data, const size_t len) { int maxLen = ( len > 1024/3) ? 1024/3 : len; @@ -139,7 +156,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea size_t in_index = 0; // loop through the out_index to make sure we don't go too far - for (size_t out_index=0; out_index < max_len; out_index++) { + for (size_t out_index=0; out_index < max_len-1; out_index++) { // set character - (should be binary but verify it isn't more than 1 digit) if (data[in_index]<10) sprintf(tmp++, "%u", (unsigned int) data[in_index]); @@ -158,6 +175,41 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea char *sprint_bin(const uint8_t *data, const size_t len) { return sprint_bin_break(data, len, 0); } + +char *sprint_hex_ascii(const uint8_t *data, const size_t len) { + static char buf[1024]; + char *tmp = buf; + memset(buf, 0x00, 1024); + size_t max_len = (len > 1010) ? 1010 : len; + + sprintf(tmp, "%s| ", sprint_hex(data, max_len) ); + + size_t i = 0; + size_t pos = (max_len * 3)+2; + while(i < max_len){ + char c = data[i]; + if ( (c < 32) || (c == 127)) + c = '.'; + sprintf(tmp+pos+i, "%c", c); + ++i; + } + return buf; +} + +char *sprint_ascii(const uint8_t *data, const size_t len) { + static char buf[1024]; + char *tmp = buf; + memset(buf, 0x00, 1024); + size_t max_len = (len > 1010) ? 1010 : len; + size_t i = 0; + while(i < max_len){ + char c = data[i]; + tmp[i] = ((c < 32) || (c == 127)) ? '.' : c; + ++i; + } + return buf; +} + void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { while (len--) { @@ -184,6 +236,15 @@ void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) { } } +//least significant bit first +void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest) { + for(int i = 0 ; i < len ; ++i) { + dest[i] = n & 1; + n >>= 1; + } +} + + // aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp // to // hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii @@ -200,6 +261,16 @@ uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockS return tmp; } +// takes a uint8_t src array, for len items and reverses the byte order in blocksizes (8,16,32,64), +// returns: the dest array contains the reordered src array. +void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest){ + for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ + for (size_t i = 0; i < blockSize; i++){ + dest[i+(blockSize*block)] = src[(blockSize-1-i)+(blockSize*block)]; + } + } +} + //assumes little endian char * printBits(size_t const size, void const * const ptr) { @@ -332,8 +403,6 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base) return strtoull(&line[bg], NULL, base); else return deflt; - - return 0; } int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt) @@ -490,6 +559,7 @@ void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length) *(target)= GetParity(source + length / 2, ODD, length / 2); } +// xor two arrays together for len items. The dst array contains the new xored values. void xor(unsigned char *dst, unsigned char *src, size_t len) { for( ; len > 0; len--,dst++,src++) *dst ^= *src; diff --git a/client/util.h b/client/util.h index 1b6b2fb1..8c0ed950 100644 --- a/client/util.h +++ b/client/util.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include //time, gmtime #include "data.h" //for FILE_PATH_SIZE #ifndef ROTR @@ -42,12 +42,16 @@ void print_hex(const uint8_t * data, const size_t len); char * sprint_hex(const uint8_t * data, const size_t len); char * sprint_bin(const uint8_t * data, const size_t len); char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks); +char * sprint_hex_ascii(const uint8_t *data, const size_t len); +char * sprint_ascii(const uint8_t *data, const size_t len); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest); +void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest); char * printBits(size_t const size, void const * const ptr); uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); +void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest); char param_getchar(const char *line, int paramnum); int param_getptr(const char *line, int *bg, int *en, int paramnum); diff --git a/common/lfdemod.c b/common/lfdemod.c index 8324c440..6c09c9ee 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -148,6 +148,9 @@ uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits) //search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx) { + // Sanity check. If preamble length is bigger than bitstream length. + if ( *size <= pLen ) return 0; + uint8_t foundCnt=0; for (int idx=0; idx < *size - pLen; idx++){ if (memcmp(BitStream+idx, preamble, pLen) == 0){ From 2d99d9912c430b09c8178c9154a44a99e7ee6561 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Thu, 16 Feb 2017 13:57:14 -0500 Subject: [PATCH 04/19] a couple em4x05 fixes. --- client/cmdlfem4x.c | 30 ++++++++++++++++-------------- client/graph.c | 5 +++-- common/lfdemod.c | 4 ++-- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 7d8d2931..2d1600f6 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -514,17 +514,17 @@ int usage_lf_em_read(void) { } //search for given preamble in given BitStream and return success=1 or fail=0 and startIndex -uint8_t EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx) -{ +uint8_t EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx) { // Sanity check. If preamble length is bigger than bitstream length. if ( size <= pLen ) return 0; // em only sends preamble once, so look for it once in the first x bits uint8_t foundCnt = 0; - for (int idx = 0; idx < size - pLen; idx++){ + for (size_t idx = 0; idx < size - pLen; idx++){ if (memcmp(BitStream+idx, preamble, pLen) == 0){ //first index found foundCnt++; if (foundCnt == 1) { + if (g_debugMode) PrintAndLog("DEBUG: preamble found at %u", idx); *startIdx = idx; return 1; } @@ -542,6 +542,7 @@ int demodEM4x05resp(uint8_t bitsNeeded) { DemodBufferLen = 0x00; // skip first two 0 bits as they might have been missed in the demod uint8_t preamble[6] = {0,0,1,0,1,0}; + size_t startIdx = 0; // test for FSK wave (easiest to 99% ID) if (GetFskClock("", FALSE, FALSE)) { @@ -552,11 +553,11 @@ int demodEM4x05resp(uint8_t bitsNeeded) { } else { // set size to 10 to only test first 4 positions for the preamble size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - size_t startIdx = 0; + startIdx = 0; if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); if ( errChk == 0) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); } else { @@ -577,18 +578,19 @@ int demodEM4x05resp(uint8_t bitsNeeded) { // more common than biphase if (!demodFound) { DemodBufferLen = 0x00; + bool stcheck = false; // try manchester - NOTE: ST only applies to T55x7 tags. - ans = ASKDemod_ext("0,0,1", false, false, 1, false); + ans = ASKDemod_ext("0,0,1", false, false, 1, &stcheck); if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); } else { // set size to 10 to only test first 4 positions for the preamble size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - size_t startIdx = 0; + startIdx = 0; if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); if ( errChk == 0) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); } else { @@ -608,11 +610,11 @@ int demodEM4x05resp(uint8_t bitsNeeded) { } else { // set size to 10 to only test first 4 positions for the preamble size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - size_t startIdx = 0; + startIdx = 0; if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); if ( errChk == 0) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); } else { @@ -632,11 +634,11 @@ int demodEM4x05resp(uint8_t bitsNeeded) { } else { // set size to 10 to only test first 4 positions for the preamble size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - size_t startIdx = 0; + startIdx = 0; if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); if ( errChk == 0) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); } else { @@ -649,7 +651,7 @@ int demodEM4x05resp(uint8_t bitsNeeded) { if (demodFound && bitsNeeded < DemodBufferLen) { if (bitsNeeded > 0) { - setDemodBuf(DemodBuffer + ans + sizeof(preamble), bitsNeeded, 0); + setDemodBuf(DemodBuffer + startIdx + sizeof(preamble), bitsNeeded, 0); CmdPrintDemodBuff("x"); } return 1; @@ -701,7 +703,7 @@ int CmdReadWord(const char *Cmd) { //attempt demod: //need 32 bits from a read word - return demodEM4x05resp(32); + return demodEM4x05resp(44); } int usage_lf_em_write(void) { diff --git a/client/graph.c b/client/graph.c index d216a8f2..f40f093a 100644 --- a/client/graph.c +++ b/client/graph.c @@ -14,6 +14,7 @@ #include "ui.h" #include "graph.h" #include "lfdemod.h" +#include "cmddata.h" //for g_debugmode int GraphBuffer[MAX_GRAPH_TRACE_LEN]; int GraphTraceLen; @@ -255,7 +256,7 @@ uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose) if (size==0) return 0; uint16_t ans = countFC(BitStream, size, 1); if (ans==0) { - if (verbose) PrintAndLog("DEBUG: No data found"); + if (verbose || g_debugMode) PrintAndLog("DEBUG: No data found"); return 0; } *fc1 = (ans >> 8) & 0xFF; @@ -263,7 +264,7 @@ uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose) *rf1 = detectFSKClk(BitStream, size, *fc1, *fc2); if (*rf1==0) { - if (verbose) PrintAndLog("DEBUG: Clock detect error"); + if (verbose || g_debugMode) PrintAndLog("DEBUG: Clock detect error"); return 0; } return 1; diff --git a/common/lfdemod.c b/common/lfdemod.c index 6c09c9ee..f9f2d1f1 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1375,10 +1375,10 @@ uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj) uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t fcLensFnd = 0; - uint8_t lastFCcnt=0; + uint8_t lastFCcnt = 0; uint8_t fcCounter = 0; size_t i; - if (size == 0) return 0; + if (size < 180) return 0; // prime i to first up transition for (i = 160; i < size-20; i++) From e39a92bb1d876f880ad8cbea82921838422358e8 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 17 Feb 2017 01:33:27 -0500 Subject: [PATCH 05/19] em4x05 getting better got the read/dump cmds working pretty well some tweaking still left to do. --- armsrc/lfops.c | 10 +- client/cmdlfem4x.c | 326 ++++++++++++++++++++++----------------------- common/lfdemod.c | 8 +- 3 files changed, 169 insertions(+), 175 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 1d18c709..29331754 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1573,12 +1573,12 @@ void SendForward(uint8_t fwd_bit_count) { // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); - + // force 1st mod pulse (start gap must be longer for 4305) fwd_bit_sz--; //prepare next bit modulation fwd_write_ptr++; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - SpinDelayUs(56*8); //55 cycles off (8us each)for 4305 + SpinDelayUs(55*8); //55 cycles off (8us each)for 4305 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on SpinDelayUs(16*8); //16 cycles on (8us each) @@ -1628,7 +1628,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { SendForward(fwd_bit_count); // Now do the acquisition - DoAcquisition_config(TRUE); + DoAcquisition_default(30,TRUE); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); @@ -1656,10 +1656,10 @@ void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { SendForward(fwd_bit_count); //Wait for write to complete - SpinDelay(20); + //SpinDelay(5); //Capture response if one exists - DoAcquisition_config(TRUE); + DoAcquisition_default(30, TRUE); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 2d1600f6..16faa848 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -502,21 +502,21 @@ int CmdEM4x50Read(const char *Cmd) int usage_lf_em_read(void) { PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. "); PrintAndLog(""); - PrintAndLog("Usage: lf em readword [h]
"); + PrintAndLog("Usage: lf em 4x05readword [h]
"); PrintAndLog("Options:"); PrintAndLog(" h - this help"); PrintAndLog(" address - memory address to read. (0-15)"); PrintAndLog(" pwd - password (hex) (optional)"); PrintAndLog("samples:"); - PrintAndLog(" lf em readword 1"); - PrintAndLog(" lf em readword 1 11223344"); + PrintAndLog(" lf em 4x05readword 1"); + PrintAndLog(" lf em 4x05readword 1 11223344"); return 0; } //search for given preamble in given BitStream and return success=1 or fail=0 and startIndex -uint8_t EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx) { +bool EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx) { // Sanity check. If preamble length is bigger than bitstream length. - if ( size <= pLen ) return 0; + if ( size <= pLen ) return false; // em only sends preamble once, so look for it once in the first x bits uint8_t foundCnt = 0; for (size_t idx = 0; idx < size - pLen; idx++){ @@ -526,23 +526,62 @@ uint8_t EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, siz if (foundCnt == 1) { if (g_debugMode) PrintAndLog("DEBUG: preamble found at %u", idx); *startIdx = idx; - return 1; + + return true; } } } - return 0; + return false; +} + +bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { + // skip first two 0 bits as they might have been missed in the demod + uint8_t preamble[6] = {0,0,1,0,1,0}; + size_t startIdx = 0; + // set size to 10 to only test first 4 positions for the preamble + size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; + startIdx = 0; + + //test preamble + bool errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); + if ( !errChk ) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); + return false; + } + if (readCmd) { + //test for even parity bits. + size = removeParity(DemodBuffer, startIdx + sizeof(preamble),9,0,44); + if (size == 0) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Parity not detected"); + return false; + } + + //todo test last 8 bits for even parity || (xor) + + setDemodBuf(DemodBuffer, 40, 0); + + *word = bytebits_to_byteLSBF(DemodBuffer , 32); + + uint8_t lo = (uint8_t) bytebits_to_byteLSBF(DemodBuffer , 8); + uint8_t lo2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 8, 8); + uint8_t hi = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 16, 8); + uint8_t hi2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 24, 8); + uint8_t cs = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 32, 8); + uint8_t cs2 = lo ^ lo2 ^ hi ^ hi2; + if (g_debugMode) PrintAndLog("EM4x05/4x69 : %08X CS: %02X %s",*word,cs, (cs2==cs) ? "Passed" : "Failed"); + + return (cs2==cs) ? true : false; + } + return true; } // FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE // should cover 90% of known used configs // the rest will need to be manually demoded for now... -int demodEM4x05resp(uint8_t bitsNeeded) { +int demodEM4x05resp(uint32_t *word, bool readCmd) { int ans = 0; bool demodFound = false; DemodBufferLen = 0x00; - // skip first two 0 bits as they might have been missed in the demod - uint8_t preamble[6] = {0,0,1,0,1,0}; - size_t startIdx = 0; // test for FSK wave (easiest to 99% ID) if (GetFskClock("", FALSE, FALSE)) { @@ -551,19 +590,8 @@ int demodEM4x05resp(uint8_t bitsNeeded) { if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed"); } else { - // set size to 10 to only test first 4 positions for the preamble - size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - startIdx = 0; - - if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - - uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); - if ( errChk == 0) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); - } else { - //can't test size because the preamble doesn't repeat :( - //meaning chances of false positives are high. - demodFound = true; + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; } } } @@ -584,19 +612,8 @@ int demodEM4x05resp(uint8_t bitsNeeded) { if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); } else { - // set size to 10 to only test first 4 positions for the preamble - size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - startIdx = 0; - - if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - - uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); - if ( errChk == 0) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); - } else { - //can't test size because the preamble doesn't repeat :( - //meaning chances of false positives are high. - demodFound = true; + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; } } } @@ -608,19 +625,8 @@ int demodEM4x05resp(uint8_t bitsNeeded) { if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); } else { - // set size to 10 to only test first 4 positions for the preamble - size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - startIdx = 0; - - if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - - uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); - if ( errChk == 0) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); - } else { - //can't test size because the preamble doesn't repeat :( - //meaning chances of false positives are high. - demodFound = true; + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; } } } @@ -632,53 +638,23 @@ int demodEM4x05resp(uint8_t bitsNeeded) { if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); } else { - // set size to 10 to only test first 4 positions for the preamble - size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; - startIdx = 0; - - if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size); - - uint8_t errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); - if ( errChk == 0) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); - } else { - //can't test size because the preamble doesn't repeat :( - //meaning chances of false positives are high. - demodFound = true; + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; } } } - if (demodFound && bitsNeeded < DemodBufferLen) { + /*if (demodFound && bitsNeeded < DemodBufferLen) { if (bitsNeeded > 0) { setDemodBuf(DemodBuffer + startIdx + sizeof(preamble), bitsNeeded, 0); CmdPrintDemodBuff("x"); } return 1; - } + }*/ return -1; } -int CmdReadWord(const char *Cmd) { - int addr, pwd; - bool usePwd = false; - uint8_t ctmp = param_getchar(Cmd, 0); - if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_read(); - - addr = param_get8ex(Cmd, 0, -1, 10); - pwd = param_get32ex(Cmd, 1, -1, 16); - - if ( (addr > 15) || (addr < 0 ) || ( addr == -1) ) { - PrintAndLog("Address must be between 0 and 15"); - return 1; - } - if ( pwd == -1 ) - PrintAndLog("Reading address %d", addr); - else { - usePwd = true; - PrintAndLog("Reading address %d | password %08X", addr, pwd); - } - +int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) { UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}}; clearCommandBuffer(); SendCommand(&c); @@ -700,47 +676,115 @@ int CmdReadWord(const char *Cmd) { PrintAndLog("no tag not found"); return -1; } - //attempt demod: - //need 32 bits from a read word - return demodEM4x05resp(44); + uint32_t wordData = 0; + int success = demodEM4x05resp(&wordData, true); + if (success == 1) PrintAndLog("Got Address %02d | %08X",addr,wordData); + return success; } +int CmdEM4x05ReadWord(const char *Cmd) { + uint8_t addr; + uint32_t pwd; + bool usePwd = false; + uint8_t ctmp = param_getchar(Cmd, 0); + if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_read(); + + addr = param_get8ex(Cmd, 0, 50, 10); + // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) + pwd = param_get32ex(Cmd, 1, 1, 16); + + if ( (addr > 15) ) { + PrintAndLog("Address must be between 0 and 15"); + return 1; + } + if ( pwd == 1 ) + PrintAndLog("Reading address %02u", addr); + else { + usePwd = true; + PrintAndLog("Reading address %02u | password %08X", addr, pwd); + } + return EM4x05ReadWord(addr, pwd, usePwd); +} + +int usage_lf_em_dump(void) { + PrintAndLog("Dump EM4x05/EM4x69. Tag must be on antenna. "); + PrintAndLog(""); + PrintAndLog("Usage: lf em 4x05dump [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog("samples:"); + PrintAndLog(" lf em 4x05dump"); + PrintAndLog(" lf em 4x05dump 11223344"); + return 0; +} + +int CmdEM4x05dump(const char *Cmd) { + uint8_t addr = 0; + uint32_t pwd; + bool usePwd = false; + uint8_t ctmp = param_getchar(Cmd, 0); + if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump(); + + // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) + pwd = param_get32ex(Cmd, 0, 1, 16); + + if ( pwd != 1 ) { + usePwd = true; + } + int success = 1; + for (; addr < 16; addr++) { + if (addr == 2) { + if (usePwd) { + PrintAndLog("PWD Address %02u | %08X",addr,pwd); + } else { + PrintAndLog("PWD Address 02 | cannot read"); + } + } else { + success &= EM4x05ReadWord(addr, pwd, usePwd); + } + } + + return success; +} + + int usage_lf_em_write(void) { PrintAndLog("Write EM4x05/EM4x69. Tag must be on antenna. "); PrintAndLog(""); - PrintAndLog("Usage: lf em writeword [h]
"); + PrintAndLog("Usage: lf em 4x05writeword [h]
"); PrintAndLog("Options:"); PrintAndLog(" h - this help"); PrintAndLog(" address - memory address to write to. (0-15)"); PrintAndLog(" data - data to write (hex)"); PrintAndLog(" pwd - password (hex) (optional)"); PrintAndLog("samples:"); - PrintAndLog(" lf em writeword 1"); - PrintAndLog(" lf em writeword 1 deadc0de 11223344"); + PrintAndLog(" lf em 4x05writeword 1"); + PrintAndLog(" lf em 4x05writeword 1 deadc0de 11223344"); return 0; } -int CmdWriteWord(const char *Cmd) { +int CmdEM4x05WriteWord(const char *Cmd) { uint8_t ctmp = param_getchar(Cmd, 0); if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write(); bool usePwd = false; - int addr = 16; // default to invalid address - int data = 0xFFFFFFFF; // default to blank data - int pwd = 0xFFFFFFFF; // default to blank password + uint8_t addr = 16; // default to invalid address + uint32_t data = 0xFFFFFFFF; // default to blank data + uint32_t pwd = 0xFFFFFFFF; // default to blank password - addr = param_get8ex(Cmd, 0, -1, 10); - data = param_get32ex(Cmd, 1, -1, 16); - pwd = param_get32ex(Cmd, 2, -1, 16); + addr = param_get8ex(Cmd, 0, 16, 10); + data = param_get32ex(Cmd, 1, 0, 16); + pwd = param_get32ex(Cmd, 2, 1, 16); - if ( (addr > 15) || (addr < 0 ) || ( addr == -1) ) { + if ( (addr > 15) ) { PrintAndLog("Address must be between 0 and 15"); return 1; } - if ( pwd == -1 ) + if ( pwd == 1 ) PrintAndLog("Writing address %d data %08X", addr, data); else { usePwd = true; @@ -753,93 +797,41 @@ int CmdWriteWord(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){ + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)){ PrintAndLog("Error occurred, device did not respond during write operation."); return -1; } //get response if there is one uint8_t got[6000]; // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) GetFromBigBuf(got, sizeof(got), 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 8000) ) { + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) { PrintAndLog("command execution time out"); return 0; } setGraphBuf(got, sizeof(got)); - //todo: check response for 00001010 then write data for write confirmation! - + //check response for 00001010 for write confirmation! //attempt demod: - //need 0 bits demoded (after preamble) to verify write cmd - int result = demodEM4x05resp(0); + uint32_t dummy = 0; + int result = demodEM4x05resp(&dummy,false); if (result == 1) { PrintAndLog("Write Verified"); } return result; } -/* -int CmdWriteWord(const char *Cmd) -{ - int Word = 16; //default to invalid block - int Data = 0xFFFFFFFF; //default to blank data - UsbCommand c; - - sscanf(Cmd, "%x %d", &Data, &Word); - - if (Word > 15) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Writing word %d with data %08X", Word, Data); - - c.cmd = CMD_EM4X_WRITE_WORD; - c.d.asBytes[0] = 0x0; //Normal mode - c.arg[0] = Data; - c.arg[1] = Word; - c.arg[2] = 0; - SendCommand(&c); - return 0; -} - -int CmdWriteWordPWD(const char *Cmd) -{ - int Word = 16; //default to invalid word - int Data = 0xFFFFFFFF; //default to blank data - int Password = 0xFFFFFFFF; //default to blank password - UsbCommand c; - - sscanf(Cmd, "%x %d %x", &Data, &Word, &Password); - - if (Word > 15) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password); - - c.cmd = CMD_EM4X_WRITE_WORD; - c.d.asBytes[0] = 0x1; //Password mode - c.arg[0] = Data; - c.arg[1] = Word; - c.arg[2] = Password; - SendCommand(&c); - return 0; -} -*/ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"}, - {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"}, - {"em410xsim", CmdEM410xSim, 0, " [clock rate] -- Simulate EM410x tag"}, - {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, - {"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, - {"em410xwrite", CmdEM410xWrite, 0, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, - {"em4x50read", CmdEM4x50Read, 1, "demod data from EM4x50 tag from the graph buffer"}, - {"readword", CmdReadWord, 1, " (pwd) -- Read EM4x05/EM4x69 word data"}, - //{"readwordPWD", CmdReadWordPWD, 1, " -- Read EM4xxx word data in password mode"}, - {"writeword", CmdWriteWord, 1, " (pwd) -- Write EM4x05/EM4x69 word data"}, - //{"writewordPWD", CmdWriteWordPWD, 1, " -- Write EM4xxx word data in password mode"}, + {"410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"}, + {"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"}, + {"410xsim", CmdEM410xSim, 0, " [clock rate] -- Simulate EM410x tag"}, + {"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, + {"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, + {"410xwrite", CmdEM410xWrite, 0, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, + {"4x05dump", CmdEM4x05dump, 1, "(pwd) -- Read EM4x05/EM4x69 all word data"}, + {"4x05readword", CmdEM4x05ReadWord, 1, " (pwd) -- Read EM4x05/EM4x69 word data"}, + {"4x05writeword", CmdEM4x05WriteWord, 1, " (pwd) -- Write EM4x05/EM4x69 word data"}, + {"4x50read", CmdEM4x50Read, 1, "demod data from EM4x50 tag from the graph buffer"}, {NULL, NULL, 0, NULL} }; diff --git a/common/lfdemod.c b/common/lfdemod.c index f9f2d1f1..2ee66a52 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -62,7 +62,7 @@ uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType) for (uint8_t i = 0; i < bitLen; i++){ ans ^= ((bits >> i) & 1); } - //PrintAndLog("DEBUG: ans: %d, ptype: %d",ans,pType); + if (g_debugMode) prnt("DEBUG: ans: %d, ptype: %d, bits: %08X",ans,pType,bits); return (ans == pType); } @@ -73,11 +73,13 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p { uint32_t parityWd = 0; size_t j = 0, bitCnt = 0; - for (int word = 0; word < (bLen); word+=pLen){ - for (int bit=0; bit < pLen; bit++){ + for (int word = 0; word < (bLen); word+=pLen) { + for (int bit=0; bit < pLen; bit++) { parityWd = (parityWd << 1) | BitStream[startIdx+word+bit]; BitStream[j++] = (BitStream[startIdx+word+bit]); } + if (word+pLen >= bLen) break; + j--; // overwrite parity with next data // if parity fails then return 0 switch (pType) { From c85858f5247daf444cf2db070ba54df4f646d9f8 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 17 Feb 2017 12:59:35 -0500 Subject: [PATCH 06/19] minor fixes for FSK demod works better with EM4x03 and t55x7 tags (in theory)... --- armsrc/lfops.c | 4 ++-- common/lfdemod.c | 40 ++++++++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 29331754..72ab360e 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1656,10 +1656,10 @@ void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { SendForward(fwd_bit_count); //Wait for write to complete - //SpinDelay(5); + SpinDelayUs(8000); //Capture response if one exists - DoAcquisition_default(30, TRUE); + DoAcquisition_default(20, TRUE); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); diff --git a/common/lfdemod.c b/common/lfdemod.c index 2ee66a52..a32d3b85 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -487,19 +487,42 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow size_t preLastSample = 0; size_t LastSample = 0; size_t currSample = 0; - // sync to first lo-hi transition, and threshold + if ( size < 1024 ) return 0; // not enough samples + + // jump to modulating data by finding the first 4 threshold crossings (or first 2 waves) + // in case you have junk or noise at the beginning of the trace... + uint8_t thresholdCnt = 0; + size_t waveSizeCnt = 0; + bool isAboveThreshold = dest[idx] >= threshold_value; + for (; idx < size-20; idx++ ) { + if(dest[idx] < threshold_value && isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 4 && waveSizeCnt < fchigh+1) break; + isAboveThreshold = false; + waveSizeCnt = 0; + } else if (dest[idx] >= threshold_value && !isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 4 && waveSizeCnt < fchigh+1) break; + isAboveThreshold = true; + waveSizeCnt = 0; + } else { + waveSizeCnt++; + } + if (thresholdCnt > 10) break; + } + if (g_debugMode == 2) prnt("threshold Count reached at %u",idx); // Need to threshold first sample - // skip 160 samples to allow antenna/samples to settle - if(dest[160] < threshold_value) dest[0] = 0; + if(dest[idx] < threshold_value) dest[0] = 0; else dest[0] = 1; - + idx++; + size_t numBits = 0; // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8) // or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10 // (could also be fc/5 && fc/7 for fsk1 = 4-9) - for(idx = 161; idx < size-20; idx++) { + for(; idx < size-20; idx++) { // threshold current value if (dest[idx] < threshold_value) dest[idx] = 0; @@ -514,13 +537,14 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow //do nothing with extra garbage } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5) //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5) - if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1) || preLastSample == 0 )){ + if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){ dest[numBits-1]=1; } dest[numBits++]=1; - } else if (currSample > (fchigh) && !numBits) { //12 + and first bit = unusable garbage - //do nothing with beginning garbage + } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage + //do nothing with beginning garbage and reset.. should be rare.. + numBits = 0; } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's) dest[numBits++]=1; } else { //9+ = 10 sample waves (or 6+ = 7) From 6980d66b054071c75dfa522ad36eda97a2556159 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 17 Feb 2017 14:40:40 -0500 Subject: [PATCH 07/19] add psk to em4x05 reads and tweak psk demod --- armsrc/lfops.c | 4 +- client/cmdlfem4x.c | 105 ++++++++++++++++++++++++++------------------- common/lfdemod.c | 42 ++++++++++++++---- 3 files changed, 96 insertions(+), 55 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 72ab360e..2ddd2a06 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1628,7 +1628,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { SendForward(fwd_bit_count); // Now do the acquisition - DoAcquisition_default(30,TRUE); + DoAcquisition_default(0,TRUE); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); @@ -1656,7 +1656,7 @@ void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { SendForward(fwd_bit_count); //Wait for write to complete - SpinDelayUs(8000); + SpinDelay(10); //Capture response if one exists DoAcquisition_default(20, TRUE); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 16faa848..1ecf64d5 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -538,8 +538,8 @@ bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { // skip first two 0 bits as they might have been missed in the demod uint8_t preamble[6] = {0,0,1,0,1,0}; size_t startIdx = 0; - // set size to 10 to only test first 4 positions for the preamble - size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10; + // set size to 15 to only test first 9 positions for the preamble + size_t size = (15 > DemodBufferLen) ? DemodBufferLen : 15; startIdx = 0; //test preamble @@ -580,7 +580,6 @@ bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { // the rest will need to be manually demoded for now... int demodEM4x05resp(uint32_t *word, bool readCmd) { int ans = 0; - bool demodFound = false; DemodBufferLen = 0x00; // test for FSK wave (easiest to 99% ID) @@ -596,61 +595,77 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { } } // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... ) - if (!demodFound) { - ans = GetPskClock("", FALSE, FALSE); - if (ans>0) { - PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod"); + ans = GetPskClock("", FALSE, FALSE); + if (ans>0) { + //try psk1 + DemodBufferLen = 0x00; + ans = PSKDemod("0 0 6", FALSE); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed"); + } else { + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; + } else { + //try psk2 + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; + } + } + //try psk1 inverted + DemodBufferLen = 0x00; + ans = PSKDemod("0 1 6", FALSE); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed"); + } else { + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; + } else { + //try psk2 + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; + } + } + } } } // more common than biphase - if (!demodFound) { - DemodBufferLen = 0x00; - bool stcheck = false; - // try manchester - NOTE: ST only applies to T55x7 tags. - ans = ASKDemod_ext("0,0,1", false, false, 1, &stcheck); - if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); - } else { - if (EM4x05testDemodReadData(word, readCmd)) { - return 1; - } + DemodBufferLen = 0x00; + bool stcheck = false; + // try manchester - NOTE: ST only applies to T55x7 tags. + ans = ASKDemod_ext("0,0,1", false, false, 1, &stcheck); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); + } else { + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; } } - if (!demodFound) { - DemodBufferLen = 0x00; - //try biphase - ans = ASKbiphaseDemod("0 0 1", FALSE); - if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); - } else { - if (EM4x05testDemodReadData(word, readCmd)) { - return 1; - } + DemodBufferLen = 0x00; + //try biphase + ans = ASKbiphaseDemod("0 0 1", FALSE); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); + } else { + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; } } - if (!demodFound) { - DemodBufferLen = 0x00; - //try diphase (differential biphase or inverted) - ans = ASKbiphaseDemod("0 1 1", FALSE); - if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); - } else { - if (EM4x05testDemodReadData(word, readCmd)) { - return 1; - } + DemodBufferLen = 0x00; + //try diphase (differential biphase or inverted) + ans = ASKbiphaseDemod("0 1 1", FALSE); + if (!ans) { + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); + } else { + if (EM4x05testDemodReadData(word, readCmd)) { + return 1; } } - /*if (demodFound && bitsNeeded < DemodBufferLen) { - if (bitsNeeded > 0) { - setDemodBuf(DemodBuffer + startIdx + sizeof(preamble), bitsNeeded, 0); - CmdPrintDemodBuff("x"); - } - return 1; - }*/ return -1; } diff --git a/common/lfdemod.c b/common/lfdemod.c index a32d3b85..c66f3e04 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -493,16 +493,16 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow // in case you have junk or noise at the beginning of the trace... uint8_t thresholdCnt = 0; size_t waveSizeCnt = 0; - bool isAboveThreshold = dest[idx] >= threshold_value; + bool isAboveThreshold = dest[idx++] >= threshold_value; for (; idx < size-20; idx++ ) { if(dest[idx] < threshold_value && isAboveThreshold) { thresholdCnt++; - if (thresholdCnt > 4 && waveSizeCnt < fchigh+1) break; + if (thresholdCnt > 2 && waveSizeCnt < fchigh+1) break; isAboveThreshold = false; waveSizeCnt = 0; } else if (dest[idx] >= threshold_value && !isAboveThreshold) { thresholdCnt++; - if (thresholdCnt > 4 && waveSizeCnt < fchigh+1) break; + if (thresholdCnt > 2 && waveSizeCnt < fchigh+1) break; isAboveThreshold = true; waveSizeCnt = 0; } else { @@ -1491,7 +1491,7 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) size_t numBits=0; uint8_t curPhase = *invert; - size_t i, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0; + size_t i=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0; uint8_t fc=0, fullWaveLen=0, tol=1; uint16_t errCnt=0, waveLenCnt=0; fc = countFC(dest, *size, 0); @@ -1499,19 +1499,45 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) //PrintAndLog("DEBUG: FC: %d",fc); *clock = DetectPSKClock(dest, *size, *clock); if (*clock == 0) return -1; + // jump to modulating data by finding the first 2 threshold crossings (or first 1 waves) + // in case you have junk or noise at the beginning of the trace... + uint8_t thresholdCnt = 0; + size_t waveSizeCnt = 0; + uint8_t threshold_value = 123; //-5 + bool isAboveThreshold = dest[i++] >= threshold_value; + for (; i < *size-20; i++ ) { + if(dest[i] < threshold_value && isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 2 && waveSizeCnt < fc+1) break; + isAboveThreshold = false; + waveSizeCnt = 0; + } else if (dest[i] >= threshold_value && !isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 2 && waveSizeCnt < fc+1) break; + isAboveThreshold = true; + waveSizeCnt = 0; + } else { + waveSizeCnt++; + } + if (thresholdCnt > 10) break; + } + if (g_debugMode == 2) prnt("DEBUG PSK: threshold Count reached at %u, count: %u",i, thresholdCnt); + + int avgWaveVal=0, lastAvgWaveVal=0; + waveStart = i+1; //find first phase shift - for (i=0; i= dest[i+2]){ waveEnd = i+1; - //PrintAndLog("DEBUG: waveEnd: %d",waveEnd); + if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u",waveEnd, waveStart); waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+2)){ //not first peak and is a large wave but not out of whack + if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+3)){ //not first peak and is a large wave but not out of whack lastAvgWaveVal = avgWaveVal/(waveLenCnt); firstFullWave = waveStart; fullWaveLen=waveLenCnt; //if average wave value is > graph 0 then it is an up wave or a 1 - if (lastAvgWaveVal > 123) curPhase ^= 1; //fudge graph 0 a little 123 vs 128 + if (lastAvgWaveVal > threshold_value) curPhase ^= 1; //fudge graph 0 a little 123 vs 128 break; } waveStart = i+1; From 61500621bcceb9b210ee2191f257244bf80de474 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 17 Feb 2017 14:48:19 -0500 Subject: [PATCH 08/19] @iceman1001 s idea to output failure report --- client/cmdlfem4x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 1ecf64d5..531199c4 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -719,7 +719,12 @@ int CmdEM4x05ReadWord(const char *Cmd) { usePwd = true; PrintAndLog("Reading address %02u | password %08X", addr, pwd); } - return EM4x05ReadWord(addr, pwd, usePwd); + + int result = EM4x05ReadWord(addr, pwd, usePwd); + if (result == -1) + PrintAndLog("Read failed"); + + return result; } int usage_lf_em_dump(void) { From 4c6ccc2b042d4c6821d579f2d9ee967cfd2cde18 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sun, 19 Feb 2017 20:47:45 -0500 Subject: [PATCH 09/19] a little cleanup --- client/cmdlfem4x.c | 115 +++++++++++++++++---------------------------- common/lfdemod.c | 17 +++++++ common/lfdemod.h | 1 + 3 files changed, 60 insertions(+), 73 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 531199c4..397b21e7 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -228,6 +228,7 @@ int CmdEM410xWrite(const char *Cmd) return 0; } +//**************** Start of EM4x50 Code ************************ bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { if (rows*cols>size) return false; @@ -499,6 +500,7 @@ int CmdEM4x50Read(const char *Cmd) return EM4x50Read(Cmd, true); } +//**************** Start of EM4x05/EM4x69 Code ************************ int usage_lf_em_read(void) { PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. "); PrintAndLog(""); @@ -513,64 +515,47 @@ int usage_lf_em_read(void) { return 0; } -//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex -bool EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx) { - // Sanity check. If preamble length is bigger than bitstream length. - if ( size <= pLen ) return false; - // em only sends preamble once, so look for it once in the first x bits - uint8_t foundCnt = 0; - for (size_t idx = 0; idx < size - pLen; idx++){ - if (memcmp(BitStream+idx, preamble, pLen) == 0){ - //first index found - foundCnt++; - if (foundCnt == 1) { - if (g_debugMode) PrintAndLog("DEBUG: preamble found at %u", idx); - *startIdx = idx; - - return true; - } - } +// for command responses from em4x05 or em4x69 +// download samples from device and copy them to the Graphbuffer +bool downloadSamplesEM() { + // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) + uint8_t got[6000]; + GetFromBigBuf(got, sizeof(got), 0); + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) { + PrintAndLog("command execution time out"); + return false; } - return false; + setGraphBuf(got, sizeof(got)); + return true; } bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { - // skip first two 0 bits as they might have been missed in the demod - uint8_t preamble[6] = {0,0,1,0,1,0}; + // em4x05/em4x69 preamble is 00001010 + // skip first two 0 bits as they might have been missed in the demod + uint8_t preamble[] = {0,0,1,0,1,0}; size_t startIdx = 0; // set size to 15 to only test first 9 positions for the preamble size_t size = (15 > DemodBufferLen) ? DemodBufferLen : 15; - startIdx = 0; //test preamble - bool errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx); - if ( !errChk ) { + if ( !onePreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx) ) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); return false; } + // if this is a readword command, get the read bytes and test the parities if (readCmd) { + if (!EM_EndParityTest(DemodBuffer + startIdx + sizeof(preamble), 45, 5, 9, 0)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - End Parity check failed"); + return false; + } //test for even parity bits. - size = removeParity(DemodBuffer, startIdx + sizeof(preamble),9,0,44); - if (size == 0) { + if ( removeParity(DemodBuffer, startIdx + sizeof(preamble),9,0,44) == 0 ) { if (g_debugMode) PrintAndLog("DEBUG: Error - Parity not detected"); return false; } - //todo test last 8 bits for even parity || (xor) - setDemodBuf(DemodBuffer, 40, 0); - - *word = bytebits_to_byteLSBF(DemodBuffer , 32); - - uint8_t lo = (uint8_t) bytebits_to_byteLSBF(DemodBuffer , 8); - uint8_t lo2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 8, 8); - uint8_t hi = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 16, 8); - uint8_t hi2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 24, 8); - uint8_t cs = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 32, 8); - uint8_t cs2 = lo ^ lo2 ^ hi ^ hi2; - if (g_debugMode) PrintAndLog("EM4x05/4x69 : %08X CS: %02X %s",*word,cs, (cs2==cs) ? "Passed" : "Failed"); - - return (cs2==cs) ? true : false; + *word = bytebits_to_byteLSBF(DemodBuffer, 32); } return true; } @@ -580,14 +565,13 @@ bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { // the rest will need to be manually demoded for now... int demodEM4x05resp(uint32_t *word, bool readCmd) { int ans = 0; - DemodBufferLen = 0x00; // test for FSK wave (easiest to 99% ID) if (GetFskClock("", FALSE, FALSE)) { //valid fsk clocks found ans = FSKrawDemod("0 0", false); if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed"); + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed, ans: %d", ans); } else { if (EM4x05testDemodReadData(word, readCmd)) { return 1; @@ -598,10 +582,9 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { ans = GetPskClock("", FALSE, FALSE); if (ans>0) { //try psk1 - DemodBufferLen = 0x00; ans = PSKDemod("0 0 6", FALSE); if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed"); + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans); } else { if (EM4x05testDemodReadData(word, readCmd)) { return 1; @@ -613,10 +596,9 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { } } //try psk1 inverted - DemodBufferLen = 0x00; ans = PSKDemod("0 1 6", FALSE); if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed"); + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans); } else { if (EM4x05testDemodReadData(word, readCmd)) { return 1; @@ -631,35 +613,32 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { } } - // more common than biphase - DemodBufferLen = 0x00; + // manchester is more common than biphase... try first bool stcheck = false; // try manchester - NOTE: ST only applies to T55x7 tags. ans = ASKDemod_ext("0,0,1", false, false, 1, &stcheck); if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed"); + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed, ans: %d", ans); } else { if (EM4x05testDemodReadData(word, readCmd)) { return 1; } } - DemodBufferLen = 0x00; //try biphase ans = ASKbiphaseDemod("0 0 1", FALSE); if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans); } else { if (EM4x05testDemodReadData(word, readCmd)) { return 1; } } - DemodBufferLen = 0x00; //try diphase (differential biphase or inverted) ans = ASKbiphaseDemod("0 1 1", FALSE); if (!ans) { - if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed"); + if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans); } else { if (EM4x05testDemodReadData(word, readCmd)) { return 1; @@ -678,14 +657,9 @@ int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) { PrintAndLog("Command timed out"); return -1; } - - uint8_t got[6000]; - GetFromBigBuf(got, sizeof(got), 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { - PrintAndLog("command execution time out"); + if ( !downloadSamplesEM() ) { return -1; } - setGraphBuf(got, sizeof(got)); int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000; if (graphJustNoise(GraphBuffer, testLen)) { PrintAndLog("no tag not found"); @@ -694,7 +668,11 @@ int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) { //attempt demod: uint32_t wordData = 0; int success = demodEM4x05resp(&wordData, true); - if (success == 1) PrintAndLog("Got Address %02d | %08X",addr,wordData); + if (success == 1) + PrintAndLog(" Got Address %02d | %08X",addr,wordData); + else + PrintAndLog("RSead Address %02d | failed",addr); + return success; } @@ -713,18 +691,14 @@ int CmdEM4x05ReadWord(const char *Cmd) { PrintAndLog("Address must be between 0 and 15"); return 1; } - if ( pwd == 1 ) + if ( pwd == 1 ) { PrintAndLog("Reading address %02u", addr); - else { + } else { usePwd = true; PrintAndLog("Reading address %02u | password %08X", addr, pwd); } - int result = EM4x05ReadWord(addr, pwd, usePwd); - if (result == -1) - PrintAndLog("Read failed"); - - return result; + return EM4x05ReadWord(addr, pwd, usePwd); } int usage_lf_em_dump(void) { @@ -821,14 +795,9 @@ int CmdEM4x05WriteWord(const char *Cmd) { PrintAndLog("Error occurred, device did not respond during write operation."); return -1; } - //get response if there is one - uint8_t got[6000]; // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) - GetFromBigBuf(got, sizeof(got), 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) { - PrintAndLog("command execution time out"); - return 0; + if ( !downloadSamplesEM() ) { + return -1; } - setGraphBuf(got, sizeof(got)); //check response for 00001010 for write confirmation! //attempt demod: uint32_t dummy = 0; diff --git a/common/lfdemod.c b/common/lfdemod.c index c66f3e04..fbed6a9a 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -170,6 +170,23 @@ uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_ return 0; } +// search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) +// does not look for a repeating preamble +// em4x05/4x69 only sends preamble once, so look for it once in the first pLen bits +// leave it generic so it could be reused later... +bool onePreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx) { + // Sanity check. If preamble length is bigger than bitstream length. + if ( size <= pLen ) return false; + for (size_t idx = 0; idx < size - pLen; idx++) { + if (memcmp(BitStream+idx, preamble, pLen) == 0) { + if (g_debugMode) prnt("DEBUG: preamble found at %u", idx); + *startIdx = idx; + return true; + } + } + return false; +} + //by marshmellow //takes 1s and 0s and searches for EM410x format - output EM ID uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo) diff --git a/common/lfdemod.h b/common/lfdemod.h index b988c1bf..9c5c83fb 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -39,6 +39,7 @@ int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert); int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert); uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); +bool onePreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx); int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert); void psk2TOpsk1(uint8_t *BitStream, size_t size); void psk1TOpsk2(uint8_t *BitStream, size_t size); From 34212c662c0448143733b60484a83b371325e4a7 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sun, 19 Feb 2017 21:31:46 -0500 Subject: [PATCH 10/19] fix dump output --- client/cmdlfem4x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 397b21e7..8e535b9a 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -567,7 +567,7 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { int ans = 0; // test for FSK wave (easiest to 99% ID) - if (GetFskClock("", FALSE, FALSE)) { + if (GetFskClock("", false, false)) { //valid fsk clocks found ans = FSKrawDemod("0 0", false); if (!ans) { @@ -579,10 +579,10 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { } } // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... ) - ans = GetPskClock("", FALSE, FALSE); + ans = GetPskClock("", false, false); if (ans>0) { //try psk1 - ans = PSKDemod("0 0 6", FALSE); + ans = PSKDemod("0 0 6", false); if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans); } else { @@ -596,7 +596,7 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { } } //try psk1 inverted - ans = PSKDemod("0 1 6", FALSE); + ans = PSKDemod("0 1 6", false); if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans); } else { @@ -626,7 +626,7 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { } //try biphase - ans = ASKbiphaseDemod("0 0 1", FALSE); + ans = ASKbiphaseDemod("0 0 1", false); if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans); } else { @@ -636,7 +636,7 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { } //try diphase (differential biphase or inverted) - ans = ASKbiphaseDemod("0 1 1", FALSE); + ans = ASKbiphaseDemod("0 1 1", false); if (!ans) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans); } else { @@ -731,9 +731,9 @@ int CmdEM4x05dump(const char *Cmd) { for (; addr < 16; addr++) { if (addr == 2) { if (usePwd) { - PrintAndLog("PWD Address %02u | %08X",addr,pwd); + PrintAndLog(" PWD Address %02u | %08X",addr,pwd); } else { - PrintAndLog("PWD Address 02 | cannot read"); + PrintAndLog(" PWD Address 02 | cannot read"); } } else { success &= EM4x05ReadWord(addr, pwd, usePwd); From fa1e00cfbbabec0580adc94f799a44068d05296f Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 20 Feb 2017 09:50:00 -0500 Subject: [PATCH 11/19] add em4x05 info command plus some minor adjustments and added a quick em4x05 test: bool EM4x05Block0Test(uint32_t *wordData) if successful very likely the tag is an em4x05 or compatible... --- armsrc/lfops.c | 10 +++--- client/cmdlfem4x.c | 85 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 11 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 2ddd2a06..87b21efc 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1573,14 +1573,14 @@ void SendForward(uint8_t fwd_bit_count) { // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); - + // force 1st mod pulse (start gap must be longer for 4305) fwd_bit_sz--; //prepare next bit modulation fwd_write_ptr++; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - SpinDelayUs(55*8); //55 cycles off (8us each)for 4305 + SpinDelayUs(56*8); //55 cycles off (8us each)for 4305 /another reader has 37 here... FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on - SpinDelayUs(16*8); //16 cycles on (8us each) + SpinDelayUs(18*8); //16 cycles on (8us each) // another reader has 18 here // now start writting while(fwd_bit_sz-- > 0) { //prepare next bit modulation @@ -1589,9 +1589,9 @@ void SendForward(uint8_t fwd_bit_count) { else { //These timings work for 4469/4269/4305 (with the 55*8 above) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - SpinDelayUs(20*8); //16-4 cycles off (8us each) //23 + SpinDelayUs(23*8); //16-4 cycles off (8us each) //23 //one reader goes as high as 25 here FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on - SpinDelayUs(12*8); //16 cycles on (8us each) //9 + SpinDelayUs(16*8); //16 cycles on (8us each) //9 // another reader goes to 17 here } } } diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 8e535b9a..6781b03d 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -648,7 +648,7 @@ int demodEM4x05resp(uint32_t *word, bool readCmd) { return -1; } -int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) { +int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *wordData) { UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}}; clearCommandBuffer(); SendCommand(&c); @@ -666,12 +666,16 @@ int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) { return -1; } //attempt demod: + return demodEM4x05resp(wordData, true); +} + +int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) { uint32_t wordData = 0; - int success = demodEM4x05resp(&wordData, true); + int success = EM4x05ReadWord_ext(addr, pwd, usePwd, &wordData); if (success == 1) PrintAndLog(" Got Address %02d | %08X",addr,wordData); else - PrintAndLog("RSead Address %02d | failed",addr); + PrintAndLog("Read Address %02d | failed",addr); return success; } @@ -808,6 +812,74 @@ int CmdEM4x05WriteWord(const char *Cmd) { return result; } +void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t serial) { + switch (chipType) { + case 9: PrintAndLog("\nChip Type: %u | EM4305", chipType); break; + case 4: PrintAndLog("Chip Type: %u | Unknown", chipType); break; + case 2: PrintAndLog("Chip Type: %u | EM4469", chipType); break; + //add more here when known + default: PrintAndLog("Chip Type: %u Unknown", chipType); break; + } + + switch (cap) { + case 3: PrintAndLog(" Cap Type: %u | 330pF",cap); break; + case 2: PrintAndLog(" Cap Type: %u | 210pF",cap); break; + case 1: PrintAndLog(" Cap Type: %u | 250pF",cap); break; + default: PrintAndLog(" Cap Type: %u | unknown",cap); break; + } + + PrintAndLog("Cust Code: %03u | %s", custCode, (custCode == 0x200) ? "Default": "Unknown"); + if (serial != 0) { + PrintAndLog("\n Serial #: %08X\n", serial); + } +} + +//quick test for EM4x05/EM4x69 tag +bool EM4x05Block0Test(uint32_t *wordData) { + if (EM4x05ReadWord_ext(0,0,false,wordData) == 1) { + return true; + } + return false; +} + +int CmdEM4x05info(const char *Cmd) { + //uint8_t addr = 0; + //uint32_t pwd; + uint32_t wordData = 0; + // bool usePwd = false; + uint8_t ctmp = param_getchar(Cmd, 0); + if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump(); + + // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) + //pwd = param_get32ex(Cmd, 0, 1, 16); + + //if ( pwd != 1 ) { + // usePwd = true; + //} + int success = 1; + // read blk 0 + + //block 0 can be read even without a password. + if ( !EM4x05Block0Test(&wordData) ) + return -1; + + uint8_t chipType = (wordData >> 1) & 0xF; + uint8_t cap = (wordData >> 5) & 3; + uint16_t custCode = (wordData >> 9) & 0x3FF; + + wordData = 0; + if (EM4x05ReadWord_ext(1, 0, false, &wordData) != 1) { + //failed, but continue anyway... + } + printEM4x05info(chipType, cap, custCode, wordData); + + // add read block 4 and read out config if successful + // needs password if one is set + + return success; +} + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -817,9 +889,10 @@ static command_t CommandTable[] = {"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, {"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, {"410xwrite", CmdEM410xWrite, 0, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, - {"4x05dump", CmdEM4x05dump, 1, "(pwd) -- Read EM4x05/EM4x69 all word data"}, - {"4x05readword", CmdEM4x05ReadWord, 1, " (pwd) -- Read EM4x05/EM4x69 word data"}, - {"4x05writeword", CmdEM4x05WriteWord, 1, " (pwd) -- Write EM4x05/EM4x69 word data"}, + {"4x05dump", CmdEM4x05dump, 0, "(pwd) -- Read EM4x05/EM4x69 all word data"}, + {"4x05info", CmdEM4x05info, 0, "(pwd) -- Get info from EM4x05/EM4x69 tag"}, + {"4x05readword", CmdEM4x05ReadWord, 0, " (pwd) -- Read EM4x05/EM4x69 word data"}, + {"4x05writeword", CmdEM4x05WriteWord, 0, " (pwd) -- Write EM4x05/EM4x69 word data"}, {"4x50read", CmdEM4x50Read, 1, "demod data from EM4x50 tag from the graph buffer"}, {NULL, NULL, 0, NULL} }; From 893534d3b5753b110b84144596da6c6d0815c1cc Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 20 Feb 2017 15:06:22 -0500 Subject: [PATCH 12/19] speed up the em4x05 cmds by only getting 6k... samples back --- armsrc/lfops.c | 2 +- client/cmdlfem4x.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 87b21efc..cfe032fc 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1628,7 +1628,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { SendForward(fwd_bit_count); // Now do the acquisition - DoAcquisition_default(0,TRUE); + doT55x7Acquisition(6000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 6781b03d..e0c415bb 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -534,8 +534,8 @@ bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { // skip first two 0 bits as they might have been missed in the demod uint8_t preamble[] = {0,0,1,0,1,0}; size_t startIdx = 0; - // set size to 15 to only test first 9 positions for the preamble - size_t size = (15 > DemodBufferLen) ? DemodBufferLen : 15; + // set size to 20 to only test first 14 positions for the preamble + size_t size = (20 > DemodBufferLen) ? DemodBufferLen : 20; //test preamble if ( !onePreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx) ) { From a37228c8c26f32c3462f6b1641e64acddd62e0cc Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 20 Feb 2017 17:39:39 -0500 Subject: [PATCH 13/19] shorten em4x05 capture samples add cap option for 4469 add sample size option for DoAcquisition so i can limit how many samples i want to collect. use with DoPartialAcquisition --- armsrc/lfops.c | 6 +++--- armsrc/lfsampling.c | 13 +++++++++---- armsrc/lfsampling.h | 4 +++- client/cmdlfem4x.c | 3 ++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index cfe032fc..35f220c0 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1628,7 +1628,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { SendForward(fwd_bit_count); // Now do the acquisition - doT55x7Acquisition(6000); + DoPartialAcquisition(20, true, 5500); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); @@ -1656,10 +1656,10 @@ void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { SendForward(fwd_bit_count); //Wait for write to complete - SpinDelay(10); + //SpinDelay(10); //Capture response if one exists - DoAcquisition_default(20, TRUE); + DoPartialAcquisition(20, true, 5500); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 72aabe00..aff31e9e 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -119,11 +119,11 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) * @param silent - is true, now outputs are made. If false, dbprints the status * @return the number of bits occupied by the samples. */ -uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent) +uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize) { //. uint8_t *dest = BigBuf_get_addr(); - int bufsize = BigBuf_max_traceLen(); + bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen(); //memset(dest, 0, bufsize); //creates issues with cmdread (marshmellow) @@ -213,7 +213,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag */ uint32_t DoAcquisition_default(int trigger_threshold, bool silent) { - return DoAcquisition(1,8,0,trigger_threshold,silent); + return DoAcquisition(1,8,0,trigger_threshold,silent,0); } uint32_t DoAcquisition_config( bool silent) { @@ -221,7 +221,12 @@ uint32_t DoAcquisition_config( bool silent) ,config.bits_per_sample ,config.averaging ,config.trigger_threshold - ,silent); + ,silent + ,0); +} + +uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size) { + return DoAcquisition(1,8,0,trigger_threshold,silent,sample_size); } uint32_t ReadLF(bool activeField, bool silent) diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index ba4fc3f7..cd774c15 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -24,9 +24,11 @@ uint32_t SampleLF(bool silent); * Initializes the FPGA for snoop-mode (field off), and acquires the samples. * @return number of bits sampled **/ - uint32_t SnoopLF(); +// adds sample size to default options +uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size); + /** * @brief Does sample acquisition, ignoring the config values set in the sample_config. * This method is typically used by tag-specific readers who just wants to read the samples diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index e0c415bb..6208e63c 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -823,8 +823,9 @@ void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t switch (cap) { case 3: PrintAndLog(" Cap Type: %u | 330pF",cap); break; - case 2: PrintAndLog(" Cap Type: %u | 210pF",cap); break; + case 2: PrintAndLog(" Cap Type: %u | %spF",cap, (chipType==2)? "75":"210"); break; case 1: PrintAndLog(" Cap Type: %u | 250pF",cap); break; + case 0: PrintAndLog(" Cap Type: %u | no resonant capacitor",cap); break; default: PrintAndLog(" Cap Type: %u | unknown",cap); break; } From 0a85edf471497a491fa3900fca9a585a6ed8f0c6 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 21 Feb 2017 11:06:19 -0500 Subject: [PATCH 14/19] add em4x05 config printout --- client/cmdlfem4x.c | 109 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 23 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 6208e63c..662629f0 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -812,26 +812,84 @@ int CmdEM4x05WriteWord(const char *Cmd) { return result; } +void printEM4x05config(uint32_t wordData) { + uint16_t datarate = (((wordData & 0x3F)+1)*2); + uint8_t encoder = ((wordData >> 6) & 0xF); + char enc[14]; + memset(enc,0,sizeof(enc)); + + uint8_t PSKcf = (wordData >> 10) & 0x3; + char cf[10]; + memset(cf,0,sizeof(cf)); + uint8_t delay = (wordData >> 12) & 0x3; + char cdelay[33]; + memset(cdelay,0,sizeof(cdelay)); + uint8_t LWR = (wordData >> 14) & 0xF; //last word read + + switch (encoder) { + case 0: snprintf(enc,sizeof(enc),"NRZ"); break; + case 1: snprintf(enc,sizeof(enc),"Manchester"); break; + case 2: snprintf(enc,sizeof(enc),"Biphase"); break; + case 3: snprintf(enc,sizeof(enc),"Miller"); break; + case 4: snprintf(enc,sizeof(enc),"PSK1"); break; + case 5: snprintf(enc,sizeof(enc),"PSK2"); break; + case 6: snprintf(enc,sizeof(enc),"PSK3"); break; + case 7: snprintf(enc,sizeof(enc),"Unknown"); break; + case 8: snprintf(enc,sizeof(enc),"FSK1"); break; + case 9: snprintf(enc,sizeof(enc),"FSK2"); break; + default: snprintf(enc,sizeof(enc),"Unknown"); break; + } + + switch (PSKcf) { + case 0: snprintf(cf,sizeof(cf),"RF/2"); break; + case 1: snprintf(cf,sizeof(cf),"RF/8"); break; + case 2: snprintf(cf,sizeof(cf),"RF/4"); break; + case 3: snprintf(cf,sizeof(cf),"unknown"); break; + } + + switch (delay) { + case 0: snprintf(cdelay, sizeof(cdelay),"no delay"); break; + case 1: snprintf(cdelay, sizeof(cdelay),"BP/8 or 1/8th bit period delay"); break; + case 2: snprintf(cdelay, sizeof(cdelay),"BP/4 or 1/4th bit period delay"); break; + case 3: snprintf(cdelay, sizeof(cdelay),"no delay"); break; + } + PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData); + PrintAndLog("Config Breakdown:", wordData); + PrintAndLog(" Data Rate: %02X | RF/%u", wordData & 0x3F, datarate); + PrintAndLog(" Encoder: %u | %s", encoder, enc); + PrintAndLog(" PSK CF: %u | %s", PSKcf, cf); + PrintAndLog(" Delay: %u | %s", delay, cdelay); + PrintAndLog(" LastWordR: %02u | Address of last default word read", LWR); + PrintAndLog(" ReadLogin: %u | Read Login is %s", (wordData & 0x40000)>>18, (wordData & 0x40000) ? "Required" : "Not Required"); + PrintAndLog(" ReadHKL: %u | Read Housekeeping Words Login is %s", (wordData & 0x80000)>>19, (wordData & 0x80000) ? "Required" : "Not Required"); + PrintAndLog("WriteLogin: %u | Write Login is %s", (wordData & 0x100000)>>20, (wordData & 0x100000) ? "Required" : "Not Required"); + PrintAndLog(" WriteHKL: %u | Write Housekeeping Words Login is %s", (wordData & 0x200000)>>21, (wordData & 0x200000) ? "Required" : "Not Required"); + PrintAndLog(" R.A.W.: %u | Read After Write is %s", (wordData & 0x400000)>>22, (wordData & 0x400000) ? "On" : "Off"); + PrintAndLog(" Disable: %u | Disable Command is %s", (wordData & 0x800000)>>23, (wordData & 0x800000) ? "Accepted" : "Not Accepted"); + PrintAndLog(" R.T.F.: %u | Reader Talk First is %s", (wordData & 0x1000000)>>24, (wordData & 0x1000000) ? "Enabled" : "Disabled"); + PrintAndLog(" Pigeon: %u | Pigeon Mode is %s\n", (wordData & 0x4000000)>>26, (wordData & 0x4000000) ? "Enabled" : "Disabled"); +} + void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t serial) { switch (chipType) { - case 9: PrintAndLog("\nChip Type: %u | EM4305", chipType); break; - case 4: PrintAndLog("Chip Type: %u | Unknown", chipType); break; - case 2: PrintAndLog("Chip Type: %u | EM4469", chipType); break; + case 9: PrintAndLog("\n Chip Type: %u | EM4305", chipType); break; + case 4: PrintAndLog(" Chip Type: %u | Unknown", chipType); break; + case 2: PrintAndLog(" Chip Type: %u | EM4469", chipType); break; //add more here when known - default: PrintAndLog("Chip Type: %u Unknown", chipType); break; + default: PrintAndLog(" Chip Type: %u Unknown", chipType); break; } switch (cap) { - case 3: PrintAndLog(" Cap Type: %u | 330pF",cap); break; - case 2: PrintAndLog(" Cap Type: %u | %spF",cap, (chipType==2)? "75":"210"); break; - case 1: PrintAndLog(" Cap Type: %u | 250pF",cap); break; - case 0: PrintAndLog(" Cap Type: %u | no resonant capacitor",cap); break; - default: PrintAndLog(" Cap Type: %u | unknown",cap); break; + case 3: PrintAndLog(" Cap Type: %u | 330pF",cap); break; + case 2: PrintAndLog(" Cap Type: %u | %spF",cap, (chipType==2)? "75":"210"); break; + case 1: PrintAndLog(" Cap Type: %u | 250pF",cap); break; + case 0: PrintAndLog(" Cap Type: %u | no resonant capacitor",cap); break; + default: PrintAndLog(" Cap Type: %u | unknown",cap); break; } - PrintAndLog("Cust Code: %03u | %s", custCode, (custCode == 0x200) ? "Default": "Unknown"); + PrintAndLog(" Cust Code: %03u | %s", custCode, (custCode == 0x200) ? "Default": "Unknown"); if (serial != 0) { - PrintAndLog("\n Serial #: %08X\n", serial); + PrintAndLog("\n Serial #: %08X\n", serial); } } @@ -845,22 +903,21 @@ bool EM4x05Block0Test(uint32_t *wordData) { int CmdEM4x05info(const char *Cmd) { //uint8_t addr = 0; - //uint32_t pwd; + uint32_t pwd; uint32_t wordData = 0; - // bool usePwd = false; + bool usePwd = false; uint8_t ctmp = param_getchar(Cmd, 0); if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump(); // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) - //pwd = param_get32ex(Cmd, 0, 1, 16); + pwd = param_get32ex(Cmd, 0, 1, 16); - //if ( pwd != 1 ) { - // usePwd = true; - //} - int success = 1; - // read blk 0 + if ( pwd != 1 ) { + usePwd = true; + } - //block 0 can be read even without a password. + // read word 0 (chip info) + // block 0 can be read even without a password. if ( !EM4x05Block0Test(&wordData) ) return -1; @@ -868,16 +925,22 @@ int CmdEM4x05info(const char *Cmd) { uint8_t cap = (wordData >> 5) & 3; uint16_t custCode = (wordData >> 9) & 0x3FF; + // read word 1 (serial #) doesn't need pwd wordData = 0; if (EM4x05ReadWord_ext(1, 0, false, &wordData) != 1) { //failed, but continue anyway... } printEM4x05info(chipType, cap, custCode, wordData); - // add read block 4 and read out config if successful + // read word 4 (config block) // needs password if one is set - - return success; + wordData = 0; + if ( EM4x05ReadWord_ext(4, pwd, usePwd, &wordData) != 1 ) { + //failed + return 0; + } + printEM4x05config(wordData); + return 1; } From d0b0586411805d505047229e9bfd75fdc5c61559 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 21 Feb 2017 11:46:13 -0500 Subject: [PATCH 15/19] cleanup cmdlfem4x.h - add chip detection to ... ... lf search --- client/cmdlf.c | 52 ++++++++++++++++++++++++++++++++++------------ client/cmdlfem4x.h | 13 +++++++----- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 34104518..8b6f32b6 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1078,9 +1078,29 @@ int CmdVchDemod(const char *Cmd) return 0; } + +//by marshmellow +int CheckChipType(char cmdp) { + uint32_t wordData = 0; + + //check for em4x05/em4x69 chips first + save_restoreGB(1); + if ((!offline && (cmdp != '1')) && EM4x05Block0Test(&wordData)) { + PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nTry lf em 4x05... commands\n"); + save_restoreGB(0); + return 1; + } + + //TODO check for t55xx chip... + + save_restoreGB(0); + return 1; +} + //by marshmellow int CmdLFfind(const char *Cmd) { + uint32_t wordData = 0; int ans=0; size_t minLength = 1000; char cmdp = param_getchar(Cmd, 0); @@ -1115,7 +1135,12 @@ int CmdLFfind(const char *Cmd) // only run if graphbuffer is just noise as it should be for hitag/cotag if (graphJustNoise(GraphBuffer, testLen)) { // only run these tests if we are in online mode - if (!offline && (cmdp != '1')){ + if (!offline && (cmdp != '1')) { + // test for em4x05 in reader talk first mode. + if (EM4x05Block0Test(&wordData)) { + PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n"); + return 1; + } ans=CmdLFHitagReader("26"); if (ans==0) { return 1; @@ -1132,49 +1157,49 @@ int CmdLFfind(const char *Cmd) ans=CmdFSKdemodIO(""); if (ans>0) { PrintAndLog("\nValid IO Prox ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdFSKdemodPyramid(""); if (ans>0) { PrintAndLog("\nValid Pyramid ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdFSKdemodParadox(""); if (ans>0) { PrintAndLog("\nValid Paradox ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdFSKdemodAWID(""); if (ans>0) { PrintAndLog("\nValid AWID ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdFSKdemodHID(""); if (ans>0) { PrintAndLog("\nValid HID Prox ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdAskEM410xDemod(""); if (ans>0) { PrintAndLog("\nValid EM410x ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdG_Prox_II_Demod(""); if (ans>0) { PrintAndLog("\nValid G Prox II ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdFDXBdemodBI(""); if (ans>0) { PrintAndLog("\nValid FDX-B ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=EM4x50Read("", false); @@ -1186,24 +1211,25 @@ int CmdLFfind(const char *Cmd) ans=CmdVikingDemod(""); if (ans>0) { PrintAndLog("\nValid Viking ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdIndalaDecode(""); if (ans>0) { PrintAndLog("\nValid Indala ID Found!"); - return 1; + return CheckChipType(cmdp); } ans=CmdPSKNexWatch(""); if (ans>0) { PrintAndLog("\nValid NexWatch ID Found!"); - return 1; + return CheckChipType(cmdp); } PrintAndLog("\nNo Known Tags Found!\n"); if (testRaw=='u' || testRaw=='U'){ - //test unknown tag formats (raw mode) + ans=CheckChipType(cmdp); + //test unknown tag formats (raw mode)0 PrintAndLog("\nChecking for Unknown tags:\n"); ans=AutoCorrelate(4000, FALSE, FALSE); if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans); diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index 400536d3..7faf6f49 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -18,11 +18,14 @@ int CmdEM410xWatch(const char *Cmd); int CmdEM410xWatchnSpoof(const char *Cmd); int CmdEM410xWrite(const char *Cmd); int CmdEM4x50Read(const char *Cmd); -int CmdLFEM4X(const char *Cmd); -int CmdReadWord(const char *Cmd); -int CmdReadWordPWD(const char *Cmd); -int CmdWriteWord(const char *Cmd); -int CmdWriteWordPWD(const char *Cmd); int EM4x50Read(const char *Cmd, bool verbose); +int CmdLFEM4X(const char *Cmd); +bool EM4x05Block0Test(uint32_t *wordData); +int CmdEM4x05info(const char *Cmd); +int CmdEM4x05WriteWord(const char *Cmd); +int CmdEM4x05dump(const char *Cmd); +int CmdEM4x05ReadWord(const char *Cmd); +int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *wordData); + #endif From 73a2a84f75f37c4c4397e06b825d4356507d497b Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 21 Feb 2017 12:00:09 -0500 Subject: [PATCH 16/19] simplified lf em command structure WARNING changes command calling! --- client/cmdlf.c | 2 +- client/cmdlfem4x.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 8b6f32b6..206d5355 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1265,7 +1265,7 @@ static command_t CommandTable[] = {"help", CmdHelp, 1, "This help"}, {"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"}, {"cotag", CmdLFCOTAG, 1, "{ COTAG RFIDs... }"}, - {"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, + {"em", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, {"io", CmdLFIO, 1, "{ ioProx tags... }"}, diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 662629f0..76649786 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -72,9 +72,9 @@ int CmdEM410xSim(const char *Cmd) uint8_t uid[5] = {0x00}; if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: lf em4x em410xsim "); + PrintAndLog("Usage: lf em 410xsim "); PrintAndLog(""); - PrintAndLog(" sample: lf em4x em410xsim 0F0368568B"); + PrintAndLog(" sample: lf em 410xsim 0F0368568B"); return 0; } /* clock is 64 in EM410x tags */ From b7fc61f0c947da24d8283fec67a5910e224eb2d6 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 21 Feb 2017 16:57:32 -0500 Subject: [PATCH 17/19] update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7c5fcbf..936fbbd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added +- Added EM4x05/EM4x69 chip detection to lf search (marshmellow) +- Added lf em 4x05dump command to read and output all the blocks of the chip (marshmellow) +- Added lf em 4x05info command to read and display information about the chip (marshmellow) - Added lf cotag read, and added it to lf search (iceman) - Added hitag2 read UID only and added that to lf search (marshmellow) - Added lf pyramid commands (iceman) @@ -38,6 +41,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added option c to 'hf list' (mark CRC bytes) (piwi) ### Changed +- small changes to lf psk and fsk demods to improve results when the trace begins with noise or the chip isn't broadcasting yet (marshmellow) +- NOTE CHANGED ALL `lf em4x em*` cmds to simpler `lf em ` - example: `lf em4x em410xdemod` is now `lf em 410xdemod` +- Renamed and rebuilt `lf em readword` && readwordpwd to `lf em 4x05readword` - it now demods and outputs the read block (marshmellow/iceman) +- Renamed and rebuilt `lf em writeword` && writewordpwd to `lf em 4x05writeword` - it now also reads validation output from the tag (marshmellow/iceman) - Fixed bug in lf sim and continuous demods not turning off antenna when finished - Fixed bug(s) in hf iclass write - Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow) From 34ff898553f3392c66c50d1a524070882d237fb5 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 21 Feb 2017 23:00:43 -0500 Subject: [PATCH 18/19] fix false positive psk demod with fsk wave also break out new find start of modulation routine. --- armsrc/lfops.c | 3 +- client/cmdlfem4x.c | 40 +++++++++++++++--- common/lfdemod.c | 102 +++++++++++++++++++++------------------------ 3 files changed, 84 insertions(+), 61 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 35f220c0..0bbd62c2 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1626,7 +1626,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { fwd_bit_count += Prepare_Addr( Address ); SendForward(fwd_bit_count); - + SpinDelayUs(700); // Now do the acquisition DoPartialAcquisition(20, true, 5500); @@ -1658,6 +1658,7 @@ void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { //Wait for write to complete //SpinDelay(10); + SpinDelayUs(6500); //Capture response if one exists DoPartialAcquisition(20, true, 5500); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 76649786..d1245306 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -530,14 +530,16 @@ bool downloadSamplesEM() { } bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { - // em4x05/em4x69 preamble is 00001010 + // em4x05/em4x69 command response preamble is 00001010 // skip first two 0 bits as they might have been missed in the demod uint8_t preamble[] = {0,0,1,0,1,0}; size_t startIdx = 0; - // set size to 20 to only test first 14 positions for the preamble - size_t size = (20 > DemodBufferLen) ? DemodBufferLen : 20; - //test preamble + // set size to 20 to only test first 14 positions for the preamble or less if not a read command + size_t size = (readCmd) ? 20 : 11; + // sanity check + size = (size > DemodBufferLen) ? DemodBufferLen : size; + // test preamble if ( !onePreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx) ) { if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx); return false; @@ -548,7 +550,7 @@ bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { if (g_debugMode) PrintAndLog("DEBUG: Error - End Parity check failed"); return false; } - //test for even parity bits. + // test for even parity bits. if ( removeParity(DemodBuffer, startIdx + sizeof(preamble),9,0,44) == 0 ) { if (g_debugMode) PrintAndLog("DEBUG: Error - Parity not detected"); return false; @@ -808,6 +810,8 @@ int CmdEM4x05WriteWord(const char *Cmd) { int result = demodEM4x05resp(&dummy,false); if (result == 1) { PrintAndLog("Write Verified"); + } else { + PrintAndLog("Write could not be verified"); } return result; } @@ -893,6 +897,12 @@ void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t } } +void printEM4x05ProtectionBits(uint32_t wordData) { + for (uint8_t i = 0; i < 14; i++) { + PrintAndLog(" Word: %02u | %s", i, (((1 << i) & wordData ) || i < 2) ? "Is Locked" : "Is Not Locked"); + } +} + //quick test for EM4x05/EM4x69 tag bool EM4x05Block0Test(uint32_t *wordData) { if (EM4x05ReadWord_ext(0,0,false,wordData) == 1) { @@ -940,6 +950,26 @@ int CmdEM4x05info(const char *Cmd) { return 0; } printEM4x05config(wordData); + + // read word 14 and 15 to see which is being used for the protection bits + wordData = 0; + if ( EM4x05ReadWord_ext(14, pwd, usePwd, &wordData) != 1 ) { + //failed + return 0; + } + // if status bit says this is not the used protection word + if (!(wordData & 0x8000)) { + if ( EM4x05ReadWord_ext(15, pwd, usePwd, &wordData) != 1 ) { + //failed + return 0; + } + } + if (!(wordData & 0x8000)) { + //something went wrong + return 0; + } + printEM4x05ProtectionBits(wordData); + return 1; } diff --git a/common/lfdemod.c b/common/lfdemod.c index fbed6a9a..406b0445 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -187,6 +187,32 @@ bool onePreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_ return false; } +// find start of modulating data (for fsk and psk) in case of beginning noise or slow chip startup. +size_t findModStart(uint8_t dest[], size_t size, uint8_t threshold_value, uint8_t expWaveSize) { + size_t i = 0; + size_t waveSizeCnt = 0; + uint8_t thresholdCnt = 0; + bool isAboveThreshold = dest[i++] >= threshold_value; + for (; i < size-20; i++ ) { + if(dest[i] < threshold_value && isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; + isAboveThreshold = false; + waveSizeCnt = 0; + } else if (dest[i] >= threshold_value && !isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; + isAboveThreshold = true; + waveSizeCnt = 0; + } else { + waveSizeCnt++; + } + if (thresholdCnt > 10) break; + } + if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at %u, count: %u",i, thresholdCnt); + return i; +} + //by marshmellow //takes 1s and 0s and searches for EM410x format - output EM ID uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo) @@ -496,7 +522,6 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow { size_t last_transition = 0; size_t idx = 1; - //uint32_t maxVal=0; if (fchigh==0) fchigh=10; if (fclow==0) fclow=8; //set the threshold close to 0 (graph) or 128 std to avoid static @@ -506,28 +531,8 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow size_t currSample = 0; if ( size < 1024 ) return 0; // not enough samples - // jump to modulating data by finding the first 4 threshold crossings (or first 2 waves) - // in case you have junk or noise at the beginning of the trace... - uint8_t thresholdCnt = 0; - size_t waveSizeCnt = 0; - bool isAboveThreshold = dest[idx++] >= threshold_value; - for (; idx < size-20; idx++ ) { - if(dest[idx] < threshold_value && isAboveThreshold) { - thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < fchigh+1) break; - isAboveThreshold = false; - waveSizeCnt = 0; - } else if (dest[idx] >= threshold_value && !isAboveThreshold) { - thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < fchigh+1) break; - isAboveThreshold = true; - waveSizeCnt = 0; - } else { - waveSizeCnt++; - } - if (thresholdCnt > 10) break; - } - if (g_debugMode == 2) prnt("threshold Count reached at %u",idx); + //find start of modulating data in trace + idx = findModStart(dest, size, threshold_value, fchigh); // Need to threshold first sample if(dest[idx] < threshold_value) dest[0] = 0; @@ -1509,42 +1514,26 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) size_t numBits=0; uint8_t curPhase = *invert; size_t i=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0; - uint8_t fc=0, fullWaveLen=0, tol=1; - uint16_t errCnt=0, waveLenCnt=0; - fc = countFC(dest, *size, 0); + uint16_t fc=0, fullWaveLen=0, tol=1; + uint16_t errCnt=0, waveLenCnt=0, errCnt2=0; + fc = countFC(dest, *size, 1); + uint8_t fc2 = fc >> 8; + if (fc2 == 10) return -1; //fsk found - quit + fc = fc & 0xFF; if (fc!=2 && fc!=4 && fc!=8) return -1; //PrintAndLog("DEBUG: FC: %d",fc); *clock = DetectPSKClock(dest, *size, *clock); if (*clock == 0) return -1; - // jump to modulating data by finding the first 2 threshold crossings (or first 1 waves) - // in case you have junk or noise at the beginning of the trace... - uint8_t thresholdCnt = 0; - size_t waveSizeCnt = 0; + + //find start of modulating data in trace uint8_t threshold_value = 123; //-5 - bool isAboveThreshold = dest[i++] >= threshold_value; - for (; i < *size-20; i++ ) { - if(dest[i] < threshold_value && isAboveThreshold) { - thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < fc+1) break; - isAboveThreshold = false; - waveSizeCnt = 0; - } else if (dest[i] >= threshold_value && !isAboveThreshold) { - thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < fc+1) break; - isAboveThreshold = true; - waveSizeCnt = 0; - } else { - waveSizeCnt++; - } - if (thresholdCnt > 10) break; - } - if (g_debugMode == 2) prnt("DEBUG PSK: threshold Count reached at %u, count: %u",i, thresholdCnt); + i = findModStart(dest, *size, threshold_value, fc); - - int avgWaveVal=0, lastAvgWaveVal=0; - waveStart = i+1; //find first phase shift - for (; i= dest[i+2]){ waveEnd = i+1; if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u",waveEnd, waveStart); @@ -1553,8 +1542,8 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) lastAvgWaveVal = avgWaveVal/(waveLenCnt); firstFullWave = waveStart; fullWaveLen=waveLenCnt; - //if average wave value is > graph 0 then it is an up wave or a 1 - if (lastAvgWaveVal > threshold_value) curPhase ^= 1; //fudge graph 0 a little 123 vs 128 + //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting) + if (lastAvgWaveVal > threshold_value) curPhase ^= 1; break; } waveStart = i+1; @@ -1575,7 +1564,7 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) //set start of wave as clock align lastClkBit = firstFullWave; if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen); - if (g_debugMode==2) prnt("DEBUG: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc); + if (g_debugMode==2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc); waveStart = 0; dest[numBits++] = curPhase; //set first read bit for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){ @@ -1606,6 +1595,9 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) } else if (i+1 > lastClkBit + *clock + tol + fc){ lastClkBit += *clock; //no phase shift but clock bit dest[numBits++] = curPhase; + } else if (waveLenCnt < fc - 1) { //wave is smaller than field clock (shouldn't happen often) + errCnt2++; + if(errCnt2 > 101) return errCnt2; } avgWaveVal = 0; waveStart = i+1; From 33a1fe9636ddc00cedfec34e0d8a77899ca4494c Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 22 Feb 2017 10:41:40 -0500 Subject: [PATCH 19/19] small text adjustments plus... small improvement to fsk clock detect + fixed a bug where it would default to rf/16 when it couldn't find a valid one... --- armsrc/lfops.c | 6 +++--- client/cmdlfem4x.c | 13 ++++++++----- common/lfdemod.c | 7 +++++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 0bbd62c2..d79c75a0 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1626,9 +1626,9 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { fwd_bit_count += Prepare_Addr( Address ); SendForward(fwd_bit_count); - SpinDelayUs(700); + SpinDelayUs(400); // Now do the acquisition - DoPartialAcquisition(20, true, 5500); + DoPartialAcquisition(20, true, 6000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); @@ -1660,7 +1660,7 @@ void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { SpinDelayUs(6500); //Capture response if one exists - DoPartialAcquisition(20, true, 5500); + DoPartialAcquisition(20, true, 6000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index d1245306..0788b138 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -675,7 +675,7 @@ int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) { uint32_t wordData = 0; int success = EM4x05ReadWord_ext(addr, pwd, usePwd, &wordData); if (success == 1) - PrintAndLog(" Got Address %02d | %08X",addr,wordData); + PrintAndLog("%s Address %02d | %08X", (addr>13) ? "Lock":" Got",addr,wordData); else PrintAndLog("Read Address %02d | failed",addr); @@ -859,11 +859,11 @@ void printEM4x05config(uint32_t wordData) { } PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData); PrintAndLog("Config Breakdown:", wordData); - PrintAndLog(" Data Rate: %02X | RF/%u", wordData & 0x3F, datarate); + PrintAndLog(" Data Rate: %02u | RF/%u", wordData & 0x3F, datarate); PrintAndLog(" Encoder: %u | %s", encoder, enc); PrintAndLog(" PSK CF: %u | %s", PSKcf, cf); PrintAndLog(" Delay: %u | %s", delay, cdelay); - PrintAndLog(" LastWordR: %02u | Address of last default word read", LWR); + PrintAndLog(" LastWordR: %02u | Address of last word for default read", LWR); PrintAndLog(" ReadLogin: %u | Read Login is %s", (wordData & 0x40000)>>18, (wordData & 0x40000) ? "Required" : "Not Required"); PrintAndLog(" ReadHKL: %u | Read Housekeeping Words Login is %s", (wordData & 0x80000)>>19, (wordData & 0x80000) ? "Required" : "Not Required"); PrintAndLog("WriteLogin: %u | Write Login is %s", (wordData & 0x100000)>>20, (wordData & 0x100000) ? "Required" : "Not Required"); @@ -898,8 +898,11 @@ void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t } void printEM4x05ProtectionBits(uint32_t wordData) { - for (uint8_t i = 0; i < 14; i++) { - PrintAndLog(" Word: %02u | %s", i, (((1 << i) & wordData ) || i < 2) ? "Is Locked" : "Is Not Locked"); + for (uint8_t i = 0; i < 15; i++) { + PrintAndLog(" Word: %02u | %s", i, (((1 << i) & wordData ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked"); + if (i==14) { + PrintAndLog(" Word: %02u | %s", i+1, (((1 << i) & wordData ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked"); + } } } diff --git a/common/lfdemod.c b/common/lfdemod.c index 406b0445..e9f19311 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1343,7 +1343,10 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc continue; // else new peak // if we got less than the small fc + tolerance then set it to the small fc - if (fcCounter < fcLow+fcTol) + // if it is inbetween set it to the last counter + if (fcCounter < fcHigh && fcCounter > fcLow) + fcCounter = lastFCcnt; + else if (fcCounter < fcLow+fcTol) fcCounter = fcLow; else //set it to the large fc fcCounter = fcHigh; @@ -1409,7 +1412,7 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc } } - if (ii<0) return 0; // oops we went too far + if (ii<2) return 0; // oops we went too far return clk[ii]; }