diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f92d755e..7dad22edd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added support for PCSC's proprietary HID 37bit format P10004 (@bthedorff) - Added `nfc decode` - now NDEF vCard messages with a PHOTO in base64 format is shown (@iceman1001) - Changed - AID limitations when using Gallagher key diversification (@DarkMatterMatt) + - Added new standalone mode `lf_em4100rsww` (@zabszk) ## [Frostbit.4.14831] [2022-01-11] - Changed Wiegand format lookup - now case-insensitive (@iceman1001) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 0d6b0527a..5a3887c1b 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -35,6 +35,9 @@ define KNOWN_STANDALONE_DEFINITIONS | LF_EM4100RSWB | Read/simulate/brute em4100 tags & | | | clone it to T555x tags | +----------------------------------------------------------+ +| LF_EM4100RSWW | Read/simulate/validate em4100 tags & | +| | clone it to T55xx tags, wipe T55xx tags| ++----------------------------------------------------------+ | LF_EM4100RWC | Read/simulate em4100 tags & clone it | | | to T555x tags | +----------------------------------------------------------+ @@ -109,7 +112,7 @@ define KNOWN_STANDALONE_DEFINITIONS +----------------------------------------------------------+ endef -STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID +STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID STANDALONE_MODES += HF_14ASNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY DANKARMULTI STANDALONE_MODES_REQ_BT := HF_REBLAY STANDALONE_MODES_REQ_SMARTCARD := diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index 6f8e3c994..54ccbe1a6 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -85,6 +85,10 @@ endif ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWB,$(APP_CFLAGS))) SRC_STANDALONE = lf_em4100rswb.c endif +# WITH_STANDALONE_LF_EM4100RSWW +ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RSWW,$(APP_CFLAGS))) + SRC_STANDALONE = lf_em4100rsww.c +endif # WITH_STANDALONE_LF_EM4100RWC ifneq (,$(findstring WITH_STANDALONE_LF_EM4100RWC,$(APP_CFLAGS))) SRC_STANDALONE = lf_em4100rwc.c diff --git a/armsrc/Standalone/lf_em4100rsww.c b/armsrc/Standalone/lf_em4100rsww.c new file mode 100644 index 000000000..5ec39881a --- /dev/null +++ b/armsrc/Standalone/lf_em4100rsww.c @@ -0,0 +1,363 @@ +//----------------------------------------------------------------------------- +// Copyright by Łukasz Jurczyk, 2021-2022 +// +// This code is licensed to you under the terms of the GNU GPL, version 3. +// See the LICENSE.txt file for the text of the license. +//----------------------------------------------------------------------------- +// LF rsww - This mode can read EM4100 tag, save it to flash (RDV4 only), emulate it, clone it to T55xx tag, validate the write and wipe T55xx tag. +// +// To recall stored ID from flash execute: +// mem spiffs dump -s lf +// then from shell: +// hexdump lf.bin -e '5/1 "%02X" /0 "\n"' +// +// To recall only LAST stored ID from flash use lf-last instead of lf file. +// +//----------------------------------------------------------------------------- +// Modes of operation: +// +// --- Read --- +// Proxmark reads an EM4100 tag. LED A is turned on. When the tag is detected, it is saved to flash (RDV4 only) and proxmark enters the emulation mode. +// It's the default mode for non-RDV4 devices, and if no previous read is present in the flash it's the default mode for RDV4 devices. +// Pressing the button exists reading mode and enters emulation mode (only if any read is present in the memory). +// Double pressing the button enters wiping mode. +// +// --- Emulate --- +// Proxmark emulates last read tag. LED B is turned on. +// It's the default mode for RDV4 if lf-last file is present on the flash. +// Pressing the button enters writing mode and clones the emulated tag. +// Double pressing the button enters the validation mode. +// Holding the button enters the reading mode. +// +// --- Write --- +// Proxmarks writes the last read tag. LEDs A and B are turned on. +// When writing is complete LEDs A and B blink three times and proxmark enters the emulation mode. +// +// --- Validate --- +// Proxmark reads an EM4100 tag. LED C is turned on. +// If tag matches the last saved tag, LED C blinks three times. If it doesn't all LEDs blink three times. Proxmark enters the emulation mode afterwards. +// The result of the read is DISCARDED. +// Pressing the button enters the emulation mode. +// +// --- Wipe --- +// Proxmark continously wipes all approached T55xx tags. LED D is turned on, LEDs A-C are blinking. +// Pressing the button enters the default mode (reading or emulation). +//----------------------------------------------------------------------------- + +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "BigBuf.h" +#include "spiffs.h" +#include "inttypes.h" +#include "parity.h" +#include "lfops.h" + +#ifdef WITH_FLASH +#include "flashmem.h" +char *filename = "lf"; +char *filenameLast = "lf-last"; +#endif + +#define LF_CLOCK 64 // for 125kHz +#define LF_RWSB_T55XX_TYPE 1 // Tag type: 0 - T5555, 1-T55x7 + +static uint64_t low = 0; +static uint64_t low2 = 0; +static uint32_t high = 0; +static uint32_t high2 = 0; +static unsigned char mode = 0; +static int buflen; + +void ModInfo(void) { + DbpString("=== LF EM4100 read/sim/write/wipe/validate ==="); +} + +static uint64_t rev_quads(uint64_t bits) { + uint64_t result = 0; + for (int i = 0; i < 16; i++) { + result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i); + } + return result >> 24; +} + +static void fill_buff(uint8_t bit) { + uint8_t *bba = BigBuf_get_addr(); + memset(bba + buflen, bit, LF_CLOCK / 2); + buflen += (LF_CLOCK / 2); + memset(bba + buflen, bit ^ 1, LF_CLOCK / 2); + buflen += (LF_CLOCK / 2); +} + +static void construct_EM410x_emul(uint64_t id) { + int i, j; + int binary[4] = {0, 0, 0, 0}; + int parity[4] = {0, 0, 0, 0}; + buflen = 0; + + for (i = 0; i < 9; i++) + fill_buff(1); + + for (i = 0; i < 10; i++) { + for (j = 3; j >= 0; j--, id /= 2) + binary[j] = id % 2; + + for (j = 0; j < 4; j++) + fill_buff(binary[j]); + + fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + for (j = 0; j < 4; j++) + parity[j] ^= binary[j]; + } + + for (j = 0; j < 4; j++) + fill_buff(parity[j]); + + fill_buff(0); +} + +#ifdef WITH_FLASH +static void SaveIDtoFlash(uint64_t id) { + uint8_t bt[5]; + rdv40_spiffs_mount(); + for (int i = 0; i < 5; i++) { + bt[4 - i] = (uint8_t)(id >> 8 * i & 0xff); + } + if (exists_in_spiffs(filename)) + rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); + else + rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); + + if (exists_in_spiffs(filenameLast)) + rdv40_spiffs_remove(filenameLast, RDV40_SPIFFS_SAFETY_NORMAL); + + rdv40_spiffs_write(filenameLast, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL); +} + +static bool ReadFlash(void) { + if (exists_in_spiffs(filenameLast) == false) + return false; + + uint8_t bt[5]; + if (rdv40_spiffs_read(filenameLast, (uint8_t *) &bt, 5, RDV40_SPIFFS_SAFETY_NORMAL) < 0) + return false; + + low = bt[0]; + low <<= 32; + low |= (bt[1] << 24) | (bt[2] << 16) | (bt[3] << 8) | bt[4]; + low2 = low; + high = 0; + high2 = 0; + return true; +} +#endif + +static void Wipe(void) { + DbpString("Wipe mode"); + LEDsoff(); + + for (;;) { + LED_A_ON(); + LED_B_ON(); + LED_C_ON(); + LED_D_ON(); + copy_em410x_to_t55xx(LF_RWSB_T55XX_TYPE, LF_CLOCK, (uint32_t) 0, (uint32_t) 0, false); + SpinDelay(60); + LEDsoff(); + LED_D_ON(); + + int b = BUTTON_HELD(100); + if (b != BUTTON_NO_CLICK || data_available()) + return; + + SpinDelay(100); + + b = BUTTON_HELD(100); + if (b != BUTTON_NO_CLICK || data_available()) + return; + } +} + +static void Read(void) { + mode = 0; + + while (low2 == 0 || mode == 0) + { + DbpString("Read"); + LEDsoff(); + LED_A_ON(); + + low2 = 0; + high2 = 0; + lf_em410x_watch(1, &high2, &low2, false); + + if (low2 != 0) { + LED_B_ON(); + low = low2; + high = high2; + mode = 1; + + #ifdef WITH_FLASH + SaveIDtoFlash(low2); + #endif + + SpinDelay(50); + LED_C_ON(); + SpinDelay(50); + LED_D_ON(); + SpinDelay(50); + LEDsoff(); + return; + } + + if (data_available()) + return; + + int b = BUTTON_CLICKED(1000); + + if ((b == BUTTON_SINGLE_CLICK || b == BUTTON_HOLD) && low != 0) { + mode = 1; + return; + } + + if (b == BUTTON_DOUBLE_CLICK) { + Wipe(); + + if (low != 0) { + mode = 1; + return; + } + } + } +} + +static void Validate(void) { + DbpString("Validate"); + LEDsoff(); + LED_C_ON(); + + for (;;) { + low2 = 0; + high2 = 0; + + lf_em410x_watch(1, &high2, &low2, false); + + if (low == low2 && high == high2) { + LED_C_OFF(); + SpinDelay(150); + for (int i = 0; i < 3; i++) { + LED_C_ON(); + SpinDelay(150); + LED_C_OFF(); + SpinDelay(150); + } + + return; + } + else if (low2 != 0 || high2 != 0) { + LEDsoff(); + for (int i = 0; i < 3; i++) { + LED_A_ON(); + LED_B_ON(); + LED_C_ON(); + LED_D_ON(); + SpinDelay(250); + LEDsoff(); + SpinDelay(150); + } + + return; + } + else + SpinDelay(200); + + int b = BUTTON_HELD(200); + if (b != BUTTON_NO_CLICK || data_available()) + return; + } +} + +static void Write(void) { + DbpString("Write"); + LED_A_ON(); + LED_B_ON(); + copy_em410x_to_t55xx(LF_RWSB_T55XX_TYPE, LF_CLOCK, (uint32_t)(low >> 32), (uint32_t)(low & 0xffffffff), false); + SpinDelay(75); + LEDsoff(); + + for (int i = 0; i < 3; i++) { + LED_A_ON(); + LED_B_ON(); + SpinDelay(75); + LED_A_OFF(); + LED_B_OFF(); + SpinDelay(75); + } +} + +static void Emulate(void) { + DbpString("Emulate"); + LEDsoff(); + + for (;;) { + int bx = BUTTON_HELD(50); + if (bx == BUTTON_NO_CLICK) + break; + SpinDelay(50); + } + + LED_B_ON(); + construct_EM410x_emul(rev_quads(low)); + SimulateTagLowFrequencyEx(buflen, 0, false, -1); + + int b = BUTTON_CLICKED(800); + + if (b == BUTTON_NO_CLICK) + return; + + for (;;) { + int bx = BUTTON_HELD(50); + if (bx == BUTTON_NO_CLICK) + break; + SpinDelay(50); + } + + if (b == BUTTON_SINGLE_CLICK) + Write(); + else if (b == BUTTON_HOLD) + mode = 0; + else if (b == BUTTON_DOUBLE_CLICK) + Validate(); +} + +void RunMod() { + StandAloneMode(); + LEDsoff(); + LED_D_ON(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + WDT_HIT(); + +#ifdef WITH_FLASH + if (ReadFlash()) + mode = 1; + else Read(); +#else + Read(); +#endif + + for (;;) { + WDT_HIT(); + LEDsoff(); + + if (data_available()) return; + + if (mode == 0) + Read(); + else Emulate(); + } +} diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 5813caf48..6d9866aa4 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -103,6 +103,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo | | No standalone mode | LF_EM4100EMUL | LF EM4100 simulator standalone mode - temskiy | LF_EM4100RSWB | LF EM4100 read/write/clone/brute mode - Monster1024 +| LF_EM4100RSWW | LF EM4100 read/write/clone/validate/wipe mode - Łukasz "zabszk" Jurczyk | LF_EM4100RWC | LF EM4100 read/write/clone mode - temskiy | LF_HIDBRUTE | HID corporate 1000 bruteforce - Federico dotta & Maurizio Agazzini | LF_HIDFCBRUTE | LF HID facility code bruteforce - ss23 diff --git a/tools/build_all_firmwares.sh b/tools/build_all_firmwares.sh index 7514a9757..330441b13 100755 --- a/tools/build_all_firmwares.sh +++ b/tools/build_all_firmwares.sh @@ -30,7 +30,7 @@ mkdir -p "$DEST" mv bootrom/obj/bootrom.elf "$DEST/PM3BOOTROM.elf" # cf armsrc/Standalone/Makefile.hal -STANDALONE_MODES=(LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID) +STANDALONE_MODES=(LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID) STANDALONE_MODES+=(HF_14ASNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY DANKARMULTI) STANDALONE_MODES_REQ_BT=(HF_REBLAY) STANDALONE_MODES_REQ_SMARTCARD=()