From 4ab135c0cdb190d6d29608204d3d7c15a25b07ee Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 31 Mar 2017 12:14:28 -0400 Subject: [PATCH 1/1] a few more tools for em4x05 writing. ready to begin coding cloning cmds to em4x05. --- client/cmdlfem4x.c | 143 +++++++++++++++++++++++++++++++-------------- client/cmdlfem4x.h | 2 + common/protocols.h | 29 +++++++++ 3 files changed, 131 insertions(+), 43 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 1dfab394..47b240c8 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; @@ -899,47 +900,32 @@ 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 EM4x05WriteWord(uint8_t addr, uint32_t data, uint32_t pwd, bool usePwd, bool swap, bool invert) { + if (swap) data = SwapBits(data, 32); - 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); - - 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; } - 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 +954,70 @@ 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 + + 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); + 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(); + + 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 +1028,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 +1057,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 +1158,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); diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index cdb59acd..869d72d0 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -12,6 +12,7 @@ #define CMDLFEM4X_H__ #include // for bool +#include extern int CmdLFEM4X(const char *Cmd); extern void printEM410x(uint32_t hi, uint64_t id); @@ -25,6 +26,7 @@ extern int CmdEM410xWatchnSpoof(const char *Cmd); extern int CmdEM410xWrite(const char *Cmd); extern bool EM4x05Block0Test(uint32_t *wordData); extern int CmdEM4x05info(const char *Cmd); +extern int EM4x05WriteWord(uint8_t addr, uint32_t data, uint32_t pwd, bool usePwd, bool swap, bool invert); extern int CmdEM4x05WriteWord(const char *Cmd); extern int CmdEM4x05dump(const char *Cmd); extern int CmdEM4x05ReadWord(const char *Cmd); diff --git a/common/protocols.h b/common/protocols.h index 0798db47..bb888d3d 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -264,6 +264,8 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * #define T5555_PSK_RF_8 0x00000200 #define T5555_USE_PWD 0x00000400 #define T5555_USE_AOR 0x00000800 +#define T5555_SET_BITRATE(x) (((x-2)/2)<<12) +#define T5555_GET_BITRATE(x) ((((x >> 12) & 0x3F)*2)+2) #define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2 #define T5555_FAST_WRITE 0x00004000 #define T5555_PAGE_SELECT 0x00008000 @@ -272,5 +274,32 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * uint32_t GetT55xxClockBit(uint32_t clock); +// em4x05 & em4x69 chip configuration register definitions +#define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2) +#define EM4x05_SET_BITRATE(x) ((x-2)/2) +#define EM4x05_MODULATION_NRZ 0x00000000 +#define EM4x05_MODULATION_MANCHESTER 0x00000040 +#define EM4x05_MODULATION_BIPHASE 0x00000080 +#define EM4x05_MODULATION_MILLER 0x000000C0 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_PSK1 0x00000100 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_PSK2 0x00000140 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_PSK3 0x00000180 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_FSK1 0x00000200 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_FSK2 0x00000240 //not supported by all 4x05/4x69 chips +#define EM4x05_PSK_RF_2 0 +#define EM4x05_PSK_RF_4 0x00000400 +#define EM4x05_PSK_RF_8 0x00000800 +#define EM4x05_MAXBLOCK_SHIFT 14 +#define EM4x05_FIRST_USER_BLOCK 5 +#define EM4x05_SET_NUM_BLOCKS(x) ((x+5-1)<<14) //# of blocks sent during default read mode +#define EM4x05_GET_NUM_BLOCKS(x) (((x>>14) & 0xF)-5+1) +#define EM4x05_READ_LOGIN_REQ 1<<18 +#define EM4x05_READ_HK_LOGIN_REQ 1<<19 +#define EM4x05_WRITE_LOGIN_REQ 1<<20 +#define EM4x05_WRITE_HK_LOGIN_REQ 1<<21 +#define EM4x05_READ_AFTER_WRITE 1<<22 +#define EM4x05_DISABLE_ALLOWED 1<<23 +#define EM4x05_READER_TALK_FIRST 1<<24 + #endif // PROTOCOLS_H -- 2.39.5