From 9a96157e824cb573b3b615b7751dc339ec64eb47 Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 14 Feb 2021 12:20:18 +0100 Subject: [PATCH] initial implementation of em4x50 standalone mode --- armsrc/Standalone/lf_tharexde.c | 57 +++++++++++++++------------------ armsrc/em4x50.c | 30 ++++++++--------- armsrc/iso14443a.c | 4 +-- client/src/cmdhfjooki.c | 13 +++++--- 4 files changed, 49 insertions(+), 55 deletions(-) diff --git a/armsrc/Standalone/lf_tharexde.c b/armsrc/Standalone/lf_tharexde.c index 44dbc8a4f..c88437f4f 100644 --- a/armsrc/Standalone/lf_tharexde.c +++ b/armsrc/Standalone/lf_tharexde.c @@ -28,8 +28,8 @@ * * On entering stand-alone mode, this module will start simulating EM4x50 data. * Data is read from eml dump file uploaded to flash memory (lf_em4x50_simulate.eml). - * If reader sends password different from dump file password, 'new' password - * is saved in file lf_em4x50_passwords.log in flash memory. + * If reader sends password different from dump file password, it is saved in + * file lf_em4x50_passwords.log in flash memory. * * On switching to read/record mode by pressing pm3 button, module will start * reading EM4x50 data. Each collected data set will be written/appended to the @@ -65,7 +65,6 @@ #define STATE_SIM 0 #define STATE_READ 1 -#define EM4X50_TAG_WORD 45 #define LF_EM4X50_INPUTFILE_SIM "lf_em4x50_simulate.eml" #define LF_EM4X50_LOGFILE_SIM "lf_em4x50_passwords.log" #define LF_EM4X50_LOGFILE_COLLECT "lf_em4x50_collect.log" @@ -75,25 +74,24 @@ uint32_t gPassword; static void LoadDataInstructions(const char *inputfile) { Dbprintf(""); Dbprintf("To load datafile to flash and display it:"); - Dbprintf(_YELLOW_("1.") " edit input file %s", inputfile); - Dbprintf(_YELLOW_("2.") " start proxmark3 client"); - Dbprintf(_YELLOW_("3.") " mem spiffs load f o %s", inputfile); - Dbprintf(_YELLOW_("4.") " start standalone mode"); + Dbprintf("1. edit input file %s", inputfile); + Dbprintf("2. start proxmark3 client"); + Dbprintf("3. mem spiffs load f o %s", inputfile); + Dbprintf("4. start standalone mode"); } static void DownloadLogInstructions(const char *logfile) { Dbprintf(""); Dbprintf("To get the logfile from flash and display it:"); - Dbprintf(_YELLOW_("1.") " mem spiffs dump o %s f ", logfile); - Dbprintf(_YELLOW_("2.") " exit proxmark3 client"); - Dbprintf(_YELLOW_("3.") " cat "); + Dbprintf("1. mem spiffs dump o %s f ", logfile); + Dbprintf("2. exit proxmark3 client"); + Dbprintf("3. cat "); } static bool get_input_data_from_file(uint32_t *tag, char *inputfile) { size_t now = 0; -#ifdef WITH_FLASH if (exists_in_spiffs(inputfile)) { uint32_t size = size_in_spiffs(inputfile); @@ -111,23 +109,21 @@ static bool get_input_data_from_file(uint32_t *tag, char *inputfile) { } Dbprintf(_YELLOW_("read tag data from input file")); + } else { + Dbprintf(_RED_("no input file %s"), inputfile); } BigBuf_free(); -#endif - + return ((now == EM4X50_NO_WORDS) && (tag[EM4X50_DEVICE_SERIAL] != tag[EM4X50_DEVICE_ID])); } static void append(const char *filename, uint8_t *entry, size_t entry_len) { - -#ifdef WITH_FLASH if (exists_in_spiffs(filename)) { rdv40_spiffs_append(filename, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); } else { rdv40_spiffs_write(filename, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); } -#endif } void ModInfo(void) { @@ -141,10 +137,8 @@ void RunMod(void) { uint8_t entry[400], state = STATE_SIM; uint32_t tag[EM4X50_NO_WORDS] = {0x0}; -#ifdef WITH_FLASH rdv40_spiffs_lazy_mount(); -#endif - + StandAloneMode(); Dbprintf(_YELLOW_("Standalone mode THAREXDE started")); @@ -191,8 +185,9 @@ void RunMod(void) { Dbprintf(_YELLOW_("tag data ok")); } else { Dbprintf(_RED_("error in tag data")); + LoadDataInstructions(LF_EM4X50_INPUTFILE_SIM); } - + // init; start with command = standard read mode em4x50_setup_sim(); gLogin = false; @@ -209,22 +204,22 @@ void RunMod(void) { LED(LED_A, 200); SpinDelay(200); } - + em4x50_handle_commands(&command, tag); // check if new password was found - if (gPassword != reflect32(tag[0])) { - + if (gPassword != reflect32(tag[EM4X50_DEVICE_PASSWORD])) { + Dbprintf("received password: %08"PRIx32"", gPassword); - + // append password to logfile in flash memory memset(entry, 0, sizeof(entry)); sprintf((char *)entry, "%08"PRIx32"\n", gPassword); append(LF_EM4X50_LOGFILE_SIM, entry, strlen((char *)entry)); - - gPassword = reflect32(tag[0]); + + gPassword = reflect32(tag[EM4X50_DEVICE_PASSWORD]); } - + // if timeout (e.g. no reader field) continue with standard read // mode and reset former authentication if (command == PM3_ETIMEOUT) { @@ -232,7 +227,7 @@ void RunMod(void) { gLogin = false; LED_D_OFF(); } - + } else if (state == STATE_READ) { if (state_change) { @@ -263,7 +258,7 @@ void RunMod(void) { append(LF_EM4X50_LOGFILE_COLLECT, entry, strlen((char *)entry)); } } - + // reset timer AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0 AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero @@ -271,17 +266,15 @@ void RunMod(void) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer } -#ifdef WITH_FLASH if (state == STATE_READ) { DownloadLogInstructions(LF_EM4X50_LOGFILE_COLLECT); } else { - LoadDataInstructions(LF_EM4X50_INPUTFILE_SIM); + DownloadLogInstructions(LF_EM4X50_LOGFILE_SIM); } LED_D_ON(); rdv40_spiffs_lazy_unmount(); LED_D_OFF(); -#endif FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 17db0cfb1..6c5f9c2d2 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -256,7 +256,7 @@ static uint32_t get_pulse_length(void) { int32_t timeout = EM4X50_TIMEOUT_PULSE_EVAL, tval = 0; - // iterates pulse length (low -> high -> low) + // iterates pulse lengths (low -> high -> low) volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -267,7 +267,6 @@ static uint32_t get_pulse_length(void) { return 0; tval = GetTicks(); - //timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD); timeout = EM4X50_TIMEOUT_PULSE_EVAL; while (sample < gHigh && (timeout--)) @@ -276,7 +275,6 @@ static uint32_t get_pulse_length(void) { if (timeout <= 0) return 0; - //timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD); timeout = EM4X50_TIMEOUT_PULSE_EVAL; while (sample > gLow && (timeout--)) sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -305,7 +303,6 @@ static void em4x50_reader_send_bit(int bit) { // disable modulation (activate the field) for 7 cycles of carrier // period (Opt64) LOW(GPIO_SSC_DOUT); - //while (AT91C_BASE_TC0->TC_CV < T0 * 7); while (GetTicks() - tval < 7 * CYCLES2TICKS); // enable modulation (drop the field) for remaining first @@ -862,16 +859,16 @@ void em4x50_read(em4x50_data_t *etd) { LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - LED_C_OFF(); - LED_D_ON(); + LED_C_OFF(); + LED_D_ON(); - // try to login with given password - if (etd->pwd_given) - blogin = (login(etd->password1) == PM3_SUCCESS); + // try to login with given password + if (etd->pwd_given) + blogin = (login(etd->password1) == PM3_SUCCESS); - // only one word has to be read -> first word read = last word read - if (blogin) - status = selective_read(etd->addresses, words); + // only one word has to be read -> first word read = last word read + if (blogin) + status = selective_read(etd->addresses, words); } LEDsoff(); @@ -914,7 +911,7 @@ void em4x50_reader(void) { int now = 0; uint32_t words[EM4X50_NO_WORDS] = {0x0}; - em4x50_setup_read(); + em4x50_setup_read(); LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { @@ -1245,7 +1242,6 @@ static int em4x50_sim_read_bit(void) { if (timeout <= 0) { return PM3_ETIMEOUT; } - //timeout = EM4X50_T_SIMULATION_TIMEOUT_READ; // now we have a reference "position", from here it will take // slightly less than 32 cycles until the end of the bit period @@ -1447,7 +1443,7 @@ static int em4x50_sim_handle_standard_read_command(uint32_t *tag) { WDT_HIT(); command = em4x50_sim_send_listen_window(tag); - + if (command != PM3_SUCCESS) { return command; } @@ -1543,7 +1539,7 @@ static int em4x50_sim_handle_login_command(uint32_t *tag) { em4x50_sim_send_nak(); gLogin = false; LED_D_OFF(); - + // save transmitted password for future use (e.g. standalone mode) gPassword = password; } @@ -1782,7 +1778,7 @@ void em4x50_handle_commands(int *command, uint32_t *tag) { // LED D -> operations that require authentication are possible void em4x50_sim(uint32_t *password) { - int command = 0; + int command = PM3_ENODATA; uint8_t *em4x50_mem = BigBuf_get_EM_addr(); uint32_t tag[EM4X50_NO_WORDS] = {0x0}; diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 999c5eded..cd07a4007 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -920,14 +920,14 @@ bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) { uint16_t checker = 0; for (;;) { WDT_HIT(); - if (flip == 2) { + if (flip == 3) { if (data_available()) return false; flip = 0; } - if (checker >= 4000) { + if (checker >= 3000) { if (BUTTON_PRESS()) return false; diff --git a/client/src/cmdhfjooki.c b/client/src/cmdhfjooki.c index 352c61ae7..9b1a14b8b 100644 --- a/client/src/cmdhfjooki.c +++ b/client/src/cmdhfjooki.c @@ -327,15 +327,19 @@ static int CmdHF14AJookiSim(const char *Cmd) { jooki_print(b64, result, false); + // copy UID from base64 url parameter + uint8_t uid[7] = {0}; + memcpy(uid, result + 5, 7); + // hf mfu sim... uint8_t *data = calloc(144, sizeof(uint8_t)); - // copy UID from base64 url parameter - memcpy(data, result + 5, 3); + memcpy(data, uid, 3); + memcpy(data + (1*4), uid + 3, 4); + // bbc0 data[3] = 0x88 ^ data[0] ^ data[1] ^ data[2]; - memcpy(data + (1*4), result + 8, 4); // bbc1 data[8] = data[4] ^ data[5] ^ data[6] ^ data[7]; @@ -398,8 +402,9 @@ static int CmdHF14AJookiSim(const char *Cmd) { // NTAG, 7 byte UID in eloaded data. payload.tagtype = 7; - payload.flags = FLAG_7B_UID_IN_DATA; + payload.flags = FLAG_UID_IN_EMUL; payload.exitAfter = 0; + memcpy(payload.uid, uid, sizeof(uid)); clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload));