From 95bf65cda94536b420f4e449d33b9cb364c4367c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 18 Oct 2020 23:46:36 +0200 Subject: [PATCH] Add EM 4x05 Login --- armsrc/appmain.c | 8 ++++ armsrc/lfops.c | 31 ++++++++++-- armsrc/lfops.h | 1 + client/src/cmdlfem4x05.c | 101 +++++++++++++++++++-------------------- include/pm3_cmd.h | 1 + 5 files changed, 87 insertions(+), 55 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 6b40a3909..02d6f1d23 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -970,6 +970,14 @@ static void PacketReceived(PacketCommandNG *packet) { ); break; } + case CMD_LF_EM4X_LOGIN: { + struct p { + uint32_t password; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + EM4xLogin(payload->password); + break; + } case CMD_LF_EM4X_READWORD: { struct p { uint32_t password; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 03e322681..de1803690 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2501,7 +2501,7 @@ static void SendForward(uint8_t fwd_bit_count) { } } -static void EM4xLogin(uint32_t pwd) { +static void EM4xLoginEx(uint32_t pwd) { forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN); len += Prepare_Data(pwd & 0xFFFF, pwd >> 16); @@ -2512,6 +2512,29 @@ static void EM4xLogin(uint32_t pwd) { // 0000 0001 fail } +void EM4xLogin(uint32_t pwd) { + + StartTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitMS(20); + + LED_A_ON(); + + // clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + + EM4xLoginEx(pwd); + + WaitUS(400); + + DoPartialAcquisition(20, false, 1000, 1000); + + StopTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + reply_ng(CMD_LF_EM4X_LOGIN, PM3_SUCCESS, NULL, 0); + LEDsoff(); +} + void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { StartTicks(); @@ -2529,7 +2552,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { * 0000 1010 ok * 0000 0001 fail **/ - if (usepwd) EM4xLogin(pwd); + if (usepwd) EM4xLoginEx(pwd); forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_READ); @@ -2564,7 +2587,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) { * 0000 1010 ok. * 0000 0001 fail **/ - if (usepwd) EM4xLogin(pwd); + if (usepwd) EM4xLoginEx(pwd); forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_WRITE); @@ -2607,7 +2630,7 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) { * 0000 1010 ok. * 0000 0001 fail **/ - if (usepwd) EM4xLogin(pwd); + if (usepwd) EM4xLoginEx(pwd); forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT); diff --git a/armsrc/lfops.h b/armsrc/lfops.h index 1c191d65d..bf251ac85 100644 --- a/armsrc/lfops.h +++ b/armsrc/lfops.h @@ -56,6 +56,7 @@ void T55xxDangerousRawTest(uint8_t *data); void TurnReadLFOn(uint32_t delay); +void EM4xLogin(uint32_t pwd); void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd); void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd); diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index a1999dd9d..75e20e9eb 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -361,6 +361,29 @@ static int demodEM4x05resp(uint32_t *word, bool onlyPreamble) { //////////////// 4205 / 4305 commands +static int EM4x05Login_ext(uint32_t pwd) { + + struct { + uint32_t password; + } PACKED payload; + + payload.password = pwd; + + clearCommandBuffer(); + SendCommandNG(CMD_LF_EM4X_LOGIN, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_LF_EM4X_LOGIN, &resp, 10000)) { + PrintAndLogEx(WARNING, "(EM4x05Login_ext) timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + if (downloadSamplesEM() == false) { + return PM3_ESOFT; + } + uint32_t word; + return demodEM4x05resp(&word, true); +} + int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) { struct { @@ -438,7 +461,6 @@ int CmdEM4x05Dump(const char *Cmd) { if (EM4x05IsBlock0(&block0) == false) return PM3_ESOFT; - bool needReadPwd = true; uint8_t bytes[4] = {0}; uint32_t data[16]; @@ -456,28 +478,32 @@ int CmdEM4x05Dump(const char *Cmd) { em_tech_type_t card_type = em_get_card_type(block0); PrintAndLogEx(INFO, "Found a " _GREEN_("%s") " tag", em_get_card_str(block0)); - PrintAndLogEx(NORMAL, ""); + if (usePwd) { + // Test first if the password is correct + status = EM4x05Login_ext(pwd); + if (status == PM3_SUCCESS) { + PrintAndLogEx(INFO, "Password is " _GREEN_("correct")); + } else if (status == PM3_EFAILED) { + PrintAndLogEx(WARNING, "Password is " _RED_("incorrect") ", will try without password"); + usePwd = false; + } else if (status != PM3_EFAILED) { + PrintAndLogEx(WARNING, "Login attempt: No answer from tag"); + return status; + } + } + + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "Addr | data | ascii |lck| info"); PrintAndLogEx(INFO, "-----+----------+-------+---+-----"); if ( card_type == EM_4205 || card_type == EM_4305 || card_type == EM_UNKNOWN) { - if (usePwd) { - // Test first if a password is required - status = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, false, &word); - if (status == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Note that password doesn't seem to be needed"); - needReadPwd = false; - } - } // To flag any blocks locked we need to read blocks 14 and 15 first // dont swap endin until we get block lock flags. status14 = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word); if (status14 == PM3_SUCCESS) { - if (!usePwd) - needReadPwd = false; if ((word & 0x00008000) != 0x00) { lock_bits = word; gotLockBits = true; @@ -503,14 +529,9 @@ int CmdEM4x05Dump(const char *Cmd) { lockbit = (lock_bits >> addr) & 1; if (addr == 2) { if (usePwd) { - if ((needReadPwd) && (success != PM3_ESOFT)) { - data[addr] = BSWAP_32(pwd); - num_to_bytes(pwd, 4, bytes); - PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]); - } else { - // The pwd is not needed for Login so we're not sure what's the actual content of that block - PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]); - } + data[addr] = BSWAP_32(pwd); + num_to_bytes(pwd, 4, bytes); + PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]); } else { data[addr] = 0x00; // Unknown password, but not used to set to zeros PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]); @@ -550,21 +571,10 @@ int CmdEM4x05Dump(const char *Cmd) { } else if (card_type == EM_4X69) { - if (usePwd) { - // Test first if a password is required - status = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, false, &word); - if (status == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Note that password doesn't seem to be needed"); - needReadPwd = false; - } - } - // To flag any blocks locked we need to read blocks 14 and 15 first // dont swap endin until we get block lock flags. status14 = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word); if (status14 == PM3_SUCCESS) { - if (!usePwd) - needReadPwd = false; if ((word & 0x00008000) != 0x00) { lock_bits = word; gotLockBits = true; @@ -580,14 +590,9 @@ int CmdEM4x05Dump(const char *Cmd) { lockbit = (lock_bits >> addr) & 1; if (addr == 2) { if (usePwd) { - if ((needReadPwd) && (success != PM3_ESOFT)) { - data[addr] = BSWAP_32(pwd); - num_to_bytes(pwd, 4, bytes); - PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]); - } else { - // The pwd is not needed for Login so we're not sure what's the actual content of that block - PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]); - } + data[addr] = BSWAP_32(pwd); + num_to_bytes(pwd, 4, bytes); + PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]); } else { data[addr] = 0x00; // Unknown password, but not used to set to zeros PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]); @@ -1095,15 +1100,6 @@ int CmdEM4x05Chk(const char *Cmd) { uint64_t card_id = arg_get_u64_def(ctx, 2, 0); CLIParserFree(ctx); - uint8_t addr = 4; - uint32_t word = 0; - // Test first if a password is required - int status = EM4x05ReadWord_ext(addr, 0, false, &word); - if (status == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Password doesn't seem to be needed to read the tag"); - return PM3_SUCCESS; - } - if (strlen(filename) == 0) { snprintf(filename, sizeof(filename), "t55xx_default_pwds"); } @@ -1118,10 +1114,12 @@ int CmdEM4x05Chk(const char *Cmd) { uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF); PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd); - status = EM4x05ReadWord_ext(addr, pwd, true, &word); + int status = EM4x05Login_ext(pwd); if (status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd); found = true; + } else if (status != PM3_EFAILED) { + PrintAndLogEx(WARNING, "No answer from tag"); } } @@ -1131,7 +1129,6 @@ int CmdEM4x05Chk(const char *Cmd) { PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command"); - word = 0; uint32_t keycount = 0; int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount); @@ -1160,11 +1157,13 @@ int CmdEM4x05Chk(const char *Cmd) { PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password); - status = EM4x05ReadWord_ext(addr, curr_password, 1, &word); + int status = EM4x05Login_ext(curr_password); if (status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password); found = true; break; + } else if (status != PM3_EFAILED) { + PrintAndLogEx(WARNING, "No answer from tag"); } } } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 6fca06786..7fb978d75 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -496,6 +496,7 @@ typedef struct { #define CMD_LF_T55XX_RESET_READ 0x0216 #define CMD_LF_PCF7931_READ 0x0217 #define CMD_LF_PCF7931_WRITE 0x0223 +#define CMD_LF_EM4X_LOGIN 0x0229 #define CMD_LF_EM4X_READWORD 0x0218 #define CMD_LF_EM4X_WRITEWORD 0x0219 #define CMD_LF_EM4X_PROTECTWORD 0x021B