initial implementation of em4x50 standalone mode

This commit is contained in:
tharexde 2021-02-14 12:20:18 +01:00
commit 9a96157e82
4 changed files with 49 additions and 55 deletions

View file

@ -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 <filename> 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 <filename> 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 <filename>", logfile);
Dbprintf(_YELLOW_("2.") " exit proxmark3 client");
Dbprintf(_YELLOW_("3.") " cat <filename>");
Dbprintf("1. mem spiffs dump o %s f <filename>", logfile);
Dbprintf("2. exit proxmark3 client");
Dbprintf("3. cat <filename>");
}
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,9 +137,7 @@ 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,6 +185,7 @@ 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
@ -213,7 +208,7 @@ void RunMod(void) {
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);
@ -222,7 +217,7 @@ void RunMod(void) {
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
@ -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();

View file

@ -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
@ -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
@ -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};

View file

@ -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;

View file

@ -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));