From c8b51ccf255166537c640272201c6df73aab9e8c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2020 15:11:48 +0200 Subject: [PATCH] chg: legic standalone - now saves read cards to flashmemory (RDV4)\n also simulates correct cardtype.\n It goes direct into recording / reading a tag. Once a complete dump is done, it starts to simulate --- armsrc/Standalone/hf_legic.c | 147 ++++++++++++++++++++++++++++------- armsrc/legicrf.c | 51 +++++++++++- armsrc/legicrf.h | 7 +- armsrc/legicrfsim.c | 6 +- 4 files changed, 176 insertions(+), 35 deletions(-) diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index 1e7aa7114..2b826528f 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// Stefanie Hofmann, 2020 -// Uli Heilmeier, 2020 +// (c) Stefanie Hofmann, 2020 +// (c) Uli Heilmeier, 2020 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -8,19 +8,89 @@ //----------------------------------------------------------------------------- // main code for Legic Prime read/sim //----------------------------------------------------------------------------- + #include "standalone.h" #include "proxmark3_arm.h" +#include "BigBuf.h" #include "appmain.h" #include "fpgaloader.h" #include "util.h" #include "dbprint.h" #include "ticks.h" - #include "legicrf.h" #include "legicrfsim.h" +#include "legic.h" // legic_card_select_t struct +#include "spiffs.h" // flashmem + + +/* + * To list all dump files from flash: + * + * 1. mem spiffs tree + * + * + * To retrieve dump files from flash: + * + * 1. mem spiffs dump o hf-legic-XXYYZZWW-dump.bin f hf-legic-XXYYZZWW-dump.bin + * Copies log file from flash to your client. + * + * + * This module emits debug strings during normal operation -- so try it out in + * the lab connected to PM3 client before taking it into the field. + * + * To delete a dump file from flash: + * + * 1. mem spiffs remove hf-legic-XXYYZZWW-dump.bin + * +*/ + +void DownloadLogInstructions() { + Dbprintf(""); + Dbprintf("[=] List all dumps from flash:"); + Dbprintf("[=] " _YELLOW_("-") "mem spiffs tree"); + Dbprintf(""); + Dbprintf("[=] To save a dump file from flash to client:"); + Dbprintf("[=] " _YELLOW_("-") "mem spiffs dump o hf-legic-UID-dump.bin f hf-legic-UID-dump.bin"); +} + +void save_dump_to_file(legic_card_select_t *p_card) { + +#ifdef WITH_FLASH + + // legic functions puts it memory in Emulator reserved memory. + uint8_t *mem = BigBuf_get_EM_addr(); + + char *preferredName = (char*)BigBuf_malloc(30); + if (preferredName == NULL) { + goto OUT; + } + + sprintf(preferredName, "hf-legic-%02X%02X%02X%02X-dump", p_card->uid[0], p_card->uid[1], p_card->uid[2], p_card->uid[3]); + uint16_t preferredNameLen = strlen(preferredName); + + char *filename = (char*)BigBuf_malloc(preferredNameLen + 4 + 1 + 10); + if (filename == NULL) { + goto OUT; + } + + sprintf(filename, "%.*s%s", preferredNameLen, preferredName, ".bin"); + uint16_t num = 1; + while (exists_in_spiffs(filename)) { + sprintf(filename, "%.*s-%d%s", preferredNameLen, preferredName, num, ".bin"); + num++; + } + + rdv40_spiffs_write(filename, mem, p_card->cardsize, RDV40_SPIFFS_SAFETY_SAFE); + + Dbprintf("[=] saved card dump to flashmem::" _YELLOW_("%s"), filename); +OUT: + BigBuf_free_keep_EM(); +#endif + +} void ModInfo(void) { - DbpString(" HF Legic Prime standalone "); + DbpString(" HF Legic Prime standalone"); } // Searching for Legic card until found and read. @@ -32,49 +102,72 @@ void ModInfo(void) { void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - Dbprintf(">> HF Legic Prime Read/Simulate Started <<"); - - int read_success; + Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<"); + DbpString("[=] press and HOLD button to exit standalone mode"); for (;;) { WDT_HIT(); - + //exit from hf_legic, send usbcommand if (data_available()) break; //Was our button held down or pressed? int button_pressed = BUTTON_HELD(280); - if (button_pressed != BUTTON_HOLD) continue; + if (button_pressed == BUTTON_HOLD) { + break; + } - LED_A_OFF(); - LED_B_OFF(); + LEDsoff(); LED_C_ON(); - LED_D_OFF(); - WAIT_BUTTON_RELEASED(); - - //record - DbpString("[=] start recording"); + DbpString("[=] looking for tags"); + int read_success = PM3_ESOFT; //search for legic card until reading successfull or button pressed do { LED_C_ON(); - SpinDelay(1000); + SpinDelay(500); // We don't care if we read a MIM256, MIM512 or MIM1024 // we just read 1024 bytes - read_success = LegicRfReader(0, 1024, 0x55); - } while (read_success == 0 && !BUTTON_PRESS()); + read_success = LegicRfReaderEx(0, 1024, 0x55); + + } while (read_success == PM3_ESOFT && !BUTTON_PRESS()); + + LEDsoff(); //simulate if read successfully - if (read_success == 1) { - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); + if (read_success != PM3_ESOFT) { + + legic_card_select_t *p_card; + p_card = getLegicCardInfo(); + if (p_card->cardsize == 0) + continue; + + save_dump_to_file(p_card); + LED_D_ON(); + uint8_t ct; + switch(p_card->tagtype) { + case 0x0D: + ct = 0; + break; + case 0x1D: + ct = 1; + break; + case 0x3D: + ct = 2; + break; + default: + continue; + } + // The read data is migrated to a MIM1024 card - LegicRfSimulate(2); - } else { - LEDsoff(); - WAIT_BUTTON_RELEASED(); + LegicRfSimulate(ct); } } + + LEDsoff(); +#ifdef WITH_FLASH + DownloadLogInstructions(); +#endif + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 313b38fc5..35b638298 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -404,6 +404,10 @@ bool write_byte(uint16_t index, uint8_t byte, uint8_t addr_sz) { // // Only this functions are public / called from appmain.c //----------------------------------------------------------------------------- +legic_card_select_t* getLegicCardInfo(void) { + return &card; +} + void LegicRfInfo(void) { // configure ARM and FPGA init_reader(false); @@ -441,8 +445,45 @@ OUT: StopTicks(); } -int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { - int read_success = 0; +int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) { + + int res = PM3_SUCCESS; + + // configure ARM and FPGA + init_reader(false); + + // establish shared secret and detect card type + uint8_t card_type = setup_phase(iv); + if (init_card(card_type, &card) != 0) { + res = PM3_ESOFT; + goto OUT; + } + + // do not read beyond card memory + if (len + offset > card.cardsize) { + len = card.cardsize - offset; + } + + for (uint16_t i = 0; i < len; ++i) { + int16_t byte = read_byte(offset + i, card.cmdsize); + if (byte == -1) { + res = PM3_EOVFLOW; + goto OUT; + } + legic_mem[i] = byte; + + if (i < 4) { + card.uid[i] = byte; + } + } + +OUT: + switch_off(); + StopTicks(); + return res; +} + +void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { // configure ARM and FPGA init_reader(false); @@ -465,16 +506,18 @@ int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { goto OUT; } legic_mem[i] = byte; + + if (i < 4) { + card.uid[i] = byte; + } } // OK - read_success = 1; reply_old(CMD_ACK, 1, len, 0, legic_mem, len); OUT: switch_off(); StopTicks(); - return read_success; } void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) { diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 6e59f4ca7..ae4c78cdc 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -1,6 +1,7 @@ //----------------------------------------------------------------------------- // (c) 2009 Henryk Plötz // 2018 AntiCat +// 2020 iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -13,8 +14,12 @@ #define __LEGICRF_H #include "common.h" +#include "legic.h" /* legic_card_select_t struct */ void LegicRfInfo(void); -int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); +int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv); +void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data); + +legic_card_select_t* getLegicCardInfo(void); #endif /* __LEGICRF_H */ diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 34f8458ce..bbec86fa5 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -460,12 +460,12 @@ void LegicRfSimulate(uint8_t cardtype) { // verify command line input if (init_card(cardtype, &card) != 0) { - DbpString("Unknown tagtype."); + DbpString("[!] Unknown tagtype."); goto OUT; } LED_A_ON(); - DbpString("Starting Legic emulator, press button to end"); + DbpString("[=] Starting Legic emulator, press " _YELLOW_("button") "to end"); while (!BUTTON_PRESS() && !data_available()) { WDT_HIT(); @@ -486,7 +486,7 @@ void LegicRfSimulate(uint8_t cardtype) { } OUT: - DbpString("Stopped"); + DbpString("[=] Sim stopped"); switch_off(); StopTicks(); }