From dc35f79bd2542d5e7712b7e26068423c0599a86e Mon Sep 17 00:00:00 2001 From: Christian Molson Date: Tue, 15 Dec 2020 11:22:43 -0500 Subject: [PATCH] em4x70: Add write pin convenience function to write and verify a new pin --- armsrc/appmain.c | 4 +++ armsrc/em4x70.c | 49 ++++++++++++++++++++++++++--- armsrc/em4x70.h | 1 + client/src/cmdlfem4x70.c | 68 +++++++++++++++++++++++++++++++++++++--- client/src/cmdlfem4x70.h | 1 + include/em4x70.h | 4 +++ include/pm3_cmd.h | 1 + 7 files changed, 118 insertions(+), 10 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 57c2f36c7..af6e6c956 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1182,6 +1182,10 @@ static void PacketReceived(PacketCommandNG *packet) { em4x70_auth((em4x70_data_t *)packet->data.asBytes); break; } + case CMD_LF_EM4X70_WRITEPIN: { + em4x70_write_pin((em4x70_data_t *)packet->data.asBytes); + break; + } #endif #ifdef WITH_ISO15693 diff --git a/armsrc/em4x70.c b/armsrc/em4x70.c index 61b7e76cb..758b6e08e 100644 --- a/armsrc/em4x70.c +++ b/armsrc/em4x70.c @@ -538,7 +538,7 @@ static bool em4x70_read_um2(void) { } -static bool find_em4x70_Tag(void) { +static bool find_em4x70_tag(void) { // function is used to check wether a tag on the proxmark is an // EM4170 tag or not -> speed up "lf search" process return find_listen_window(false); @@ -635,7 +635,7 @@ void em4x70_info(em4x70_data_t *etd) { em4x70_setup_read(); // Find the Tag - if (get_signalproperties() && find_em4x70_Tag()) { + if (get_signalproperties() && find_em4x70_tag()) { // Read ID, UM1 and UM2 status = em4x70_read_id() && em4x70_read_um1() && em4x70_read_um2(); } @@ -655,7 +655,7 @@ void em4x70_write(em4x70_data_t *etd) { em4x70_setup_read(); // Find the Tag - if (get_signalproperties() && find_em4x70_Tag()) { + if (get_signalproperties() && find_em4x70_tag()) { // Write status = write(etd->word, etd->address) == PM3_SUCCESS; @@ -684,7 +684,7 @@ void em4x70_unlock(em4x70_data_t *etd) { em4x70_setup_read(); // Find the Tag - if (get_signalproperties() && find_em4x70_Tag()) { + if (get_signalproperties() && find_em4x70_tag()) { // Read ID (required for send_pin command) if (em4x70_read_id()) { @@ -718,7 +718,7 @@ void em4x70_auth(em4x70_data_t *etd) { em4x70_setup_read(); // Find the Tag - if (get_signalproperties() && find_em4x70_Tag()) { + if (get_signalproperties() && find_em4x70_tag()) { // Authenticate and get tag response status = authenticate(etd->rnd, etd->frnd, response) == PM3_SUCCESS; @@ -729,3 +729,42 @@ void em4x70_auth(em4x70_data_t *etd) { reply_ng(CMD_LF_EM4X70_AUTH, status, response, sizeof(response)); } +void em4x70_write_pin(em4x70_data_t *etd) { + + uint8_t status = 0; + + command_parity = etd->parity; + + init_tag(); + em4x70_setup_read(); + + // Find the Tag + if (get_signalproperties() && find_em4x70_tag()) { + + // Read ID (required for send_pin command) + if (em4x70_read_id()) { + + // Write new PIN + if( (write( etd->pin & 0xFFFF, EM4X70_PIN_WORD_UPPER) == PM3_SUCCESS) && + (write((etd->pin >> 16) & 0xFFFF, EM4X70_PIN_WORD_LOWER) == PM3_SUCCESS)) { + + // Now Try to authenticate using the new PIN + + // Send PIN + status = send_pin(etd->pin) == PM3_SUCCESS; + + // If the write succeeded, read the rest of the tag + if (status) { + // Read Tag + // ID doesn't change + em4x70_read_um1(); + em4x70_read_um2(); + } + } + } + } + + StopTicks(); + lf_finalize(); + reply_ng(CMD_LF_EM4X70_WRITEPIN, status, tag.data, sizeof(tag.data)); +} diff --git a/armsrc/em4x70.h b/armsrc/em4x70.h index 7331a2201..41bfe824d 100644 --- a/armsrc/em4x70.h +++ b/armsrc/em4x70.h @@ -26,5 +26,6 @@ void em4x70_info(em4x70_data_t *etd); void em4x70_write(em4x70_data_t *etd); void em4x70_unlock(em4x70_data_t *etd); void em4x70_auth(em4x70_data_t *etd); +void em4x70_write_pin(em4x70_data_t *etd); #endif /* EM4x70_H */ diff --git a/client/src/cmdlfem4x70.c b/client/src/cmdlfem4x70.c index 05d8d52b4..b2ccb3a0e 100644 --- a/client/src/cmdlfem4x70.c +++ b/client/src/cmdlfem4x70.c @@ -338,12 +338,70 @@ int CmdEM4x70Auth(const char *Cmd) { return PM3_ESOFT; } +int CmdEM4x70WritePIN(const char *Cmd) { + + // send pin code to device, unlocking it for writing + em4x70_data_t etd = {0}; + + CLIParserContext *ctx; + + CLIParserInit(&ctx, "lf em 4x70 writepin", + "Write PIN\n", + "lf em 4x70 writepin -p 11223344 -> Write PIN\n" + "lf em 4x70 writepin -p 11223344 --par -> Write PIN using parity commands\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "par", "Add parity bit when sending commands"), + arg_str1("p", "pin", "", "pin, 4 bytes"), + arg_param_end + }; + + CLIExecWithReturn(ctx, Cmd, argtable, true); + + etd.parity = arg_get_lit(ctx, 1); + + int pin_len = 0; + uint8_t pin[4] = {0x0}; + + CLIGetHexWithReturn(ctx, 2, pin, &pin_len); + + CLIParserFree(ctx); + + if (pin_len != 4) { + PrintAndLogEx(FAILED, "PIN length must be 4 bytes instead of %d", pin_len); + return PM3_EINVARG; + } + + etd.pin = BYTES2UINT32(pin); + + clearCommandBuffer(); + SendCommandNG(CMD_LF_EM4X70_WRITEPIN, (uint8_t *)&etd, sizeof(etd)); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_LF_EM4X70_WRITEPIN, &resp, TIMEOUT)) { + PrintAndLogEx(WARNING, "Timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + if (resp.status) { + print_info_result(resp.data.asBytes); + PrintAndLogEx(INFO, "Writing new PIN: " _GREEN_("SUCCESS")); + return PM3_SUCCESS; + } + + PrintAndLogEx(FAILED, "Writing new PIN: " _RED_("FAILED")); + return PM3_ESOFT; +} + static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"info", CmdEM4x70Info, IfPm3EM4x70, "Tag information EM4x70"}, - {"write", CmdEM4x70Write, IfPm3EM4x70, "Write EM4x70"}, - {"unlock", CmdEM4x70Unlock, IfPm3EM4x70, "Unlock EM4x70 for writing"}, - {"auth", CmdEM4x70Auth, IfPm3EM4x70, "Authenticate EM4x70"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"info", CmdEM4x70Info, IfPm3EM4x70, "Tag information EM4x70"}, + {"write", CmdEM4x70Write, IfPm3EM4x70, "Write EM4x70"}, + {"unlock", CmdEM4x70Unlock, IfPm3EM4x70, "Unlock EM4x70 for writing"}, + {"auth", CmdEM4x70Auth, IfPm3EM4x70, "Authenticate EM4x70"}, + {"writepin", CmdEM4x70WritePIN, IfPm3EM4x70, "Write PIN"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdlfem4x70.h b/client/src/cmdlfem4x70.h index 755ff74d2..09a9b9361 100644 --- a/client/src/cmdlfem4x70.h +++ b/client/src/cmdlfem4x70.h @@ -21,6 +21,7 @@ int CmdEM4x70Info(const char *Cmd); int CmdEM4x70Write(const char *Cmd); int CmdEM4x70Unlock(const char *Cmd); int CmdEM4x70Auth(const char *Cmd); +int CmdEM4x70WritePIN(const char *Cmd); int em4x70_info(void); bool detect_4x70_block(void); diff --git a/include/em4x70.h b/include/em4x70.h index 0703c3900..4d08d622b 100644 --- a/include/em4x70.h +++ b/include/em4x70.h @@ -13,6 +13,10 @@ #define EM4X70_NUM_BLOCKS 16 +// Common word/block addresses +#define EM4X70_PIN_WORD_LOWER 10 +#define EM4X70_PIN_WORD_UPPER 11 + typedef struct { bool parity; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 95ef41ebb..0249d15a7 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -520,6 +520,7 @@ typedef struct { #define CMD_LF_EM4X70_WRITE 0x0261 #define CMD_LF_EM4X70_UNLOCK 0x0262 #define CMD_LF_EM4X70_AUTH 0x0263 +#define CMD_LF_EM4X70_WRITEPIN 0x0264 // Sampling configuration for LF reader/sniffer #define CMD_LF_SAMPLING_SET_CONFIG 0x021D #define CMD_LF_FSK_SIMULATE 0x021E