X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/f513388ee056cfaa34799ed19e451383db1065c3..890738733a64445e6565516fe20c927884b712fd:/client/cmdlfem4x.c diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 1dfab394..e84cccf9 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -22,6 +22,7 @@ #include "cmdlf.h" #include "cmdmain.h" #include "lfdemod.h" +#include "protocols.h" uint64_t g_em410xId=0; @@ -145,17 +146,20 @@ void printEM410x(uint32_t hi, uint64_t id) int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ) { size_t idx = 0; - size_t BitLen = DemodBufferLen; - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - memcpy(BitStream, DemodBuffer, BitLen); - if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)){ + uint8_t BitStream[512]={0}; + size_t BitLen = sizeof(BitStream); + if ( !getDemodBuf(BitStream, &BitLen) ) return 0; + + if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)) { //set GraphBuffer for clone or sim command - setDemodBuf(BitStream, BitLen, idx); - if (g_debugMode){ + setDemodBuf(DemodBuffer, (BitLen==40) ? 64 : 128, idx+1); + setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx+1)*g_DemodClock)); + + if (g_debugMode) { PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen); printDemodBuff(); } - if (verbose){ + if (verbose) { PrintAndLog("EM410x pattern found: "); printEM410x(*hi, *lo); g_em410xId = *lo; @@ -297,9 +301,7 @@ int CmdEM410xWatch(const char *Cmd) printf("\naborted via keyboard!\n"); break; } - - CmdLFRead("s"); - getSamples("8201",true); + lf_read(true, 8201); } while (!CmdAskEM410xDemod("")); return 0; @@ -472,9 +474,6 @@ int EM4x50Read(const char *Cmd, bool verbose) // get user entry if any sscanf(Cmd, "%i %i", &clk, &invert); - // save GraphBuffer - to restore it later - save_restoreGB(1); - // first get high and low values for (i = 0; i < GraphTraceLen; i++) { if (GraphBuffer[i] > high) @@ -571,6 +570,8 @@ int EM4x50Read(const char *Cmd, bool verbose) } else if (start < 0) return 0; start = skip; snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47); + // save GraphBuffer - to restore it later + save_restoreGB(GRAPH_SAVE); // get rid of leading crap snprintf(tmp, sizeof(tmp), "%i", skip); CmdLtrim(tmp); @@ -598,7 +599,7 @@ int EM4x50Read(const char *Cmd, bool verbose) phaseoff = 0; i += 2; if (ASKDemod(tmp2, false, false, 1) < 1) { - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return 0; } //set DemodBufferLen to just one block @@ -637,7 +638,7 @@ int EM4x50Read(const char *Cmd, bool verbose) } //restore GraphBuffer - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return (int)AllPTest; } @@ -703,6 +704,8 @@ bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) { } setDemodBuf(DemodBuffer, 32, 0); + //setClockGrid(0,0); + *word = bytebits_to_byteLSBF(DemodBuffer, 32); } return true; @@ -899,47 +902,35 @@ int CmdEM4x05dump(const char *Cmd) { int usage_lf_em_write(void) { PrintAndLog("Write EM4x05/EM4x69. Tag must be on antenna. "); PrintAndLog(""); - PrintAndLog("Usage: lf em 4x05writeword [h] [s]
"); + PrintAndLog("Usage: lf em 4x05writeword [h] a
d p [s] [i]"); PrintAndLog("Options:"); - PrintAndLog(" h - this help"); - PrintAndLog(" s - swap data bit order before write"); - PrintAndLog(" address - memory address to write to. (0-15)"); - PrintAndLog(" data - data to write (hex)"); - PrintAndLog(" pwd - password (hex) (optional)"); + PrintAndLog(" h - this help"); + PrintAndLog(" a
- memory address to write to. (0-15)"); + PrintAndLog(" d - data to write (hex)"); + PrintAndLog(" p - password (hex) (optional)"); + PrintAndLog(" s - swap the data bit order before write"); + PrintAndLog(" i - invert the data bits before write"); PrintAndLog("samples:"); - PrintAndLog(" lf em 4x05writeword 1"); - PrintAndLog(" lf em 4x05writeword 1 deadc0de 11223344"); + PrintAndLog(" lf em 4x05writeword a 5 d 11223344"); + PrintAndLog(" lf em 4x05writeword a 5 p deadc0de d 11223344 s i"); return 0; } -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; - - uint8_t addr = 16; // default to invalid address - uint32_t data = 0xFFFFFFFF; // default to blank data - uint32_t pwd = 0xFFFFFFFF; // default to blank password - char swap = 0; - - int p = 0; - swap = param_getchar(Cmd, 0); - if (swap == 's' || swap=='S') p++; - addr = param_get8ex(Cmd, p++, 16, 10); - data = param_get32ex(Cmd, p++, 0, 16); - pwd = param_get32ex(Cmd, p++, 1, 16); +// note: em4x05 doesn't have a way to invert data output so we must invert the data prior to writing +// it if invertion is needed. (example FSK2a vs FSK) +// also em4x05 requires swapping word data when compared to the data used for t55xx chips. +int EM4x05WriteWord(uint8_t addr, uint32_t data, uint32_t pwd, bool usePwd, bool swap, bool invert) { + if (swap) data = SwapBits(data, 32); - if (swap == 's' || swap=='S') data = SwapBits(data, 32); + if (invert) data ^= 0xFFFFFFFF; if ( (addr > 15) ) { PrintAndLog("Address must be between 0 and 15"); - return 1; + return -1; } - if ( pwd == 1 ) - PrintAndLog("Writing address %d data %08X", addr, data); - else { - usePwd = true; + if ( !usePwd ) { + PrintAndLog("Writing address %d data %08X", addr, data); + } else { PrintAndLog("Writing address %d data %08X using password %08X", addr, data, pwd); } @@ -968,8 +959,75 @@ int CmdEM4x05WriteWord(const char *Cmd) { return result; } +int CmdEM4x05WriteWord(const char *Cmd) { + bool errors = false; + bool usePwd = false; + uint32_t data = 0xFFFFFFFF; + uint32_t pwd = 0xFFFFFFFF; + bool swap = false; + bool invert = false; + uint8_t addr = 16; // default to invalid address + bool gotData = false; + char cmdp = 0; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_lf_em_write(); + case 'a': + case 'A': + addr = param_get8ex(Cmd, cmdp+1, 16, 10); + cmdp += 2; + break; + case 'd': + case 'D': + data = param_get32ex(Cmd, cmdp+1, 0, 16); + gotData = true; + cmdp += 2; + break; + case 'i': + case 'I': + invert = true; + cmdp++; + break; + case 'p': + case 'P': + pwd = param_get32ex(Cmd, cmdp+1, 1, 16); + if (pwd == 1) { + PrintAndLog("invalid pwd"); + errors = true; + } + usePwd = true; + cmdp += 2; + break; + case 's': + case 'S': + swap = true; + cmdp++; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; + } + //Validations + if(errors) return usage_lf_em_write(); + + if ( strlen(Cmd) == 0 ) return usage_lf_em_write(); + + if (!gotData) { + PrintAndLog("You must enter the data you want to write"); + return usage_lf_em_write(); + } + return EM4x05WriteWord(addr, data, pwd, usePwd, swap, invert); +} + void printEM4x05config(uint32_t wordData) { - uint16_t datarate = (((wordData & 0x3F)+1)*2); + uint16_t datarate = EM4x05_GET_BITRATE(wordData); uint8_t encoder = ((wordData >> 6) & 0xF); char enc[14]; memset(enc,0,sizeof(enc)); @@ -980,8 +1038,8 @@ void printEM4x05config(uint32_t wordData) { uint8_t delay = (wordData >> 12) & 0x3; char cdelay[33]; memset(cdelay,0,sizeof(cdelay)); - uint8_t LWR = (wordData >> 14) & 0xF; //last word read - + uint8_t numblks = EM4x05_GET_NUM_BLOCKS(wordData); + uint8_t LWR = numblks+5-1; //last word read switch (encoder) { case 0: snprintf(enc,sizeof(enc),"NRZ"); break; case 1: snprintf(enc,sizeof(enc),"Manchester"); break; @@ -1009,21 +1067,29 @@ void printEM4x05config(uint32_t wordData) { case 2: snprintf(cdelay, sizeof(cdelay),"BP/4 or 1/4th bit period delay"); break; case 3: snprintf(cdelay, sizeof(cdelay),"no delay"); break; } + uint8_t readLogin = (wordData & EM4x05_READ_LOGIN_REQ)>>18; + uint8_t readHKL = (wordData & EM4x05_READ_HK_LOGIN_REQ)>>19; + uint8_t writeLogin = (wordData & EM4x05_WRITE_LOGIN_REQ)>>20; + uint8_t writeHKL = (wordData & EM4x05_WRITE_HK_LOGIN_REQ)>>21; + uint8_t raw = (wordData & EM4x05_READ_AFTER_WRITE)>>22; + uint8_t disable = (wordData & EM4x05_DISABLE_ALLOWED)>>23; + uint8_t rtf = (wordData & EM4x05_READER_TALK_FIRST)>>24; + uint8_t pigeon = (wordData & (1<<26))>>26; PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData); - PrintAndLog("Config Breakdown:", wordData); + PrintAndLog("Config Breakdown:"); 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 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"); - 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"); + PrintAndLog(" LastWordR: %02u | Address of last word for default read - meaning %u blocks are output", LWR, numblks); + PrintAndLog(" ReadLogin: %u | Read Login is %s", readLogin, readLogin ? "Required" : "Not Required"); + PrintAndLog(" ReadHKL: %u | Read Housekeeping Words Login is %s", readHKL, readHKL ? "Required" : "Not Required"); + PrintAndLog("WriteLogin: %u | Write Login is %s", writeLogin, writeLogin ? "Required" : "Not Required"); + PrintAndLog(" WriteHKL: %u | Write Housekeeping Words Login is %s", writeHKL, writeHKL ? "Required" : "Not Required"); + PrintAndLog(" R.A.W.: %u | Read After Write is %s", raw, raw ? "On" : "Off"); + PrintAndLog(" Disable: %u | Disable Command is %s", disable, disable ? "Accepted" : "Not Accepted"); + PrintAndLog(" R.T.F.: %u | Reader Talk First is %s", rtf, rtf ? "Enabled" : "Disabled"); + PrintAndLog(" Pigeon: %u | Pigeon Mode is %s\n", pigeon, pigeon ? "Enabled" : "Disabled"); } void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t serial) { @@ -1102,6 +1168,7 @@ int CmdEM4x05info(const char *Cmd) { wordData = 0; if ( EM4x05ReadWord_ext(4, pwd, usePwd, &wordData) != 1 ) { //failed + PrintAndLog("Config block read failed - might be password protected."); return 0; } printEM4x05config(wordData);