mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-16 01:53:04 -07:00
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
This commit is contained in:
parent
7af2457158
commit
c8b51ccf25
4 changed files with 176 additions and 35 deletions
|
@ -1,6 +1,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Stefanie Hofmann, 2020
|
// (c) Stefanie Hofmann, 2020
|
||||||
// Uli Heilmeier, 2020
|
// (c) Uli Heilmeier, 2020
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// 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
|
// 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
|
// main code for Legic Prime read/sim
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "standalone.h"
|
#include "standalone.h"
|
||||||
#include "proxmark3_arm.h"
|
#include "proxmark3_arm.h"
|
||||||
|
#include "BigBuf.h"
|
||||||
#include "appmain.h"
|
#include "appmain.h"
|
||||||
#include "fpgaloader.h"
|
#include "fpgaloader.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "dbprint.h"
|
#include "dbprint.h"
|
||||||
#include "ticks.h"
|
#include "ticks.h"
|
||||||
|
|
||||||
#include "legicrf.h"
|
#include "legicrf.h"
|
||||||
#include "legicrfsim.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) {
|
void ModInfo(void) {
|
||||||
DbpString(" HF Legic Prime standalone ");
|
DbpString(" HF Legic Prime standalone");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Searching for Legic card until found and read.
|
// Searching for Legic card until found and read.
|
||||||
|
@ -32,9 +102,8 @@ void ModInfo(void) {
|
||||||
void RunMod() {
|
void RunMod() {
|
||||||
StandAloneMode();
|
StandAloneMode();
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
Dbprintf(">> HF Legic Prime Read/Simulate Started <<");
|
Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<");
|
||||||
|
DbpString("[=] press and HOLD button to exit standalone mode");
|
||||||
int read_success;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
@ -43,38 +112,62 @@ void RunMod() {
|
||||||
|
|
||||||
//Was our button held down or pressed?
|
//Was our button held down or pressed?
|
||||||
int button_pressed = BUTTON_HELD(280);
|
int button_pressed = BUTTON_HELD(280);
|
||||||
if (button_pressed != BUTTON_HOLD) continue;
|
if (button_pressed == BUTTON_HOLD) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
LED_A_OFF();
|
LEDsoff();
|
||||||
LED_B_OFF();
|
|
||||||
LED_C_ON();
|
LED_C_ON();
|
||||||
LED_D_OFF();
|
|
||||||
|
|
||||||
WAIT_BUTTON_RELEASED();
|
DbpString("[=] looking for tags");
|
||||||
|
int read_success = PM3_ESOFT;
|
||||||
//record
|
|
||||||
DbpString("[=] start recording");
|
|
||||||
|
|
||||||
//search for legic card until reading successfull or button pressed
|
//search for legic card until reading successfull or button pressed
|
||||||
do {
|
do {
|
||||||
LED_C_ON();
|
LED_C_ON();
|
||||||
SpinDelay(1000);
|
SpinDelay(500);
|
||||||
// We don't care if we read a MIM256, MIM512 or MIM1024
|
// We don't care if we read a MIM256, MIM512 or MIM1024
|
||||||
// we just read 1024 bytes
|
// we just read 1024 bytes
|
||||||
read_success = LegicRfReader(0, 1024, 0x55);
|
read_success = LegicRfReaderEx(0, 1024, 0x55);
|
||||||
} while (read_success == 0 && !BUTTON_PRESS());
|
|
||||||
|
} while (read_success == PM3_ESOFT && !BUTTON_PRESS());
|
||||||
|
|
||||||
|
LEDsoff();
|
||||||
|
|
||||||
//simulate if read successfully
|
//simulate if read successfully
|
||||||
if (read_success == 1) {
|
if (read_success != PM3_ESOFT) {
|
||||||
LED_A_OFF();
|
|
||||||
LED_B_OFF();
|
legic_card_select_t *p_card;
|
||||||
LED_C_OFF();
|
p_card = getLegicCardInfo();
|
||||||
|
if (p_card->cardsize == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
save_dump_to_file(p_card);
|
||||||
|
|
||||||
LED_D_ON();
|
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
|
// The read data is migrated to a MIM1024 card
|
||||||
LegicRfSimulate(2);
|
LegicRfSimulate(ct);
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
WAIT_BUTTON_RELEASED();
|
#ifdef WITH_FLASH
|
||||||
}
|
DownloadLogInstructions();
|
||||||
}
|
#endif
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// Only this functions are public / called from appmain.c
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
legic_card_select_t* getLegicCardInfo(void) {
|
||||||
|
return &card;
|
||||||
|
}
|
||||||
|
|
||||||
void LegicRfInfo(void) {
|
void LegicRfInfo(void) {
|
||||||
// configure ARM and FPGA
|
// configure ARM and FPGA
|
||||||
init_reader(false);
|
init_reader(false);
|
||||||
|
@ -441,8 +445,45 @@ OUT:
|
||||||
StopTicks();
|
StopTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
|
int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) {
|
||||||
int read_success = 0;
|
|
||||||
|
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
|
// configure ARM and FPGA
|
||||||
init_reader(false);
|
init_reader(false);
|
||||||
|
|
||||||
|
@ -465,16 +506,18 @@ int LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
legic_mem[i] = byte;
|
legic_mem[i] = byte;
|
||||||
|
|
||||||
|
if (i < 4) {
|
||||||
|
card.uid[i] = byte;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK
|
// OK
|
||||||
read_success = 1;
|
|
||||||
reply_old(CMD_ACK, 1, len, 0, legic_mem, len);
|
reply_old(CMD_ACK, 1, len, 0, legic_mem, len);
|
||||||
|
|
||||||
OUT:
|
OUT:
|
||||||
switch_off();
|
switch_off();
|
||||||
StopTicks();
|
StopTicks();
|
||||||
return read_success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
|
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
|
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
|
||||||
// 2018 AntiCat
|
// 2018 AntiCat
|
||||||
|
// 2020 iceman
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// 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
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
@ -13,8 +14,12 @@
|
||||||
#define __LEGICRF_H
|
#define __LEGICRF_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "legic.h" /* legic_card_select_t struct */
|
||||||
|
|
||||||
void LegicRfInfo(void);
|
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);
|
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data);
|
||||||
|
|
||||||
|
legic_card_select_t* getLegicCardInfo(void);
|
||||||
#endif /* __LEGICRF_H */
|
#endif /* __LEGICRF_H */
|
||||||
|
|
|
@ -460,12 +460,12 @@ void LegicRfSimulate(uint8_t cardtype) {
|
||||||
|
|
||||||
// verify command line input
|
// verify command line input
|
||||||
if (init_card(cardtype, &card) != 0) {
|
if (init_card(cardtype, &card) != 0) {
|
||||||
DbpString("Unknown tagtype.");
|
DbpString("[!] Unknown tagtype.");
|
||||||
goto OUT;
|
goto OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_A_ON();
|
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()) {
|
while (!BUTTON_PRESS() && !data_available()) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
@ -486,7 +486,7 @@ void LegicRfSimulate(uint8_t cardtype) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OUT:
|
OUT:
|
||||||
DbpString("Stopped");
|
DbpString("[=] Sim stopped");
|
||||||
switch_off();
|
switch_off();
|
||||||
StopTicks();
|
StopTicks();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue