diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 5a465c2bd..2ba931a01 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1041,6 +1041,10 @@ static void PacketReceived(PacketCommandNG *packet) { em4x50_brute((em4x50_data_t *)packet->data.asBytes); break; } + case CMD_LF_EM4X50_LOGIN: { + em4x50_login((em4x50_data_t *)packet->data.asBytes); + break; + } #endif #ifdef WITH_ISO15693 diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index ebf381a69..95769e98b 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -1184,3 +1184,30 @@ void em4x50_brute(em4x50_data_t *etd) { lf_finalize(); reply_ng(CMD_ACK, bsuccess, (uint8_t *)(&pwd), 32); } + +void em4x50_login(em4x50_data_t *etd) { + + // login into EM4x50 + + uint8_t status = 0; + uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0}; + uint32_t rpwd = 0x0; + + em4x50_setup_read(); + + // set gHigh and gLow + if (get_signalproperties() && find_em4x50_tag()) { + + // lsb -> msb + rpwd = reflect32(etd->login_password); + + // convert to "old" data format + for (int i = 0; i < 4; i++) + bytes[i] = (rpwd >> ((3 - i) * 8)) & 0xFF; + + status = login(bytes); + } + + lf_finalize(); + reply_ng(CMD_ACK, status, 0, 0); +} diff --git a/armsrc/em4x50.h b/armsrc/em4x50.h index d1f897b8a..5c3648a39 100644 --- a/armsrc/em4x50.h +++ b/armsrc/em4x50.h @@ -27,5 +27,6 @@ void em4x50_write_password(em4x50_data_t *etd); void em4x50_read(em4x50_data_t *etd); void em4x50_wipe(em4x50_data_t *etd); void em4x50_brute(em4x50_data_t *etd); +void em4x50_login(em4x50_data_t *etd); #endif /* EM4X50_H */ diff --git a/client/src/cmdlfem4x.c b/client/src/cmdlfem4x.c index b09f2f102..16a408956 100644 --- a/client/src/cmdlfem4x.c +++ b/client/src/cmdlfem4x.c @@ -1399,6 +1399,7 @@ static command_t CommandTable[] = { {"4x50_read", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"}, {"4x50_wipe", CmdEM4x50Wipe, IfPm3EM4x50, "wipe data from EM4x50"}, {"4x50_brute", CmdEM4x50Brute, IfPm3EM4x50, "guess password of EM4x50"}, + {"4x50_login", CmdEM4x50Login, IfPm3EM4x50, "login into EM4x50"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 15ac9fb4b..4c1dbad67 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -97,31 +97,6 @@ static int usage_lf_em4x50_wipe(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_lf_em4x50_sim(void) { - PrintAndLogEx(NORMAL, "Simulate EM4x50 tag. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_sim [h] w "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " w - word (hex)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_sim w 12345678")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} -static int usage_lf_em4x50_test(void) { - PrintAndLogEx(NORMAL, "Test functionality for EM4x50 tag. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_test [h] ..."); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " c <0|1> - carrier on|off (optional)"); - PrintAndLogEx(NORMAL, " b - byte (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_test ...")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_lf_em4x50_brute(void) { PrintAndLogEx(NORMAL, "Guess password of EM4x50 tag. Tag must be on antenna. "); PrintAndLogEx(NORMAL, ""); @@ -135,6 +110,18 @@ static int usage_lf_em4x50_brute(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } +static int usage_lf_em4x50_login(void) { + PrintAndLogEx(NORMAL, "Login into EM4x50 tag. Tag must be on antenna. "); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf em 4x50_login [h] p "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb notation)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_login p 11200000")); + PrintAndLogEx(NORMAL, ""); + return PM3_SUCCESS; +} static void prepare_result(const uint8_t *byte, int fwr, int lwr, em4x50_word_t *words) { @@ -841,3 +828,44 @@ int CmdEM4x50Brute(const char *Cmd) { return PM3_SUCCESS; } + +int CmdEM4x50Login(const char *Cmd) { + + bool errors = false, pwd_given = false; + uint8_t cmdp = 0; + em4x50_data_t etd; + PacketResponseNG resp; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_em4x50_login(); + case 'p': + etd.login_password = param_get32ex(Cmd, cmdp + 1, 0, 16); + pwd_given = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (errors || !pwd_given) + return usage_lf_em4x50_login(); + + // start + clearCommandBuffer(); + SendCommandNG(CMD_LF_EM4X50_LOGIN, (uint8_t *)&etd, sizeof(etd)); + WaitForResponse(CMD_ACK, &resp); + + // print response + if ((bool)resp.status) + PrintAndLogEx(NORMAL, "\nlogin " _GREEN_("ok") "\n"); + else + PrintAndLogEx(NORMAL, "\nlogin " _RED_("failed") "\n"); + + return PM3_SUCCESS; +} diff --git a/client/src/cmdlfem4x50.h b/client/src/cmdlfem4x50.h index 9a86adfed..dbf94c660 100644 --- a/client/src/cmdlfem4x50.h +++ b/client/src/cmdlfem4x50.h @@ -25,5 +25,6 @@ int CmdEM4x50Read(const char *Cmd); int CmdEM4x50Dump(const char *Cmd); int CmdEM4x50Wipe(const char *Cmd); int CmdEM4x50Brute(const char *Cmd); +int CmdEM4x50Login(const char *Cmd); #endif diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 69a75a1ad..8060a3998 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -494,6 +494,7 @@ typedef struct { #define CMD_LF_EM4X50_READ 0x0243 #define CMD_LF_EM4X50_WIPE 0x0244 #define CMD_LF_EM4X50_BRUTE 0x0245 +#define CMD_LF_EM4X50_LOGIN 0x0246 // Sampling configuration for LF reader/sniffer #define CMD_LF_SAMPLING_SET_CONFIG 0x021D #define CMD_LF_FSK_SIMULATE 0x021E