mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
initial implementation of em4x50 standalone mode
This commit is contained in:
parent
ac0ef23d5e
commit
9a96157e82
4 changed files with 49 additions and 55 deletions
|
@ -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,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();
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue