mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-01-31 12:31:32 +08:00
redesign
This commit is contained in:
parent
a84074686b
commit
a04002ab1b
5 changed files with 228 additions and 334 deletions
|
@ -1034,7 +1034,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_LF_EM4X50_WIPE: {
|
||||
em4x50_wipe((em4x50_data_t *)packet->data.asBytes);
|
||||
em4x50_wipe((uint32_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X50_BRUTE: {
|
||||
|
@ -1042,7 +1042,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_LF_EM4X50_LOGIN: {
|
||||
em4x50_login((em4x50_data_t *)packet->data.asBytes);
|
||||
em4x50_login((uint32_t *)packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X50_RESET: {
|
||||
|
|
299
armsrc/em4x50.c
299
armsrc/em4x50.c
|
@ -13,7 +13,6 @@
|
|||
#include "dbprint.h"
|
||||
#include "lfadc.h"
|
||||
#include "commonutil.h"
|
||||
#include "BigBuf.h"
|
||||
#include "em4x50.h"
|
||||
|
||||
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||
|
@ -47,45 +46,17 @@
|
|||
#define EM4X50_COMMAND_WRITE_PASSWORD 0x11
|
||||
#define EM4X50_COMMAND_SELECTIVE_READ 0x0A
|
||||
|
||||
#define EM4X50_COMMAND_TIMEOUT 5000
|
||||
#define FPGA_TIMER_0 0
|
||||
|
||||
int gHigh = 0;
|
||||
int gLow = 0;
|
||||
|
||||
// auxiliary functions
|
||||
|
||||
static void msb2lsb_word(uint8_t *word) {
|
||||
|
||||
// reorders given <word> according to EM4x50 datasheet (msb -> lsb)
|
||||
|
||||
uint8_t buff[4];
|
||||
buff[0] = reflect8(word[3]);
|
||||
buff[1] = reflect8(word[2]);
|
||||
buff[2] = reflect8(word[1]);
|
||||
buff[3] = reflect8(word[0]);
|
||||
|
||||
word[0] = buff[0];
|
||||
word[1] = buff[1];
|
||||
word[2] = buff[2];
|
||||
word[3] = buff[3];
|
||||
}
|
||||
|
||||
static void wait_timer(int timer, uint32_t period) {
|
||||
static void wait_timer0(uint32_t period) {
|
||||
|
||||
// do nothing for <period> using timer <timer>
|
||||
|
||||
if (timer == FPGA_TIMER_0) {
|
||||
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
while (AT91C_BASE_TC0->TC_CV < period);
|
||||
|
||||
} else {
|
||||
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
while (AT91C_BASE_TC1->TC_CV < period);
|
||||
|
||||
}
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
while (AT91C_BASE_TC0->TC_CV < period);
|
||||
}
|
||||
|
||||
static void em4x50_setup_read(void) {
|
||||
|
@ -160,7 +131,7 @@ static bool get_signalproperties(void) {
|
|||
if (BUTTON_PRESS()) return false;
|
||||
|
||||
// about 2 samples per bit period
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_HALF_PERIOD);
|
||||
wait_timer0(T0 * EM4X50_T_TAG_HALF_PERIOD);
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_RHR > noise) {
|
||||
signal_found = true;
|
||||
|
@ -194,31 +165,31 @@ static bool get_signalproperties(void) {
|
|||
// set global envelope variables
|
||||
gHigh = sample_ref + pct * (sample_max_mean - sample_ref) / 100;
|
||||
gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100;
|
||||
|
||||
Dbprintf("gHigh = %i, gLow = %i", gHigh, gLow);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int get_next_bit(void) {
|
||||
static bool unvalid_bit(void) {
|
||||
|
||||
// returns bit value (or EM4X50_BIT_OTHER -> no bit pattern) by evaluating
|
||||
// a single sample within a bit period (given there is no LIW, ACK or NAK)
|
||||
// This function is not used for decoding, it is only used for identifying
|
||||
// a listen window (return value = EM4X50_BIT_OTHER) in functions
|
||||
// returns true if bit is undefined by evaluating a single sample within
|
||||
// a bit period (given there is no LIW, ACK or NAK)
|
||||
// This function is used for identifying a listen window in functions
|
||||
// "find_double_listen_window" and "check_ack"
|
||||
|
||||
// get sample at 3/4 of bit period
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD);
|
||||
wait_timer0(T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD);
|
||||
uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
// wait until end of bit period
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_QUARTER_PERIOD);
|
||||
wait_timer0(T0 * EM4X50_T_TAG_QUARTER_PERIOD);
|
||||
|
||||
// decide wether "0" or "1"
|
||||
if (sample > gHigh)
|
||||
return EM4X50_BIT_0;
|
||||
else if (sample < gLow)
|
||||
return EM4X50_BIT_1;
|
||||
// bit in "undefined" state?
|
||||
if (sample <= gHigh && sample >= gLow)
|
||||
return true;
|
||||
|
||||
return EM4X50_BIT_OTHER;
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t get_pulse_length(void) {
|
||||
|
@ -229,9 +200,8 @@ static uint32_t get_pulse_length(void) {
|
|||
|
||||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
while (sample > gLow && (timeout--)) {
|
||||
while (sample > gLow && (timeout--))
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
return 0;
|
||||
|
@ -239,17 +209,15 @@ static uint32_t get_pulse_length(void) {
|
|||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
|
||||
while (sample < gHigh && (timeout--)) {
|
||||
while (sample < gHigh && (timeout--))
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
return 0;
|
||||
|
||||
timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
while (sample > gLow && (timeout--)) {
|
||||
while (sample > gLow && (timeout--))
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
return 0;
|
||||
|
@ -319,13 +287,18 @@ static void em4x50_reader_send_byte_with_parity(uint8_t byte) {
|
|||
em4x50_reader_send_bit(parity);
|
||||
}
|
||||
|
||||
static void em4x50_reader_send_word(const uint8_t bytes[4]) {
|
||||
static void em4x50_reader_send_word(const uint32_t word) {
|
||||
|
||||
// send 32 bit word with parity bits according to EM4x50 datasheet
|
||||
// word hast be sent in msb notation
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
bytes[i] = (word >> (24 - (8 * i))) & 0xFF;
|
||||
em4x50_reader_send_byte_with_parity(bytes[i]);
|
||||
|
||||
}
|
||||
|
||||
// send column parities
|
||||
em4x50_reader_send_byte(bytes[0] ^ bytes[1] ^ bytes[2] ^ bytes[3]);
|
||||
|
||||
|
@ -387,12 +360,12 @@ static int find_double_listen_window(bool bcommand) {
|
|||
// second window follows - sync on this to issue a command
|
||||
|
||||
// skip the next bit...
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
wait_timer0(T0 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
|
||||
// ...and check if the following bit does make sense
|
||||
// (if not it is the correct position within the second
|
||||
// listen window)
|
||||
if (get_next_bit() == EM4X50_BIT_OTHER) {
|
||||
if (unvalid_bit()) {
|
||||
|
||||
// send RM for request mode
|
||||
em4x50_reader_send_bit(0);
|
||||
|
@ -606,11 +579,11 @@ static bool check_ack(bool bliw) {
|
|||
|
||||
// wait for 2 bits (remaining "bit" of ACK signal + first
|
||||
// "bit" of listen window)
|
||||
wait_timer(FPGA_TIMER_0, T0 * 2 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
wait_timer0(T0 * 2 * EM4X50_T_TAG_FULL_PERIOD);
|
||||
|
||||
// check for listen window (if first bit cannot be inerpreted
|
||||
// as a valid bit it must belong to a listen window)
|
||||
if (get_next_bit() == EM4X50_BIT_OTHER) {
|
||||
if (unvalid_bit()) {
|
||||
|
||||
// send RM for request mode
|
||||
em4x50_reader_send_bit(0);
|
||||
|
@ -776,7 +749,7 @@ static int get_word_from_bitstream(uint32_t *data) {
|
|||
// login function
|
||||
//==============================================================================
|
||||
|
||||
static bool login(uint8_t password[4]) {
|
||||
static bool login(uint32_t password) {
|
||||
|
||||
// simple login to EM4x50,
|
||||
// used in operations that require authentication
|
||||
|
@ -857,15 +830,14 @@ static bool standard_read(int *now, uint32_t *words) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool selective_read(uint8_t addresses[4], uint32_t *words) {
|
||||
static bool selective_read(uint32_t addresses, uint32_t *words) {
|
||||
|
||||
// reads from "first word read" (fwr = addresses[3]) to "last word read"
|
||||
// (lwr = addresses[2])
|
||||
// reads from "first word read" (fwr) to "last word read" (lwr)
|
||||
// result is verified by "standard read mode"
|
||||
|
||||
int fwr = addresses[3]; // first word read
|
||||
int lwr = addresses[2]; // last word read
|
||||
int now = fwr; // number of words
|
||||
uint8_t fwr = addresses & 0xFF; // first word read (first byte)
|
||||
uint8_t lwr = (addresses >> 8) & 0xFF; // last word read (second byte)
|
||||
int now = fwr; // number of words
|
||||
|
||||
if (request_receive_mode()) {
|
||||
|
||||
|
@ -894,12 +866,10 @@ static bool selective_read(uint8_t addresses[4], uint32_t *words) {
|
|||
void em4x50_info(em4x50_data_t *etd) {
|
||||
|
||||
// collects as much information as possible via selective read mode
|
||||
// if no password is given -> try with standard password "0x00000000"
|
||||
// otherwise continue without login
|
||||
|
||||
bool bsuccess = false, blogin = false;
|
||||
uint8_t status = 0;
|
||||
uint8_t addresses[] = {0x00, 0x00, 0x21, 0x00}; // fwr = 0, lwr = 33
|
||||
uint32_t addresses = 0x00002100; // read from fwr = 0 to lwr = 33 (0x21)
|
||||
uint32_t words[32] = {0x0};
|
||||
|
||||
em4x50_setup_read();
|
||||
|
@ -907,12 +877,9 @@ void em4x50_info(em4x50_data_t *etd) {
|
|||
// set gHigh and gLow
|
||||
if (get_signalproperties() && find_em4x50_tag()) {
|
||||
|
||||
if (etd->pwd_given) {
|
||||
|
||||
// try to login with given password
|
||||
blogin = login(etd->password);
|
||||
|
||||
}
|
||||
// login with given password
|
||||
if (etd->pwd_given)
|
||||
blogin = login(etd->password1);
|
||||
|
||||
bsuccess = selective_read(addresses, words);
|
||||
}
|
||||
|
@ -933,7 +900,6 @@ void em4x50_read(em4x50_data_t *etd) {
|
|||
bool bsuccess = false, blogin = false;
|
||||
int now = 0;
|
||||
uint8_t status = 0;
|
||||
uint8_t addresses[] = {0x00, 0x00, 0x00, 0x00};
|
||||
uint32_t words[32] = {0x0};
|
||||
|
||||
em4x50_setup_read();
|
||||
|
@ -947,11 +913,10 @@ void em4x50_read(em4x50_data_t *etd) {
|
|||
|
||||
// try to login with given password
|
||||
if (etd->pwd_given)
|
||||
blogin = login(etd->password);
|
||||
blogin = login(etd->password1);
|
||||
|
||||
// only one word has to be read -> first word read = last word read
|
||||
addresses[2] = addresses[3] = etd->address;
|
||||
bsuccess = selective_read(addresses, words);
|
||||
bsuccess = selective_read(etd->addresses, words);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -966,14 +931,13 @@ void em4x50_read(em4x50_data_t *etd) {
|
|||
LOW(GPIO_SSC_DOUT);
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, (uint8_t *)words, 136);
|
||||
//reply_ng(CMD_ACK, status, (uint8_t *)em4x50_tag, 136);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// write functions
|
||||
//==============================================================================
|
||||
|
||||
static bool write(uint8_t word[4], uint8_t address) {
|
||||
static bool write(uint32_t word, uint32_t addresses) {
|
||||
|
||||
// writes <word> to specified <address>
|
||||
|
||||
|
@ -983,13 +947,13 @@ static bool write(uint8_t word[4], uint8_t address) {
|
|||
em4x50_reader_send_byte_with_parity(EM4X50_COMMAND_WRITE);
|
||||
|
||||
// send address data
|
||||
em4x50_reader_send_byte_with_parity(address);
|
||||
em4x50_reader_send_byte_with_parity(addresses & 0xFF);
|
||||
|
||||
// send data
|
||||
em4x50_reader_send_word(word);
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
wait_timer0(T0 * EM4X50_T_TAG_TWA);
|
||||
|
||||
// look for ACK sequence
|
||||
if (check_ack(false)) {
|
||||
|
@ -1009,7 +973,7 @@ static bool write(uint8_t word[4], uint8_t address) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||
static bool write_password(uint32_t password, uint32_t new_password) {
|
||||
|
||||
// changes password from <password> to <new_password>
|
||||
|
||||
|
@ -1022,7 +986,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
|||
em4x50_reader_send_word(password);
|
||||
|
||||
// wait for T0 * EM4x50_T_TAG_TPP (processing pause time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TPP);
|
||||
wait_timer0(T0 * EM4X50_T_TAG_TPP);
|
||||
|
||||
// look for ACK sequence and send rm request
|
||||
// during following listen window
|
||||
|
@ -1032,7 +996,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
|||
em4x50_reader_send_word(new_password);
|
||||
|
||||
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
|
||||
wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA);
|
||||
wait_timer0(T0 * EM4X50_T_TAG_TWA);
|
||||
|
||||
if (check_ack(false))
|
||||
if (check_ack(false))
|
||||
|
@ -1055,7 +1019,6 @@ void em4x50_write(em4x50_data_t *etd) {
|
|||
|
||||
bool bsuccess = false, blogin = false;
|
||||
uint8_t status = 0;
|
||||
uint8_t addresses[4] = {0x00, 0x00, 0x00, 0x00};
|
||||
uint32_t words[34] = {0x0};
|
||||
|
||||
em4x50_setup_read();
|
||||
|
@ -1063,37 +1026,25 @@ void em4x50_write(em4x50_data_t *etd) {
|
|||
// set gHigh and gLow
|
||||
if (get_signalproperties() && find_em4x50_tag()) {
|
||||
|
||||
// reorder word according to datasheet
|
||||
msb2lsb_word(etd->word);
|
||||
|
||||
// if password is given try to login first
|
||||
if (etd->pwd_given)
|
||||
blogin = login(etd->password);
|
||||
blogin = login(etd->password1);
|
||||
|
||||
// write word to given address
|
||||
if (write(etd->word, etd->address)) {
|
||||
if (write(etd->word, etd->addresses)) {
|
||||
|
||||
// to verify result reset EM4x50
|
||||
if (reset()) {
|
||||
|
||||
// if password is given login
|
||||
if (etd->pwd_given)
|
||||
blogin &= login(etd->password);
|
||||
blogin &= login(etd->password1);
|
||||
|
||||
// call a selective read
|
||||
addresses[2] = addresses[3] = etd->address;
|
||||
if (selective_read(addresses, words)) {
|
||||
if (selective_read(etd->addresses, words)) {
|
||||
|
||||
// compare with given word
|
||||
uint32_t tmp = 0x0;
|
||||
tmp = etd->word[0];
|
||||
tmp <<= 8;
|
||||
tmp |= etd->word[1];
|
||||
tmp <<= 8;
|
||||
tmp |= etd->word[2];
|
||||
tmp <<= 8;
|
||||
tmp |= etd->word[3];
|
||||
bsuccess = (words[etd->address] == reflect32(tmp));
|
||||
bsuccess = (words[etd->addresses & 0xFF] == reflect32(etd->word));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1110,43 +1061,29 @@ void em4x50_write_password(em4x50_data_t *etd) {
|
|||
// simple change of password
|
||||
|
||||
bool bsuccess = false;
|
||||
uint8_t rpwd[4] = {0x0, 0x0, 0x0, 0x0};
|
||||
uint8_t rnewpwd[4] = {0x0, 0x0, 0x0, 0x0};
|
||||
|
||||
em4x50_setup_read();
|
||||
|
||||
// set gHigh and gLow
|
||||
if (get_signalproperties() && find_em4x50_tag()) {
|
||||
|
||||
// lsb -> msb
|
||||
rpwd[0] = reflect8(etd->password[3]);
|
||||
rpwd[1] = reflect8(etd->password[2]);
|
||||
rpwd[2] = reflect8(etd->password[1]);
|
||||
rpwd[3] = reflect8(etd->password[0]);
|
||||
|
||||
rnewpwd[0] = reflect8(etd->new_password[3]);
|
||||
rnewpwd[1] = reflect8(etd->new_password[2]);
|
||||
rnewpwd[2] = reflect8(etd->new_password[1]);
|
||||
rnewpwd[3] = reflect8(etd->new_password[0]);
|
||||
|
||||
// login and change password
|
||||
if (login(rpwd)) {
|
||||
bsuccess = write_password(rpwd, rnewpwd);
|
||||
}
|
||||
if (login(etd->password1))
|
||||
bsuccess = write_password(etd->password1, etd->password2);
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, bsuccess, 0, 0);
|
||||
}
|
||||
|
||||
void em4x50_wipe(em4x50_data_t *etd) {
|
||||
void em4x50_wipe(uint32_t *password) {
|
||||
|
||||
// set all data of EM4x50 tag to 0x0 including password
|
||||
|
||||
bool bsuccess = false;
|
||||
uint8_t zero[4] = {0, 0, 0, 0};
|
||||
uint8_t addresses[4] = {0, 0, EM4X50_NO_WORDS - 3, 1};
|
||||
uint32_t addresses = 0x00001E01; // from fwr = 1 to lwr = 31 (0x1E)
|
||||
uint32_t words[34] = {0x0};
|
||||
uint32_t zero = 0x0;
|
||||
|
||||
em4x50_setup_read();
|
||||
|
||||
|
@ -1154,15 +1091,14 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
|||
if (get_signalproperties() && find_em4x50_tag()) {
|
||||
|
||||
// login first
|
||||
if (login(etd->password)) {
|
||||
if (login(*password)) {
|
||||
|
||||
// write 0x0 to each address but ignore addresses
|
||||
// 0 -> password, 32 -> serial, 33 -> uid
|
||||
// writing 34 words takes about 3.6 seconds -> high timeout needed
|
||||
for (int i = 1; i <= EM4X50_NO_WORDS - 3; i++)
|
||||
for (int i = 1; i <= 33; i++)
|
||||
write(zero, i);
|
||||
|
||||
// to verify result reset EM4x50
|
||||
// to verify result -> reset EM4x50
|
||||
if (reset()) {
|
||||
|
||||
// login not necessary because protected word has been set to 0
|
||||
|
@ -1172,7 +1108,7 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
|||
|
||||
// check if everything is zero
|
||||
bsuccess = true;
|
||||
for (int i = 1; i <= EM4X50_NO_WORDS - 3; i++)
|
||||
for (int i = 1; i <= 33; i++)
|
||||
bsuccess &= (words[i] == 0);
|
||||
|
||||
}
|
||||
|
@ -1181,8 +1117,8 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
|||
|
||||
// so far everything is fine
|
||||
// last task: reset password
|
||||
if (login(etd->password))
|
||||
bsuccess = write_password(etd->password, zero);
|
||||
if (login(*password))
|
||||
bsuccess = write_password(*password, zero);
|
||||
|
||||
// verify by login with new password
|
||||
if (bsuccess)
|
||||
|
@ -1205,37 +1141,24 @@ void em4x50_reset(void) {
|
|||
em4x50_setup_read();
|
||||
|
||||
// set gHigh and gLow
|
||||
if (get_signalproperties() && find_em4x50_tag()) {
|
||||
|
||||
if (get_signalproperties() && find_em4x50_tag())
|
||||
status = reset();
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, 0, 0);
|
||||
}
|
||||
|
||||
void em4x50_login(em4x50_data_t *etd) {
|
||||
void em4x50_login(uint32_t *password) {
|
||||
|
||||
// login into EM4x50
|
||||
|
||||
uint8_t status = false;
|
||||
uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0};
|
||||
uint32_t rpwd = 0x0;
|
||||
|
||||
em4x50_setup_read();
|
||||
|
||||
// set gHigh and gLow
|
||||
if (get_signalproperties() && find_em4x50_tag()) {
|
||||
|
||||
// lsb -> msb
|
||||
rpwd = reflect32(etd->login_password);
|
||||
|
||||
// convert to "old" data format
|
||||
for (int i = 0; i < 4; i++)
|
||||
bytes[i] = (rpwd >> ((3 - i) * 8)) & 0xFF;
|
||||
|
||||
status = login(bytes);
|
||||
}
|
||||
if (get_signalproperties() && find_em4x50_tag())
|
||||
status = login(*password);
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, status, 0, 0);
|
||||
|
@ -1247,18 +1170,10 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
|
|||
|
||||
bool pwd_found = false;
|
||||
int cnt = 0;
|
||||
uint32_t rpwd = 0x0;
|
||||
uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0};
|
||||
|
||||
for (*pwd = start; *pwd <= stop; (*pwd)++) {
|
||||
|
||||
// lsb -> msb
|
||||
rpwd = reflect32(*pwd);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
bytes[i] = (rpwd >> ((3 - i) * 8)) & 0xFF;
|
||||
|
||||
if (login(bytes)) {
|
||||
if (login(*pwd)) {
|
||||
pwd_found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1274,7 +1189,7 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
|
|||
}
|
||||
|
||||
// print data
|
||||
Dbprintf("|%8i | 0x%08x | 0x%08x |", cnt, rpwd, *pwd);
|
||||
Dbprintf("|%8i | 0x%08x | 0x%08x |", cnt, reflect32(*pwd), *pwd);
|
||||
}
|
||||
|
||||
if (BUTTON_PRESS())
|
||||
|
@ -1299,44 +1214,12 @@ void em4x50_brute(em4x50_data_t *etd) {
|
|||
em4x50_setup_read();
|
||||
|
||||
if (get_signalproperties() && find_em4x50_tag())
|
||||
bsuccess = brute(etd->start_password, etd->stop_password, &pwd);
|
||||
bsuccess = brute(etd->password1, etd->password2, &pwd);
|
||||
|
||||
lf_finalize();
|
||||
reply_ng(CMD_ACK, bsuccess, (uint8_t *)(&pwd), 32);
|
||||
}
|
||||
|
||||
int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
|
||||
|
||||
// envoke password search in standalone mode
|
||||
|
||||
int status = false;
|
||||
|
||||
em4x50_setup_read();
|
||||
|
||||
if (get_signalproperties() && find_em4x50_tag())
|
||||
status = brute(start, stop, pwd);
|
||||
else
|
||||
status = PM3_ETIMEOUT;
|
||||
|
||||
lf_finalize();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int em4x50_standalone_read(uint32_t *words) {
|
||||
|
||||
int now = 0;
|
||||
|
||||
em4x50_setup_read();
|
||||
|
||||
if (get_signalproperties() && find_em4x50_tag())
|
||||
if (find_double_listen_window(false))
|
||||
while (get_word_from_bitstream(&words[now]) == EM4X50_TAG_WORD)
|
||||
now++;
|
||||
|
||||
return now;
|
||||
}
|
||||
|
||||
void em4x50_watch() {
|
||||
|
||||
// read continuously and display standard reads of tag
|
||||
|
@ -1373,3 +1256,39 @@ void em4x50_watch() {
|
|||
lf_finalize();
|
||||
reply_ng(CMD_ACK, 1, 0, 0);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// standalone mode functions
|
||||
//==============================================================================
|
||||
|
||||
int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
|
||||
|
||||
// envoke password search in standalone mode
|
||||
|
||||
int status = false;
|
||||
|
||||
em4x50_setup_read();
|
||||
|
||||
if (get_signalproperties() && find_em4x50_tag())
|
||||
status = brute(start, stop, pwd);
|
||||
else
|
||||
status = PM3_ETIMEOUT;
|
||||
|
||||
lf_finalize();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int em4x50_standalone_read(uint32_t *words) {
|
||||
|
||||
int now = 0;
|
||||
|
||||
em4x50_setup_read();
|
||||
|
||||
if (get_signalproperties() && find_em4x50_tag())
|
||||
if (find_double_listen_window(false))
|
||||
while (get_word_from_bitstream(&words[now]) == EM4X50_TAG_WORD)
|
||||
now++;
|
||||
|
||||
return now;
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ void em4x50_info(em4x50_data_t *etd);
|
|||
void em4x50_write(em4x50_data_t *etd);
|
||||
void em4x50_write_password(em4x50_data_t *etd);
|
||||
void em4x50_read(em4x50_data_t *etd);
|
||||
void em4x50_wipe(em4x50_data_t *etd);
|
||||
void em4x50_wipe(uint32_t *password);
|
||||
void em4x50_brute(em4x50_data_t *etd);
|
||||
void em4x50_login(em4x50_data_t *etd);
|
||||
void em4x50_login(uint32_t *password);
|
||||
void em4x50_reset(void);
|
||||
void em4x50_watch(void);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ static int usage_lf_em4x50_info(void) {
|
|||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " v - verbose output");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb) (optional)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_info"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_info p fa225de1"));
|
||||
|
@ -37,8 +37,8 @@ static int usage_lf_em4x50_write(void) {
|
|||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " a <addr> - memory address to write to (dec)");
|
||||
PrintAndLogEx(NORMAL, " w <word> - word to write (hex, lsb notation)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb notation) (optional)");
|
||||
PrintAndLogEx(NORMAL, " w <word> - word to write (hex, lsb)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb) (optional)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_write a 3 w deadc0de"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -50,8 +50,8 @@ static int usage_lf_em4x50_write_password(void) {
|
|||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_write_password [h] [p <pwd>] [n <pwd>]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb notation)");
|
||||
PrintAndLogEx(NORMAL, " n <pwd> - new password (hex, lsb notation)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb)");
|
||||
PrintAndLogEx(NORMAL, " n <pwd> - new password (hex, lsb)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_write_password p 11223344 n 01020304"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -64,7 +64,7 @@ static int usage_lf_em4x50_read(void) {
|
|||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " a <addr> - memory address to read (dec) (optional)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb) (optional)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_read"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_read a 2 p 00000000"));
|
||||
|
@ -78,7 +78,7 @@ static int usage_lf_em4x50_dump(void) {
|
|||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " f <filename prefix> - overide filename prefix (optional). Default is based on UID");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb) (optional)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_dump"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_dump p 11223344"));
|
||||
|
@ -91,7 +91,7 @@ static int usage_lf_em4x50_wipe(void) {
|
|||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_wipe [h] [p <pwd>]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_wipe p 11223344"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -103,8 +103,8 @@ static int usage_lf_em4x50_brute(void) {
|
|||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_brute [h] f <pwd> l <pwd>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " f <pwd> - start password (hex, lsb notation)");
|
||||
PrintAndLogEx(NORMAL, " l <pwd> - stop password (hex, lsb notation)");
|
||||
PrintAndLogEx(NORMAL, " f <pwd> - start password (hex, lsb)");
|
||||
PrintAndLogEx(NORMAL, " l <pwd> - stop password (hex, lsb)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_brute f 11200000 l 11300000"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -116,7 +116,7 @@ static int usage_lf_em4x50_login(void) {
|
|||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_login [h] p <pwd>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb notation)");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex, lsb)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_login p 11200000"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -251,7 +251,7 @@ bool detect_4x50_block(void) {
|
|||
em4x50_data_t etd = {
|
||||
.pwd_given = false,
|
||||
.addr_given = true,
|
||||
.address = EM4X50_DEVICE_ID,
|
||||
.addresses = EM4X50_DEVICE_ID,
|
||||
};
|
||||
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||
return (em4x50_read(&etd, words, false) == PM3_SUCCESS);
|
||||
|
@ -261,7 +261,7 @@ int read_em4x50_uid(void) {
|
|||
em4x50_data_t etd = {
|
||||
.pwd_given = false,
|
||||
.addr_given = true,
|
||||
.address = EM4X50_DEVICE_SERIAL,
|
||||
.addresses = EM4X50_DEVICE_SERIAL,
|
||||
};
|
||||
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||
int res = em4x50_read(&etd, words, false);
|
||||
|
@ -279,7 +279,7 @@ int CmdEM4x50Info(const char *Cmd) {
|
|||
uint8_t cmdp = 0;
|
||||
em4x50_data_t etd;
|
||||
etd.pwd_given = false;
|
||||
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
||||
|
@ -287,21 +287,13 @@ int CmdEM4x50Info(const char *Cmd) {
|
|||
return usage_lf_em4x50_info();
|
||||
|
||||
case 'p':
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
||||
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
etd.pwd_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
cmdp += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, " Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
@ -337,48 +329,48 @@ int CmdEM4x50Write(const char *Cmd) {
|
|||
em4x50_data_t etd = { .pwd_given = false };
|
||||
|
||||
bool errors = false, bword = false, baddr = false;
|
||||
uint8_t address = 0x0;
|
||||
uint8_t cmdp = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h': {
|
||||
|
||||
case 'h':
|
||||
return usage_lf_em4x50_write();
|
||||
}
|
||||
case 'p': {
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
||||
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
etd.pwd_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.word, 8)) {
|
||||
PrintAndLogEx(FAILED, "\n word has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
case 'w':
|
||||
etd.word = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
bword = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
param_getdec(Cmd, cmdp + 1, &etd.address);
|
||||
|
||||
case 'a':
|
||||
param_getdec(Cmd, cmdp + 1, &address);
|
||||
|
||||
// validation
|
||||
if (etd.address < 1 || etd.address > 31) {
|
||||
PrintAndLogEx(FAILED, "\n error, address has to be in range [1-31]\n");
|
||||
if (address < 1 || address > 31) {
|
||||
PrintAndLogEx(FAILED, "error, address has to be in range [1-31]\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
etd.addresses = address; // lwr
|
||||
etd.addresses <<= 8;
|
||||
etd.addresses |= address; // fwr
|
||||
baddr = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,32 +397,20 @@ int CmdEM4x50Write(const char *Cmd) {
|
|||
PrintAndLogEx(FAILED, "login failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%s"), sprint_hex_inrow(etd.password, 4));
|
||||
PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%08x"), etd.password1);
|
||||
}
|
||||
|
||||
// display result of writing operation in structured format
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||
|
||||
prepare_result(data, etd.address, etd.address, words);
|
||||
print_result(words, etd.address, etd.address);
|
||||
prepare_result(data, address, address, words);
|
||||
print_result(words, address, address);
|
||||
PrintAndLogEx(SUCCESS, "Successfully wrote to tag");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("lf em 4x50_read a %u") "` - to read your data", etd.address);
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("lf em 4x50_read a %u") "` - to read your data", address);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static void print_write_password_result(PacketResponseNG *resp, const em4x50_data_t *etd) {
|
||||
|
||||
// display result of password changing operation
|
||||
|
||||
char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0};
|
||||
|
||||
sprintf(pstring, "\n writing new password " _GREEN_("ok"));
|
||||
strcat(string, pstring);
|
||||
|
||||
PrintAndLogEx(NORMAL, "%s\n", string);
|
||||
}
|
||||
|
||||
int CmdEM4x50WritePassword(const char *Cmd) {
|
||||
|
||||
// envokes changing the password of EM4x50 tag
|
||||
|
@ -442,7 +422,6 @@ int CmdEM4x50WritePassword(const char *Cmd) {
|
|||
|
||||
// init
|
||||
etd.pwd_given = false;
|
||||
etd.newpwd_given = false;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
|
@ -451,27 +430,20 @@ int CmdEM4x50WritePassword(const char *Cmd) {
|
|||
return usage_lf_em4x50_write_password();
|
||||
|
||||
case 'p':
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
||||
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
bpwd = true;
|
||||
etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
etd.pwd_given = true;
|
||||
bpwd = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.new_password, 8)) {
|
||||
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
etd.password2 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
bnpwd = true;
|
||||
etd.newpwd_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
@ -489,11 +461,11 @@ int CmdEM4x50WritePassword(const char *Cmd) {
|
|||
}
|
||||
success = (bool)resp.status;
|
||||
|
||||
// get, prepare and print response
|
||||
// print response
|
||||
if (success)
|
||||
print_write_password_result(&resp, &etd);
|
||||
PrintAndLogEx(SUCCESS, "\nwriting new password " _GREEN_("ok") "\n");
|
||||
else
|
||||
PrintAndLogEx(NORMAL, "\nwriting password " _RED_("failed") "\n");
|
||||
PrintAndLogEx(FAILED, "\nwriting password " _RED_("failed") "\n");
|
||||
|
||||
return (success) ? PM3_SUCCESS : PM3_ESOFT;
|
||||
}
|
||||
|
@ -534,14 +506,14 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
|
|||
PrintAndLogEx(FAILED, "login failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%s"), sprint_hex_inrow(etd->password, 4));
|
||||
PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%08x"), etd->password1);
|
||||
}
|
||||
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||
int now = (resp.status & STATUS_NO_WORDS) >> 2;
|
||||
if (edata.addr_given) {
|
||||
prepare_result(data, etd->address, etd->address, words);
|
||||
prepare_result(data, etd->addresses & 0xFF, (etd->addresses >> 8) & 0xFF, words);
|
||||
} else {
|
||||
prepare_result(data, 0, now - 1, words);
|
||||
}
|
||||
|
@ -551,7 +523,7 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
|
|||
}
|
||||
|
||||
if (edata.addr_given)
|
||||
print_result(words, etd->address, etd->address);
|
||||
print_result(words, etd->addresses & 0xFF, (etd->addresses >> 8) & 0xFF);
|
||||
else
|
||||
print_result(words, 0, now - 1);
|
||||
|
||||
|
@ -560,47 +532,48 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
|
|||
|
||||
int CmdEM4x50Read(const char *Cmd) {
|
||||
|
||||
uint8_t address = 0x0;
|
||||
em4x50_data_t etd;
|
||||
memset(&etd, 0x00, sizeof(em4x50_data_t));
|
||||
|
||||
etd.pwd_given = false;
|
||||
etd.addr_given = false;
|
||||
etd.newpwd_given = false;
|
||||
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h': {
|
||||
|
||||
case 'h':
|
||||
return usage_lf_em4x50_read();
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
param_getdec(Cmd, cmdp + 1, &etd.address);
|
||||
param_getdec(Cmd, cmdp + 1, &address);
|
||||
// lsb: byte 1 = fwr, byte 2 = lwr, byte 3 = 0x0, byte 4 = 0x0
|
||||
etd.addresses = address; // lwr
|
||||
etd.addresses <<= 8;
|
||||
etd.addresses |= address; // fwr
|
||||
|
||||
// validation
|
||||
if (etd.address <= 0 || etd.address >= EM4X50_NO_WORDS) {
|
||||
PrintAndLogEx(FAILED, "\n error, address has to be in range [1-33]\n");
|
||||
if (address <= 0 || address >= EM4X50_NO_WORDS) {
|
||||
PrintAndLogEx(FAILED, "error, address has to be in range [1-33]\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
etd.addr_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
||||
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
case 'p':
|
||||
etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
etd.pwd_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -616,7 +589,6 @@ int CmdEM4x50Dump(const char *Cmd) {
|
|||
em4x50_data_t etd;
|
||||
etd.pwd_given = false;
|
||||
etd.addr_given = false;
|
||||
etd.newpwd_given = false;
|
||||
|
||||
char filename[FILE_PATH_SIZE] = {0x00};
|
||||
char *fptr = filename;
|
||||
|
@ -625,24 +597,24 @@ int CmdEM4x50Dump(const char *Cmd) {
|
|||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
||||
case 'h':
|
||||
return usage_lf_em4x50_dump();
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'p': {
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
||||
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
etd.pwd_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, " Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
};
|
||||
|
@ -698,38 +670,36 @@ int CmdEM4x50Wipe(const char *Cmd) {
|
|||
|
||||
// fills EM4x50 tag with zeros including password
|
||||
|
||||
bool errors = false, bpwd = false;
|
||||
bool errors = false, pwd_given = false;
|
||||
uint8_t cmdp = 0;
|
||||
em4x50_data_t etd;
|
||||
uint32_t password = 0x0;
|
||||
PacketResponseNG resp;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
||||
case 'h':
|
||||
return usage_lf_em4x50_wipe();
|
||||
|
||||
case 'p':
|
||||
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
||||
PrintAndLogEx(FAILED, "\npassword has to be 8 hex symbols\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
bpwd = true;
|
||||
password = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
pwd_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "\nUnknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors || !bpwd)
|
||||
if (errors || !pwd_given)
|
||||
return usage_lf_em4x50_wipe();
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X50_WIPE, (uint8_t *)&etd, sizeof(etd));
|
||||
SendCommandNG(CMD_LF_EM4X50_WIPE, (uint8_t *)&password, sizeof(password));
|
||||
WaitForResponse(CMD_ACK, &resp);
|
||||
|
||||
// print response
|
||||
|
@ -756,20 +726,24 @@ int CmdEM4x50Brute(const char *Cmd) {
|
|||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
||||
case 'h':
|
||||
return usage_lf_em4x50_brute();
|
||||
|
||||
case 'f':
|
||||
etd.start_password = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
startpwd = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
etd.stop_password = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
etd.password2 = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
stoppwd = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
@ -779,14 +753,14 @@ int CmdEM4x50Brute(const char *Cmd) {
|
|||
return usage_lf_em4x50_brute();
|
||||
|
||||
// print some information
|
||||
no_iter = etd.stop_password - etd.start_password + 1;
|
||||
no_iter = etd.password2 - etd.password1 + 1;
|
||||
dur_s = no_iter / speed;
|
||||
dur_h = dur_s / 3600;
|
||||
dur_m = (dur_s - dur_h * 3600) / 60;
|
||||
dur_s -= dur_h * 3600 + dur_m * 60;
|
||||
PrintAndLogEx(NORMAL, "\ntrying %i passwords in range [0x%08x, 0x%08x]",
|
||||
no_iter, etd.start_password, etd.stop_password);
|
||||
PrintAndLogEx(NORMAL, "estimated duration: %ih%im%is\n", dur_h, dur_m, dur_s);
|
||||
PrintAndLogEx(INFO, "trying %i passwords in range [0x%08x, 0x%08x]",
|
||||
no_iter, etd.password1, etd.password2);
|
||||
PrintAndLogEx(INFO, "estimated duration: %ih%im%is", dur_h, dur_m, dur_s);
|
||||
|
||||
// start
|
||||
clearCommandBuffer();
|
||||
|
@ -795,9 +769,9 @@ int CmdEM4x50Brute(const char *Cmd) {
|
|||
|
||||
// print response
|
||||
if ((bool)resp.status)
|
||||
PrintAndLogEx(NORMAL, "\npassword " _GREEN_("found") ": 0x%08x\n", resp.data.asDwords[0]);
|
||||
PrintAndLogEx(SUCCESS, "\npassword " _GREEN_("found") ": 0x%08x\n", resp.data.asDwords[0]);
|
||||
else
|
||||
PrintAndLogEx(NORMAL, "\npassword: " _RED_("not found") "\n");
|
||||
PrintAndLogEx(FAILED, "\npassword: " _RED_("not found") "\n");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -806,21 +780,24 @@ int CmdEM4x50Login(const char *Cmd) {
|
|||
|
||||
bool errors = false, pwd_given = false;
|
||||
uint8_t cmdp = 0;
|
||||
em4x50_data_t etd;
|
||||
uint32_t password = 0x0;
|
||||
PacketResponseNG resp;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
||||
case 'h':
|
||||
return usage_lf_em4x50_login();
|
||||
|
||||
case 'p':
|
||||
etd.login_password = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
password = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
||||
pwd_given = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
@ -831,14 +808,14 @@ int CmdEM4x50Login(const char *Cmd) {
|
|||
|
||||
// start
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X50_LOGIN, (uint8_t *)&etd, sizeof(etd));
|
||||
SendCommandNG(CMD_LF_EM4X50_LOGIN, (uint8_t *)&password, sizeof(password));
|
||||
WaitForResponse(CMD_ACK, &resp);
|
||||
|
||||
// print response
|
||||
if ((bool)resp.status)
|
||||
PrintAndLogEx(NORMAL, "\nlogin " _GREEN_("ok") "\n");
|
||||
PrintAndLogEx(SUCCESS, "\nlogin " _GREEN_("ok") "\n");
|
||||
else
|
||||
PrintAndLogEx(NORMAL, "\nlogin " _RED_("failed") "\n");
|
||||
PrintAndLogEx(FAILED, "\nlogin " _RED_("failed") "\n");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -852,10 +829,12 @@ int CmdEM4x50Reset(const char *Cmd) {
|
|||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
||||
case 'h':
|
||||
return usage_lf_em4x50_reset();
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
@ -871,9 +850,9 @@ int CmdEM4x50Reset(const char *Cmd) {
|
|||
|
||||
// print response
|
||||
if ((bool)resp.status)
|
||||
PrintAndLogEx(NORMAL, "\nreset " _GREEN_("ok") "\n");
|
||||
PrintAndLogEx(SUCCESS, "\nreset " _GREEN_("ok") "\n");
|
||||
else
|
||||
PrintAndLogEx(NORMAL, "\nreset " _RED_("failed") "\n");
|
||||
PrintAndLogEx(FAILED, "\nreset " _RED_("failed") "\n");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -893,7 +872,7 @@ int CmdEM4x50Watch(const char *Cmd) {
|
|||
return usage_lf_em4x50_watch();
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, " Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -43,14 +43,10 @@
|
|||
typedef struct {
|
||||
bool addr_given;
|
||||
bool pwd_given;
|
||||
bool newpwd_given;
|
||||
uint8_t password[4];
|
||||
uint8_t new_password[4];
|
||||
uint8_t address;
|
||||
uint8_t word[4];
|
||||
uint32_t start_password;
|
||||
uint32_t stop_password;
|
||||
uint32_t login_password;
|
||||
uint32_t password1;
|
||||
uint32_t password2;
|
||||
uint32_t word;
|
||||
uint32_t addresses;
|
||||
} em4x50_data_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Reference in a new issue