proxmark3/armsrc/Standalone/lf_em4100rwc.c

219 lines
6.8 KiB
C
Raw Normal View History

2020-03-08 01:07:38 +08:00
//-----------------------------------------------------------------------------
// Artyom Gnatyuk, 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
// the license.
//-----------------------------------------------------------------------------
2020-03-21 22:39:30 +08:00
// LF rwc - This mode can simulate ID from selected slot, read ID to
// selected slot, write from selected slot to T5555 tag and store
// readed ID to flash (only RDV4). Also you can set predefined IDs
2020-03-21 22:39:30 +08:00
// in any slot.
2020-03-08 01:07:38 +08:00
// To recall stored ID from flash execute:
// mem spifss dump o emdump p
// or:
// mem spifss dump o emdump f emdump
// then from shell:
// hexdump emdump -e '5/1 "%02X" /0 "\n"'
2020-03-08 01:07:38 +08:00
//-----------------------------------------------------------------------------
#include "standalone.h"
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "lfops.h"
#include "util.h"
#include "dbprint.h"
#include "ticks.h"
#include "string.h"
#include "BigBuf.h"
#include "spiffs.h"
2020-05-11 00:04:50 +08:00
#include "commonutil.h"
2020-03-08 01:07:38 +08:00
#ifdef WITH_FLASH
#include "flashmem.h"
#endif
#define MAX_IND 16 // 4 LEDs - 2^4 combinations
2020-07-14 21:57:21 +08:00
#define LF_CLOCK 64 // for 125kHz
2020-03-08 01:07:38 +08:00
// low & high - array for storage IDs. Its length must be equal.
2020-03-21 22:39:30 +08:00
// Predefined IDs must be stored in low[].
2020-03-08 01:07:38 +08:00
// In high[] must be nulls
static uint64_t low[] = {0x565AF781C7, 0x540053E4E2, 0x1234567890, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static uint32_t high[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static uint8_t slots_count;
static int buflen;
2020-03-08 01:07:38 +08:00
void ModInfo(void) {
2020-03-22 01:03:16 +08:00
DbpString(" LF EM4100 read/write/clone mode");
2020-03-08 01:07:38 +08:00
}
2020-06-23 18:10:09 +08:00
static uint64_t rev_quads(uint64_t bits) {
2020-03-21 22:39:30 +08:00
uint64_t result = 0;
for (int i = 0; i < 16; i++) {
result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
}
return result >> 24;
2020-03-08 01:07:38 +08:00
}
2021-01-28 06:30:37 +08:00
static void fill_buff(uint8_t bit) {
uint8_t *bba = BigBuf_get_addr();
2020-07-14 21:57:21 +08:00
memset(bba + buflen, bit, LF_CLOCK / 2);
buflen += (LF_CLOCK / 2);
memset(bba + buflen, bit ^ 1, LF_CLOCK / 2);
buflen += (LF_CLOCK / 2);
2020-03-08 01:07:38 +08:00
}
2020-06-23 18:10:09 +08:00
static void construct_EM410x_emul(uint64_t id) {
2020-08-13 18:25:04 +08:00
2020-07-14 21:57:21 +08:00
int i, j;
2021-02-09 23:56:55 +08:00
int binary[4] = {0, 0, 0, 0};
int parity[4] = {0, 0, 0, 0};
2020-03-21 22:39:30 +08:00
buflen = 0;
2020-08-13 18:25:04 +08:00
2020-07-14 21:57:21 +08:00
for (i = 0; i < 9; i++)
2021-01-28 06:30:37 +08:00
fill_buff(1);
2020-06-23 18:10:09 +08:00
2020-07-14 21:57:21 +08:00
for (i = 0; i < 10; i++) {
for (j = 3; j >= 0; j--, id /= 2)
2020-03-08 01:07:38 +08:00
binary[j] = id % 2;
2020-06-23 18:10:09 +08:00
2020-07-14 21:57:21 +08:00
for (j = 0; j < 4; j++)
2021-01-28 06:30:37 +08:00
fill_buff(binary[j]);
2020-06-23 18:10:09 +08:00
2021-01-28 06:30:37 +08:00
fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
2020-07-14 21:57:21 +08:00
for (j = 0; j < 4; j++)
2020-03-21 22:39:30 +08:00
parity[j] ^= binary[j];
2020-03-08 01:07:38 +08:00
}
2020-06-23 18:10:09 +08:00
2020-07-14 21:57:21 +08:00
for (j = 0; j < 4; j++)
2021-01-28 06:30:37 +08:00
fill_buff(parity[j]);
2020-06-23 18:10:09 +08:00
2021-01-28 06:30:37 +08:00
fill_buff(0);
2020-03-08 01:07:38 +08:00
}
2020-06-23 18:10:09 +08:00
static void led_slot(int i) {
2020-03-21 22:39:30 +08:00
LEDsoff();
if (slots_count > 4) {
LED(i % MAX_IND, 0); //binary indication, usefully for slots_count > 4
} else {
LED(1 << i, 0); //simple indication for slots_count <=4
}
2020-03-08 01:07:38 +08:00
}
2020-06-23 18:10:09 +08:00
static void flash_leds(uint32_t speed, uint8_t times) {
for (uint16_t i = 0; i < times * 2; i++) {
2020-03-08 01:07:38 +08:00
LED_A_INV();
LED_B_INV();
LED_C_INV();
LED_D_INV();
SpinDelay(speed);
}
}
#ifdef WITH_FLASH
2020-05-11 00:04:50 +08:00
static void SaveIDtoFlash(int addr, uint64_t id) {
2020-03-21 22:39:30 +08:00
uint8_t bt[5];
2020-05-11 00:04:50 +08:00
const char *filename = "emdump";
2020-03-21 22:39:30 +08:00
rdv40_spiffs_mount();
for (int i = 0; i < 5; i++) {
bt[4 - i] = (uint8_t)(id >> 8 * i & 0xff);
}
if (exists_in_spiffs(filename) == false) {
rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
} else {
rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
}
2020-03-08 01:07:38 +08:00
}
#endif
2020-05-10 22:59:38 +08:00
void RunMod(void) {
2020-03-08 01:07:38 +08:00
StandAloneMode();
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
2020-03-30 21:12:37 +08:00
Dbprintf("[=] >> LF EM4100 read/write/clone started <<");
2020-04-16 15:01:14 +08:00
2020-03-21 22:39:30 +08:00
int selected = 0;
//state 0 - select slot
// 1 - read tag to selected slot,
// 2 - simulate tag from selected slot
// 3 - write to T5555 tag
uint8_t state = 0;
2020-04-25 00:44:42 +08:00
slots_count = ARRAYLEN(low);
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
for (;;) {
2020-06-23 18:10:09 +08:00
2020-03-21 22:39:30 +08:00
WDT_HIT();
2020-06-23 18:10:09 +08:00
2020-03-08 01:07:38 +08:00
if (data_available()) break;
2020-06-23 18:10:09 +08:00
2020-03-21 22:39:30 +08:00
int button_pressed = BUTTON_HELD(1000);
SpinDelay(300);
2020-06-23 18:10:09 +08:00
2020-03-21 22:39:30 +08:00
switch (state) {
case 0:
// Select mode
2020-05-15 06:00:42 +08:00
if (button_pressed == BUTTON_HOLD) {
2020-03-21 22:39:30 +08:00
// Long press - switch to simulate mode
SpinUp(100);
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
state = 2;
2020-05-15 06:00:42 +08:00
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
2020-03-21 22:39:30 +08:00
// Click - switch to next slot
selected = (selected + 1) % slots_count;
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
}
break;
case 1:
// Read mode.
2020-05-15 06:00:42 +08:00
if (button_pressed == BUTTON_HOLD) {
2020-03-21 22:39:30 +08:00
// Long press - switch to read mode
SpinUp(100);
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
state = 3;
2020-05-15 06:00:42 +08:00
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
2020-03-21 22:39:30 +08:00
// Click - exit to select mode
2020-06-23 18:10:09 +08:00
lf_em410x_watch(1, &high[selected], &low[selected]);
flash_leds(100, 5);
2020-03-21 22:39:30 +08:00
#ifdef WITH_FLASH
SaveIDtoFlash(selected, low[selected]);
#endif
state = 0;
}
break;
case 2:
// Simulate mode
2020-05-15 06:00:42 +08:00
if (button_pressed == BUTTON_HOLD) {
2020-03-21 22:39:30 +08:00
// Long press - switch to read mode
SpinDown(100);
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
state = 1;
2020-05-15 06:00:42 +08:00
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
2020-03-21 22:39:30 +08:00
// Click - start simulating. Click again to exit from simulate mode
2020-06-23 18:10:09 +08:00
led_slot(selected);
construct_EM410x_emul(rev_quads(low[selected]));
flash_leds(100, 5);
2021-03-15 22:54:15 +08:00
SimulateTagLowFrequency(buflen, 0, true);
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
state = 0; // Switch to select mode
}
break;
case 3:
// Write tag mode
2020-05-15 06:00:42 +08:00
if (button_pressed == BUTTON_HOLD) {
2020-03-21 22:39:30 +08:00
// Long press - switch to select mode
SpinDown(100);
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
state = 0;
2020-05-15 06:00:42 +08:00
} else if (button_pressed == BUTTON_SINGLE_CLICK) {
2020-03-21 22:39:30 +08:00
// Click - write ID to tag
2020-07-14 21:57:21 +08:00
copy_em410x_to_t55xx(0, LF_CLOCK, (uint32_t)(low[selected] >> 32), (uint32_t)(low[selected] & 0xffffffff));
2020-06-23 18:10:09 +08:00
led_slot(selected);
2020-03-21 22:39:30 +08:00
state = 0; // Switch to select mode
}
break;
}
}
2020-03-08 01:07:38 +08:00
}