mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
Merge pull request #4 from RfidResearchGroup/master
Updated from upstream.
This commit is contained in:
commit
4e6fef76d0
60 changed files with 1294 additions and 1221 deletions
12
.github/ISSUE_TEMPLATE/bug_report.md
vendored
12
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -7,6 +7,18 @@ assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
***Things to try before submitting bug report***
|
||||||
|
read the [troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md)
|
||||||
|
|
||||||
|
***Compilation problems***
|
||||||
|
Try compiling with verbose. `make VERBOSE=1` with main makefile or `make V=1` with cmake.
|
||||||
|
|
||||||
|
***flashing problems***
|
||||||
|
Have you followed the instructions properly? ie, flashed bootrom seperately first if you are going from Offical repo to RRG/Iceman repo.
|
||||||
|
|
||||||
|
|
||||||
|
-
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Added lf em function: 4x50_sread (@tharexde)
|
||||||
- Added lf em functions: 4x50_info, 4x50_write, 4x50_write_password (@tharexde)
|
- Added lf em functions: 4x50_info, 4x50_write, 4x50_write_password (@tharexde)
|
||||||
- Fix em4x50 demodulation error (@tharexde)
|
- Fix em4x50 demodulation error (@tharexde)
|
||||||
- Fix `hf mfdes` authentification issues, DES working (@bkerler)
|
- Fix `hf mfdes` authentification issues, DES working (@bkerler)
|
||||||
|
|
|
@ -1019,6 +1019,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
em4x50_write_password((em4x50_data_t *)packet->data.asBytes);
|
em4x50_write_password((em4x50_data_t *)packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_LF_EM4X50_READ: {
|
||||||
|
em4x50_read((em4x50_data_t *)packet->data.asBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_ISO15693
|
#ifdef WITH_ISO15693
|
||||||
|
|
151
armsrc/em4x50.c
151
armsrc/em4x50.c
|
@ -72,9 +72,10 @@ static em4x50_tag_t tag = {
|
||||||
#define EM4X50_T_TAG_HALF_PERIOD 32
|
#define EM4X50_T_TAG_HALF_PERIOD 32
|
||||||
#define EM4X50_T_TAG_THREE_QUARTER_PERIOD 48
|
#define EM4X50_T_TAG_THREE_QUARTER_PERIOD 48
|
||||||
#define EM4X50_T_TAG_FULL_PERIOD 64
|
#define EM4X50_T_TAG_FULL_PERIOD 64
|
||||||
#define EM4X50_T_WAITING_FOR_LIW 500
|
|
||||||
#define EM4X50_T_TAG_TPP 64
|
#define EM4X50_T_TAG_TPP 64
|
||||||
#define EM4X50_T_TAG_TWA 64
|
#define EM4X50_T_TAG_TWA 64
|
||||||
|
#define EM4X50_T_WAITING_FOR_SNGLLIW 50
|
||||||
|
#define EM4X50_T_WAITING_FOR_DBLLIW 1550
|
||||||
|
|
||||||
#define EM4X50_TAG_TOLERANCE 8
|
#define EM4X50_TAG_TOLERANCE 8
|
||||||
#define EM4X50_TAG_WORD 45
|
#define EM4X50_TAG_WORD 45
|
||||||
|
@ -237,19 +238,34 @@ static void em4x50_setup_read(void) {
|
||||||
|
|
||||||
// functions for "reader" use case
|
// functions for "reader" use case
|
||||||
|
|
||||||
static void get_signalproperties(void) {
|
static bool get_signalproperties(void) {
|
||||||
|
|
||||||
// calculate signal properties (mean amplitudes) from measured data:
|
// calculate signal properties (mean amplitudes) from measured data:
|
||||||
// 32 amplitudes (maximum values) -> mean amplitude value -> gHigh -> gLow
|
// 32 amplitudes (maximum values) -> mean amplitude value -> gHigh -> gLow
|
||||||
|
|
||||||
|
bool signal_found = false;
|
||||||
int no_periods = 32, pct = 75, noise = 140;
|
int no_periods = 32, pct = 75, noise = 140;
|
||||||
uint8_t sample = 0, sample_ref = 127;
|
uint8_t sample = 0, sample_ref = 127;
|
||||||
uint8_t sample_max_mean = 0;
|
uint8_t sample_max_mean = 0;
|
||||||
uint8_t sample_max[no_periods];
|
uint8_t sample_max[no_periods];
|
||||||
uint32_t sample_max_sum = 0;
|
uint32_t sample_max_sum = 0;
|
||||||
|
|
||||||
// wait until signal/noise > 1
|
|
||||||
while (AT91C_BASE_SSC->SSC_RHR < noise);
|
// wait until signal/noise > 1 (max. 32 periods)
|
||||||
|
for (int i = 0; i < T0 * no_periods; i++) {
|
||||||
|
|
||||||
|
// about 2 samples per bit period
|
||||||
|
wait_timer(0, T0 * EM4X50_T_TAG_HALF_PERIOD);
|
||||||
|
|
||||||
|
if (AT91C_BASE_SSC->SSC_RHR > noise) {
|
||||||
|
signal_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!signal_found)
|
||||||
|
return false;
|
||||||
|
|
||||||
// calculate mean maximum value of 32 periods, each period has a length of
|
// calculate mean maximum value of 32 periods, each period has a length of
|
||||||
// 3 single "full periods" to eliminate the influence of a listen window
|
// 3 single "full periods" to eliminate the influence of a listen window
|
||||||
|
@ -274,6 +290,7 @@ static void get_signalproperties(void) {
|
||||||
gHigh = sample_ref + pct * (sample_max_mean - sample_ref) / 100;
|
gHigh = sample_ref + pct * (sample_max_mean - sample_ref) / 100;
|
||||||
gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100;
|
gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_next_bit(void) {
|
static int get_next_bit(void) {
|
||||||
|
@ -404,13 +421,45 @@ static void em4x50_send_word(const uint8_t bytes[4]) {
|
||||||
em4x50_send_bit(0);
|
em4x50_send_bit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool find_single_listen_window(void) {
|
||||||
|
|
||||||
|
// find single listen window
|
||||||
|
|
||||||
|
int cnt_pulses = 0;
|
||||||
|
|
||||||
|
while (cnt_pulses < EM4X50_T_WAITING_FOR_SNGLLIW) {
|
||||||
|
|
||||||
|
// identification of listen window is done via evaluation of
|
||||||
|
// pulse lengths
|
||||||
|
if (check_pulse_length(get_pulse_length(), 3 * EM4X50_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
|
if (check_pulse_length(get_pulse_length(), 2 * EM4X50_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
|
// listen window found
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
cnt_pulses++;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool find_double_listen_window(bool bcommand) {
|
static bool find_double_listen_window(bool bcommand) {
|
||||||
|
|
||||||
// find two successive listen windows that indicate the beginning of
|
// find two successive listen windows that indicate the beginning of
|
||||||
// data transmission
|
// data transmission
|
||||||
|
// double listen window to be detected within 1600 pulses -> worst case
|
||||||
|
// reason: first detectable double listen window after 34 words
|
||||||
|
// -> 34 words + 34 single listen windows -> about 1600 pulses
|
||||||
|
|
||||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
int cnt_pulses = 0;
|
||||||
while (AT91C_BASE_TC0->TC_CV < T0 * EM4X50_T_WAITING_FOR_LIW) {
|
|
||||||
|
while (cnt_pulses < EM4X50_T_WAITING_FOR_DBLLIW) {
|
||||||
|
|
||||||
// identification of listen window is done via evaluation of
|
// identification of listen window is done via evaluation of
|
||||||
// pulse lengths
|
// pulse lengths
|
||||||
|
@ -454,12 +503,23 @@ static bool find_double_listen_window(bool bcommand) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cnt_pulses++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool find_em4x50_tag(void) {
|
||||||
|
|
||||||
|
// function is used to check wether a tag on the proxmark is an
|
||||||
|
// EM4x50 tag or not -> speed up "lf search" process
|
||||||
|
|
||||||
|
return (find_single_listen_window());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static bool request_receive_mode(void) {
|
static bool request_receive_mode(void) {
|
||||||
|
|
||||||
// To issue a command we have to find a listen window first.
|
// To issue a command we have to find a listen window first.
|
||||||
|
@ -513,6 +573,10 @@ static bool check_ack(bool bliw) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// It's NAK -> stop searching
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,7 +668,9 @@ static int get_word_from_bitstream(uint8_t bits[EM4X50_TAG_WORD]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
// login function
|
// login function
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
static bool login(uint8_t password[4]) {
|
static bool login(uint8_t password[4]) {
|
||||||
|
|
||||||
|
@ -624,14 +690,16 @@ static bool login(uint8_t password[4]) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("error in command request");
|
Dbprintf("error in command request");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
// reset function
|
// reset function
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
static bool reset(void) {
|
static bool reset(void) {
|
||||||
|
|
||||||
|
@ -646,14 +714,16 @@ static bool reset(void) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("error in command request");
|
Dbprintf("error in command request");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
// read functions
|
// read functions
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
static bool standard_read(int *now) {
|
static bool standard_read(int *now) {
|
||||||
|
|
||||||
|
@ -676,7 +746,7 @@ static bool standard_read(int *now) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("didn't find a listen window");
|
Dbprintf("didn't find a listen window");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +780,7 @@ static bool selective_read(uint8_t addresses[4]) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("error in command request");
|
Dbprintf("error in command request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +802,7 @@ void em4x50_info(em4x50_data_t *etd) {
|
||||||
em4x50_setup_read();
|
em4x50_setup_read();
|
||||||
|
|
||||||
// set gHigh and gLow
|
// set gHigh and gLow
|
||||||
get_signalproperties();
|
if (get_signalproperties() && find_em4x50_tag()) {
|
||||||
|
|
||||||
if (etd->pwd_given) {
|
if (etd->pwd_given) {
|
||||||
|
|
||||||
|
@ -747,6 +817,7 @@ void em4x50_info(em4x50_data_t *etd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bsuccess = selective_read(addresses);
|
bsuccess = selective_read(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
status = (bsuccess << 1) + blogin;
|
status = (bsuccess << 1) + blogin;
|
||||||
|
|
||||||
|
@ -754,7 +825,53 @@ void em4x50_info(em4x50_data_t *etd) {
|
||||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void em4x50_read(em4x50_data_t *etd) {
|
||||||
|
|
||||||
|
// reads in two different ways:
|
||||||
|
// - using "selective read mode" -> bidirectional communication
|
||||||
|
// - using "standard read mode" -> unidirectional communication (read
|
||||||
|
// data that tag transmits "voluntarily")
|
||||||
|
|
||||||
|
bool bsuccess = false, blogin = false;
|
||||||
|
int now = 0;
|
||||||
|
uint8_t status = 0;
|
||||||
|
uint8_t addresses[] = {0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
|
init_tag();
|
||||||
|
em4x50_setup_read();
|
||||||
|
|
||||||
|
// set gHigh and gLow
|
||||||
|
if (get_signalproperties() && find_em4x50_tag()) {
|
||||||
|
|
||||||
|
if (etd->addr_given) {
|
||||||
|
|
||||||
|
// selective read mode
|
||||||
|
|
||||||
|
// try to login with given password
|
||||||
|
if (etd->pwd_given)
|
||||||
|
blogin = login(etd->password);
|
||||||
|
|
||||||
|
// only one word has to be read -> first word read = last word read
|
||||||
|
addresses[2] = addresses[3] = etd->address;
|
||||||
|
bsuccess = selective_read(addresses);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// standard read mode
|
||||||
|
bsuccess = standard_read(&now);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = (now << 2) + (bsuccess << 1) + blogin;
|
||||||
|
|
||||||
|
lf_finalize();
|
||||||
|
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
// write functions
|
// write functions
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
static bool write(uint8_t word[4], uint8_t address) {
|
static bool write(uint8_t word[4], uint8_t address) {
|
||||||
|
|
||||||
|
@ -785,7 +902,7 @@ static bool write(uint8_t word[4], uint8_t address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("error in command request");
|
Dbprintf("error in command request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,7 +941,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (DBGLEVEL >= DBG_ERROR)
|
if (DBGLEVEL >= DBG_DEBUG)
|
||||||
Dbprintf("error in command request");
|
Dbprintf("error in command request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,7 +962,7 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||||
em4x50_setup_read();
|
em4x50_setup_read();
|
||||||
|
|
||||||
// set gHigh and gLow
|
// set gHigh and gLow
|
||||||
get_signalproperties();
|
if (get_signalproperties() && find_em4x50_tag()) {
|
||||||
|
|
||||||
// reorder word according to datasheet
|
// reorder word according to datasheet
|
||||||
msb2lsb_word(etd->word);
|
msb2lsb_word(etd->word);
|
||||||
|
@ -864,7 +981,7 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||||
if (etd->pwd_given)
|
if (etd->pwd_given)
|
||||||
blogin &= login(etd->password);
|
blogin &= login(etd->password);
|
||||||
|
|
||||||
// perform a selective read
|
// call a selective read
|
||||||
addresses[2] = addresses[3] = etd->address;
|
addresses[2] = addresses[3] = etd->address;
|
||||||
if (selective_read(addresses)) {
|
if (selective_read(addresses)) {
|
||||||
|
|
||||||
|
@ -882,6 +999,7 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
status = (bsuccess << 1) + blogin;
|
status = (bsuccess << 1) + blogin;
|
||||||
|
|
||||||
|
@ -899,12 +1017,13 @@ void em4x50_write_password(em4x50_data_t *etd) {
|
||||||
em4x50_setup_read();
|
em4x50_setup_read();
|
||||||
|
|
||||||
// set gHigh and gLow
|
// set gHigh and gLow
|
||||||
get_signalproperties();
|
if (get_signalproperties() && find_em4x50_tag()) {
|
||||||
|
|
||||||
// login and change password
|
// login and change password
|
||||||
if (login(etd->password)) {
|
if (login(etd->password)) {
|
||||||
bsuccess = write_password(etd->password, etd->new_password);
|
bsuccess = write_password(etd->password, etd->new_password);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lf_finalize();
|
lf_finalize();
|
||||||
reply_ng(CMD_ACK, bsuccess, 0, 0);
|
reply_ng(CMD_ACK, bsuccess, 0, 0);
|
||||||
|
|
|
@ -20,5 +20,6 @@ typedef struct {
|
||||||
void em4x50_info(em4x50_data_t *etd);
|
void em4x50_info(em4x50_data_t *etd);
|
||||||
void em4x50_write(em4x50_data_t *etd);
|
void em4x50_write(em4x50_data_t *etd);
|
||||||
void em4x50_write_password(em4x50_data_t *etd);
|
void em4x50_write_password(em4x50_data_t *etd);
|
||||||
|
void em4x50_read(em4x50_data_t *etd);
|
||||||
|
|
||||||
#endif /* EM4X50_H */
|
#endif /* EM4X50_H */
|
||||||
|
|
|
@ -387,9 +387,10 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
|
||||||
// returns:
|
// returns:
|
||||||
// number of decoded bytes
|
// number of decoded bytes
|
||||||
// logging enabled
|
// logging enabled
|
||||||
|
#define SIGNAL_BUFF_SIZE 20000
|
||||||
|
|
||||||
static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
|
static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
|
||||||
|
|
||||||
#define SIGNAL_BUFF_SIZE 15000
|
|
||||||
// get current clock
|
// get current clock
|
||||||
uint32_t time_0 = GetCountSspClk();
|
uint32_t time_0 = GetCountSspClk();
|
||||||
uint32_t time_stop = 0;
|
uint32_t time_stop = 0;
|
||||||
|
@ -446,7 +447,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
|
||||||
bool getNext = false;
|
bool getNext = false;
|
||||||
int counter = 0, ci, cq = 0;
|
int counter = 0, ci, cq = 0;
|
||||||
uint32_t time_0 = 0, time_stop = 0;
|
uint32_t time_0 = 0, time_stop = 0;
|
||||||
uint8_t *buf = BigBuf_get_addr();
|
uint8_t *buf = BigBuf_malloc(SIGNAL_BUFF_SIZE);
|
||||||
|
|
||||||
// get current clock
|
// get current clock
|
||||||
time_0 = GetCountSspClk();
|
time_0 = GetCountSspClk();
|
||||||
|
@ -481,6 +482,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
|
||||||
time_stop = GetCountSspClk();
|
time_stop = GetCountSspClk();
|
||||||
int k = DemodAnswer(received, buf, counter);
|
int k = DemodAnswer(received, buf, counter);
|
||||||
LogTrace(received, k, time_0 << 4, time_stop << 4, NULL, false);
|
LogTrace(received, k, time_0 << 4, time_stop << 4, NULL, false);
|
||||||
|
BigBuf_free();
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,7 +523,6 @@ void AcquireRawAdcSamplesIso15693(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LogTrace(cmd, CMD_ID_RESP, time_start << 4, GetCountSspClk() << 4, NULL, true);
|
LogTrace(cmd, CMD_ID_RESP, time_start << 4, GetCountSspClk() << 4, NULL, true);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
|
@ -10,9 +10,25 @@
|
||||||
{
|
{
|
||||||
"AID": "D3494F",
|
"AID": "D3494F",
|
||||||
"Vendor": "HID",
|
"Vendor": "HID",
|
||||||
"Country": "United States",
|
"Country": "US",
|
||||||
"Name": "SIO DESFire Ev1",
|
"Name": "SIO DESFire Ev1",
|
||||||
"Description": "",
|
"Description": "Field Encoder",
|
||||||
|
"Type": "pacs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AID": "D9494F",
|
||||||
|
"Vendor": "HID",
|
||||||
|
"Country": "US",
|
||||||
|
"Name": "Access control",
|
||||||
|
"Description": "Field Encoder",
|
||||||
|
"Type": "pacs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AID": "53494F",
|
||||||
|
"Vendor": "HID",
|
||||||
|
"Country": "US",
|
||||||
|
"Name": "Access control",
|
||||||
|
"Description": "HID Factory",
|
||||||
"Type": "pacs"
|
"Type": "pacs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1276,8 +1276,7 @@ int PSKDemod(const char *Cmd, bool verbose) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdIdteckDemod(const char *Cmd) {
|
int demodIdteck(void) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
|
||||||
|
|
||||||
if (PSKDemod("", false) != PM3_SUCCESS) {
|
if (PSKDemod("", false) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
|
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
|
||||||
|
@ -1337,10 +1336,12 @@ static int CmdIdteckDemod(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int demodIdteck(void) {
|
/*
|
||||||
return CmdIdteckDemod("");
|
static int CmdIdteckDemod(const char *Cmd) {
|
||||||
|
(void)Cmd; // Cmd is not used so far
|
||||||
|
return demodIdteck();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// by marshmellow
|
// by marshmellow
|
||||||
// takes 3 arguments - clock, invert, maxErr as integers
|
// takes 3 arguments - clock, invert, maxErr as integers
|
||||||
|
@ -1710,6 +1711,7 @@ int CmdTuneSamples(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "---------- " _CYAN_("LF Antenna") " ----------");
|
||||||
// in mVolt
|
// in mVolt
|
||||||
struct p {
|
struct p {
|
||||||
uint32_t v_lf134;
|
uint32_t v_lf134;
|
||||||
|
@ -1746,8 +1748,9 @@ int CmdTuneSamples(const char *Cmd) {
|
||||||
else
|
else
|
||||||
sprintf(judgement, _GREEN_("OK"));
|
sprintf(judgement, _GREEN_("OK"));
|
||||||
|
|
||||||
PrintAndLogEx((package->peak_v < LF_UNUSABLE_V) ? WARNING : SUCCESS, "LF antenna is %s \n", judgement);
|
PrintAndLogEx((package->peak_v < LF_UNUSABLE_V) ? WARNING : SUCCESS, "LF antenna is %s", judgement);
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "---------- " _CYAN_("HF Antenna") " ----------");
|
||||||
// HF evaluation
|
// HF evaluation
|
||||||
if (package->v_hf > NON_VOLTAGE)
|
if (package->v_hf > NON_VOLTAGE)
|
||||||
PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (package->v_hf * ANTENNA_ERROR) / 1000.0);
|
PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (package->v_hf * ANTENNA_ERROR) / 1000.0);
|
||||||
|
@ -1761,7 +1764,7 @@ int CmdTuneSamples(const char *Cmd) {
|
||||||
else
|
else
|
||||||
sprintf(judgement, _GREEN_("OK"));
|
sprintf(judgement, _GREEN_("OK"));
|
||||||
|
|
||||||
PrintAndLogEx((package->v_hf < HF_UNUSABLE_V) ? WARNING : SUCCESS, "HF antenna is %s \n", judgement);
|
PrintAndLogEx((package->v_hf < HF_UNUSABLE_V) ? WARNING : SUCCESS, "HF antenna is %s", judgement);
|
||||||
|
|
||||||
// graph LF measurements
|
// graph LF measurements
|
||||||
// even here, these values has 3% error.
|
// even here, these values has 3% error.
|
||||||
|
|
|
@ -1328,6 +1328,7 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) {
|
||||||
|
|
||||||
if ((sak & 0x20) == 0x20) {
|
if ((sak & 0x20) == 0x20) {
|
||||||
if (atqa == 0x0344) {
|
if (atqa == 0x0344) {
|
||||||
|
printTag("MIFARE DESFire MF3ICD40");
|
||||||
printTag("MIFARE DESFire EV1 2K/4K/8K / DESFire EV1 CL2 2K/4K/8K");
|
printTag("MIFARE DESFire EV1 2K/4K/8K / DESFire EV1 CL2 2K/4K/8K");
|
||||||
printTag("MIFARE NTAG424DNA");
|
printTag("MIFARE NTAG424DNA");
|
||||||
type |= MTDESFIRE;
|
type |= MTDESFIRE;
|
||||||
|
@ -1431,6 +1432,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
PrintAndLogEx(SUCCESS, "------ " _CYAN_("ISO14443-a Information") "------------------");
|
PrintAndLogEx(SUCCESS, "------ " _CYAN_("ISO14443-a Information") "------------------");
|
||||||
PrintAndLogEx(SUCCESS, "-------------------------------------------------------------");
|
PrintAndLogEx(SUCCESS, "-------------------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]);
|
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]);
|
||||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||||
|
|
|
@ -1835,6 +1835,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
|
{"-----------", CmdHF15Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
|
||||||
{"help", CmdHF15Help, AlwaysAvailable, "This help"},
|
{"help", CmdHF15Help, AlwaysAvailable, "This help"},
|
||||||
{"list", CmdHF15List, AlwaysAvailable, "List ISO15693 history"},
|
{"list", CmdHF15List, AlwaysAvailable, "List ISO15693 history"},
|
||||||
{"demod", CmdHF15Demod, AlwaysAvailable, "Demodulate ISO15693 from tag"},
|
{"demod", CmdHF15Demod, AlwaysAvailable, "Demodulate ISO15693 from tag"},
|
||||||
|
@ -1850,11 +1851,11 @@ static command_t CommandTable[] = {
|
||||||
{"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire Samples as Reader (enables carrier, sends inquiry)"},
|
{"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire Samples as Reader (enables carrier, sends inquiry)"},
|
||||||
{"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO15693 tag"},
|
{"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO15693 tag"},
|
||||||
{"write", CmdHF15Write, IfPm3Iso15693, "Write a block"},
|
{"write", CmdHF15Write, IfPm3Iso15693, "Write a block"},
|
||||||
{"-----------", CmdHF15Help, IfPm3Iso15693, ""},
|
{"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("afi") " -----------------------"},
|
||||||
{"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"},
|
{"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"},
|
||||||
{"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO15693 tag"},
|
{"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO15693 tag"},
|
||||||
{"writedsfid", CmdHF15WriteDsfid, IfPm3Iso15693, "Writes the DSFID on an ISO15693 tag"},
|
{"writedsfid", CmdHF15WriteDsfid, IfPm3Iso15693, "Writes the DSFID on an ISO15693 tag"},
|
||||||
{"-----------", CmdHF15Help, IfPm3Iso15693, ""},
|
{"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("magic") " -----------------------"},
|
||||||
{"csetuid", CmdHF15CSetUID, IfPm3Iso15693, "Set UID for magic Chinese card"},
|
{"csetuid", CmdHF15CSetUID, IfPm3Iso15693, "Set UID for magic Chinese card"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1848,7 +1848,8 @@ int readFelicaUid(bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"----------- General -----------", CmdHelp, AlwaysAvailable, ""},
|
|
||||||
|
{"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"},
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"},
|
{"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"},
|
||||||
{"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"},
|
{"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"},
|
||||||
|
@ -1856,7 +1857,7 @@ static command_t CommandTable[] = {
|
||||||
{"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"},
|
{"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"},
|
||||||
{"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."},
|
{"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."},
|
||||||
{"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."},
|
{"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."},
|
||||||
{"----------- FeliCa Standard -----------", CmdHelp, AlwaysAvailable, ""},
|
{"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Standard") " -----------------------"},
|
||||||
//{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"},
|
//{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"},
|
||||||
{"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."},
|
{"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."},
|
||||||
{"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."},
|
{"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."},
|
||||||
|
@ -1875,7 +1876,7 @@ static command_t CommandTable[] = {
|
||||||
//{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."},
|
//{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."},
|
||||||
//{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."},
|
//{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."},
|
||||||
//{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."},
|
//{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."},
|
||||||
{"----------- FeliCa Light -----------", CmdHelp, AlwaysAvailable, ""},
|
{"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Light") " -----------------------"},
|
||||||
{"litesim", CmdHFFelicaSimLite, IfPm3Felica, "<NDEF2> - only reply to poll request"},
|
{"litesim", CmdHFFelicaSimLite, IfPm3Felica, "<NDEF2> - only reply to poll request"},
|
||||||
{"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"},
|
{"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"},
|
||||||
// {"sim", CmdHFFelicaSim, IfPm3Felica, "<UID> -- Simulate ISO 18092/FeliCa tag"}
|
// {"sim", CmdHFFelicaSim, IfPm3Felica, "<UID> -- Simulate ISO 18092/FeliCa tag"}
|
||||||
|
|
|
@ -388,9 +388,9 @@ static void fuse_config(const picopass_hdr *hdr) {
|
||||||
uint8_t fuses = hdr->conf.fuses;
|
uint8_t fuses = hdr->conf.fuses;
|
||||||
|
|
||||||
if (isset(fuses, FUSE_FPERS))
|
if (isset(fuses, FUSE_FPERS))
|
||||||
PrintAndLogEx(SUCCESS, " Mode: " _GREEN_("Personalization [programmable]"));
|
PrintAndLogEx(SUCCESS, " Mode: " _GREEN_("Personalization (programmable)"));
|
||||||
else
|
else
|
||||||
PrintAndLogEx(SUCCESS, " Mode: " _YELLOW_("Application [locked]"));
|
PrintAndLogEx(SUCCESS, " Mode: " _YELLOW_("Application (locked)"));
|
||||||
|
|
||||||
if (isset(fuses, FUSE_CODING1)) {
|
if (isset(fuses, FUSE_CODING1)) {
|
||||||
PrintAndLogEx(SUCCESS, "Coding: RFU");
|
PrintAndLogEx(SUCCESS, "Coding: RFU");
|
||||||
|
@ -414,9 +414,20 @@ static void fuse_config(const picopass_hdr *hdr) {
|
||||||
else
|
else
|
||||||
PrintAndLogEx(INFO, " RA: Read access not enabled");
|
PrintAndLogEx(INFO, " RA: Read access not enabled");
|
||||||
|
|
||||||
PrintAndLogEx(INFO, " Block write lock 0x%02X", hdr->conf.block_writelock);
|
PrintAndLogEx(INFO,
|
||||||
PrintAndLogEx(INFO, " EAS 0x%02X", hdr->conf.eas);
|
"App limit " _YELLOW_("0x%02X") ", OTP " _YELLOW_("0x%02X%02X") ", Block write lock " _YELLOW_("0x%02X")
|
||||||
|
, hdr->conf.app_limit
|
||||||
|
, hdr->conf.otp[1]
|
||||||
|
, hdr->conf.otp[0]
|
||||||
|
, hdr->conf.block_writelock
|
||||||
|
);
|
||||||
|
PrintAndLogEx(INFO,
|
||||||
|
" Chip " _YELLOW_("0x%02X") ", Mem " _YELLOW_("0x%02X") ", EAS " _YELLOW_("0x%02X") ", Fuses " _YELLOW_("0x%02X")
|
||||||
|
, hdr->conf.chip_config
|
||||||
|
, hdr->conf.mem_config
|
||||||
|
, hdr->conf.eas
|
||||||
|
, hdr->conf.fuses
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) {
|
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) {
|
||||||
|
@ -466,12 +477,12 @@ static void mem_app_config(const picopass_hdr *hdr) {
|
||||||
if (kb == 2 && (applimit > 0x1f)) applimit = 26;
|
if (kb == 2 && (applimit > 0x1f)) applimit = 26;
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "------ " _CYAN_("Memory") " ------");
|
PrintAndLogEx(INFO, "------ " _CYAN_("Memory") " ------");
|
||||||
PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem);
|
PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u bytes), max blocks 0x%02X (%02d)", kb, app_areas, max_blk * 8, mem, mem);
|
||||||
PrintAndLogEx(INFO, " AA1 blocks 06-%02X", applimit);
|
PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", applimit - 5 , applimit, applimit);
|
||||||
PrintAndLogEx(INFO, " AA2 blocks %02X-%02X", applimit + 1, max_blk);
|
PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", max_blk - applimit, applimit + 1, max_blk, applimit + 1, max_blk);
|
||||||
PrintAndLogEx(INFO, " OTP 0x%02X%02X", hdr->conf.otp[1], hdr->conf.otp[0]);
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "------ " _CYAN_("KeyAccess") " ------");
|
PrintAndLogEx(INFO, "------ " _CYAN_("KeyAccess") " ------");
|
||||||
|
PrintAndLogEx(INFO, " Kd = Debit key (AA1), Kc = Credit key (AA2)");
|
||||||
uint8_t book = isset(mem, 0x20);
|
uint8_t book = isset(mem, 0x20);
|
||||||
if (book) {
|
if (book) {
|
||||||
PrintAndLogEx(INFO, " Read A - Kd");
|
PrintAndLogEx(INFO, " Read A - Kd");
|
||||||
|
@ -491,6 +502,7 @@ static void mem_app_config(const picopass_hdr *hdr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_picopass_info(const picopass_hdr *hdr) {
|
static void print_picopass_info(const picopass_hdr *hdr) {
|
||||||
|
PrintAndLogEx(INFO, "------ " _CYAN_("card configuration") " ------");
|
||||||
fuse_config(hdr);
|
fuse_config(hdr);
|
||||||
mem_app_config(hdr);
|
mem_app_config(hdr);
|
||||||
}
|
}
|
||||||
|
@ -2922,7 +2934,7 @@ int readIclass(bool loop, bool verbose) {
|
||||||
|
|
||||||
uint32_t res = PM3_ETIMEOUT;
|
uint32_t res = PM3_ETIMEOUT;
|
||||||
// loop in client not device - else on windows have a communication error
|
// loop in client not device - else on windows have a communication error
|
||||||
while (!kbd_enter_pressed()) {
|
while (kbd_enter_pressed() == false) {
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||||
|
@ -2931,25 +2943,43 @@ int readIclass(bool loop, bool verbose) {
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
|
||||||
|
|
||||||
uint8_t readStatus = resp.oldarg[0] & 0xff;
|
uint8_t readStatus = resp.oldarg[0] & 0xff;
|
||||||
uint8_t *data = resp.data.asBytes;
|
|
||||||
|
|
||||||
// if (verbose) PrintAndLogEx(INFO, "Readstatus:%02x", readStatus);
|
|
||||||
|
|
||||||
// no tag found or button pressed
|
// no tag found or button pressed
|
||||||
if ((readStatus == 0 && !loop) || readStatus == 0xFF) {
|
if ((readStatus == 0 && !loop) || readStatus == 0xFF) {
|
||||||
// abort
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *data = resp.data.asBytes;
|
||||||
|
picopass_hdr *hdr = (picopass_hdr *)data;
|
||||||
|
uint16_t length = resp.length;
|
||||||
|
|
||||||
|
if ( length != sizeof(picopass_hdr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------");
|
||||||
|
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||||
|
|
||||||
if (readStatus & FLAG_ICLASS_READER_CSN) {
|
if (readStatus & FLAG_ICLASS_READER_CSN) {
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " (uid)", sprint_hex(hdr->csn, sizeof(hdr->csn)));
|
||||||
PrintAndLogEx(SUCCESS, " CSN: " _YELLOW_("%s"), sprint_hex(data, 8));
|
|
||||||
tagFound = true;
|
tagFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (readStatus & FLAG_ICLASS_READER_CONF) {
|
||||||
|
PrintAndLogEx(SUCCESS, " Config: %s (Card configuration)", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
|
||||||
|
}
|
||||||
|
|
||||||
if (readStatus & FLAG_ICLASS_READER_CC) {
|
if (readStatus & FLAG_ICLASS_READER_CC) {
|
||||||
PrintAndLogEx(SUCCESS, " CC: %s", sprint_hex(data + 16, 8));
|
PrintAndLogEx(SUCCESS, "E-purse: %s (Card challenge, CC)", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, " Kd: %s (Debit key, hidden)", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||||
|
PrintAndLogEx(SUCCESS, " Kc: %s (Credit key, hidden)", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||||
|
|
||||||
|
if (readStatus & FLAG_ICLASS_READER_AIA) {
|
||||||
|
// PrintAndLogEx(INFO, "--------- " _CYAN_("AIA") " ---------");
|
||||||
|
PrintAndLogEx(SUCCESS, " AIA: %s (Application Issuer area)", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readStatus & FLAG_ICLASS_READER_CONF) {
|
if (readStatus & FLAG_ICLASS_READER_CONF) {
|
||||||
|
@ -2964,17 +2994,14 @@ int readIclass(bool loop, bool verbose) {
|
||||||
|
|
||||||
bool se_enabled = (memcmp((uint8_t *)(data + 8 * 5), "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0);
|
bool se_enabled = (memcmp((uint8_t *)(data + 8 * 5), "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, " App IA: %s", sprint_hex(data + 8 * 5, 8));
|
PrintAndLogEx(INFO, "------ " _CYAN_("Fingerprint") " ------");
|
||||||
PrintAndLogEx(INFO, "------ " _CYAN_("fingerprint") " ------");
|
|
||||||
|
|
||||||
if (isHidRange) {
|
if (isHidRange) {
|
||||||
PrintAndLogEx(SUCCESS, _YELLOW_("iClass")" (CSN is in HID range)");
|
|
||||||
|
|
||||||
if (legacy)
|
if (legacy)
|
||||||
PrintAndLogEx(SUCCESS, " possible "_YELLOW_("iClass legacy")" credential");
|
PrintAndLogEx(SUCCESS, _GREEN_("iCLASS legacy")" credential");
|
||||||
|
|
||||||
if (se_enabled)
|
if (se_enabled)
|
||||||
PrintAndLogEx(SUCCESS, " possible "_YELLOW_("iClass SE")" credential");
|
PrintAndLogEx(SUCCESS, _GREEN_("iCLASS SE")" credential");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, _YELLOW_("PicoPass")" (CSN is not in HID range)");
|
PrintAndLogEx(SUCCESS, _YELLOW_("PicoPass")" (CSN is not in HID range)");
|
||||||
|
@ -2982,6 +3009,7 @@ int readIclass(bool loop, bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tagFound && !loop) {
|
if (tagFound && !loop) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -2991,6 +3019,7 @@ int readIclass(bool loop, bool verbose) {
|
||||||
}
|
}
|
||||||
if (!loop) break;
|
if (!loop) break;
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
DropField();
|
DropField();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1693,7 +1693,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||||
uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0};
|
uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0};
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
char filename[FILE_PATH_SIZE] = {0}, *fptr;
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
char szTemp[FILE_PATH_SIZE - 20];
|
char szTemp[FILE_PATH_SIZE - 20];
|
||||||
char ctmp;
|
char ctmp;
|
||||||
|
|
||||||
|
@ -1706,19 +1706,21 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||||
case 'h':
|
case 'h':
|
||||||
return usage_hf14_hardnested();
|
return usage_hf14_hardnested();
|
||||||
case 'r':
|
case 'r': {
|
||||||
fptr = GenerateFilename("hf-mf-", "-nonces.bin");
|
char *fptr = GenerateFilename("hf-mf-", "-nonces.bin");
|
||||||
if (fptr == NULL)
|
if (fptr == NULL)
|
||||||
strncpy(filename, "nonces.bin", FILE_PATH_SIZE - 1);
|
strncpy(filename, "nonces.bin", FILE_PATH_SIZE - 1);
|
||||||
else
|
else
|
||||||
strncpy(filename, fptr, FILE_PATH_SIZE - 1);
|
strncpy(filename, fptr, FILE_PATH_SIZE - 1);
|
||||||
|
|
||||||
|
free(fptr);
|
||||||
nonce_file_read = true;
|
nonce_file_read = true;
|
||||||
if (!param_gethex(Cmd, cmdp + 1, trgkey, 12)) {
|
if (!param_gethex(Cmd, cmdp + 1, trgkey, 12)) {
|
||||||
know_target_key = true;
|
know_target_key = true;
|
||||||
}
|
}
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 't':
|
case 't':
|
||||||
tests = param_get32ex(Cmd, cmdp + 1, 100, 10);
|
tests = param_get32ex(Cmd, cmdp + 1, 100, 10);
|
||||||
if (!param_gethex(Cmd, cmdp + 2, trgkey, 12)) {
|
if (!param_gethex(Cmd, cmdp + 2, trgkey, 12)) {
|
||||||
|
@ -1729,9 +1731,9 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
default:
|
default:
|
||||||
if (param_getchar(Cmd, cmdp) == 0x00) {
|
if (param_getchar(Cmd, cmdp) == 0x00) {
|
||||||
PrintAndLogEx(WARNING, "Block number is missing");
|
PrintAndLogEx(WARNING, "Block number is missing");
|
||||||
return 1;
|
return usage_hf14_hardnested();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockNo = param_get8(Cmd, cmdp);
|
blockNo = param_get8(Cmd, cmdp);
|
||||||
ctmp = tolower(param_getchar(Cmd, cmdp + 1));
|
ctmp = tolower(param_getchar(Cmd, cmdp + 1));
|
||||||
if (ctmp != 'a' && ctmp != 'b') {
|
if (ctmp != 'a' && ctmp != 'b') {
|
||||||
|
@ -1775,13 +1777,15 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
case 's':
|
case 's':
|
||||||
slow = true;
|
slow = true;
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w': {
|
||||||
nonce_file_write = true;
|
nonce_file_write = true;
|
||||||
fptr = GenerateFilename("hf-mf-", "-nonces.bin");
|
char *fptr = GenerateFilename("hf-mf-", "-nonces.bin");
|
||||||
if (fptr == NULL)
|
if (fptr == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
strncpy(filename, fptr, FILE_PATH_SIZE - 1);
|
strncpy(filename, fptr, FILE_PATH_SIZE - 1);
|
||||||
|
free(fptr);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 'u':
|
case 'u':
|
||||||
param_getstr(Cmd, cmdp + 1, szTemp, FILE_PATH_SIZE - 20);
|
param_getstr(Cmd, cmdp + 1, szTemp, FILE_PATH_SIZE - 20);
|
||||||
snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", szTemp);
|
snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", szTemp);
|
||||||
|
@ -1837,7 +1841,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
// check if tag doesn't have static nonce
|
// check if tag doesn't have static nonce
|
||||||
if (detect_classic_static_nonce() == 1) {
|
if (detect_classic_static_nonce() == 1) {
|
||||||
PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
|
PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
|
||||||
PrintAndLogEx(INFO, "\t Try use `" _YELLOW_("hf mf staticnested") "`");
|
PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`");
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1849,11 +1853,13 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d ",
|
PrintAndLogEx(INFO, "Target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s",
|
||||||
trgBlockNo,
|
trgBlockNo,
|
||||||
trgKeyType ? 'B' : 'A',
|
trgKeyType ? 'B' : 'A',
|
||||||
trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5],
|
trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5],
|
||||||
know_target_key ? "" : " (not set)",
|
know_target_key ? "" : " (not set)"
|
||||||
|
);
|
||||||
|
PrintAndLogEx(INFO , "File action: %s, Slow: %s, Tests: %d ",
|
||||||
nonce_file_write ? "write" : nonce_file_read ? "read" : "none",
|
nonce_file_write ? "write" : nonce_file_read ? "read" : "none",
|
||||||
slow ? "Yes" : "No",
|
slow ? "Yes" : "No",
|
||||||
tests);
|
tests);
|
||||||
|
@ -1861,7 +1867,9 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
|
||||||
uint64_t foundkey = 0;
|
uint64_t foundkey = 0;
|
||||||
int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename);
|
int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename);
|
||||||
|
|
||||||
if (tests == 0) DropField();
|
if (tests == 0)
|
||||||
|
DropField();
|
||||||
|
|
||||||
if (isOK) {
|
if (isOK) {
|
||||||
switch (isOK) {
|
switch (isOK) {
|
||||||
case 1 :
|
case 1 :
|
||||||
|
@ -4828,6 +4836,7 @@ static int CmdHF14AMfList(const char *Cmd) {
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
|
{"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
|
||||||
|
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("recovery") " -----------------------"},
|
||||||
{"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"},
|
{"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"},
|
||||||
{"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"},
|
{"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"},
|
||||||
{"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"},
|
{"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"},
|
||||||
|
@ -4838,7 +4847,7 @@ static command_t CommandTable[] = {
|
||||||
{"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"},
|
{"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"},
|
||||||
{"fchk", CmdHF14AMfChk_fast, IfPm3Iso14443a, "Check keys fast, targets all keys on card"},
|
{"fchk", CmdHF14AMfChk_fast, IfPm3Iso14443a, "Check keys fast, targets all keys on card"},
|
||||||
{"decrypt", CmdHf14AMfDecryptBytes, AlwaysAvailable, "[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace"},
|
{"decrypt", CmdHf14AMfDecryptBytes, AlwaysAvailable, "[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace"},
|
||||||
{"-----------", CmdHelp, IfPm3Iso14443a, ""},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"},
|
||||||
{"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"},
|
{"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"},
|
||||||
{"dump", CmdHF14AMfDump, IfPm3Iso14443a, "Dump MIFARE classic tag to binary file"},
|
{"dump", CmdHF14AMfDump, IfPm3Iso14443a, "Dump MIFARE classic tag to binary file"},
|
||||||
{"mad", CmdHF14AMfMAD, IfPm3Iso14443a, "Checks and prints MAD"},
|
{"mad", CmdHF14AMfMAD, IfPm3Iso14443a, "Checks and prints MAD"},
|
||||||
|
@ -4850,7 +4859,7 @@ static command_t CommandTable[] = {
|
||||||
{"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE classic block"},
|
{"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE classic block"},
|
||||||
{"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"},
|
{"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"},
|
||||||
// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
||||||
{"-----------", CmdHelp, IfPm3Iso14443a, ""},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
|
||||||
{"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"},
|
{"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"},
|
||||||
{"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear simulator memory"},
|
{"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear simulator memory"},
|
||||||
{"eget", CmdHF14AMfEGet, IfPm3Iso14443a, "Get simulator memory block"},
|
{"eget", CmdHF14AMfEGet, IfPm3Iso14443a, "Get simulator memory block"},
|
||||||
|
@ -4859,7 +4868,7 @@ static command_t CommandTable[] = {
|
||||||
{"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"},
|
{"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"},
|
||||||
{"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill simulator memory with help of keys from simulator"},
|
{"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill simulator memory with help of keys from simulator"},
|
||||||
{"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from simulator memory"},
|
{"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from simulator memory"},
|
||||||
{"-----------", CmdHelp, IfPm3Iso14443a, ""},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " -----------------------"},
|
||||||
{"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID (magic chinese card)"},
|
{"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID (magic chinese card)"},
|
||||||
{"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"},
|
{"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"},
|
||||||
{"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block (magic chinese card)"},
|
{"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block (magic chinese card)"},
|
||||||
|
@ -4867,7 +4876,7 @@ static command_t CommandTable[] = {
|
||||||
{"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector (magic chinese card)"},
|
{"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector (magic chinese card)"},
|
||||||
{"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump (magic chinese card)"},
|
{"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump (magic chinese card)"},
|
||||||
{"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from magic chinese card into file or emulator"},
|
{"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from magic chinese card into file or emulator"},
|
||||||
{"-----------", CmdHelp, IfPm3Iso14443a, ""},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"},
|
||||||
{"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
|
{"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,10 +30,14 @@
|
||||||
#include "mifare/desfire_crypto.h"
|
#include "mifare/desfire_crypto.h"
|
||||||
#include "crapto1/crapto1.h"
|
#include "crapto1/crapto1.h"
|
||||||
#include "fileutils.h"
|
#include "fileutils.h"
|
||||||
|
#include "mifare/mifaredefault.h" // default keys
|
||||||
|
#include "mifare/ndef.h" // NDEF
|
||||||
|
|
||||||
#define MAX_KEY_LEN 24
|
#define MAX_KEY_LEN 24
|
||||||
#define MAX_KEYS_LIST_LEN 1024
|
#define MAX_KEYS_LIST_LEN 1024
|
||||||
|
|
||||||
|
#define status(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x )
|
||||||
|
|
||||||
struct desfire_key default_key = {0};
|
struct desfire_key default_key = {0};
|
||||||
|
|
||||||
uint8_t desdefaultkeys[3][8] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //Official
|
uint8_t desdefaultkeys[3][8] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //Official
|
||||||
|
@ -113,8 +117,6 @@ typedef enum {
|
||||||
MFDES_VALUE_FILE
|
MFDES_VALUE_FILE
|
||||||
} MFDES_FILE_TYPE_T;
|
} MFDES_FILE_TYPE_T;
|
||||||
|
|
||||||
#define status(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x )
|
|
||||||
|
|
||||||
// NXP Appnote AN10787 - Application Directory (MAD)
|
// NXP Appnote AN10787 - Application Directory (MAD)
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CL_ADMIN = 0,
|
CL_ADMIN = 0,
|
||||||
|
@ -380,8 +382,8 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor);
|
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor);
|
||||||
else if (major == 0x12 && minor == 0x00)
|
else if (major == 0x12 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
|
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor);
|
||||||
// else if (major == 0x13 && minor == 0x00)
|
else if (major == 0x13 && minor == 0x00)
|
||||||
// sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
|
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor);
|
||||||
else if (major == 0x30 && minor == 0x00)
|
else if (major == 0x30 && minor == 0x00)
|
||||||
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
|
sprintf(retStr, "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor);
|
||||||
else
|
else
|
||||||
|
@ -389,7 +391,6 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) {
|
static int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) {
|
||||||
|
|
||||||
*result_len = 0;
|
*result_len = 0;
|
||||||
|
@ -956,7 +957,6 @@ static void AuthToError(int error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -- test if card supports 0x0A
|
// -- test if card supports 0x0A
|
||||||
static int test_desfire_authenticate(void) {
|
static int test_desfire_authenticate(void) {
|
||||||
uint8_t data[] = {0x00};
|
uint8_t data[] = {0x00};
|
||||||
|
@ -1011,7 +1011,8 @@ static int desfire_print_freemem(uint32_t free_mem) {
|
||||||
static int handler_desfire_freemem(uint32_t *free_mem) {
|
static int handler_desfire_freemem(uint32_t *free_mem) {
|
||||||
if (free_mem == NULL) return PM3_EINVARG;
|
if (free_mem == NULL) return PM3_EINVARG;
|
||||||
|
|
||||||
sAPDU apdu = {0x90, MFDES_GET_FREE_MEMORY, 0x00, 0x00, 0x00, NULL}; // 0x6E
|
uint8_t data[] = {0x00};
|
||||||
|
sAPDU apdu = {0x90, MFDES_GET_FREE_MEMORY, 0x00, 0x00, 0x00, data}; // 0x6E
|
||||||
*free_mem = 0;
|
*free_mem = 0;
|
||||||
uint32_t recv_len = 0;
|
uint32_t recv_len = 0;
|
||||||
uint16_t sw = 0;
|
uint16_t sw = 0;
|
||||||
|
@ -1071,7 +1072,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t cmdcnt = 0;
|
size_t cmdcnt = 0;
|
||||||
memcpy(data + cmdcnt + 1, new_key, new_key_length);
|
memcpy(data + cmdcnt + 1, new_key, new_key_length);
|
||||||
|
|
||||||
if ((tag->authenticated_key_no & 0x0f) != (key_no & 0x0f)) {
|
if ((tag->authenticated_key_no & 0x0f) != (key_no & 0x0f)) {
|
||||||
|
@ -1405,16 +1406,16 @@ static int handler_desfire_appids(uint8_t *dest, uint32_t *app_ids_len) {
|
||||||
|
|
||||||
// --- GET DF NAMES
|
// --- GET DF NAMES
|
||||||
static int handler_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) {
|
static int handler_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) {
|
||||||
*dfname_count = 0;
|
|
||||||
if (g_debugMode > 1) {
|
if (g_debugMode > 1) {
|
||||||
if (dest == NULL) PrintAndLogEx(ERR, "DEST = NULL");
|
if (dest == NULL) PrintAndLogEx(ERR, "DEST = NULL");
|
||||||
if (dfname_count == NULL) PrintAndLogEx(ERR, "DFNAME_COUNT = NULL");
|
if (dfname_count == NULL) PrintAndLogEx(ERR, "DFNAME_COUNT = NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest == NULL || dfname_count == NULL) return PM3_EINVARG;
|
if (dest == NULL || dfname_count == NULL)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
|
||||||
*dfname_count = 0;
|
*dfname_count = 0;
|
||||||
|
|
||||||
sAPDU apdu = {0x90, MFDES_GET_DF_NAMES, 0x00, 0x00, 0x00, NULL}; //0x6d
|
sAPDU apdu = {0x90, MFDES_GET_DF_NAMES, 0x00, 0x00, 0x00, NULL}; //0x6d
|
||||||
uint32_t recv_len = 0;
|
uint32_t recv_len = 0;
|
||||||
uint16_t sw = 0;
|
uint16_t sw = 0;
|
||||||
|
@ -1648,9 +1649,11 @@ static int handler_desfire_readdata(mfdes_data_t *data, MFDES_FILE_TYPE_T type,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int handler_desfire_getvalue(mfdes_value_t *value, uint32_t *resplen, uint8_t cs) {
|
static int handler_desfire_getvalue(mfdes_value_t *value, uint32_t *resplen, uint8_t cs) {
|
||||||
if (value->fileno > 0x1F) return PM3_EINVARG;
|
|
||||||
|
if (value->fileno > 0x1F)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
|
||||||
sAPDU apdu = {0x90, MFDES_GET_VALUE, 0x00, 0x00, 0x01, &value->fileno}; // 0xBD
|
sAPDU apdu = {0x90, MFDES_GET_VALUE, 0x00, 0x00, 0x01, &value->fileno}; // 0xBD
|
||||||
uint16_t sw = 0;
|
uint16_t sw = 0;
|
||||||
*resplen = 0;
|
*resplen = 0;
|
||||||
|
@ -1735,7 +1738,6 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int handler_desfire_deletefile(uint8_t fileno) {
|
static int handler_desfire_deletefile(uint8_t fileno) {
|
||||||
if (fileno > 0x1F) return PM3_EINVARG;
|
if (fileno > 0x1F) return PM3_EINVARG;
|
||||||
sAPDU apdu = {0x90, MFDES_DELETE_FILE, 0x00, 0x00, 1, &fileno}; // 0xDF
|
sAPDU apdu = {0x90, MFDES_DELETE_FILE, 0x00, 0x00, 1, &fileno}; // 0xDF
|
||||||
|
@ -2096,7 +2098,6 @@ static int CmdHF14ADesSelectApp(const char *Cmd) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdHF14ADesCreateApp(const char *Cmd) {
|
static int CmdHF14ADesCreateApp(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes createaid",
|
CLIParserInit(&ctx, "hf mfdes createaid",
|
||||||
|
@ -2290,7 +2291,6 @@ static int selectfile(uint8_t *aid, uint32_t fileno, uint8_t *cs) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes clearrecord",
|
CLIParserInit(&ctx, "hf mfdes clearrecord",
|
||||||
|
@ -2442,7 +2442,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) {
|
||||||
|
|
||||||
int fidlength = 0;
|
int fidlength = 0;
|
||||||
uint8_t fid[2] = {0};
|
uint8_t fid[2] = {0};
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 2), fid, 2, &fidlength);
|
int res_flen = CLIParamHexToBuf(arg_get_str(ctx, 2), fid, 2, &fidlength);
|
||||||
|
|
||||||
uint8_t comset = arg_get_int(ctx, 3);
|
uint8_t comset = arg_get_int(ctx, 3);
|
||||||
int arlength = 0;
|
int arlength = 0;
|
||||||
|
@ -2487,7 +2487,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fidlength != 2) {
|
if (res_flen || fidlength != 2) {
|
||||||
PrintAndLogEx(ERR, "ISO File id must have 2 hex bytes length.");
|
PrintAndLogEx(ERR, "ISO File id must have 2 hex bytes length.");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -2633,11 +2633,11 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
|
|
||||||
int offsetlength = 0;
|
int offsetlength = 0;
|
||||||
uint8_t offset[3] = {0};
|
uint8_t offset[3] = {0};
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 2), offset, 3, &offsetlength);
|
int res_offset = CLIParamHexToBuf(arg_get_str(ctx, 2), offset, 3, &offsetlength);
|
||||||
|
|
||||||
int flength = 0;
|
int flength = 0;
|
||||||
uint8_t filesize[3] = {0};
|
uint8_t filesize[3] = {0};
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 3), filesize, 3, &flength);
|
int res_flen = CLIParamHexToBuf(arg_get_str(ctx, 3), filesize, 3, &flength);
|
||||||
|
|
||||||
int type = arg_get_int(ctx, 4);
|
int type = arg_get_int(ctx, 4);
|
||||||
|
|
||||||
|
@ -2652,7 +2652,7 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offsetlength != 3 && offsetlength != 0) {
|
if (res_offset || (offsetlength != 3 && offsetlength != 0)) {
|
||||||
PrintAndLogEx(ERR, "Offset needs 3 hex bytes");
|
PrintAndLogEx(ERR, "Offset needs 3 hex bytes");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -2667,6 +2667,11 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res_flen) {
|
||||||
|
PrintAndLogEx(ERR, "File size input error");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
swap24(filesize);
|
swap24(filesize);
|
||||||
swap24(offset);
|
swap24(offset);
|
||||||
|
|
||||||
|
@ -2750,7 +2755,7 @@ static int CmdHF14ADesChangeValue(const char *Cmd) {
|
||||||
value.fileno = _fileno[0];
|
value.fileno = _fileno[0];
|
||||||
|
|
||||||
int vlength = 0x0;
|
int vlength = 0x0;
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 2), value.value, 4, &vlength);
|
int res_val = CLIParamHexToBuf(arg_get_str(ctx, 2), value.value, 4, &vlength);
|
||||||
|
|
||||||
int mode = arg_get_int(ctx, 3);
|
int mode = arg_get_int(ctx, 3);
|
||||||
int aidlength = 3;
|
int aidlength = 3;
|
||||||
|
@ -2765,7 +2770,7 @@ static int CmdHF14ADesChangeValue(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vlength != 4) {
|
if (res_val || vlength != 4) {
|
||||||
PrintAndLogEx(ERR, "Value needs 4 hex bytes.");
|
PrintAndLogEx(ERR, "Value needs 4 hex bytes.");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -2820,7 +2825,6 @@ static int CmdHF14ADesChangeValue(const char *Cmd) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdHF14ADesWriteData(const char *Cmd) {
|
static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
|
@ -2849,16 +2853,14 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
|
|
||||||
int offsetlength = 0;
|
int offsetlength = 0;
|
||||||
uint8_t offset[3] = {0};
|
uint8_t offset[3] = {0};
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 2), offset, 3, &offsetlength);
|
int res_offset = CLIParamHexToBuf(arg_get_str(ctx, 2), offset, 3, &offsetlength);
|
||||||
|
|
||||||
int dlength = 0xFFFF;
|
// iceman: we only have a 1024 byte commandline input array. So this is pointlessly large.
|
||||||
uint8_t *data = (uint8_t *)calloc(dlength, sizeof(uint8_t));
|
// with 2char hex, 512bytes could be input.
|
||||||
if (data == NULL) {
|
// Instead large binary inputs should be BINARY files and written to card.
|
||||||
PrintAndLogEx(ERR, "failed to allocate memory");
|
int dlength = 512;
|
||||||
CLIParserFree(ctx);
|
uint8_t data[512] = {0};
|
||||||
return PM3_EMALLOC;
|
int res_data = CLIParamHexToBuf(arg_get_str(ctx, 3), data, 512, &dlength);
|
||||||
}
|
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 3), data, 0xFFFF, &dlength);
|
|
||||||
|
|
||||||
int type = arg_get_int(ctx, 4);
|
int type = arg_get_int(ctx, 4);
|
||||||
int aidlength = 3;
|
int aidlength = 3;
|
||||||
|
@ -2872,31 +2874,26 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
|
|
||||||
if (type < 0 || type > 1) {
|
if (type < 0 || type > 1) {
|
||||||
PrintAndLogEx(ERR, "Unknown type (0=Standard/Backup, 1=Record)");
|
PrintAndLogEx(ERR, "Unknown type (0=Standard/Backup, 1=Record)");
|
||||||
if (data) free(data);
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dlength == 0) {
|
if (res_data || dlength == 0) {
|
||||||
PrintAndLogEx(ERR, "Data needs some hex bytes to write");
|
PrintAndLogEx(ERR, "Data needs some hex bytes to write");
|
||||||
if (data) free(data);
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offsetlength != 3 && offsetlength != 0) {
|
if (res_offset || (offsetlength != 3 && offsetlength != 0)) {
|
||||||
PrintAndLogEx(ERR, "Offset needs 3 hex bytes");
|
PrintAndLogEx(ERR, "Offset needs 3 hex bytes");
|
||||||
if (data) free(data);
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filenolen != 1) {
|
if (filenolen != 1) {
|
||||||
PrintAndLogEx(ERR, "File number is missing");
|
PrintAndLogEx(ERR, "File number is missing");
|
||||||
if (data) free(data);
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_fileno[0] > 0x1F) {
|
if (_fileno[0] > 0x1F) {
|
||||||
PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)");
|
PrintAndLogEx(ERR, "File number range is invalid (0x00-0x1F)");
|
||||||
if (data) free(data);
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2919,11 +2916,11 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
uint8_t cs = 0;
|
uint8_t cs = 0;
|
||||||
if (selectfile(aid, _fileno[0], &cs) != PM3_SUCCESS) {
|
if (selectfile(aid, _fileno[0], &cs) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, _RED_(" Error on selecting file."));
|
PrintAndLogEx(ERR, _RED_(" Error on selecting file."));
|
||||||
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = PM3_ESOFT;
|
int res = PM3_ESOFT;
|
||||||
if (data != NULL) {
|
|
||||||
ft.data = data;
|
ft.data = data;
|
||||||
res = handler_desfire_writedata(&ft, type, cs);
|
res = handler_desfire_writedata(&ft, type, cs);
|
||||||
if (res == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
|
@ -2931,13 +2928,10 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(ERR, "Couldn't read data. Error %d", res);
|
PrintAndLogEx(ERR, "Couldn't read data. Error %d", res);
|
||||||
}
|
}
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
DropField();
|
DropField();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
|
static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes createrecordfile",
|
CLIParserInit(&ctx, "hf mfdes createrecordfile",
|
||||||
|
@ -2967,7 +2961,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
|
||||||
|
|
||||||
int fidlength = 0;
|
int fidlength = 0;
|
||||||
uint8_t fid[2] = {0};
|
uint8_t fid[2] = {0};
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 2), fid, 2, &fidlength);
|
int res_flen = CLIParamHexToBuf(arg_get_str(ctx, 2), fid, 2, &fidlength);
|
||||||
|
|
||||||
uint8_t comset = arg_get_int(ctx, 3);
|
uint8_t comset = arg_get_int(ctx, 3);
|
||||||
int arlength = 0;
|
int arlength = 0;
|
||||||
|
@ -3028,7 +3022,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fidlength != 2) {
|
if (res_flen || fidlength != 2) {
|
||||||
PrintAndLogEx(ERR, "ISO File id must have 2 hex bytes length.");
|
PrintAndLogEx(ERR, "ISO File id must have 2 hex bytes length.");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -3214,24 +3208,20 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
||||||
"\n\thf mfdes formatpicc\n"
|
"\n\thf mfdes formatpicc\n"
|
||||||
"Make sure to authenticate picc before running this command.\n"
|
"Make sure to authenticate picc before running this command.\n"
|
||||||
);
|
);
|
||||||
|
CLIParserFree(ctx);
|
||||||
sAPDU apdu = {0x90, MFDES_FORMAT_PICC, 0x00, 0x00, 0, NULL}; // 0xDF
|
sAPDU apdu = {0x90, MFDES_FORMAT_PICC, 0x00, 0x00, 0, NULL}; // 0xDF
|
||||||
uint16_t sw = 0;
|
uint16_t sw = 0;
|
||||||
uint32_t recvlen = 0;
|
uint32_t recvlen = 0;
|
||||||
int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true);
|
int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(WARNING, _RED_(" Can't format picc -> %s"), GetErrorString(res, &sw));
|
PrintAndLogEx(WARNING, _RED_(" Can't format picc -> %s"), GetErrorString(res, &sw));
|
||||||
DropField();
|
|
||||||
return res;
|
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Card successfully reset");
|
PrintAndLogEx(INFO, "Card successfully reset");
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
}
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_SUCCESS;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdHF14ADesInfo(const char *Cmd) {
|
static int CmdHF14ADesInfo(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
DropField();
|
DropField();
|
||||||
|
@ -3315,8 +3305,8 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "\t1.4 - DESFire Ev1 MF3ICD21/41/81, EAL4+");
|
PrintAndLogEx(INFO, "\t1.4 - DESFire Ev1 MF3ICD21/41/81, EAL4+");
|
||||||
if (major == 2 && minor == 0)
|
if (major == 2 && minor == 0)
|
||||||
PrintAndLogEx(INFO, "\t2.0 - DESFire Ev2, Originality check, proximity check, EAL5");
|
PrintAndLogEx(INFO, "\t2.0 - DESFire Ev2, Originality check, proximity check, EAL5");
|
||||||
// if (major == 3 && minor == 0)
|
if (major == 3 && minor == 0)
|
||||||
// PrintAndLogEx(INFO, "\t3.0 - DESFire Ev3, Originality check, proximity check, badass EAL5");
|
PrintAndLogEx(INFO, "\t3.0 - DESFire Ev3, Originality check, proximity check, badass EAL6 ?");
|
||||||
|
|
||||||
if (major == 0 && minor == 2)
|
if (major == 0 && minor == 2)
|
||||||
PrintAndLogEx(INFO, "\t0.2 - DESFire Light, Originality check, ");
|
PrintAndLogEx(INFO, "\t0.2 - DESFire Light, Originality check, ");
|
||||||
|
@ -3370,7 +3360,6 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void DecodeFileType(uint8_t filetype) {
|
static void DecodeFileType(uint8_t filetype) {
|
||||||
switch (filetype) {
|
switch (filetype) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
|
@ -3777,11 +3766,13 @@ static int CmdHF14ADesChangeKey(const char *Cmd) {
|
||||||
uint8_t cmdAuthAlgo = arg_get_int_def(ctx, 2, 0);
|
uint8_t cmdAuthAlgo = arg_get_int_def(ctx, 2, 0);
|
||||||
uint8_t key[24] = {0};
|
uint8_t key[24] = {0};
|
||||||
int keylen = 0;
|
int keylen = 0;
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen);
|
int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen);
|
||||||
|
|
||||||
uint8_t newcmdAuthAlgo = arg_get_int_def(ctx, 4, 0);
|
uint8_t newcmdAuthAlgo = arg_get_int_def(ctx, 4, 0);
|
||||||
uint8_t newkey[24] = {0};
|
uint8_t newkey[24] = {0};
|
||||||
int newkeylen = 0;
|
int newkeylen = 0;
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 5), newkey, 24, &newkeylen);
|
int res_newklen = CLIParamHexToBuf(arg_get_str(ctx, 5), newkey, 24, &newkeylen);
|
||||||
|
|
||||||
uint8_t aesversion = arg_get_int_def(ctx, 6, 0);
|
uint8_t aesversion = arg_get_int_def(ctx, 6, 0);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
@ -3805,12 +3796,12 @@ static int CmdHF14ADesChangeKey(const char *Cmd) {
|
||||||
newkeylength = 24;
|
newkeylength = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((keylen < 8) || (keylen > 24)) {
|
if (res_klen || (keylen < 8) || (keylen > 24)) {
|
||||||
PrintAndLogEx(ERR, "Specified key must have %d bytes length.", keylen);
|
PrintAndLogEx(ERR, "Specified key must have %d bytes length.", keylen);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((newkeylen < 8) || (newkeylen > 24)) {
|
if (res_newklen || (newkeylen < 8) || (newkeylen > 24)) {
|
||||||
PrintAndLogEx(ERR, "Specified key must have %d bytes length.", newkeylen);
|
PrintAndLogEx(ERR, "Specified key must have %d bytes length.", newkeylen);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -4470,6 +4461,107 @@ static int CmdHF14ADesList(const char *Cmd) {
|
||||||
return CmdTraceList("des");
|
return CmdTraceList("des");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int CmdHF14aDesNDEF(const char *Cmd) {
|
||||||
|
DropField();
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf mfdes ndef",
|
||||||
|
"Prints NFC Data Exchange Format (NDEF)",
|
||||||
|
"Usage:\n"
|
||||||
|
_YELLOW_("\thf mfdes ndef") " -> shows NDEF data\n"
|
||||||
|
_YELLOW_("\thf mfdes ndef -vv") " -> shows NDEF parsed and raw data\n"
|
||||||
|
_YELLOW_("\thf mfdes ndef -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7") " -> shows NDEF data with custom AID and key\n");
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_litn("vV", "verbose", 0, 2, "show technical data"),
|
||||||
|
arg_str0("", "aid", "<aid>", "replace default aid for NDEF"),
|
||||||
|
arg_str0("kK", "key", "<key>", "replace default key for NDEF"),
|
||||||
|
arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
|
bool verbose = arg_get_lit(ctx, 1);
|
||||||
|
bool verbose2 = arg_get_lit(ctx, 1) > 1;
|
||||||
|
uint8_t aid[2] = {0};
|
||||||
|
int aidlen;
|
||||||
|
CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
|
||||||
|
uint8_t key[16] = {0};
|
||||||
|
int keylen;
|
||||||
|
CLIGetHexWithReturn(ctx, 3, key, &keylen);
|
||||||
|
bool keyB = arg_get_lit(ctx, 4);
|
||||||
|
|
||||||
|
uint16_t ndefAID = 0xe103;
|
||||||
|
if (aidlen == 2)
|
||||||
|
ndefAID = (aid[0] << 8) + aid[1];
|
||||||
|
|
||||||
|
uint8_t ndefkey[16] = {0};
|
||||||
|
memcpy(ndefkey, g_mifarep_ndef_key, 16);
|
||||||
|
if (keylen == 16) {
|
||||||
|
memcpy(ndefkey, key, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t data[4096] = {0};
|
||||||
|
int datalen = 0;
|
||||||
|
|
||||||
|
for (int j = (int)file_ids_len - 1; j >= 0; j--) {
|
||||||
|
PrintAndLogEx(SUCCESS, "\n\n Fileid %d (0x%02x)", file_ids[j], file_ids[j]);
|
||||||
|
|
||||||
|
uint8_t filesettings[20] = {0};
|
||||||
|
uint32_t fileset_len = 0;
|
||||||
|
|
||||||
|
res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len);
|
||||||
|
if (res != PM3_SUCCESS) continue;
|
||||||
|
|
||||||
|
int maclen = 0; // To be implemented
|
||||||
|
|
||||||
|
if (fileset_len == 1 + 1 + 2 + 3 + maclen) {
|
||||||
|
int filesize = (filesettings[6] << 16) + (filesettings[5] << 8) + filesettings[4];
|
||||||
|
mfdes_data_t fdata;
|
||||||
|
fdata.fileno = file_ids[j];
|
||||||
|
memset(fdata.offset, 0, 3);
|
||||||
|
memset(fdata.length, 0, 3);
|
||||||
|
|
||||||
|
uint8_t *data = (uint8_t *)calloc(filesize, sizeof(uint8_t));
|
||||||
|
if (data == NULL) {
|
||||||
|
DropField();
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdata.data = data;
|
||||||
|
int res = handler_desfire_readdata(&fdata, MFDES_DATA_FILE, filesettings[1]);
|
||||||
|
if (res == PM3_SUCCESS) {
|
||||||
|
uint32_t len = le24toh(fdata.length);
|
||||||
|
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Couldn't read value. Error %d", res);
|
||||||
|
res = handler_desfire_select_application(aid);
|
||||||
|
if (res != PM3_SUCCESS) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintAndLogEx(INFO, "reading data from tag");
|
||||||
|
|
||||||
|
if (!datalen) {
|
||||||
|
PrintAndLogEx(ERR, "no NDEF data");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose2) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--- " _CYAN_("DESfire NDEF raw") " ----------------");
|
||||||
|
dump_buffer(data, datalen, stdout, 1);
|
||||||
|
}
|
||||||
|
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfdes ndef -vv`") " for more details");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*static int CmdTest(const char *Cmd) {
|
/*static int CmdTest(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
uint8_t IV[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
uint8_t IV[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
@ -4496,7 +4588,6 @@ static int CmdHF14ADesList(const char *Cmd) {
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
//{"test", CmdTest, AlwaysAvailable, "Test"},
|
|
||||||
{"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"},
|
{"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"},
|
||||||
{"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"},
|
{"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"},
|
||||||
{"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"},
|
{"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "Tries enumerate all applications"},
|
||||||
|
@ -4518,6 +4609,7 @@ static command_t CommandTable[] = {
|
||||||
{"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"},
|
{"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"},
|
||||||
{"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"},
|
{"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"},
|
||||||
{"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"},
|
{"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"},
|
||||||
|
// {"ndef", CmdHF14aDesNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1429,9 +1429,9 @@ static int CmdHFMFPNDEF(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "hf mfp ndef",
|
CLIParserInit(&ctx, "hf mfp ndef",
|
||||||
"Prints NFC Data Exchange Format (NDEF)",
|
"Prints NFC Data Exchange Format (NDEF)",
|
||||||
"Usage:\n"
|
"Usage:\n"
|
||||||
"\thf mfp ndef -> shows NDEF data\n"
|
_YELLOW_("\thf mfp ndef") " -> shows NDEF data\n"
|
||||||
"\thf mfp ndef -vv -> shows NDEF parsed and raw data\n"
|
_YELLOW_("\thf mfp ndef -vv") " -> shows NDEF parsed and raw data\n"
|
||||||
"\thf mfp ndef -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data with custom AID and key\n");
|
_YELLOW_("\thf mfp ndef -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7") " -> shows NDEF data with custom AID and key\n");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -1530,12 +1530,12 @@ static int CmdHFMFPNDEF(const char *Cmd) {
|
||||||
|
|
||||||
if (verbose2) {
|
if (verbose2) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("MFC NDEF raw") " ----------------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("MF Plus NDEF raw") " ----------------");
|
||||||
dump_buffer(data, datalen, stdout, 1);
|
dump_buffer(data, datalen, stdout, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NDEFDecodeAndPrint(data, datalen, verbose);
|
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||||
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndef -vv`") " for more details");
|
PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfp ndef -vv`") " for more details");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1088,6 +1088,7 @@ uint32_t GetHF14AMfU_Type(void) {
|
||||||
MF0UNH1001DUx 0004030203000B03
|
MF0UNH1001DUx 0004030203000B03
|
||||||
NT2L1001G0DUx 0004040102000B03
|
NT2L1001G0DUx 0004040102000B03
|
||||||
NT2H1001G0DUx 0004040202000B03
|
NT2H1001G0DUx 0004040202000B03
|
||||||
|
Micron UL 0034210101000E03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0B", 7) == 0) { tagtype = UL_EV1_48; break; }
|
if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0B", 7) == 0) { tagtype = UL_EV1_48; break; }
|
||||||
|
@ -1106,6 +1107,7 @@ uint32_t GetHF14AMfU_Type(void) {
|
||||||
else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x15", 7) == 0) { tagtype = NTAG_I2C_2K; break; }
|
else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x15", 7) == 0) { tagtype = NTAG_I2C_2K; break; }
|
||||||
else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x13", 7) == 0) { tagtype = NTAG_I2C_1K_PLUS; break; }
|
else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x13", 7) == 0) { tagtype = NTAG_I2C_1K_PLUS; break; }
|
||||||
else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x15", 7) == 0) { tagtype = NTAG_I2C_2K_PLUS; break; }
|
else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x15", 7) == 0) { tagtype = NTAG_I2C_2K_PLUS; break; }
|
||||||
|
else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { tagtype = UL; break; }
|
||||||
else if (version[2] == 0x04) { tagtype = NTAG; break; }
|
else if (version[2] == 0x04) { tagtype = NTAG; break; }
|
||||||
else if (version[2] == 0x03) { tagtype = UL_EV1; }
|
else if (version[2] == 0x03) { tagtype = UL_EV1; }
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -22,7 +22,6 @@ typedef struct {
|
||||||
|
|
||||||
uint32_t GetHF14AMfU_Type(void);
|
uint32_t GetHF14AMfU_Type(void);
|
||||||
int ul_print_type(uint32_t tagtype, uint8_t spaces);
|
int ul_print_type(uint32_t tagtype, uint8_t spaces);
|
||||||
void printMFUdump(mfu_dump_t *card);
|
|
||||||
void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage);
|
void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage);
|
||||||
|
|
||||||
int CmdHFMFUltra(const char *Cmd);
|
int CmdHFMFUltra(const char *Cmd);
|
||||||
|
|
|
@ -507,19 +507,23 @@ static int CmdStatus(const char *Cmd) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
SendCommandNG(CMD_STATUS, NULL, 0);
|
SendCommandNG(CMD_STATUS, NULL, 0);
|
||||||
if (WaitForResponseTimeout(CMD_STATUS, &resp, 2000) == false)
|
if (WaitForResponseTimeout(CMD_STATUS, &resp, 2000) == false) {
|
||||||
PrintAndLogEx(WARNING, "Status command failed. Communication speed test timed out");
|
PrintAndLogEx(WARNING, "Status command timeout. Communication speed test timed out");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdTia(const char *Cmd) {
|
static int CmdTia(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
clearCommandBuffer();
|
|
||||||
PrintAndLogEx(INFO, "Triggering new Timing Interval Acquisition (TIA)...");
|
PrintAndLogEx(INFO, "Triggering new Timing Interval Acquisition (TIA)...");
|
||||||
PacketResponseNG resp;
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_TIA, NULL, 0);
|
SendCommandNG(CMD_TIA, NULL, 0);
|
||||||
if (WaitForResponseTimeout(CMD_TIA, &resp, 2000) == false)
|
PacketResponseNG resp;
|
||||||
PrintAndLogEx(WARNING, "TIA command failed. You probably need to unplug the Proxmark3.");
|
if (WaitForResponseTimeout(CMD_TIA, &resp, 2000) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "TIA command timeout. You probably need to unplug the Proxmark3.");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
PrintAndLogEx(INFO, "TIA done.");
|
PrintAndLogEx(INFO, "TIA done.");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "cmddata.h" // for `lf search`
|
#include "cmddata.h" // for `lf search`
|
||||||
#include "cmdlfawid.h" // for awid menu
|
#include "cmdlfawid.h" // for awid menu
|
||||||
#include "cmdlfem4x.h" // for em4x menu
|
#include "cmdlfem4x.h" // for em4x menu
|
||||||
|
#include "cmdlfem4x50.h" // for em4x50
|
||||||
#include "cmdlfhid.h" // for hid menu
|
#include "cmdlfhid.h" // for hid menu
|
||||||
#include "cmdlfhitag.h" // for hitag menu
|
#include "cmdlfhitag.h" // for hitag menu
|
||||||
#include "cmdlfio.h" // for ioprox menu
|
#include "cmdlfio.h" // for ioprox menu
|
||||||
|
@ -1206,6 +1207,14 @@ static bool CheckChipType(bool getDeviceData) {
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for em4x50 chips
|
||||||
|
if (detect_4x50_block()) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x50"));
|
||||||
|
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x50`") " commands");
|
||||||
|
retval = true;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
save_restoreGB(GRAPH_RESTORE);
|
save_restoreGB(GRAPH_RESTORE);
|
||||||
save_restoreDB(GRAPH_RESTORE);
|
save_restoreDB(GRAPH_RESTORE);
|
||||||
|
@ -1250,6 +1259,13 @@ int CmdLFfind(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IfPm3EM4x50()) {
|
||||||
|
if (read_em4x50_uid() == PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// only run if graphbuffer is just noise as it should be for hitag
|
// only run if graphbuffer is just noise as it should be for hitag
|
||||||
// The improved noise detection will find Cotag.
|
// The improved noise detection will find Cotag.
|
||||||
if (getSignalProperties()->isnoise) {
|
if (getSignalProperties()->isnoise) {
|
||||||
|
@ -1270,21 +1286,20 @@ int CmdLFfind(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EM4x50Read("", false) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); return PM3_SUCCESS;}
|
|
||||||
|
|
||||||
if (demodHID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;}
|
if (demodHID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;}
|
||||||
if (demodAWID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;}
|
if (demodAWID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;}
|
||||||
|
if (demodIOProx() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;}
|
||||||
if (demodParadox() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;}
|
if (demodParadox() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;}
|
||||||
|
if (demodNexWatch() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); goto out;}
|
||||||
|
if (demodIndala() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;}
|
||||||
|
|
||||||
if (demodEM410x() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;}
|
if (demodEM410x() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;}
|
||||||
if (demodFDX() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;}
|
if (demodFDX() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;}
|
||||||
if (demodGuard() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; }
|
if (demodGuard() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; }
|
||||||
if (demodIdteck() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
|
if (demodIdteck() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
|
||||||
if (demodIndala() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;}
|
|
||||||
if (demodIOProx() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;}
|
|
||||||
if (demodJablotron() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;}
|
if (demodJablotron() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;}
|
||||||
if (demodNedap() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!"); goto out;}
|
if (demodNedap() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!"); goto out;}
|
||||||
if (demodNexWatch() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); goto out;}
|
|
||||||
if (demodNoralsy() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;}
|
if (demodNoralsy() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;}
|
||||||
if (demodKeri() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;}
|
if (demodKeri() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;}
|
||||||
if (demodPac() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;}
|
if (demodPac() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;}
|
||||||
|
|
|
@ -290,21 +290,21 @@ static int CmdAWIDDemod(const char *Cmd) {
|
||||||
fc = bytebits_to_byte(bits + 9, 8);
|
fc = bytebits_to_byte(bits + 9, 8);
|
||||||
cardnum = bytebits_to_byte(bits + 17, 16);
|
cardnum = bytebits_to_byte(bits + 17, 16);
|
||||||
code1 = bytebits_to_byte(bits + 8, fmtLen);
|
code1 = bytebits_to_byte(bits + 8, fmtLen);
|
||||||
PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " FC: " _GREEN_("%d") " Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||||
break;
|
break;
|
||||||
case 34:
|
case 34:
|
||||||
fc = bytebits_to_byte(bits + 9, 8);
|
fc = bytebits_to_byte(bits + 9, 8);
|
||||||
cardnum = bytebits_to_byte(bits + 17, 24);
|
cardnum = bytebits_to_byte(bits + 17, 24);
|
||||||
code1 = bytebits_to_byte(bits + 8, (fmtLen - 32));
|
code1 = bytebits_to_byte(bits + 8, (fmtLen - 32));
|
||||||
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
||||||
PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " FC: " _GREEN_("%d") " Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
||||||
break;
|
break;
|
||||||
case 37:
|
case 37:
|
||||||
fc = bytebits_to_byte(bits + 9, 13);
|
fc = bytebits_to_byte(bits + 9, 13);
|
||||||
cardnum = bytebits_to_byte(bits + 22, 18);
|
cardnum = bytebits_to_byte(bits + 22, 18);
|
||||||
code1 = bytebits_to_byte(bits + 8, (fmtLen - 32));
|
code1 = bytebits_to_byte(bits + 8, (fmtLen - 32));
|
||||||
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
||||||
PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d")" FC: " _GREEN_("%d")" Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
||||||
break;
|
break;
|
||||||
// case 40:
|
// case 40:
|
||||||
// break;
|
// break;
|
||||||
|
@ -313,18 +313,18 @@ static int CmdAWIDDemod(const char *Cmd) {
|
||||||
cardnum = bytebits_to_byte(bits + 25, 32);
|
cardnum = bytebits_to_byte(bits + 25, 32);
|
||||||
code1 = bytebits_to_byte(bits + 8, (fmtLen - 32));
|
code1 = bytebits_to_byte(bits + 8, (fmtLen - 32));
|
||||||
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
||||||
PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " FC: " _GREEN_("%d") " Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (fmtLen > 32) {
|
if (fmtLen > 32) {
|
||||||
cardnum = bytebits_to_byte(bits + 8 + (fmtLen - 17), 16);
|
cardnum = bytebits_to_byte(bits + 8 + (fmtLen - 17), 16);
|
||||||
code1 = bytebits_to_byte(bits + 8, fmtLen - 32);
|
code1 = bytebits_to_byte(bits + 8, fmtLen - 32);
|
||||||
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32);
|
||||||
PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " -unknown- (%u) - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
|
||||||
} else {
|
} else {
|
||||||
cardnum = bytebits_to_byte(bits + 8 + (fmtLen - 17), 16);
|
cardnum = bytebits_to_byte(bits + 8 + (fmtLen - 17), 16);
|
||||||
code1 = bytebits_to_byte(bits + 8, fmtLen);
|
code1 = bytebits_to_byte(bits + 8, fmtLen);
|
||||||
PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " -unknown- (%u) - Wiegand: " _GREEN_("%x") ", Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,41 +116,6 @@ static int usage_lf_em410x_brute(void) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////// 4050 / 4450 commands
|
|
||||||
static int usage_lf_em4x50_demod(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_demod [h]");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_demod");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_lf_em4x50_dump(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Dump EM4x50/EM4x69. Tag must be on antenna. ");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_dump [h] <pwd>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
|
||||||
PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_dump");
|
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_dump 11223344");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_lf_em4x50_read(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Read EM 4x50/EM4x69. Tag must be on antenna. ");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_read [h] <address> <pwd>");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
|
||||||
PrintAndLogEx(NORMAL, " address - memory address to read. (0-15)");
|
|
||||||
PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_read 1");
|
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_read 1 11223344");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////// 4205 / 4305 commands
|
//////////////// 4205 / 4305 commands
|
||||||
static int usage_lf_em4x05_dump(void) {
|
static int usage_lf_em4x05_dump(void) {
|
||||||
PrintAndLogEx(NORMAL, "Dump EM4x05/EM4x69. Tag must be on antenna. ");
|
PrintAndLogEx(NORMAL, "Dump EM4x05/EM4x69. Tag must be on antenna. ");
|
||||||
|
@ -659,8 +624,8 @@ static int CmdEM410xWrite(const char *Cmd) {
|
||||||
|
|
||||||
// Allowed clock rates: 16, 32, 40 and 64
|
// Allowed clock rates: 16, 32, 40 and 64
|
||||||
if ((clock1 != 16) && (clock1 != 32) && (clock1 != 64) && (clock1 != 40)) {
|
if ((clock1 != 16) && (clock1 != 32) && (clock1 != 64) && (clock1 != 40)) {
|
||||||
PrintAndLogEx(ERR, "error, clock rate" _RED_("%d")" not valid");
|
PrintAndLogEx(FAILED, "error, clock rate" _RED_("%d")" not valid", clock1);
|
||||||
PrintAndLogEx(INFO, "supported clock rates: " _YELLOW_("16, 32, 40, 60") "\n", clock1);
|
PrintAndLogEx(INFO, "supported clock rates: " _YELLOW_("16, 32, 40, 60") "\n");
|
||||||
usage_lf_em410x_write();
|
usage_lf_em410x_write();
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -723,329 +688,6 @@ static bool EM_ColParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t col
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// even parity ROW
|
|
||||||
static bool EM_RowParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) {
|
|
||||||
if (rows * cols > size) return false;
|
|
||||||
uint8_t rowP = 0;
|
|
||||||
|
|
||||||
for (uint8_t r = 0; r < rows - 1; r++) {
|
|
||||||
for (uint8_t c = 0; c < cols; c++) {
|
|
||||||
rowP ^= bs[(r * cols) + c];
|
|
||||||
}
|
|
||||||
if (rowP != pType) return false;
|
|
||||||
rowP = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EM word parity test.
|
|
||||||
// 9*5 = 45 bits in total
|
|
||||||
// 012345678|r0
|
|
||||||
// 012345678|r1
|
|
||||||
// 012345678|r2
|
|
||||||
// 012345678|r3
|
|
||||||
// ------------
|
|
||||||
//c012345678| 0
|
|
||||||
// |- must be zero
|
|
||||||
|
|
||||||
/*
|
|
||||||
static int EMwordparitytest(uint8_t *bits) {
|
|
||||||
|
|
||||||
// last row/col parity must be 0
|
|
||||||
if (bits[44] != 0) return PM3_ESOFT;
|
|
||||||
|
|
||||||
// col parity check
|
|
||||||
uint8_t c1 = bytebits_to_byte(bits, 8) ^ bytebits_to_byte(bits + 9, 8) ^ bytebits_to_byte(bits + 18, 8) ^ bytebits_to_byte(bits + 27, 8);
|
|
||||||
uint8_t c2 = bytebits_to_byte(bits + 36, 8);
|
|
||||||
if (c1 != c2) return PM3_ESOFT;
|
|
||||||
|
|
||||||
// row parity check
|
|
||||||
uint8_t rowP = 0;
|
|
||||||
for (uint8_t i = 0; i < 36; ++i) {
|
|
||||||
|
|
||||||
rowP ^= bits[i];
|
|
||||||
if (i > 0 && (i % 9) == 0) {
|
|
||||||
|
|
||||||
if (rowP != EVEN)
|
|
||||||
return PM3_ESOFT;
|
|
||||||
|
|
||||||
rowP = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// all checks ok.
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//////////////// 4050 / 4450 commands
|
|
||||||
|
|
||||||
static uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest) {
|
|
||||||
if (size < 45) return 0;
|
|
||||||
|
|
||||||
uint32_t code = bytebits_to_byte(BitStream, 8);
|
|
||||||
code = code << 8 | bytebits_to_byte(BitStream + 9, 8);
|
|
||||||
code = code << 8 | bytebits_to_byte(BitStream + 18, 8);
|
|
||||||
code = code << 8 | bytebits_to_byte(BitStream + 27, 8);
|
|
||||||
|
|
||||||
if (verbose || g_debugMode) {
|
|
||||||
for (uint8_t i = 0; i < 5; i++) {
|
|
||||||
if (i == 4) PrintAndLogEx(NORMAL, ""); //parity byte spacer
|
|
||||||
PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d -> 0x%02x",
|
|
||||||
BitStream[i * 9],
|
|
||||||
BitStream[i * 9 + 1],
|
|
||||||
BitStream[i * 9 + 2],
|
|
||||||
BitStream[i * 9 + 3],
|
|
||||||
BitStream[i * 9 + 4],
|
|
||||||
BitStream[i * 9 + 5],
|
|
||||||
BitStream[i * 9 + 6],
|
|
||||||
BitStream[i * 9 + 7],
|
|
||||||
BitStream[i * 9 + 8],
|
|
||||||
bytebits_to_byte(BitStream + i * 9, 8)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Parity checks | %s", (pTest) ? _GREEN_("Passed") : _RED_("Fail"));
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the transmitted data of an EM4x50 tag from the graphbuffer
|
|
||||||
* Format:
|
|
||||||
*
|
|
||||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
|
||||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
|
||||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
|
||||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
|
||||||
* CCCCCCC0 <- column parity bits
|
|
||||||
* 0 <- stop bit
|
|
||||||
* LW <- Listen Window
|
|
||||||
*
|
|
||||||
* This pattern repeats for every block of data being transmitted.
|
|
||||||
* Transmission starts with two Listen Windows (LW - a modulated
|
|
||||||
* pattern of 320 cycles each (32/32/128/64/64)).
|
|
||||||
*
|
|
||||||
* Note that this data may or may not be the UID. It is whatever data
|
|
||||||
* is stored in the blocks defined in the control word First and Last
|
|
||||||
* Word Read values. UID is stored in block 32.
|
|
||||||
*/
|
|
||||||
//completed by Marshmellow
|
|
||||||
int EM4x50Read(const char *Cmd, bool verbose) {
|
|
||||||
int clk = 0, invert = 0, tol = 0, phaseoff;
|
|
||||||
int i = 0, j = 0, startblock, skip, block, start, end, low = 0, high = 0;
|
|
||||||
uint32_t Code[6];
|
|
||||||
char tmp[6];
|
|
||||||
char tmp2[20];
|
|
||||||
bool complete = false;
|
|
||||||
|
|
||||||
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
|
|
||||||
memset(tmpbuff, 0, sizeof(tmpbuff));
|
|
||||||
|
|
||||||
// get user entry if any
|
|
||||||
sscanf(Cmd, "%i %i", &clk, &invert);
|
|
||||||
|
|
||||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
|
||||||
size_t size = getFromGraphBuf(bits);
|
|
||||||
|
|
||||||
if (size < 4000) {
|
|
||||||
if (verbose || g_debugMode) PrintAndLogEx(ERR, "Error: EM4x50 - Too little data in Graphbuffer");
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
computeSignalProperties(bits, size);
|
|
||||||
|
|
||||||
// get fuzzed HI / LOW limits in signal
|
|
||||||
getHiLo(&high, &low, 75, 75);
|
|
||||||
|
|
||||||
// get to first full low to prime loop and skip incomplete first pulse
|
|
||||||
size_t offset = 0;
|
|
||||||
getNextHigh(bits, size, high, &offset);
|
|
||||||
getNextLow(bits, size, low, &offset);
|
|
||||||
|
|
||||||
i = (int)offset;
|
|
||||||
skip = offset;
|
|
||||||
|
|
||||||
// set clock
|
|
||||||
if (clk == 0) {
|
|
||||||
DetectASKClock(bits, size, &clk, 0);
|
|
||||||
if (clk == 0) {
|
|
||||||
if (verbose || g_debugMode) PrintAndLogEx(ERR, "Error: EM4x50 - didn't find a clock");
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// tolerance
|
|
||||||
tol = clk / 8;
|
|
||||||
|
|
||||||
// populate tmpbuff buffer with pulse lengths
|
|
||||||
while (i < size) {
|
|
||||||
// measure from low to low
|
|
||||||
while ((i < size) && (bits[i] > low))
|
|
||||||
++i;
|
|
||||||
start = i;
|
|
||||||
|
|
||||||
while ((i < size) && (bits[i] < high))
|
|
||||||
++i;
|
|
||||||
|
|
||||||
while ((i < size) && (bits[i] > low))
|
|
||||||
++i;
|
|
||||||
|
|
||||||
if (j >= (MAX_GRAPH_TRACE_LEN / 64)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmpbuff[j++] = i - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2)
|
|
||||||
start = -1;
|
|
||||||
for (i = 0; i < j - 4 ; ++i) {
|
|
||||||
skip += tmpbuff[i];
|
|
||||||
if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks
|
|
||||||
if (tmpbuff[i + 1] >= clk * 2 - tol && tmpbuff[i + 1] <= clk * 2 + tol) //2 clocks
|
|
||||||
if (tmpbuff[i + 2] >= clk * 3 - tol && tmpbuff[i + 2] <= clk * 3 + tol) //3 clocks
|
|
||||||
if (tmpbuff[i + 3] >= clk - tol) { //1.5 to 2 clocks - depends on bit following
|
|
||||||
start = i + 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
startblock = i + 4;
|
|
||||||
|
|
||||||
// skip over the remainder of LW
|
|
||||||
skip += (tmpbuff[i + 1] + tmpbuff[i + 2] + clk);
|
|
||||||
|
|
||||||
if (tmpbuff[i + 3] > clk)
|
|
||||||
phaseoff = tmpbuff[i + 3] - clk;
|
|
||||||
else
|
|
||||||
phaseoff = 0;
|
|
||||||
|
|
||||||
// now do it again to find the end
|
|
||||||
for (i += 3; i < j - 4 ; ++i) {
|
|
||||||
if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks
|
|
||||||
if (tmpbuff[i + 1] >= clk * 2 - tol && tmpbuff[i + 1] <= clk * 2 + tol) //2 clocks
|
|
||||||
if (tmpbuff[i + 2] >= clk * 3 - tol && tmpbuff[i + 2] <= clk * 3 + tol) //3 clocks
|
|
||||||
if (tmpbuff[i + 3] >= clk - tol) { //1.5 to 2 clocks - depends on bit following
|
|
||||||
complete = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end = i;
|
|
||||||
|
|
||||||
// report back
|
|
||||||
if (verbose || g_debugMode) {
|
|
||||||
if (start >= 0) {
|
|
||||||
PrintAndLogEx(INFO, "\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)");
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(INFO, "No data found!, clock tried: " _YELLOW_("%d"), clk);
|
|
||||||
PrintAndLogEx(HINT, "Try again with more samples");
|
|
||||||
PrintAndLogEx(HINT, " or after a " _YELLOW_("'data askedge'") " command to clean up the read");
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
} else if (start < 0) {
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = skip;
|
|
||||||
|
|
||||||
snprintf(tmp2, sizeof(tmp2), "%d %d 1000 %d", clk, invert, clk * 47);
|
|
||||||
|
|
||||||
// save GraphBuffer - to restore it later
|
|
||||||
save_restoreGB(GRAPH_SAVE);
|
|
||||||
|
|
||||||
// get rid of leading crap
|
|
||||||
snprintf(tmp, sizeof(tmp), "%i", skip);
|
|
||||||
CmdLtrim(tmp);
|
|
||||||
|
|
||||||
bool AllPTest = true;
|
|
||||||
|
|
||||||
// now work through remaining buffer printing out data blocks
|
|
||||||
block = 0;
|
|
||||||
i = startblock;
|
|
||||||
while (block < 6) {
|
|
||||||
if (verbose || g_debugMode) PrintAndLogEx(NORMAL, "\nBlock %i:", block);
|
|
||||||
skip = phaseoff;
|
|
||||||
|
|
||||||
// look for LW before start of next block
|
|
||||||
for (; i < j - 4 ; ++i) {
|
|
||||||
skip += tmpbuff[i];
|
|
||||||
if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol)
|
|
||||||
if (tmpbuff[i + 1] >= clk - tol)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i >= j - 4) break; //next LW not found
|
|
||||||
skip += clk;
|
|
||||||
if (tmpbuff[i + 1] > clk)
|
|
||||||
phaseoff = tmpbuff[i + 1] - clk;
|
|
||||||
else
|
|
||||||
phaseoff = 0;
|
|
||||||
|
|
||||||
i += 2;
|
|
||||||
|
|
||||||
if (ASKDemod(tmp2, false, false, 1) != PM3_SUCCESS) {
|
|
||||||
save_restoreGB(GRAPH_RESTORE);
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//set DemodBufferLen to just one block
|
|
||||||
DemodBufferLen = skip / clk;
|
|
||||||
//test parities
|
|
||||||
bool pTest = EM_RowParityTest(DemodBuffer, DemodBufferLen, 5, 9, 0);
|
|
||||||
pTest &= EM_ColParityTest(DemodBuffer, DemodBufferLen, 5, 9, 0);
|
|
||||||
AllPTest &= pTest;
|
|
||||||
//get output
|
|
||||||
Code[block] = OutputEM4x50_Block(DemodBuffer, DemodBufferLen, verbose, pTest);
|
|
||||||
PrintAndLogEx(DEBUG, "\nskipping %d samples, bits:%d", skip, skip / clk);
|
|
||||||
//skip to start of next block
|
|
||||||
snprintf(tmp, sizeof(tmp), "%i", skip);
|
|
||||||
CmdLtrim(tmp);
|
|
||||||
block++;
|
|
||||||
if (i >= end) break; //in case chip doesn't output 6 blocks
|
|
||||||
}
|
|
||||||
|
|
||||||
//print full code:
|
|
||||||
if (verbose || g_debugMode || AllPTest) {
|
|
||||||
if (!complete) {
|
|
||||||
PrintAndLogEx(WARNING, _RED_("* **Warning!"));
|
|
||||||
PrintAndLogEx(INFO, "Partial data - no end found!");
|
|
||||||
PrintAndLogEx(HINT, "Try again with more samples.");
|
|
||||||
}
|
|
||||||
PrintAndLogEx(INFO, "Found data at sample: %i - using clock: %i", start, clk);
|
|
||||||
end = block;
|
|
||||||
PrintAndLogEx(INFO, "blk | data");
|
|
||||||
PrintAndLogEx(INFO, "----+--------------");
|
|
||||||
for (block = 0; block < end; block++) {
|
|
||||||
PrintAndLogEx(INFO, "%03d | %08x", block, Code[block]);
|
|
||||||
}
|
|
||||||
PrintAndLogEx(INFO, "----+--------------");
|
|
||||||
PrintAndLogEx((AllPTest) ? SUCCESS : WARNING, "Parities checks | %s", (AllPTest) ? _GREEN_("Passed") : _RED_("Fail"));
|
|
||||||
|
|
||||||
if (AllPTest == false) {
|
|
||||||
PrintAndLogEx(HINT, "Try cleaning the read samples with " _YELLOW_("'data askedge'"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//restore GraphBuffer
|
|
||||||
save_restoreGB(GRAPH_RESTORE);
|
|
||||||
return AllPTest ? PM3_SUCCESS : PM3_ESOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdEM4x50Demod(const char *Cmd) {
|
|
||||||
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (ctmp == 'h') return usage_lf_em4x50_demod();
|
|
||||||
return EM4x50Read(Cmd, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdEM4x50Read(const char *Cmd) {
|
|
||||||
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (ctmp == 'h') return usage_lf_em4x50_read();
|
|
||||||
lf_read(false, 24000);
|
|
||||||
return EM4x50Read(Cmd, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdEM4x50Dump(const char *Cmd) {
|
|
||||||
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
|
||||||
if (ctmp == 'h') return usage_lf_em4x50_dump();
|
|
||||||
PrintAndLogEx(NORMAL, "no implemented yet");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EM_PREAMBLE_LEN 6
|
#define EM_PREAMBLE_LEN 6
|
||||||
// download samples from device and copy to Graphbuffer
|
// download samples from device and copy to Graphbuffer
|
||||||
static bool downloadSamplesEM(void) {
|
static bool downloadSamplesEM(void) {
|
||||||
|
@ -1753,12 +1395,10 @@ static command_t CommandTable[] = {
|
||||||
{"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"},
|
{"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"},
|
||||||
{"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"},
|
{"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"},
|
||||||
{"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"},
|
{"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"},
|
||||||
{"4x50_demod", CmdEM4x50Demod, AlwaysAvailable, "demodulate a EM4x50 tag from the GraphBuffer"},
|
{"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "read complete data from EM4x50"},
|
||||||
{"4x50_dump", CmdEM4x50Dump, IfPm3Lf, "dump EM4x50 tag"},
|
{"4x50_write", CmdEM4x50Write, IfPm3EM4x50, "write word data to EM4x50"},
|
||||||
{"4x50_read", CmdEM4x50Read, IfPm3Lf, "read word data from EM4x50"},
|
{"4x50_write_password", CmdEM4x50WritePassword, IfPm3EM4x50, "change passwword of EM4x50 tag"},
|
||||||
{"4x50_info", CmdEM4x50Info, IfPm3Lf, "read complete data from EM4x50"},
|
{"4x50_read", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"},
|
||||||
{"4x50_write", CmdEM4x50Write, IfPm3Lf, "write word data to EM4x50"},
|
|
||||||
{"4x50_write_password", CmdEM4x50WritePassword, IfPm3Lf, "change passwword of EM4x50 tag"},
|
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
int CmdLFEM4X(const char *Cmd);
|
int CmdLFEM4X(const char *Cmd);
|
||||||
|
|
||||||
int demodEM410x(void);
|
int demodEM410x(void);
|
||||||
int EM4x50Read(const char *Cmd, bool verbose);
|
|
||||||
bool EM4x05IsBlock0(uint32_t *word);
|
bool EM4x05IsBlock0(uint32_t *word);
|
||||||
|
|
||||||
void printEM410x(uint32_t hi, uint64_t id);
|
void printEM410x(uint32_t hi, uint64_t id);
|
||||||
|
|
|
@ -15,33 +15,6 @@
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
#include "em4x50.h"
|
#include "em4x50.h"
|
||||||
|
|
||||||
#define EM4X50_NO_WORDS 34
|
|
||||||
|
|
||||||
// special words
|
|
||||||
#define EM4X50_DEVICE_PASSWORD 0
|
|
||||||
#define EM4X50_PROTECTION 1
|
|
||||||
#define EM4X50_CONTROL 2
|
|
||||||
#define EM4X50_DEVICE_SERIAL 32
|
|
||||||
#define EM4X50_DEVICE_ID 33
|
|
||||||
|
|
||||||
// control word (word = 4 bytes)
|
|
||||||
#define FIRST_WORD_READ 0 // first byte
|
|
||||||
#define LAST_WORD_READ 1 // second byte
|
|
||||||
#define CONFIG_BLOCK 2 // third byte
|
|
||||||
#define PASSWORD_CHECK 0x80 // first bit in third byte
|
|
||||||
#define READ_AFTER_WRITE 0x40 // second bit in third byte
|
|
||||||
|
|
||||||
// protection word
|
|
||||||
#define FIRST_WORD_READ_PROTECTED 0 // first byte
|
|
||||||
#define LAST_WORD_READ_PROTECTED 1 // second byte
|
|
||||||
#define FIRST_WORD_WRITE_INHIBITED 2 // third byte
|
|
||||||
#define LAST_WORD_WRITE_INHIBITED 3 // fourth byte
|
|
||||||
|
|
||||||
// misc
|
|
||||||
#define STATUS_SUCCESS 0x2
|
|
||||||
#define STATUS_LOGIN 0x1
|
|
||||||
#define NO_CHARS_MAX 400
|
|
||||||
|
|
||||||
int usage_lf_em4x50_info(void) {
|
int usage_lf_em4x50_info(void) {
|
||||||
PrintAndLogEx(NORMAL, "Read all information of EM4x50. Tag nust be on antenna.");
|
PrintAndLogEx(NORMAL, "Read all information of EM4x50. Tag nust be on antenna.");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
@ -51,34 +24,51 @@ int usage_lf_em4x50_info(void) {
|
||||||
PrintAndLogEx(NORMAL, " v - verbose output");
|
PrintAndLogEx(NORMAL, " v - verbose output");
|
||||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_info");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_info"));
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_info p fa225de1\n");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_info p fa225de1"));
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_info v p fa225de1\n");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_info v p fa225de1"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
int usage_lf_em4x50_write(void) {
|
int usage_lf_em4x50_write(void) {
|
||||||
PrintAndLogEx(NORMAL, "Write EM4x50 word. Tag must be on antenna. ");
|
PrintAndLogEx(NORMAL, "Write EM4x50 word. Tag must be on antenna. ");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_write [h] a <address> w <data>");
|
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_write [h] [a <address>] [w <data>]");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
PrintAndLogEx(NORMAL, " h - this help");
|
||||||
PrintAndLogEx(NORMAL, " a <addr> - memory address to write to (dec)");
|
PrintAndLogEx(NORMAL, " a <addr> - memory address to write to (dec)");
|
||||||
PrintAndLogEx(NORMAL, " w <word> - word to write (hex)");
|
PrintAndLogEx(NORMAL, " w <word> - word to write (hex)");
|
||||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
PrintAndLogEx(NORMAL, " p <pwd> - password (hex) (optional)");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_write a 3 w deadc0de");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_write a 3 w deadc0de"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
int usage_lf_em4x50_write_password(void) {
|
int usage_lf_em4x50_write_password(void) {
|
||||||
PrintAndLogEx(NORMAL, "Write EM4x50 password. Tag must be on antenna. ");
|
PrintAndLogEx(NORMAL, "Write EM4x50 password. Tag must be on antenna. ");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_write_password [h] p <pwd> n <pwd>");
|
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_write_password [h] [p <pwd>] [n <pwd>]");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
PrintAndLogEx(NORMAL, " h - this help");
|
||||||
PrintAndLogEx(NORMAL, " p <pwd> - password (hex)");
|
PrintAndLogEx(NORMAL, " p <pwd> - password (hex)");
|
||||||
PrintAndLogEx(NORMAL, " n <pwd> - new password (hex)");
|
PrintAndLogEx(NORMAL, " n <pwd> - new password (hex)");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf em 4x50_write_password p 11223344 n 01020304");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_write_password p 11223344 n 01020304"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
int usage_lf_em4x50_read(void) {
|
||||||
|
PrintAndLogEx(NORMAL, "Read EM4x50 word(s). Tag must be on antenna. ");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(NORMAL, "Usage: lf em 4x50_read [h] [a <address>] [p <pwd>]");
|
||||||
|
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, "Examples:");
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_read"));
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_read a 2 p 00000000"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,76 +125,10 @@ static void prepare_result(const uint8_t *byte, int fwr, int lwr, em4x50_word_t
|
||||||
|
|
||||||
if (words[i].stopbit == 1)
|
if (words[i].stopbit == 1)
|
||||||
words[i].stopparity = false;
|
words[i].stopparity = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_bit_table(const em4x50_word_t word) {
|
static void print_result(const em4x50_word_t *words, int fwr, int lwr, bool verbose) {
|
||||||
|
|
||||||
// generate output in table form for each word including parities, stop
|
|
||||||
// bit, result of parity checks and hex notation of each row in msb/lsb
|
|
||||||
// notation
|
|
||||||
// individual parity errors will be highlighted in red
|
|
||||||
|
|
||||||
int bit = 0;
|
|
||||||
char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0};
|
|
||||||
|
|
||||||
// print binary data
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
|
|
||||||
strcat(string, " ");
|
|
||||||
|
|
||||||
// lsb notation
|
|
||||||
for (int k = 0; k < 8; k++) {
|
|
||||||
sprintf(pstring, "%i", (word.byte[j] >> (7-k)) & 1);
|
|
||||||
strcat(string, pstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(string, " | ");
|
|
||||||
|
|
||||||
// binary row parities + hex bytes of word
|
|
||||||
sprintf(pstring, (word.rparity[j]) ? "%i" : _RED_("%i"), word.row_parity[j]);
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
if (j == 0)
|
|
||||||
sprintf(pstring, " msb: 0x%02x lsb: 0x%02x", word.byte[j], reflect8(word.byte[j]));
|
|
||||||
else
|
|
||||||
sprintf(pstring, " 0x%02x 0x%02x", word.byte[j], reflect8(word.byte[j]));
|
|
||||||
|
|
||||||
strcat(string, pstring);
|
|
||||||
PrintAndLogEx(NORMAL,string);
|
|
||||||
|
|
||||||
string[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(string, " ------------ --------------------\n ");
|
|
||||||
|
|
||||||
// binary column parities
|
|
||||||
for (int k = 0; k < 8; k++) {
|
|
||||||
|
|
||||||
bit = (word.col_parity >> (7-k)) & 1;
|
|
||||||
|
|
||||||
// if column parity is false -> highlight bit in red
|
|
||||||
sprintf(pstring, (word.cparity[k]) ? "%i" : _RED_("%i"), bit);
|
|
||||||
strcat(string, pstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
// binary stop bit
|
|
||||||
strcat(string, " | ");
|
|
||||||
sprintf(pstring, (word.stopparity) ? "%i" : _RED_("%i"), word.stopbit);
|
|
||||||
strcat(pstring, " parities ");
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
// parities passed/failed
|
|
||||||
sprintf(pstring, (word.parity) ? _GREEN_("ok") : _RED_("failed"));
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL,string);
|
|
||||||
|
|
||||||
string[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_result(const em4x50_word_t *words, int fwr, int lwr) {
|
|
||||||
|
|
||||||
// print available information for given word from fwr to lwr, i.e.
|
// print available information for given word from fwr to lwr, i.e.
|
||||||
// bit table + summary lines with hex notation of word (msb + lsb)
|
// bit table + summary lines with hex notation of word (msb + lsb)
|
||||||
|
@ -213,13 +137,10 @@ static void print_result(const em4x50_word_t *words, int fwr, int lwr) {
|
||||||
|
|
||||||
for (int i = fwr; i <= lwr; i++) {
|
for (int i = fwr; i <= lwr; i++) {
|
||||||
|
|
||||||
// blank line before each bit table
|
if (verbose) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
// print bit table
|
|
||||||
print_bit_table(words[i]);
|
|
||||||
|
|
||||||
// final result
|
// final result
|
||||||
|
string[0] = '\0';
|
||||||
sprintf(pstring, "\n word[%i] msb: " _GREEN_("0x"), i);
|
sprintf(pstring, "\n word[%i] msb: " _GREEN_("0x"), i);
|
||||||
strcat(string, pstring);
|
strcat(string, pstring);
|
||||||
|
|
||||||
|
@ -235,29 +156,29 @@ static void print_result(const em4x50_word_t *words, int fwr, int lwr) {
|
||||||
sprintf(pstring, "%02x", reflect8(words[i].byte[3-j]));
|
sprintf(pstring, "%02x", reflect8(words[i].byte[3-j]));
|
||||||
strcat(string, pstring);
|
strcat(string, pstring);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
PrintAndLogEx(NORMAL,string);
|
|
||||||
|
|
||||||
string[0] = '\0';
|
string[0] = '\0';
|
||||||
|
sprintf(pstring, "[" _GREEN_("+") "] word[%i]: " _YELLOW_("0x"), i);
|
||||||
|
strcat(string, pstring);
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
sprintf(pstring, _YELLOW_("%02x"), words[i].byte[j]);
|
||||||
|
strcat(string, pstring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintAndLogEx(INFO, string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_info_result(PacketResponseNG *resp, const em4x50_data_t *etd, bool bverbose) {
|
static void print_info_result(uint8_t *data, bool verbose) {
|
||||||
|
|
||||||
// display all information of info result in structured format
|
// display all information of info result in structured format
|
||||||
|
|
||||||
uint8_t *data = resp->data.asBytes;
|
|
||||||
em4x50_word_t words[EM4X50_NO_WORDS];
|
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||||
char pstring[NO_CHARS_MAX] = {0}, string[NO_CHARS_MAX] = {0};
|
|
||||||
|
|
||||||
bool bpwd_given = etd->pwd_given;
|
|
||||||
bool bsuccess = resp->status & STATUS_SUCCESS;
|
|
||||||
bool blogin = resp->status & STATUS_LOGIN;
|
|
||||||
|
|
||||||
prepare_result(data, 0, EM4X50_NO_WORDS - 1, words);
|
prepare_result(data, 0, EM4X50_NO_WORDS - 1, words);
|
||||||
|
|
||||||
bool bpwc = words[EM4X50_CONTROL].byte[CONFIG_BLOCK] & PASSWORD_CHECK;
|
bool bpwc = words[EM4X50_CONTROL].byte[CONFIG_BLOCK] & PASSWORD_CHECK;
|
||||||
bool braw = words[EM4X50_CONTROL].byte[CONFIG_BLOCK] & READ_AFTER_WRITE;
|
bool braw = words[EM4X50_CONTROL].byte[CONFIG_BLOCK] & READ_AFTER_WRITE;
|
||||||
|
|
||||||
int fwr = reflect8(words[EM4X50_CONTROL].byte[FIRST_WORD_READ]);
|
int fwr = reflect8(words[EM4X50_CONTROL].byte[FIRST_WORD_READ]);
|
||||||
int lwr = reflect8(words[EM4X50_CONTROL].byte[LAST_WORD_READ]);
|
int lwr = reflect8(words[EM4X50_CONTROL].byte[LAST_WORD_READ]);
|
||||||
int fwrp = reflect8(words[EM4X50_PROTECTION].byte[FIRST_WORD_READ_PROTECTED]);
|
int fwrp = reflect8(words[EM4X50_PROTECTION].byte[FIRST_WORD_READ_PROTECTED]);
|
||||||
|
@ -265,136 +186,91 @@ static void print_info_result(PacketResponseNG *resp, const em4x50_data_t *etd,
|
||||||
int fwwi = reflect8(words[EM4X50_PROTECTION].byte[FIRST_WORD_WRITE_INHIBITED]);
|
int fwwi = reflect8(words[EM4X50_PROTECTION].byte[FIRST_WORD_WRITE_INHIBITED]);
|
||||||
int lwwi = reflect8(words[EM4X50_PROTECTION].byte[LAST_WORD_WRITE_INHIBITED]);
|
int lwwi = reflect8(words[EM4X50_PROTECTION].byte[LAST_WORD_WRITE_INHIBITED]);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
||||||
|
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||||
|
|
||||||
// data section
|
// data section
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_("\n em4x50 data:"));
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, _YELLOW_("EM4x50 data:"));
|
||||||
if (bverbose) {
|
|
||||||
|
|
||||||
// detailed data section
|
|
||||||
print_result(words, 0, EM4X50_NO_WORDS - 1);
|
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
print_result(words, 0, EM4X50_NO_WORDS - 1, true);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "idx | word | desc");
|
||||||
|
PrintAndLogEx(INFO, "----+-------------+----------------------------------");
|
||||||
|
|
||||||
// condensed data section
|
// condensed data section
|
||||||
for (int i = 0; i < EM4X50_NO_WORDS; i++) {
|
for (int i = 0; i < EM4X50_NO_WORDS; i++) {
|
||||||
|
char s[50] = {0};
|
||||||
sprintf(pstring, " word[%2i]: ", i);
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
sprintf(pstring, "%02x", words[i].byte[j]);
|
|
||||||
strcat(string, pstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case EM4X50_DEVICE_PASSWORD:
|
case EM4X50_DEVICE_PASSWORD:
|
||||||
sprintf(pstring, _YELLOW_(" password, write only"));
|
sprintf(s, _YELLOW_("password, write only"));
|
||||||
break;
|
break;
|
||||||
case EM4X50_PROTECTION:
|
case EM4X50_PROTECTION:
|
||||||
sprintf(pstring, _YELLOW_(" protection word, write inhibited"));
|
sprintf(s, _YELLOW_("protection cfg (locked)"));
|
||||||
break;
|
break;
|
||||||
case EM4X50_CONTROL:
|
case EM4X50_CONTROL:
|
||||||
sprintf(pstring, _YELLOW_(" control word, write inhibited"));
|
sprintf(s, _YELLOW_("control cfg (locked)"));
|
||||||
break;
|
break;
|
||||||
case EM4X50_DEVICE_SERIAL:
|
case EM4X50_DEVICE_SERIAL:
|
||||||
sprintf(pstring, _YELLOW_(" device serial number, read only"));
|
sprintf(s, _YELLOW_("device serial number (read only)"));
|
||||||
break;
|
break;
|
||||||
case EM4X50_DEVICE_ID:
|
case EM4X50_DEVICE_ID:
|
||||||
sprintf(pstring, _YELLOW_(" device identification, read only"));
|
sprintf(s, _YELLOW_("device identification (read only)"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(pstring, " user data");
|
sprintf(s, "user data");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(INFO, " %2i | %s| %s", i, sprint_hex(words[i].byte, 4), s);
|
||||||
strcat(string, pstring);
|
|
||||||
PrintAndLogEx(NORMAL,"%s", string);
|
|
||||||
string[0] = '\0';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(INFO, "----+-------------+----------------------------------");
|
||||||
|
|
||||||
// configuration section
|
// configuration section
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_("\n em4x50 configuration"));
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL," control: | protection:");
|
PrintAndLogEx(INFO, "---- " _CYAN_("Configuration") " ----");
|
||||||
|
|
||||||
sprintf(pstring, " first word read: %3i |", fwr);
|
|
||||||
strcat(string, pstring);
|
|
||||||
sprintf(pstring, " first word read protected: %3i", fwrp);
|
|
||||||
strcat(string, pstring);
|
|
||||||
PrintAndLogEx(NORMAL,"%s", string);
|
|
||||||
string[0] = '\0';
|
|
||||||
|
|
||||||
sprintf(pstring, " last word read: %3i |", lwr);
|
|
||||||
strcat(string, pstring);
|
|
||||||
sprintf(pstring, " last word read protected: %3i", lwrp);
|
|
||||||
strcat(string, pstring);
|
|
||||||
PrintAndLogEx(NORMAL,"%s", string);
|
|
||||||
string[0] = '\0';
|
|
||||||
|
|
||||||
sprintf(pstring, " password check: %3s |", (bpwc) ? "on" : "off");
|
|
||||||
strcat(string, pstring);
|
|
||||||
sprintf(pstring, " first word write inhibited: %3i", fwwi);
|
|
||||||
strcat(string, pstring);
|
|
||||||
PrintAndLogEx(NORMAL,"%s", string);
|
|
||||||
string[0] = '\0';
|
|
||||||
|
|
||||||
sprintf(pstring, " read after write: %3s |", (braw) ? "on" : "off");
|
|
||||||
strcat(string, pstring);
|
|
||||||
sprintf(pstring, " last word write inhibited: %3i", lwwi);
|
|
||||||
strcat(string, pstring);
|
|
||||||
PrintAndLogEx(NORMAL,"%s", string);
|
|
||||||
string[0] = '\0';
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "\n zero values may indicate read protection!");
|
|
||||||
|
|
||||||
// status line
|
|
||||||
sprintf(pstring, " reading ");
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
if (!bsuccess) {
|
|
||||||
|
|
||||||
sprintf(pstring, _RED_("failed"));
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
sprintf(pstring, _GREEN_("ok "));
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
if (blogin) {
|
|
||||||
|
|
||||||
if (bpwd_given) {
|
|
||||||
|
|
||||||
sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)",
|
|
||||||
etd->password[0], etd->password[1],
|
|
||||||
etd->password[2], etd->password[3]);
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
sprintf(pstring, "(login with default password 0x00000000)");
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "first word read %3i", fwr);
|
||||||
|
PrintAndLogEx(INFO, "last word read %3i", lwr);
|
||||||
|
PrintAndLogEx(INFO, "password check %3s", (bpwc) ? _RED_("on"): _GREEN_("off"));
|
||||||
|
PrintAndLogEx(INFO, "read after write %3s", (braw) ? "on" : "off");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--------- " _CYAN_("Protection") " ---------");
|
||||||
|
PrintAndLogEx(INFO, "first word read protected %3i", fwrp);
|
||||||
|
PrintAndLogEx(INFO, "last word read protected %3i", lwrp);
|
||||||
|
PrintAndLogEx(INFO, "first word write inhibited %3i", fwwi);
|
||||||
|
PrintAndLogEx(INFO, "last word write inhibited %3i", lwwi);
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "zero values may indicate read protection");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
//quick test for EM4x50 tag
|
||||||
|
bool detect_4x50_block(void) {
|
||||||
if (bpwd_given) {
|
em4x50_data_t etd = {
|
||||||
|
.pwd_given = false,
|
||||||
sprintf(pstring, "(login failed)");
|
.addr_given = true,
|
||||||
strcat(string, pstring);
|
.address = EM4X50_DEVICE_ID,
|
||||||
|
};
|
||||||
} else {
|
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||||
|
return (em4x50_read(&etd, words, false) == PM3_SUCCESS);
|
||||||
sprintf(pstring, "(no login)");
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
int read_em4x50_uid(void) {
|
||||||
|
em4x50_data_t etd = {
|
||||||
PrintAndLogEx(NORMAL,"%s\n", string);
|
.pwd_given = false,
|
||||||
|
.addr_given = true,
|
||||||
|
.address = EM4X50_DEVICE_SERIAL,
|
||||||
|
};
|
||||||
|
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||||
|
int res = em4x50_read(&etd, words, false);
|
||||||
|
if (res == PM3_SUCCESS)
|
||||||
|
PrintAndLogEx(INFO, " Serial: " _GREEN_("%s"), sprint_hex(words[EM4X50_DEVICE_SERIAL].byte, 4));
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdEM4x50Info(const char *Cmd) {
|
int CmdEM4x50Info(const char *Cmd) {
|
||||||
|
@ -402,12 +278,9 @@ int CmdEM4x50Info(const char *Cmd) {
|
||||||
// envoke reading of a EM4x50 tag which has to be on the antenna because
|
// envoke reading of a EM4x50 tag which has to be on the antenna because
|
||||||
// decoding is done by the device (not on client side)
|
// decoding is done by the device (not on client side)
|
||||||
|
|
||||||
bool errors = false, verbose = false, success = false;
|
bool errors = false, verbose = false;
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
em4x50_data_t etd;
|
em4x50_data_t etd;
|
||||||
PacketResponseNG resp;
|
|
||||||
|
|
||||||
// init
|
|
||||||
etd.pwd_given = false;
|
etd.pwd_given = false;
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
|
@ -441,88 +314,40 @@ int CmdEM4x50Info(const char *Cmd) {
|
||||||
if (errors)
|
if (errors)
|
||||||
return usage_lf_em4x50_info();
|
return usage_lf_em4x50_info();
|
||||||
|
|
||||||
// call info command
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_EM4X50_INFO, (uint8_t *)&etd, sizeof(etd));
|
SendCommandNG(CMD_LF_EM4X50_INFO, (uint8_t *)&etd, sizeof(etd));
|
||||||
|
|
||||||
|
PacketResponseNG resp;
|
||||||
// get result
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||||
if (!WaitForResponse(CMD_ACK, &resp)) {
|
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print result
|
bool success = (resp.status & STATUS_SUCCESS) >> 1;
|
||||||
print_info_result(&resp, &etd, verbose);
|
if (success) {
|
||||||
|
print_info_result(resp.data.asBytes, verbose);
|
||||||
success = resp.status & STATUS_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
return (success) ? PM3_SUCCESS : PM3_ESOFT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_write_result(PacketResponseNG *resp, const em4x50_data_t *etd) {
|
PrintAndLogEx(FAILED, "reading tag " _RED_("failed"));
|
||||||
|
return PM3_ESOFT;
|
||||||
// display result of writing operation in structured format
|
|
||||||
|
|
||||||
bool pwd_given = etd->pwd_given;
|
|
||||||
bool success = resp->status & STATUS_SUCCESS;
|
|
||||||
bool login = resp->status & STATUS_LOGIN;
|
|
||||||
uint8_t *data = resp->data.asBytes;
|
|
||||||
char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0};
|
|
||||||
em4x50_word_t word;
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
|
|
||||||
sprintf(pstring, "\n writing " _RED_("failed"));
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
prepare_result(data, etd->address, etd->address, &word);
|
|
||||||
print_result(&word, etd->address, etd->address);
|
|
||||||
|
|
||||||
sprintf(pstring, "\n writing " _GREEN_("ok "));
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
if (pwd_given) {
|
|
||||||
|
|
||||||
if (login) {
|
|
||||||
sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)",
|
|
||||||
etd->password[0], etd->password[1],
|
|
||||||
etd->password[2], etd->password[3]);
|
|
||||||
strcat(string, pstring);
|
|
||||||
} else {
|
|
||||||
sprintf(pstring, "(login failed)");
|
|
||||||
strcat(string, pstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
sprintf(pstring, "(no login)");
|
|
||||||
strcat(string, pstring);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL,"%s\n", string);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdEM4x50Write(const char *Cmd) {
|
int CmdEM4x50Write(const char *Cmd) {
|
||||||
|
|
||||||
// envoke writing a single word (32 bit) to a EM4x50 tag
|
// envoke writing a single word (32 bit) to a EM4x50 tag
|
||||||
|
|
||||||
bool errors = false, bword = false, baddr = false, success = false;
|
em4x50_data_t etd = { .pwd_given = false };
|
||||||
|
|
||||||
|
bool errors = false, bword = false, baddr = false;
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
em4x50_data_t etd;
|
|
||||||
PacketResponseNG resp;
|
|
||||||
|
|
||||||
// init
|
|
||||||
etd.pwd_given = false;
|
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
|
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||||
case 'h':
|
case 'h': {
|
||||||
return usage_lf_em4x50_write();
|
return usage_lf_em4x50_write();
|
||||||
|
}
|
||||||
case 'p':
|
case 'p': {
|
||||||
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) {
|
||||||
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
@ -530,8 +355,8 @@ int CmdEM4x50Write(const char *Cmd) {
|
||||||
etd.pwd_given = true;
|
etd.pwd_given = true;
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 'w':
|
case 'w': {
|
||||||
if (param_gethex(Cmd, cmdp + 1, etd.word, 8)) {
|
if (param_gethex(Cmd, cmdp + 1, etd.word, 8)) {
|
||||||
PrintAndLogEx(FAILED, "\n word has to be 8 hex symbols\n");
|
PrintAndLogEx(FAILED, "\n word has to be 8 hex symbols\n");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
@ -539,8 +364,8 @@ int CmdEM4x50Write(const char *Cmd) {
|
||||||
bword = true;
|
bword = true;
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 'a':
|
case 'a': {
|
||||||
param_getdec(Cmd, cmdp + 1, &etd.address);
|
param_getdec(Cmd, cmdp + 1, &etd.address);
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
|
@ -551,50 +376,60 @@ int CmdEM4x50Write(const char *Cmd) {
|
||||||
baddr = true;
|
baddr = true;
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default: {
|
||||||
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||||
errors = true;
|
errors = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (errors || !bword || !baddr)
|
if (errors || !bword || !baddr)
|
||||||
return usage_lf_em4x50_write();
|
return usage_lf_em4x50_write();
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_EM4X50_WRITE, (uint8_t *)&etd, sizeof(etd));
|
SendCommandNG(CMD_LF_EM4X50_WRITE, (uint8_t *)&etd, sizeof(etd));
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||||
if (!WaitForResponse(CMD_ACK, &resp)) {
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
PrintAndLogEx(WARNING, "\n timeout while waiting for reply.\n");
|
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get, prepare and print response
|
bool isOK = (resp.status & STATUS_SUCCESS) >> 1;
|
||||||
print_write_result(&resp, &etd);
|
if (isOK == false) {
|
||||||
|
PrintAndLogEx(FAILED, "writing " _RED_("failed"));
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
success = resp.status & STATUS_SUCCESS;
|
if (etd.pwd_given) {
|
||||||
return (success) ? PM3_SUCCESS : PM3_ESOFT;
|
bool login = resp.status & STATUS_LOGIN;
|
||||||
|
if (login == false) {
|
||||||
|
PrintAndLogEx(FAILED, "login failed");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%s"), sprint_hex_inrow(etd.password, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, true);
|
||||||
|
PrintAndLogEx(SUCCESS, "Successfully wrote to tag");
|
||||||
|
PrintAndLogEx(HINT, "Try `" _YELLOW_("lf em 4x50_read a %u") "` - to read your data", etd.address);
|
||||||
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_write_password_result(PacketResponseNG *resp, const em4x50_data_t *etd) {
|
static void print_write_password_result(PacketResponseNG *resp, const em4x50_data_t *etd) {
|
||||||
|
|
||||||
// display result of password changing operation
|
// display result of password changing operation
|
||||||
|
|
||||||
bool success = resp->status;
|
|
||||||
char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0};
|
char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0};
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
|
|
||||||
sprintf(pstring, "\n writing new password " _RED_("failed"));
|
|
||||||
strcat(string, pstring);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
sprintf(pstring, "\n writing new password " _GREEN_("ok"));
|
sprintf(pstring, "\n writing new password " _GREEN_("ok"));
|
||||||
strcat(string, pstring);
|
strcat(string, pstring);
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL,"%s\n", string);
|
PrintAndLogEx(NORMAL,"%s\n", string);
|
||||||
}
|
}
|
||||||
|
@ -603,7 +438,7 @@ int CmdEM4x50WritePassword(const char *Cmd) {
|
||||||
|
|
||||||
// envokes changing the password of EM4x50 tag
|
// envokes changing the password of EM4x50 tag
|
||||||
|
|
||||||
bool errors = false, bpwd = false, bnpwd = false;
|
bool errors = false, bpwd = false, bnpwd = false, success = false;
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
em4x50_data_t etd;
|
em4x50_data_t etd;
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -651,13 +486,124 @@ int CmdEM4x50WritePassword(const char *Cmd) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_EM4X50_WRITE_PASSWORD, (uint8_t *)&etd, sizeof(etd));
|
SendCommandNG(CMD_LF_EM4X50_WRITE_PASSWORD, (uint8_t *)&etd, sizeof(etd));
|
||||||
|
|
||||||
if (!WaitForResponse(CMD_ACK, &resp)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||||
PrintAndLogEx(WARNING, "\n timeout while waiting for reply.\n");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
success = (bool)resp.status;
|
||||||
|
|
||||||
|
// get, prepare and print response
|
||||||
|
if (success)
|
||||||
|
print_write_password_result(&resp, &etd);
|
||||||
|
else
|
||||||
|
PrintAndLogEx(NORMAL,"\nwriting password " _RED_("failed") "\n");
|
||||||
|
|
||||||
|
return (success) ? PM3_SUCCESS : PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
|
||||||
|
|
||||||
|
// envoke reading
|
||||||
|
// - without option -> standard read mode
|
||||||
|
// - with given address (option a) (and optional password if address is
|
||||||
|
// read protected) -> selective read mode
|
||||||
|
|
||||||
|
em4x50_data_t edata = { .pwd_given = false, .addr_given = false };
|
||||||
|
|
||||||
|
if (etd != NULL) {
|
||||||
|
edata = *etd;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_LF_EM4X50_READ, (uint8_t *)&edata, sizeof(edata));
|
||||||
|
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
|
||||||
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get, prepare and print response
|
bool isOK = (resp.status & STATUS_SUCCESS) >> 1;
|
||||||
print_write_password_result(&resp, &etd);
|
if (isOK == false) {
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLogEx(FAILED, "reading " _RED_("failed"));
|
||||||
|
|
||||||
return ((bool)resp.status) ? PM3_SUCCESS : PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edata.pwd_given) {
|
||||||
|
bool login = resp.status & STATUS_LOGIN;
|
||||||
|
if (login == false) {
|
||||||
|
PrintAndLogEx(FAILED, "login failed");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%s"), sprint_hex_inrow(etd->password, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *data = resp.data.asBytes;
|
||||||
|
em4x50_word_t words[EM4X50_NO_WORDS];
|
||||||
|
if (edata.addr_given) {
|
||||||
|
prepare_result(data, etd->address, etd->address, words);
|
||||||
|
} else {
|
||||||
|
int now = (resp.status & STATUS_NO_WORDS) >> 2;
|
||||||
|
prepare_result(data, 0, now - 1, words);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out != NULL) {
|
||||||
|
memcpy(out, &words, sizeof(em4x50_word_t) * EM4X50_NO_WORDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
print_result(words, etd->address, etd->address, true);
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdEM4x50Read(const char *Cmd) {
|
||||||
|
|
||||||
|
em4x50_data_t etd;
|
||||||
|
etd.pwd_given = false;
|
||||||
|
etd.addr_given = false;
|
||||||
|
|
||||||
|
bool errors = false;
|
||||||
|
uint8_t cmdp = 0;
|
||||||
|
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
|
|
||||||
|
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||||
|
case 'h': {
|
||||||
|
return usage_lf_em4x50_read();
|
||||||
|
}
|
||||||
|
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.pwd_given = true;
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'a': {
|
||||||
|
param_getdec(Cmd, cmdp + 1, &etd.address);
|
||||||
|
|
||||||
|
// validation
|
||||||
|
if (etd.address <= 0 || etd.address >= EM4X50_NO_WORDS) {
|
||||||
|
PrintAndLogEx(FAILED, "\n error, address has to be in range [1-33]\n");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
etd.addr_given = true;
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||||
|
errors = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors)
|
||||||
|
return usage_lf_em4x50_read();
|
||||||
|
|
||||||
|
return em4x50_read(&etd, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,21 @@
|
||||||
#ifndef CMDLFEM4X50_H__
|
#ifndef CMDLFEM4X50_H__
|
||||||
#define CMDLFEM4X50_H__
|
#define CMDLFEM4X50_H__
|
||||||
|
|
||||||
|
#include"common.h"
|
||||||
|
#include "em4x50.h"
|
||||||
|
|
||||||
int usage_lf_em4x50_info(void);
|
int usage_lf_em4x50_info(void);
|
||||||
int usage_lf_em4x50_write(void);
|
int usage_lf_em4x50_write(void);
|
||||||
int usage_lf_em4x50_write_password(void);
|
int usage_lf_em4x50_write_password(void);
|
||||||
|
int usage_lf_em4x50_read(void);
|
||||||
|
|
||||||
|
int read_em4x50_uid(void);
|
||||||
|
bool detect_4x50_block(void);
|
||||||
|
int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose);
|
||||||
|
|
||||||
int CmdEM4x50Info(const char *Cmd);
|
int CmdEM4x50Info(const char *Cmd);
|
||||||
int CmdEM4x50Write(const char *Cmd);
|
int CmdEM4x50Write(const char *Cmd);
|
||||||
int CmdEM4x50WritePassword(const char *Cmd);
|
int CmdEM4x50WritePassword(const char *Cmd);
|
||||||
|
int CmdEM4x50Read(const char *Cmd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,8 +61,8 @@ static int usage_lf_fdx_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : Specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : Specify write to Q5 (t5555 instead of t55x7)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf fdx clone 999 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone 999 112233"));
|
||||||
PrintAndLogEx(NORMAL, " lf fdx clone 999 112233 16a");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx clone 999 112233 16a"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +78,8 @@ static int usage_lf_fdx_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <extended> : Extended data");
|
PrintAndLogEx(NORMAL, " <extended> : Extended data");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf fdx sim 999 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim 999 112233"));
|
||||||
PrintAndLogEx(NORMAL, " lf fdx sim 999 112233 16a");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf fdx sim 999 112233 16a"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ int demodFDX(void) {
|
||||||
uint8_t raw[8];
|
uint8_t raw[8];
|
||||||
num_to_bytes(rawid, 8, raw);
|
num_to_bytes(rawid, 8, raw);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "\nFDX-B / ISO 11784/5 Animal Tag ID Found: Raw : %s", sprint_hex(raw, 8));
|
PrintAndLogEx(SUCCESS, "FDX-B / ISO 11784/5 Animal");
|
||||||
PrintAndLogEx(SUCCESS, "Animal ID " _GREEN_("%04u-%012"PRIu64), countryCode, NationalCode);
|
PrintAndLogEx(SUCCESS, "Animal ID " _GREEN_("%04u-%012"PRIu64), countryCode, NationalCode);
|
||||||
PrintAndLogEx(SUCCESS, "National Code " _GREEN_("%012" PRIu64) " (0x%" PRIx64 ")", NationalCode, NationalCode);
|
PrintAndLogEx(SUCCESS, "National Code " _GREEN_("%012" PRIu64) " (0x%" PRIx64 ")", NationalCode, NationalCode);
|
||||||
PrintAndLogEx(SUCCESS, "Country Code %04u", countryCode);
|
PrintAndLogEx(SUCCESS, "Country Code %04u", countryCode);
|
||||||
|
@ -259,6 +259,8 @@ int demodFDX(void) {
|
||||||
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
|
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
|
||||||
PrintAndLogEx(SUCCESS, "CRC-16 0x%04X (%s) ", crc, (crc == (c[1] << 8 | c[0])) ? _GREEN_("ok") : _RED_("fail"));
|
PrintAndLogEx(SUCCESS, "CRC-16 0x%04X (%s) ", crc, (crc == (c[1] << 8 | c[0])) ? _GREEN_("ok") : _RED_("fail"));
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Raw " _GREEN_("%s"), sprint_hex(raw, 8));
|
||||||
|
|
||||||
if (g_debugMode) {
|
if (g_debugMode) {
|
||||||
PrintAndLogEx(DEBUG, "Start marker %d; Size %zu", preambleIndex, size);
|
PrintAndLogEx(DEBUG, "Start marker %d; Size %zu", preambleIndex, size);
|
||||||
char *bin = sprint_bin_break(DemodBuffer, size, 16);
|
char *bin = sprint_bin_break(DemodBuffer, size, 16);
|
||||||
|
|
|
@ -36,7 +36,7 @@ static int usage_lf_gallagher_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
|
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf gallagher clone b 0FFD5461A9DA1346B2D1AC32 ");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf gallagher clone b 0FFD5461A9DA1346B2D1AC32"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +127,10 @@ static int CmdGallagherDemod(const char *Cmd) {
|
||||||
// 4bit issue level
|
// 4bit issue level
|
||||||
uint8_t il = arr[7] & 0x0F;
|
uint8_t il = arr[7] & 0x0F;
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "GALLAGHER Tag Found -- Region: %u FC: %u CN: %u Issue Level: %u", rc, fc, cn, il);
|
PrintAndLogEx(SUCCESS, "GALLAGHER - Region: " _GREEN_("%u") " FC: " _GREEN_("%u") " CN: " _GREEN_("%u") " Issue Level: " _GREEN_("%u"), rc, fc, cn, il);
|
||||||
PrintAndLogEx(SUCCESS, " Printed: %C%u", rc + 0x40, fc);
|
PrintAndLogEx(SUCCESS, " Printed: " _GREEN_("%C%u"), rc + 0x40, fc);
|
||||||
PrintAndLogEx(SUCCESS, " Raw: %08X%08X%08X", raw1, raw2, raw3);
|
PrintAndLogEx(SUCCESS, " Raw: %08X%08X%08X", raw1, raw2, raw3);
|
||||||
PrintAndLogEx(SUCCESS, " CRC: %02X - %02X (%s)", crc, calc_crc, (crc == calc_crc) ? "OK" : "Failed");
|
PrintAndLogEx(SUCCESS, " CRC: %02X - %02X (%s)", crc, calc_crc, (crc == calc_crc) ? "ok" : "fail");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ static int usage_lf_guard_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf gprox clone 26 123 11223");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf gprox clone 26 123 11223"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ static int usage_lf_guard_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf gprox sim 26 123 11223");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf gprox sim 26 123 11223"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ static int CmdGuardDemod(const char *Cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!unknown)
|
if (!unknown)
|
||||||
PrintAndLogEx(SUCCESS, "G-Prox-II Found: Format Len: %ubit - FC: %u - Card: %u, Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3);
|
PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(SUCCESS, "Unknown G-Prox-II Fmt Found: Format Len: %u, Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3);
|
PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3);
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ static int usage_lf_hid_watch(void) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid watch"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid watch"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_lf_hid_sim(void) {
|
static int usage_lf_hid_sim(void) {
|
||||||
|
@ -63,6 +64,7 @@ static int usage_lf_hid_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " ID - HID id");
|
PrintAndLogEx(NORMAL, " ID - HID id");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid sim 2006ec0c86"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid sim 2006ec0c86"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_lf_hid_clone(void) {
|
static int usage_lf_hid_clone(void) {
|
||||||
|
@ -76,6 +78,7 @@ static int usage_lf_hid_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone 2006ec0c86"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone 2006ec0c86"));
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone l 2006ec0c86"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone l 2006ec0c86"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_lf_hid_brute(void) {
|
static int usage_lf_hid_brute(void) {
|
||||||
|
@ -100,6 +103,7 @@ static int usage_lf_hid_brute(void) {
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 224"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 224"));
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 21 d 2000"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute w H10301 f 21 d 2000"));
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute v w H10301 f 21 c 200 d 2000"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid brute v w H10301 f 21 c 200 d 2000"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +199,7 @@ static int CmdHIDDemod(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hi2 != 0) { //extra large HID tags
|
if (hi2 != 0) { //extra large HID tags
|
||||||
PrintAndLogEx(SUCCESS, "HID Prox TAG ID: " _GREEN_("%x%08x%08x (%u)"), hi2, hi, lo, (lo >> 1) & 0xFFFF);
|
PrintAndLogEx(SUCCESS, "HID Prox - " _GREEN_("%x%08x%08x (%u)"), hi2, hi, lo, (lo >> 1) & 0xFFFF);
|
||||||
} else { //standard HID tags <38 bits
|
} else { //standard HID tags <38 bits
|
||||||
uint8_t fmtLen = 0;
|
uint8_t fmtLen = 0;
|
||||||
uint32_t cc = 0;
|
uint32_t cc = 0;
|
||||||
|
@ -241,9 +245,11 @@ static int CmdHIDDemod(const char *Cmd) {
|
||||||
fc = ((hi & 0xF) << 12) | (lo >> 20);
|
fc = ((hi & 0xF) << 12) | (lo >> 20);
|
||||||
}
|
}
|
||||||
if (fmtLen == 32 && (lo & 0x40000000)) { //if 32 bit and Kastle bit set
|
if (fmtLen == 32 && (lo & 0x40000000)) { //if 32 bit and Kastle bit set
|
||||||
PrintAndLogEx(SUCCESS, "HID Prox TAG (Kastle format) ID: " _GREEN_("%x%08x (%u)")" - Format Len: 32bit - CC: %u - FC: %u - Card: %u", hi, lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum);
|
PrintAndLogEx(SUCCESS,
|
||||||
|
"HID Prox (Kastle format) - " _GREEN_("%x%08x (%u)") " - len: " _GREEN_("32") " bit CC: " _GREEN_("%u") " FC: " _GREEN_("%u") " Card: " _GREEN_("%u"), hi, lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, "HID Prox TAG ID: " _GREEN_("%x%08x (%u)")" - Format Len: " _GREEN_("%u bit")" - OEM: %03u - FC: " _GREEN_("%u")" - Card: " _GREEN_("%u"),
|
PrintAndLogEx(SUCCESS,
|
||||||
|
"HID Prox - " _GREEN_("%x%08x (%u)") " - len: " _GREEN_("%u") " bit - OEM: " _GREEN_("%03u") " FC: " _GREEN_("%u")" Card: " _GREEN_("%u"),
|
||||||
hi, lo, cardnum, fmtLen, oem, fc, cardnum);
|
hi, lo, cardnum, fmtLen, oem, fc, cardnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -572,6 +572,7 @@ static int CmdLFHitagReader(const char *Cmd) {
|
||||||
// No additional parameters needed
|
// No additional parameters needed
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
case RHT1F_PLAIN:
|
case RHT1F_PLAIN:
|
||||||
case RHT1F_AUTHENTICATE:
|
case RHT1F_AUTHENTICATE:
|
||||||
case WHTSF_CHALLENGE:
|
case WHTSF_CHALLENGE:
|
||||||
|
@ -680,6 +681,7 @@ static int CmdLFHitagWriter(const char *Cmd) {
|
||||||
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data);
|
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
case RHT1F_PLAIN:
|
case RHT1F_PLAIN:
|
||||||
case RHT1F_AUTHENTICATE:
|
case RHT1F_AUTHENTICATE:
|
||||||
case RHTSF_CHALLENGE:
|
case RHTSF_CHALLENGE:
|
||||||
|
|
|
@ -50,10 +50,11 @@ static int usage_lf_indala_demod(void) {
|
||||||
PrintAndLogEx(NORMAL, " maxerror : Set maximum allowed errors, default = 100.");
|
PrintAndLogEx(NORMAL, " maxerror : Set maximum allowed errors, default = 100.");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf indala demod");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod"));
|
||||||
PrintAndLogEx(NORMAL, " lf indala demod 32 = demod a Indala tag from GraphBuffer using a clock of RF/32");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod 32") " = demod a Indala tag from GraphBuffer using a clock of RF/32");
|
||||||
PrintAndLogEx(NORMAL, " lf indala demod 32 1 = demod a Indala tag from GraphBuffer using a clock of RF/32 and inverting data");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod 32 1") " = demod a Indala tag from GraphBuffer using a clock of RF/32 and inverting data");
|
||||||
PrintAndLogEx(NORMAL, " lf indala demod 64 1 0 = demod a Indala tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod 64 1 0") " = demod a Indala tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +69,8 @@ static int usage_lf_indala_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " c <cardnum> : Cardnumber for Heden 2L format (decimal)");
|
PrintAndLogEx(NORMAL, " c <cardnum> : Cardnumber for Heden 2L format (decimal)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf indala sim deadc0de");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala sim deadc0de"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +145,7 @@ static void decodeHeden2L(uint8_t *bits) {
|
||||||
if (bits[offset + 7]) cardnumber += 16384;
|
if (bits[offset + 7]) cardnumber += 16384;
|
||||||
if (bits[offset + 23]) cardnumber += 32768;
|
if (bits[offset + 23]) cardnumber += 32768;
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "\tHeden-2L | " _YELLOW_("%u"), cardnumber);
|
PrintAndLogEx(SUCCESS, "\tHeden-2L | " _GREEN_("%u"), cardnumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indala 26 bit decode
|
// Indala 26 bit decode
|
||||||
|
@ -193,13 +195,7 @@ static int CmdIndalaDemod(const char *Cmd) {
|
||||||
uint64_t foo = uid2 & 0x7FFFFFFF;
|
uint64_t foo = uid2 & 0x7FFFFFFF;
|
||||||
|
|
||||||
if (DemodBufferLen == 64) {
|
if (DemodBufferLen == 64) {
|
||||||
PrintAndLogEx(
|
PrintAndLogEx(SUCCESS, "Indala - len %zu, Raw: %x%08x", DemodBufferLen, uid1, uid2);
|
||||||
SUCCESS
|
|
||||||
, "Indala Found - bitlength %zu, Raw " _YELLOW_("%x%08x")
|
|
||||||
, DemodBufferLen
|
|
||||||
, uid1
|
|
||||||
, uid2
|
|
||||||
);
|
|
||||||
|
|
||||||
uint16_t p1 = 0;
|
uint16_t p1 = 0;
|
||||||
p1 |= DemodBuffer[32 + 3] << 8;
|
p1 |= DemodBuffer[32 + 3] << 8;
|
||||||
|
@ -246,8 +242,7 @@ static int CmdIndalaDemod(const char *Cmd) {
|
||||||
checksum |= DemodBuffer[62] << 1; // b2
|
checksum |= DemodBuffer[62] << 1; // b2
|
||||||
checksum |= DemodBuffer[63] << 0; // b1
|
checksum |= DemodBuffer[63] << 0; // b1
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(SUCCESS, "Fmt " _GREEN_("26") " FC: " _GREEN_("%u") " Card: " _GREEN_("%u") " checksum: " _GREEN_("%1d%1d")
|
||||||
PrintAndLogEx(SUCCESS, "Fmt 26 bit FC " _YELLOW_("%u") ", CN " _YELLOW_("%u") ", checksum " _YELLOW_("%1d%1d")
|
|
||||||
, fc
|
, fc
|
||||||
, csn
|
, csn
|
||||||
, checksum >> 1 & 0x01
|
, checksum >> 1 & 0x01
|
||||||
|
@ -267,7 +262,7 @@ static int CmdIndalaDemod(const char *Cmd) {
|
||||||
uint32_t uid7 = bytebits_to_byte(DemodBuffer + 192, 32);
|
uint32_t uid7 = bytebits_to_byte(DemodBuffer + 192, 32);
|
||||||
PrintAndLogEx(
|
PrintAndLogEx(
|
||||||
SUCCESS
|
SUCCESS
|
||||||
, "Indala Found - bitlength %zu, Raw 0x%x%08x%08x%08x%08x%08x%08x"
|
, "Indala - len %zu, Raw: %x%08x%08x%08x%08x%08x%08x"
|
||||||
, DemodBufferLen
|
, DemodBufferLen
|
||||||
, uid1
|
, uid1
|
||||||
, uid2
|
, uid2
|
||||||
|
@ -564,10 +559,10 @@ static int CmdIndalaClone(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "lf indala clone",
|
CLIParserInit(&ctx, "lf indala clone",
|
||||||
"clone INDALA tag to T55x7 (or to q5/T5555)",
|
"clone INDALA tag to T55x7 (or to q5/T5555)",
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
"\tlf indala clone --heden 888\n"
|
_YELLOW_("\tlf indala clone --heden 888\n")
|
||||||
"\tlf indala clone --fc 123 --cn 1337\n"
|
_YELLOW_("\tlf indala clone --fc 123 --cn 1337\n")
|
||||||
"\tlf indala clone -r a0000000a0002021\n"
|
_YELLOW_("\tlf indala clone -r a0000000a0002021\n")
|
||||||
"\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
|
_YELLOW_("\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"));
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
|
|
@ -37,6 +37,7 @@ static int usage_lf_io_watch(void) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf io watch"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf io watch"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +48,13 @@ static int usage_lf_io_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf io sim [h] <version> <facility-code> <card-number>");
|
PrintAndLogEx(NORMAL, "Usage: lf io sim [h] <version> <facility-code> <card-number>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <version> : 8bit version (decimal)");
|
PrintAndLogEx(NORMAL, " <version> : 8bit version (" _YELLOW_("decimal") ")");
|
||||||
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (hex)");
|
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (" _YELLOW_("hex") ")");
|
||||||
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (decimal)");
|
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (" _YELLOW_("decimal") ")");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf io sim 26 101 1337"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf io sim 01 101 1337"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,13 +65,14 @@ static int usage_lf_io_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf io clone [h] <version> <facility-code> <card-number> [Q5]");
|
PrintAndLogEx(NORMAL, "Usage: lf io clone [h] <version> <facility-code> <card-number> [Q5]");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <version> : 8bit version (decimal)");
|
PrintAndLogEx(NORMAL, " <version> : 8bit version (" _YELLOW_("decimal") ")");
|
||||||
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (hex)");
|
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (" _YELLOW_("hex") ")");
|
||||||
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (decimal)");
|
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (" _YELLOW_("decimal") ")");
|
||||||
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf io clone 26 101 1337"));
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf io clone 01 101 1337"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,22 +169,21 @@ static int CmdIOProxDemod(const char *Cmd) {
|
||||||
calccrc &= 0xff;
|
calccrc &= 0xff;
|
||||||
calccrc = 0xff - calccrc;
|
calccrc = 0xff - calccrc;
|
||||||
|
|
||||||
char crcStr[30];
|
char crc_str[36] = {0};
|
||||||
memset(crcStr, 0x00, sizeof(crcStr));
|
|
||||||
|
|
||||||
if (crc == calccrc) {
|
if (crc == calccrc) {
|
||||||
snprintf(crcStr, 3, "ok");
|
snprintf(crc_str, sizeof(crc_str), "(" _GREEN_("ok") ")" );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox crc failed");
|
snprintf(crc_str, sizeof(crc_str), "(" _RED_("fail") ") 0x%02X != 0x%02X", crc, calccrc);
|
||||||
|
|
||||||
snprintf(crcStr, sizeof(crcStr), "failed 0x%02X != 0x%02X", crc, calccrc);
|
|
||||||
retval = PM3_ESOFT;
|
retval = PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "IO Prox XSF(%02d)%02x:%05d (%08x%08x) [crc %s]", version, facilitycode, number, code, code2, crcStr);
|
PrintAndLogEx(SUCCESS, "IO Prox - " _GREEN_("XSF(%02d)%02x:%05d") ", Raw: %08x%08x %s", version, facilitycode, number, code, code2, crc_str);
|
||||||
|
|
||||||
if (g_debugMode) {
|
if (g_debugMode) {
|
||||||
|
if (crc != calccrc)
|
||||||
|
PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox crc failed");
|
||||||
|
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: IO prox idx: %d, Len: %zu, Printing demod buffer:", idx, size);
|
PrintAndLogEx(DEBUG, "DEBUG: IO prox idx: %d, Len: %zu, Printing demod buffer:", idx, size);
|
||||||
printDemodBuff();
|
printDemodBuff();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,8 @@ static int usage_lf_jablotron_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf jablotron clone 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf jablotron clone 112233"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +53,8 @@ static int usage_lf_jablotron_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <card ID> : jablotron card ID");
|
PrintAndLogEx(NORMAL, " <card ID> : jablotron card ID");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf jablotron sim 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf jablotron sim 112233"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +81,10 @@ static uint64_t getJablontronCardId(uint64_t rawcode) {
|
||||||
//see ASKDemod for what args are accepted
|
//see ASKDemod for what args are accepted
|
||||||
static int CmdJablotronDemod(const char *Cmd) {
|
static int CmdJablotronDemod(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
|
return demodJablotron();
|
||||||
|
}
|
||||||
|
|
||||||
|
int demodJablotron(void) {
|
||||||
//Differential Biphase / di-phase (inverted biphase)
|
//Differential Biphase / di-phase (inverted biphase)
|
||||||
//get binary from ask wave
|
//get binary from ask wave
|
||||||
if (ASKbiphaseDemod("0 64 1 0", false) != PM3_SUCCESS) {
|
if (ASKbiphaseDemod("0 64 1 0", false) != PM3_SUCCESS) {
|
||||||
|
@ -115,20 +120,16 @@ static int CmdJablotronDemod(const char *Cmd) {
|
||||||
uint64_t rawid = ((uint64_t)(bytebits_to_byte(DemodBuffer + 16, 8) & 0xff) << 32) | bytebits_to_byte(DemodBuffer + 24, 32);
|
uint64_t rawid = ((uint64_t)(bytebits_to_byte(DemodBuffer + 16, 8) & 0xff) << 32) | bytebits_to_byte(DemodBuffer + 24, 32);
|
||||||
uint64_t id = getJablontronCardId(rawid);
|
uint64_t id = getJablontronCardId(rawid);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Jablotron Tag Found: Card ID: %"PRIx64" :: Raw: %08X%08X", id, raw1, raw2);
|
PrintAndLogEx(SUCCESS, "Jablotron - Card: " _GREEN_("%"PRIx64) ", Raw: %08X%08X", id, raw1, raw2);
|
||||||
|
|
||||||
uint8_t chksum = raw2 & 0xFF;
|
uint8_t chksum = raw2 & 0xFF;
|
||||||
bool isok = (chksum == jablontron_chksum(DemodBuffer));
|
bool isok = (chksum == jablontron_chksum(DemodBuffer));
|
||||||
|
|
||||||
PrintAndLogEx(isok ? SUCCESS : INFO,
|
PrintAndLogEx(DEBUG, "Checksum: %02X (%s)", chksum, isok ? _GREEN_("ok") : _RED_("Fail"));
|
||||||
"Checksum: %02X [%s]",
|
|
||||||
chksum,
|
|
||||||
isok ? _GREEN_("OK") : _RED_("Fail")
|
|
||||||
);
|
|
||||||
|
|
||||||
id = DEC2BCD(id);
|
id = DEC2BCD(id);
|
||||||
// Printed format: 1410-nn-nnnn-nnnn
|
// Printed format: 1410-nn-nnnn-nnnn
|
||||||
PrintAndLogEx(SUCCESS, "Printed: 1410-%02X-%04X-%04X",
|
PrintAndLogEx(SUCCESS, "Printed: " _GREEN_("1410-%02X-%04X-%04X"),
|
||||||
(uint8_t)(id >> 32) & 0xFF,
|
(uint8_t)(id >> 32) & 0xFF,
|
||||||
(uint16_t)(id >> 16) & 0xFFFF,
|
(uint16_t)(id >> 16) & 0xFFFF,
|
||||||
(uint16_t)id & 0xFFFF
|
(uint16_t)id & 0xFFFF
|
||||||
|
@ -137,8 +138,8 @@ static int CmdJablotronDemod(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdJablotronRead(const char *Cmd) {
|
static int CmdJablotronRead(const char *Cmd) {
|
||||||
lf_read(true, 10000);
|
lf_read(false, 16000);
|
||||||
return CmdJablotronDemod(Cmd);
|
return demodJablotron();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdJablotronClone(const char *Cmd) {
|
static int CmdJablotronClone(const char *Cmd) {
|
||||||
|
@ -280,6 +281,3 @@ int detectJablotron(uint8_t *bits, size_t *size) {
|
||||||
return (int)startIdx;
|
return (int)startIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int demodJablotron(void) {
|
|
||||||
return CmdJablotronDemod("");
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,10 +41,10 @@ static int usage_lf_keri_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <c> <cn> : Card Number");
|
PrintAndLogEx(NORMAL, " <c> <cn> : Card Number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf keri clone 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone 112233"));
|
||||||
PrintAndLogEx(NORMAL, " lf keri clone type ms fc 6 cn 12345");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone type ms fc 6 cn 12345"));
|
||||||
PrintAndLogEx(NORMAL, " lf keri clone t m f 6 c 12345");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri clone t m f 6 c 12345"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ static int usage_lf_keri_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <id> : Keri Internal ID");
|
PrintAndLogEx(NORMAL, " <id> : Keri Internal ID");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf keri sim 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf keri sim 112233"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ static int CmdKeriMSScramble(KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID
|
||||||
// Bit 31 was fixed but not in check/parity bits
|
// Bit 31 was fixed but not in check/parity bits
|
||||||
*CardID |= 1UL << 31;
|
*CardID |= 1UL << 31;
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Scrambled MS : FC %d - CN %d to RAW : E0000000%08X", *FC, *ID, *CardID);
|
PrintAndLogEx(SUCCESS, "Scrambled MS - FC: " _GREEN_("%d") " Card: " _GREEN_("%d") ", Raw: E0000000%08X", *FC, *ID, *CardID);
|
||||||
}
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -184,8 +185,7 @@ static int CmdKeriDemod(const char *Cmd) {
|
||||||
Might be a hash of FC & CN to generate Internal ID
|
Might be a hash of FC & CN to generate Internal ID
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "KERI Tag Found -- Internal ID: %u", ID);
|
PrintAndLogEx(SUCCESS, "KERI - Internal ID: " _GREEN_("%u") ", Raw: %08X%08X" , ID, raw1, raw2);
|
||||||
PrintAndLogEx(SUCCESS, "Raw: %08X%08X", raw1, raw2);
|
|
||||||
/*
|
/*
|
||||||
Descramble Data.
|
Descramble Data.
|
||||||
*/
|
*/
|
||||||
|
@ -195,7 +195,7 @@ static int CmdKeriDemod(const char *Cmd) {
|
||||||
// Just need to the low 32 bits without the 111 trailer
|
// Just need to the low 32 bits without the 111 trailer
|
||||||
CmdKeriMSScramble(Descramble, &fc, &cardid, &raw2);
|
CmdKeriMSScramble(Descramble, &fc, &cardid, &raw2);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Descrambled MS : FC %d - CN %d\n", fc, cardid);
|
PrintAndLogEx(SUCCESS, "Descrambled MS - FC: " _GREEN_("%d") " Card: " _GREEN_("%d"), fc, cardid);
|
||||||
|
|
||||||
if (invert) {
|
if (invert) {
|
||||||
PrintAndLogEx(INFO, "Had to Invert - probably KERI");
|
PrintAndLogEx(INFO, "Had to Invert - probably KERI");
|
||||||
|
|
|
@ -30,6 +30,11 @@ static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
//see PSKDemod for what args are accepted
|
//see PSKDemod for what args are accepted
|
||||||
static int CmdMotorolaDemod(const char *Cmd) {
|
static int CmdMotorolaDemod(const char *Cmd) {
|
||||||
|
(void)Cmd;
|
||||||
|
return demodMotorola();
|
||||||
|
}
|
||||||
|
|
||||||
|
int demodMotorola(void) {
|
||||||
|
|
||||||
//PSK1
|
//PSK1
|
||||||
if (PSKDemod("32 1", true) != PM3_SUCCESS) {
|
if (PSKDemod("32 1", true) != PM3_SUCCESS) {
|
||||||
|
@ -113,10 +118,9 @@ static int CmdMotorolaDemod(const char *Cmd) {
|
||||||
checksum |= DemodBuffer[62] << 1; // b2
|
checksum |= DemodBuffer[62] << 1; // b2
|
||||||
checksum |= DemodBuffer[63] << 0; // b1
|
checksum |= DemodBuffer[63] << 0; // b1
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Motorola Tag Found -- Raw: %08X%08X", raw1, raw2);
|
|
||||||
PrintAndLogEx(SUCCESS, "Fmt 26 bit FC %u , CSN %u , checksum %1d%1d", fc, csn, checksum >> 1 & 0x01, checksum & 0x01);
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Motorola - fmt: " _GREEN_("26") " FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %08X%08X", fc, csn, raw1, raw2);
|
||||||
|
PrintAndLogEx(DEBUG, "checksum: " _GREEN_("%1d%1d"), checksum >> 1 & 0x01, checksum & 0x01);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +145,7 @@ static int CmdMotorolaRead(const char *Cmd) {
|
||||||
sc.divisor = LF_DIVISOR_125;
|
sc.divisor = LF_DIVISOR_125;
|
||||||
sc.samples_to_skip = 0;
|
sc.samples_to_skip = 0;
|
||||||
lf_config(&sc);
|
lf_config(&sc);
|
||||||
return CmdMotorolaDemod(Cmd);
|
return demodMotorola();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdMotorolaClone(const char *Cmd) {
|
static int CmdMotorolaClone(const char *Cmd) {
|
||||||
|
@ -156,7 +160,7 @@ static int CmdMotorolaClone(const char *Cmd) {
|
||||||
"defaults to 64.\n",
|
"defaults to 64.\n",
|
||||||
"\n"
|
"\n"
|
||||||
"Samples:\n"
|
"Samples:\n"
|
||||||
"\tlf motorola clone a0000000a0002021\n"
|
_YELLOW_("\tlf motorola clone a0000000a0002021") "\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
|
@ -253,10 +257,6 @@ int detectMotorola(uint8_t *dest, size_t *size) {
|
||||||
return (int)start_idx;
|
return (int)start_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int demodMotorola(void) {
|
|
||||||
return CmdMotorolaDemod("");
|
|
||||||
}
|
|
||||||
|
|
||||||
int readMotorolaUid(void) {
|
int readMotorolaUid(void) {
|
||||||
return (CmdMotorolaRead("") == PM3_SUCCESS);
|
return (CmdMotorolaRead("") == PM3_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ static int usage_lf_nedap_gen(void) {
|
||||||
PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)");
|
PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf nedap generate s 1 c 123 i 12345");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap generate s 1 c 123 i 12345"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +59,8 @@ static int usage_lf_nedap_clone(void) {
|
||||||
// PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
// PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf nedap clone s 1 c 123 i 12345");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap clone s 1 c 123 i 12345"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +78,8 @@ static int usage_lf_nedap_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
// TODO proper example?
|
// TODO proper example?
|
||||||
PrintAndLogEx(NORMAL, " lf nedap sim s 1 c 7 i 1337");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap sim s 1 c 7 i 1337"));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +175,7 @@ static int CmdLFNedapDemod(const char *Cmd) {
|
||||||
customerCode = ((data[1] & 0x01) << 11) | (data[2] << 3) | ((data[3] & 0xe0) >> 5);
|
customerCode = ((data[1] & 0x01) << 11) | (data[2] << 3) | ((data[3] & 0xe0) >> 5);
|
||||||
|
|
||||||
if (isValid == false) {
|
if (isValid == false) {
|
||||||
PrintAndLogEx(ERR, "Checksum : %s (calc 0x%04X != 0x%04X)", _RED_("failed"), checksum, checksum2);
|
PrintAndLogEx(ERR, "Checksum : %s (calc 0x%04X != 0x%04X)", _RED_("fail"), checksum, checksum2);
|
||||||
ret = PM3_ESOFT;
|
ret = PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,9 +195,9 @@ static int CmdLFNedapDemod(const char *Cmd) {
|
||||||
|
|
||||||
badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5;
|
badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5;
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "NEDAP Tag Found: Card ID "_YELLOW_("%05u")" subtype: "_YELLOW_("%1u")" customer code: "_YELLOW_("%03x"), badgeId, subtype, customerCode);
|
PrintAndLogEx(SUCCESS, "NEDAP - Card: " _YELLOW_("%05u") " subtype: " _YELLOW_("%1u")" customer code: " _YELLOW_("%03x") ", Raw: %s", badgeId, subtype, customerCode, sprint_hex(data, size / 8));
|
||||||
PrintAndLogEx(SUCCESS, "Checksum is %s (0x%04X)", _GREEN_("OK"), checksum);
|
PrintAndLogEx(DEBUG, "Checksum (%s) 0x%04X", _GREEN_("ok"), checksum);
|
||||||
PrintAndLogEx(SUCCESS, "Raw: %s", sprint_hex(data, size / 8));
|
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(ERR, "Invalid idx (1:%02x - 2:%02x - 3:%02x - 4:%02x - 5:%02x)", idxC1, idxC2, idxC3, idxC4, idxC5);
|
PrintAndLogEx(ERR, "Invalid idx (1:%02x - 2:%02x - 3:%02x - 4:%02x - 5:%02x)", idxC1, idxC2, idxC3, idxC4, idxC5);
|
||||||
ret = PM3_ESOFT;
|
ret = PM3_ESOFT;
|
||||||
|
@ -239,7 +242,7 @@ static int CmdLFNedapDemod(const char *Cmd) {
|
||||||
if (!r0 && (r1 < 10) && (r2 < 10) && (r3 < 10) && (r4 < 10) && (r5 < 10)) {
|
if (!r0 && (r1 < 10) && (r2 < 10) && (r3 < 10) && (r4 < 10) && (r5 < 10)) {
|
||||||
|
|
||||||
badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5;
|
badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5;
|
||||||
PrintAndLogEx(SUCCESS, "Second Card Id " _YELLOW_("%05u"), badgeId);
|
PrintAndLogEx(SUCCESS, "Second Card: " _YELLOW_("%05u"), badgeId);
|
||||||
|
|
||||||
if ((fixed0 == FIXED_71) && (fixed1 == FIXED_40))
|
if ((fixed0 == FIXED_71) && (fixed1 == FIXED_40))
|
||||||
PrintAndLogEx(DEBUG, "Fixed part {0 = 0x%02x, 1 = 0x%02x}", fixed0, fixed1);
|
PrintAndLogEx(DEBUG, "Fixed part {0 = 0x%02x, 1 = 0x%02x}", fixed0, fixed1);
|
||||||
|
|
|
@ -46,9 +46,9 @@ static int usage_lf_nexwatch_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " q : Quadrakey credential");
|
PrintAndLogEx(NORMAL, " q : Quadrakey credential");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf nexwatch clone r 5600000000213C9F8F150C");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch clone r 5600000000213C9F8F150C"));
|
||||||
PrintAndLogEx(NORMAL, " lf nexwatch clone c 521512301 m 1 n -- Nexkey credential");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch clone c 521512301 m 1 n") " -- Nexkey credential");
|
||||||
PrintAndLogEx(NORMAL, " lf nexwatch clone c 521512301 m 1 q -- Quadrakey credential");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch clone c 521512301 m 1 q") " -- Quadrakey credential");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ static int usage_lf_nexwatch_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " q : Quadrakey credential");
|
PrintAndLogEx(NORMAL, " q : Quadrakey credential");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf nexwatch sim r 5600000000213C9F8F150C");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch sim r 5600000000213C9F8F150C"));
|
||||||
PrintAndLogEx(NORMAL, " lf nexwatch sim c 521512301 m 1 n -- Nexkey credential");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch sim c 521512301 m 1 n") " -- Nexkey credential");
|
||||||
PrintAndLogEx(NORMAL, " lf nexwatch sim c 521512301 m 1 q -- Quadrakey credential");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf nexwatch sim c 521512301 m 1 q") " -- Quadrakey credential");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,18 +244,16 @@ int demodNexWatch(void) {
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%"PRIx32)")", cn, cn);
|
PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%"PRIx32)")", cn, cn);
|
||||||
PrintAndLogEx(SUCCESS, " mode : %x", mode);
|
PrintAndLogEx(SUCCESS, " mode : %x", mode);
|
||||||
|
|
||||||
if (parity == calc_parity) {
|
if (parity == calc_parity) {
|
||||||
PrintAndLogEx(SUCCESS, " parity : %s (0x%X)", _GREEN_("ok"), parity);
|
PrintAndLogEx(DEBUG, " parity : %s (0x%X)", _GREEN_("ok"), parity);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, " parity : %s (0x%X != 0x%X)", _RED_("fail"), parity, calc_parity);
|
PrintAndLogEx(DEBUG, " parity : %s (0x%X != 0x%X)", _RED_("fail"), parity, calc_parity);
|
||||||
}
|
|
||||||
if (m_idx < ARRAYLEN(items)) {
|
|
||||||
PrintAndLogEx(SUCCESS, " checksum : %s (0x%02X)", _GREEN_("ok"), chk);
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(WARNING, " checksum : %s (0x%02X)", _RED_("fail"), chk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, " raw : " _YELLOW_("%"PRIX32"%"PRIX32"%"PRIX32), raw1, raw2, raw3);
|
PrintAndLogEx(DEBUG, " checksum : %s (0x%02X)", (m_idx < ARRAYLEN(items)) ? _GREEN_("ok") : _RED_("fail"), chk);
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, " Raw : " _YELLOW_("%"PRIX32"%"PRIX32"%"PRIX32), raw1, raw2, raw3);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ static int usage_lf_noralsy_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf noralsy clone 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf noralsy clone 112233"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ static int usage_lf_noralsy_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <year> : Tag allocation year");
|
PrintAndLogEx(NORMAL, " <year> : Tag allocation year");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf noralsy sim 112233");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf noralsy sim 112233"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ static int CmdNoralsyDemod(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Noralsy Tag Found: Card ID %u, Year: %u Raw: %08X%08X%08X", cardid, year, raw1, raw2, raw3);
|
PrintAndLogEx(SUCCESS, "Noralsy - Card: " _GREEN_("%u")", Year: " _GREEN_("%u") ", Raw: %08X%08X%08X", cardid, year, raw1, raw2, raw3);
|
||||||
if (raw1 != 0xBB0214FF) {
|
if (raw1 != 0xBB0214FF) {
|
||||||
PrintAndLogEx(WARNING, "Unknown bits set in first block! Expected 0xBB0214FF, Found: 0x%08X", raw1);
|
PrintAndLogEx(WARNING, "Unknown bits set in first block! Expected 0xBB0214FF, Found: 0x%08X", raw1);
|
||||||
PrintAndLogEx(WARNING, "Please post this output in forum to further research on this format");
|
PrintAndLogEx(WARNING, "Please post this output in forum to further research on this format");
|
||||||
|
|
|
@ -37,8 +37,8 @@ static int usage_lf_pac_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 16 bytes max");
|
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 16 bytes max");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf pac clone c CD4F5552 ");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf pac clone c CD4F5552 "));
|
||||||
PrintAndLogEx(NORMAL, " lf pac clone b FF2049906D8511C593155B56D5B2649F ");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf pac clone b FF2049906D8511C593155B56D5B2649F "));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_lf_pac_sim(void) {
|
static int usage_lf_pac_sim(void) {
|
||||||
|
@ -51,7 +51,7 @@ static int usage_lf_pac_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Card ID> : 8 byte PAC/Stanley card id");
|
PrintAndLogEx(NORMAL, " <Card ID> : 8 byte PAC/Stanley card id");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf pac sim 12345678");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf pac sim 12345678"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
// by danshuk
|
// by danshuk
|
||||||
|
@ -176,7 +176,7 @@ static int CmdPacDemod(const char *Cmd) {
|
||||||
int retval = demodbuf_to_pacid(DemodBuffer, DemodBufferLen, cardid, sizeof(cardid));
|
int retval = demodbuf_to_pacid(DemodBuffer, DemodBufferLen, cardid, sizeof(cardid));
|
||||||
|
|
||||||
if (retval == PM3_SUCCESS)
|
if (retval == PM3_SUCCESS)
|
||||||
PrintAndLogEx(SUCCESS, "PAC/Stanley Tag Found -- Card ID: %s, Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
|
PrintAndLogEx(SUCCESS, "PAC/Stanley - Card: " _GREEN_("%s") ", Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
#include "protocols.h" // t55xx defines
|
#include "protocols.h" // t55xx defines
|
||||||
#include "cmdlft55xx.h" // clone..
|
#include "cmdlft55xx.h" // clone..
|
||||||
|
#include "crc.h" // maxim
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ static int usage_lf_paradox_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
|
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf paradox clone b 0f55555695596a6a9999a59a");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf paradox clone b 0f55555695596a6a9999a59a"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,16 +54,33 @@ static int usage_lf_paradox_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf paradox sim 123 11223");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf paradox sim 123 11223"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const uint8_t paradox_lut[] = {
|
||||||
|
0xDB, 0xFC, 0x3F, 0xC5, 0x50, 0x14, 0x05, 0x47,
|
||||||
|
0x9F, 0xED, 0x7D, 0x59, 0x22, 0x84, 0x21, 0x4E,
|
||||||
|
0x39, 0x48, 0x12, 0x88, 0x53, 0xDE, 0xBB, 0xE4,
|
||||||
|
0xB4, 0x2D, 0x4D, 0x55, 0xCA, 0xBE, 0xA3, 0xE2
|
||||||
|
};
|
||||||
|
// FC:108, Card01827
|
||||||
|
// 00000000 01101100 00000111 00100011
|
||||||
|
// hex(0xED xor 0x7D xor 0x22 xor 0x84 xor 0xDE xor 0xBB xor 0xE4 xor 0x4D xor 0xA3 xor 0xE2 xor 0x47) 0xFC
|
||||||
|
|
||||||
|
#define PARADOX_PREAMBLE_LEN 8
|
||||||
|
|
||||||
|
static int CmdParadoxDemod(const char *Cmd) {
|
||||||
|
(void)Cmd; // Cmd is not used so far
|
||||||
|
return demodParadox();
|
||||||
|
}
|
||||||
|
|
||||||
//by marshmellow
|
//by marshmellow
|
||||||
//Paradox Prox demod - FSK2a RF/50 with preamble of 00001111 (then manchester encoded)
|
//Paradox Prox demod - FSK2a RF/50 with preamble of 00001111 (then manchester encoded)
|
||||||
//print full Paradox Prox ID and some bit format details if found
|
//print full Paradox Prox ID and some bit format details if found
|
||||||
static int CmdParadoxDemod(const char *Cmd) {
|
|
||||||
(void)Cmd; // Cmd is not used so far
|
int demodParadox(void) {
|
||||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
||||||
size_t size = getFromGraphBuf(bits);
|
size_t size = getFromGraphBuf(bits);
|
||||||
|
@ -71,12 +89,10 @@ static int CmdParadoxDemod(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
int wave_idx = 0;
|
||||||
int waveIdx = 0;
|
|
||||||
//get binary from fsk wave
|
//get binary from fsk wave
|
||||||
int idx = detectParadox(bits, &size, &hi2, &hi, &lo, &waveIdx);
|
int idx = detectParadox(bits, &size, &wave_idx);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
|
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples");
|
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples");
|
||||||
else if (idx == -2)
|
else if (idx == -2)
|
||||||
|
@ -85,16 +101,52 @@ static int CmdParadoxDemod(const char *Cmd) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox problem during FSK demod");
|
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox problem during FSK demod");
|
||||||
else if (idx == -4)
|
else if (idx == -4)
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox preamble not found");
|
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox preamble not found");
|
||||||
else if (idx == -5)
|
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox error in Manchester data, size %zu", size);
|
|
||||||
else
|
else
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox error demoding fsk %d", idx);
|
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox error demoding fsk %d", idx);
|
||||||
|
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *b = bits + idx;
|
||||||
|
uint8_t rawhex[12] = {0};
|
||||||
|
for (uint8_t i = 0, m = 0, p = 1; i < 96; i++) {
|
||||||
|
|
||||||
|
// convert hex
|
||||||
|
rawhex[m] <<= 1;
|
||||||
|
rawhex[m] |= (*b & 1);
|
||||||
|
b++;
|
||||||
|
|
||||||
|
if (p == 8) {
|
||||||
|
m++;
|
||||||
|
p = 1;
|
||||||
|
} else {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||||
|
uint8_t error = 0;
|
||||||
|
|
||||||
|
// Remove manchester encoding from FSK bits, skip pre
|
||||||
|
for (uint8_t i = idx + PARADOX_PREAMBLE_LEN; i < (idx + 96 - PARADOX_PREAMBLE_LEN ); i += 2) {
|
||||||
|
|
||||||
|
// not manchester data
|
||||||
|
if (bits[i] == bits[i + 1]) {
|
||||||
|
PrintAndLogEx(WARNING, "Error Manchester at %u", i);
|
||||||
|
error++;
|
||||||
|
}
|
||||||
|
|
||||||
|
hi2 = (hi2 << 1) | (hi >> 31);
|
||||||
|
hi = (hi << 1) | (lo >> 31);
|
||||||
|
lo <<= 1;
|
||||||
|
|
||||||
|
if (bits[i] && !bits[i + 1]) {
|
||||||
|
lo |= 1; // 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setDemodBuff(bits, size, idx);
|
setDemodBuff(bits, size, idx);
|
||||||
setClockGrid(50, waveIdx + (idx * 50));
|
setClockGrid(50, wave_idx + (idx * 50));
|
||||||
|
|
||||||
if (hi2 == 0 && hi == 0 && lo == 0) {
|
if (hi2 == 0 && hi == 0 && lo == 0) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox no value found");
|
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox no value found");
|
||||||
|
@ -103,15 +155,41 @@ static int CmdParadoxDemod(const char *Cmd) {
|
||||||
|
|
||||||
uint32_t fc = ((hi & 0x3) << 6) | (lo >> 26);
|
uint32_t fc = ((hi & 0x3) << 6) | (lo >> 26);
|
||||||
uint32_t cardnum = (lo >> 10) & 0xFFFF;
|
uint32_t cardnum = (lo >> 10) & 0xFFFF;
|
||||||
|
uint8_t chksum = (lo >> 2) & 0xFF;
|
||||||
|
|
||||||
|
|
||||||
|
// Calc CRC & Checksum
|
||||||
|
// 000088f0b - FC: 8 - Card: 36619 - Checksum: 05 - RAW: 0f55555559595aa559a5566a
|
||||||
|
// checksum?
|
||||||
|
uint8_t calc_chksum = 0x47;
|
||||||
|
uint8_t pos = 0;
|
||||||
|
for(uint8_t i = 0; i < 8; i++ ) {
|
||||||
|
|
||||||
|
uint8_t ice = rawhex[i+1];
|
||||||
|
for(uint8_t j = 0x80; j > 0; j >>= 2) {
|
||||||
|
|
||||||
|
if (ice & j) {
|
||||||
|
calc_chksum ^= paradox_lut[pos];
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t crc = CRC8Maxim(rawhex + 1, 8);
|
||||||
|
PrintAndLogEx(DEBUG, " FSK/MAN raw : %s", sprint_hex(rawhex, sizeof(rawhex)));
|
||||||
|
PrintAndLogEx(DEBUG, " raw : %s = (maxim crc8) %02x == %02x", sprint_hex(rawhex + 1, 8), crc, calc_chksum);
|
||||||
|
// PrintAndLogEx(DEBUG, " OTHER sample CRC-8/MAXIM : 55 55 69 A5 55 6A 59 5A = FC");
|
||||||
|
|
||||||
uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32);
|
uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32);
|
||||||
uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32);
|
uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32);
|
||||||
uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32);
|
uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Paradox TAG ID: %x%08x - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x",
|
PrintAndLogEx(INFO, "Paradox - ID: " _GREEN_("%x%08x") " FC: " _GREEN_("%d") " Card: " _GREEN_("%d") ", Checksum: %02x, Raw: %08x%08x%08x",
|
||||||
hi >> 10,
|
hi >> 10,
|
||||||
(hi & 0x3) << 26 | (lo >> 10),
|
(hi & 0x3) << 26 | (lo >> 10),
|
||||||
fc, cardnum,
|
fc,
|
||||||
(lo >> 2) & 0xFF,
|
cardnum,
|
||||||
|
chksum,
|
||||||
rawHi2,
|
rawHi2,
|
||||||
rawHi,
|
rawHi,
|
||||||
rawLo
|
rawLo
|
||||||
|
@ -244,43 +322,25 @@ int CmdLFParadox(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop to get raw paradox waveform then FSK demodulate the TAG ID from it
|
// loop to get raw paradox waveform then FSK demodulate the TAG ID from it
|
||||||
int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) {
|
int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx) {
|
||||||
//make sure buffer has data
|
//make sure buffer has data
|
||||||
if (*size < 96 * 50) return -1;
|
if (*size < 96 * 50) return -1;
|
||||||
|
|
||||||
if (getSignalProperties()->isnoise) return -2;
|
if (getSignalProperties()->isnoise) return -2;
|
||||||
|
|
||||||
// FSK demodulator
|
// FSK demodulator
|
||||||
*size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); // paradox fsk2a
|
*size = fskdemod(dest, *size, 50, 1, 10, 8, wave_start_idx); // paradox fsk2a
|
||||||
|
|
||||||
//did we get a good demod?
|
//did we get a good demod?
|
||||||
if (*size < 96) return -3;
|
if (*size < 96) return -3;
|
||||||
|
|
||||||
// 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
|
// 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
|
||||||
size_t startIdx = 0;
|
size_t idx = 0;
|
||||||
uint8_t preamble[] = {0, 0, 0, 0, 1, 1, 1, 1};
|
uint8_t preamble[] = {0, 0, 0, 0, 1, 1, 1, 1};
|
||||||
if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx))
|
if (!preambleSearch(dest, preamble, sizeof(preamble), size, &idx))
|
||||||
return -4; //preamble not found
|
return -4; //preamble not found
|
||||||
|
|
||||||
size_t numStart = startIdx + sizeof(preamble);
|
return (int)idx;
|
||||||
// final loop, go over previously decoded FSK data and manchester decode into usable tag ID
|
|
||||||
for (size_t idx = numStart; (idx - numStart) < *size - sizeof(preamble); idx += 2) {
|
|
||||||
if (dest[idx] == dest[idx + 1])
|
|
||||||
return -5; //not manchester data
|
|
||||||
|
|
||||||
*hi2 = (*hi2 << 1) | (*hi >> 31);
|
|
||||||
*hi = (*hi << 1) | (*lo >> 31);
|
|
||||||
//Then, shift in a 0 or one into low
|
|
||||||
*lo <<= 1;
|
|
||||||
if (dest[idx] && !dest[idx + 1]) // 1 0
|
|
||||||
*lo |= 1;
|
|
||||||
else // 0 1
|
|
||||||
*lo |= 0;
|
|
||||||
}
|
|
||||||
return (int)startIdx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int demodParadox(void) {
|
|
||||||
return CmdParadoxDemod("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -14,5 +14,5 @@
|
||||||
int CmdLFParadox(const char *Cmd);
|
int CmdLFParadox(const char *Cmd);
|
||||||
|
|
||||||
int demodParadox(void);
|
int demodParadox(void);
|
||||||
int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx);
|
int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,7 +36,7 @@ static int usage_lf_presco_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf presco clone d 123456789");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf presco clone d 123456789"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ static int usage_lf_presco_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " c <hex-ID> : 8 digit hex card number");
|
PrintAndLogEx(NORMAL, " c <hex-ID> : 8 digit hex card number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf presco sim d 123456789");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf presco sim d 123456789"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,14 +86,14 @@ static int CmdPrescoDemod(const char *Cmd) {
|
||||||
uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32);
|
uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32);
|
||||||
uint32_t raw4 = bytebits_to_byte(DemodBuffer + 96, 32);
|
uint32_t raw4 = bytebits_to_byte(DemodBuffer + 96, 32);
|
||||||
uint32_t cardid = raw4;
|
uint32_t cardid = raw4;
|
||||||
PrintAndLogEx(SUCCESS, "Presco Tag Found: Card ID %08X, Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
|
PrintAndLogEx(SUCCESS, "Presco - Card: " _GREEN_("%08X") ", Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
|
||||||
|
|
||||||
uint32_t sitecode = 0, usercode = 0, fullcode = 0;
|
uint32_t sitecode = 0, usercode = 0, fullcode = 0;
|
||||||
bool Q5 = false;
|
bool Q5 = false;
|
||||||
char cmd[12] = {0};
|
char cmd[12] = {0};
|
||||||
sprintf(cmd, "H %08X", cardid);
|
sprintf(cmd, "H %08X", cardid);
|
||||||
getWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
|
getWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
|
||||||
PrintAndLogEx(SUCCESS, "SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode);
|
PrintAndLogEx(SUCCESS, "SiteCode: " _GREEN_("%u") " UserCode: " _GREEN_("%u") " FullCode: " _GREEN_("%08X"), sitecode, usercode, fullcode);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ static int usage_lf_pyramid_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf pyramid clone 123 11223");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf pyramid clone 123 11223"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ static int usage_lf_pyramid_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 16-bit value card number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf pyramid sim 123 11223");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf pyramid sim 123 11223"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,12 +181,12 @@ int demodPyramid(void) {
|
||||||
uint32_t fc = bytebits_to_byte(bits + 73, 8);
|
uint32_t fc = bytebits_to_byte(bits + 73, 8);
|
||||||
uint32_t cardnum = bytebits_to_byte(bits + 81, 16);
|
uint32_t cardnum = bytebits_to_byte(bits + 81, 16);
|
||||||
uint32_t code1 = bytebits_to_byte(bits + 72, fmtLen);
|
uint32_t code1 = bytebits_to_byte(bits + 72, fmtLen);
|
||||||
PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi3, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "Pyramid - len: " _GREEN_("%d") ", FC: " _GREEN_("%d") " Card: " _GREEN_("%d") " - Wiegand: " _GREEN_("%x")", Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi3, rawHi2, rawHi, rawLo);
|
||||||
} else if (fmtLen == 45) {
|
} else if (fmtLen == 45) {
|
||||||
fmtLen = 42; //end = 10 bits not 7 like 26 bit fmt
|
fmtLen = 42; //end = 10 bits not 7 like 26 bit fmt
|
||||||
uint32_t fc = bytebits_to_byte(bits + 53, 10);
|
uint32_t fc = bytebits_to_byte(bits + 53, 10);
|
||||||
uint32_t cardnum = bytebits_to_byte(bits + 63, 32);
|
uint32_t cardnum = bytebits_to_byte(bits + 63, 32);
|
||||||
PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, rawHi3, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "Pyramid - len: " _GREEN_("%d") ", FC: " _GREEN_("%d") " Card: " _GREEN_("%d") ", Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, rawHi3, rawHi2, rawHi, rawLo);
|
||||||
/*
|
/*
|
||||||
} else if (fmtLen > 32) {
|
} else if (fmtLen > 32) {
|
||||||
uint32_t cardnum = bytebits_to_byte(bits + 81, 16);
|
uint32_t cardnum = bytebits_to_byte(bits + 81, 16);
|
||||||
|
@ -197,13 +197,13 @@ int demodPyramid(void) {
|
||||||
} else {
|
} else {
|
||||||
uint32_t cardnum = bytebits_to_byte(bits + 81, 16);
|
uint32_t cardnum = bytebits_to_byte(bits + 81, 16);
|
||||||
//uint32_t code1 = bytebits_to_byte(bits+(size-fmtLen),fmtLen);
|
//uint32_t code1 = bytebits_to_byte(bits+(size-fmtLen),fmtLen);
|
||||||
PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo);
|
PrintAndLogEx(SUCCESS, "Pyramid - len: " _GREEN_("%d") " -unknown- Card: " _GREEN_("%d") ", Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Pyramid: checksum : 0x%02X - %02X - %s"
|
PrintAndLogEx(DEBUG, "DEBUG: Pyramid: checksum : 0x%02X - %02X - %s"
|
||||||
, checksum
|
, checksum
|
||||||
, checkCS
|
, checkCS
|
||||||
, (checksum == checkCS) ? _GREEN_("Passed") : _RED_("Fail")
|
, (checksum == checkCS) ? _GREEN_("ok") : _RED_("fail")
|
||||||
);
|
);
|
||||||
|
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Pyramid: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128);
|
PrintAndLogEx(DEBUG, "DEBUG: Pyramid: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128);
|
||||||
|
|
|
@ -118,9 +118,9 @@ int demodSecurakey(void) {
|
||||||
// test parities - evenparity32 looks to add an even parity returns 0 if already even...
|
// test parities - evenparity32 looks to add an even parity returns 0 if already even...
|
||||||
bool parity = !evenparity32(lWiegand) && !oddparity32(rWiegand);
|
bool parity = !evenparity32(lWiegand) && !oddparity32(rWiegand);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Securakey Tag Found--BitLen: %u, Card ID: %u, FC: 0x%X, Raw: %08X%08X%08X", bitLen, cardid, fc, raw1, raw2, raw3);
|
PrintAndLogEx(SUCCESS, "Securakey - len: " _GREEN_("%u") " FC: " _GREEN_("0x%X")" Card: " _GREEN_("%u") ", Raw: %08X%08X%08X", bitLen, fc, cardid, raw1, raw2, raw3);
|
||||||
if (bitLen <= 32)
|
if (bitLen <= 32)
|
||||||
PrintAndLogEx(SUCCESS, "Wiegand: %08X, Parity: %s", (lWiegand << (bitLen / 2)) | rWiegand, parity ? "Passed" : "Failed");
|
PrintAndLogEx(SUCCESS, "Wiegand: " _GREEN_("%08X") " parity (%s)", (lWiegand << (bitLen / 2)) | rWiegand, parity ? _GREEN_("ok") : _RED_("fail"));
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\nHow the FC translates to printed FC is unknown");
|
PrintAndLogEx(INFO, "\nHow the FC translates to printed FC is unknown");
|
||||||
PrintAndLogEx(INFO, "How the checksum is calculated is unknown");
|
PrintAndLogEx(INFO, "How the checksum is calculated is unknown");
|
||||||
|
|
|
@ -33,7 +33,7 @@ static int usage_lf_verichip_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
|
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf verichip clone b FF2049906D8511C593155B56D5B2649F ");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf verichip clone b FF2049906D8511C593155B56D5B2649F "));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ static int CmdVerichipDemod(const char *Cmd) {
|
||||||
// 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001
|
// 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001
|
||||||
// unknown checksum 9 bits at the end
|
// unknown checksum 9 bits at the end
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "VERICHIP Tag Found -- Raw: %08X%08X%08X%08X", raw1, raw2, raw3, raw4);
|
PrintAndLogEx(SUCCESS, "VERICHIP - Raw: %08X%08X%08X%08X", raw1, raw2, raw3, raw4);
|
||||||
PrintAndLogEx(INFO, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum");
|
PrintAndLogEx(INFO, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,8 @@ static int usage_lf_viking_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : specify write to Q5 (t5555 instead of t55x7)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf viking clone 1A337 Q5");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337"));
|
||||||
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking clone 1A337 Q5"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ static int usage_lf_viking_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, " <Card Number> : 8 digit hex viking card number");
|
PrintAndLogEx(NORMAL, " <Card Number> : 8 digit hex viking card number");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf viking sim 1A337");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf viking sim 1A337"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +77,8 @@ int demodViking(void) {
|
||||||
uint32_t raw2 = bytebits_to_byte(DemodBuffer + ans + 32, 32);
|
uint32_t raw2 = bytebits_to_byte(DemodBuffer + ans + 32, 32);
|
||||||
uint32_t cardid = bytebits_to_byte(DemodBuffer + ans + 24, 32);
|
uint32_t cardid = bytebits_to_byte(DemodBuffer + ans + 24, 32);
|
||||||
uint8_t checksum = bytebits_to_byte(DemodBuffer + ans + 32 + 24, 8);
|
uint8_t checksum = bytebits_to_byte(DemodBuffer + ans + 32 + 24, 8);
|
||||||
PrintAndLogEx(SUCCESS, "Viking Tag Found: Card ID " _YELLOW_("%08X")" checksum "_YELLOW_("%02X"), cardid, checksum);
|
PrintAndLogEx(SUCCESS, "Viking - Card " _GREEN_("%08X") ", Raw: %08X%08X", cardid, raw1, raw2);
|
||||||
PrintAndLogEx(SUCCESS, "Raw hex: %08X%08X", raw1, raw2);
|
PrintAndLogEx(DEBUG, "Checksum: %02X", checksum);
|
||||||
setDemodBuff(DemodBuffer, 64, ans);
|
setDemodBuff(DemodBuffer, 64, ans);
|
||||||
setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock));
|
setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|
|
@ -143,7 +143,7 @@ int demodVisa2k(void) {
|
||||||
|
|
||||||
// test checksums
|
// test checksums
|
||||||
if (chk != calc) {
|
if (chk != calc) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 checksum failed %x - %x\n", chk, calc);
|
PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 checksum (%s) %x - %x\n", _RED_("fail"), chk, calc);
|
||||||
save_restoreGB(GRAPH_RESTORE);
|
save_restoreGB(GRAPH_RESTORE);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -151,11 +151,11 @@ int demodVisa2k(void) {
|
||||||
uint8_t calc_par = visa_parity(raw2);
|
uint8_t calc_par = visa_parity(raw2);
|
||||||
uint8_t chk_par = (raw3 & 0xFF0) >> 4;
|
uint8_t chk_par = (raw3 & 0xFF0) >> 4;
|
||||||
if (calc_par != chk_par) {
|
if (calc_par != chk_par) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 parity failed %x - %x\n", chk_par, calc_par);
|
PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 parity (%s) %x - %x\n", _RED_("fail"), chk_par, calc_par);
|
||||||
save_restoreGB(GRAPH_RESTORE);
|
save_restoreGB(GRAPH_RESTORE);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "Visa2000 Tag Found: Card ID " _GREEN_("%u") " Raw: %08X%08X%08X", raw2, raw1, raw2, raw3);
|
PrintAndLogEx(SUCCESS, "Visa2000 - Card " _GREEN_("%u") ", Raw: %08X%08X%08X", raw2, raw1, raw2, raw3);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ static int usage_hints(void) {
|
||||||
PrintAndLogEx(NORMAL, " <0|1> off or on");
|
PrintAndLogEx(NORMAL, " <0|1> off or on");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " hints 1");
|
PrintAndLogEx(NORMAL, _YELLOW_(" hints 1"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ static int usage_msleep(void) {
|
||||||
PrintAndLogEx(NORMAL, " <ms> time in milliseconds");
|
PrintAndLogEx(NORMAL, " <ms> time in milliseconds");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " msleep 100");
|
PrintAndLogEx(NORMAL, _YELLOW_(" msleep 100"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ static int usage_auto(void) {
|
||||||
PrintAndLogEx(NORMAL, " h This help");
|
PrintAndLogEx(NORMAL, " h This help");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " auto");
|
PrintAndLogEx(NORMAL, _YELLOW_(" auto"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ static int CmdPref(const char *Cmd) {
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
|
|
||||||
{"--------",CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("sub") " -----------------------"},
|
{"--------",CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Technology") " -----------------------"},
|
||||||
|
|
||||||
{"analyse", CmdAnalyse, AlwaysAvailable, "{ Analyse utils... }"},
|
{"analyse", CmdAnalyse, AlwaysAvailable, "{ Analyse utils... }"},
|
||||||
{"data", CmdData, AlwaysAvailable, "{ Plot window / data buffer manipulation... }"},
|
{"data", CmdData, AlwaysAvailable, "{ Plot window / data buffer manipulation... }"},
|
||||||
|
@ -264,7 +264,7 @@ static command_t CommandTable[] = {
|
||||||
{"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"},
|
{"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"},
|
||||||
{"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"},
|
{"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"},
|
||||||
{"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"},
|
{"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"},
|
||||||
{"--------",CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("sub") " -----------------------"},
|
{"--------",CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"},
|
||||||
{"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"},
|
{"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"},
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help. Use " _YELLOW_("'<command> help'") " for details of a particular command."},
|
{"help", CmdHelp, AlwaysAvailable, "This help. Use " _YELLOW_("'<command> help'") " for details of a particular command."},
|
||||||
{"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"},
|
{"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"},
|
||||||
|
|
|
@ -89,6 +89,12 @@ bool IfPm3Hitag(void) {
|
||||||
return pm3_capabilities.compiled_with_hitag;
|
return pm3_capabilities.compiled_with_hitag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IfPm3EM4x50(void) {
|
||||||
|
if (!IfPm3Present())
|
||||||
|
return false;
|
||||||
|
return pm3_capabilities.compiled_with_em4x50;
|
||||||
|
}
|
||||||
|
|
||||||
bool IfPm3Hfsniff(void) {
|
bool IfPm3Hfsniff(void) {
|
||||||
if (!IfPm3Present())
|
if (!IfPm3Present())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -33,6 +33,7 @@ bool IfPm3FpcUsartDevFromUsb(void);
|
||||||
bool IfPm3FpcUsartFromUsb(void);
|
bool IfPm3FpcUsartFromUsb(void);
|
||||||
bool IfPm3Lf(void);
|
bool IfPm3Lf(void);
|
||||||
bool IfPm3Hitag(void);
|
bool IfPm3Hitag(void);
|
||||||
|
bool IfPm3EM4x50(void);
|
||||||
bool IfPm3Hfsniff(void);
|
bool IfPm3Hfsniff(void);
|
||||||
bool IfPm3Hfplot(void);
|
bool IfPm3Hfplot(void);
|
||||||
bool IfPm3Iso14443a(void);
|
bool IfPm3Iso14443a(void);
|
||||||
|
|
|
@ -389,7 +389,7 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
switch (communication_settings & MDCM_MASK) {
|
switch (communication_settings & MDCM_MASK) {
|
||||||
case MDCM_PLAIN:
|
case MDCM_PLAIN: {
|
||||||
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
|
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -404,9 +404,9 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
append_mac = false;
|
append_mac = false;
|
||||||
|
}
|
||||||
/* pass through */
|
/* pass through */
|
||||||
case MDCM_MACED:
|
case MDCM_MACED: {
|
||||||
communication_settings |= NO_CRC;
|
communication_settings |= NO_CRC;
|
||||||
|
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
|
@ -455,7 +455,8 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MDCM_ENCIPHERED:
|
}
|
||||||
|
case MDCM_ENCIPHERED: {
|
||||||
/* |<-------------- data -------------->|
|
/* |<-------------- data -------------->|
|
||||||
* |<--- offset -->| |
|
* |<--- offset -->| |
|
||||||
* +---------------+--------------------+-----+---------+
|
* +---------------+--------------------+-----+---------+
|
||||||
|
@ -473,23 +474,27 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
|
|
||||||
if (!(communication_settings & ENC_COMMAND))
|
if (!(communication_settings & ENC_COMMAND))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
|
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
|
||||||
|
|
||||||
// Fill in the crypto buffer with data ...
|
// Fill in the crypto buffer with data ...
|
||||||
memcpy(res, data, *nbytes);
|
memcpy(res, data, *nbytes);
|
||||||
|
|
||||||
if (!(communication_settings & NO_CRC)) {
|
if (!(communication_settings & NO_CRC)) {
|
||||||
// ... CRC ...
|
// ... CRC ...
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
AddCrc14A(res + offset, *nbytes - offset);
|
AddCrc14A(res + offset, *nbytes - offset);
|
||||||
*nbytes += 2;
|
*nbytes += 2;
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
|
case AS_NEW: {
|
||||||
crc32_append(res, *nbytes);
|
crc32_append(res, *nbytes);
|
||||||
*nbytes += 4;
|
*nbytes += 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// ... and padding
|
// ... and padding
|
||||||
memset(res + *nbytes, 0, edl - *nbytes);
|
memset(res + *nbytes, 0, edl - *nbytes);
|
||||||
|
|
||||||
|
@ -497,12 +502,13 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
|
|
||||||
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
|
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
default: {
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
|
|
@ -121,9 +121,13 @@ static int print_aid_description(json_t *root, uint16_t aid, char *fmt, bool ver
|
||||||
const char *company = mad_json_get_str(elm, "company");
|
const char *company = mad_json_get_str(elm, "company");
|
||||||
const char *provider = mad_json_get_str(elm, "service_provider");
|
const char *provider = mad_json_get_str(elm, "service_provider");
|
||||||
const char *integrator = mad_json_get_str(elm, "system_integrator");
|
const char *integrator = mad_json_get_str(elm, "system_integrator");
|
||||||
|
|
||||||
|
if (application && company) {
|
||||||
char result[4 + strlen(application) + strlen(company)];
|
char result[4 + strlen(application) + strlen(company)];
|
||||||
sprintf(result, " %s [%s]", application, company);
|
sprintf(result, " %s [%s]", application, company);
|
||||||
PrintAndLogEx(INFO, fmt, result);
|
PrintAndLogEx(INFO, fmt, result);
|
||||||
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(SUCCESS, " MAD: %s", vmad);
|
PrintAndLogEx(SUCCESS, " MAD: %s", vmad);
|
||||||
if (application)
|
if (application)
|
||||||
|
|
|
@ -86,7 +86,6 @@ int preferences_load(void) {
|
||||||
// to better control json cant find file error msg.
|
// to better control json cant find file error msg.
|
||||||
char *fn = prefGetFilename();
|
char *fn = prefGetFilename();
|
||||||
if (fileExists(fn)) {
|
if (fileExists(fn)) {
|
||||||
PrintAndLogEx(INFO, "Loading preferences...");
|
|
||||||
if (loadFileJSON(fn, &dummyData, sizeof(dummyData), &dummyDL, &preferences_load_callback) == PM3_SUCCESS) {
|
if (loadFileJSON(fn, &dummyData, sizeof(dummyData), &dummyDL, &preferences_load_callback) == PM3_SUCCESS) {
|
||||||
session.preferences_loaded = true;
|
session.preferences_loaded = true;
|
||||||
}
|
}
|
||||||
|
@ -384,75 +383,75 @@ static const char *prefShowMsg(prefShowOpt_t Opt) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showEmojiState(prefShowOpt_t Opt) {
|
static void showEmojiState(prefShowOpt_t opt) {
|
||||||
|
|
||||||
switch (session.emoji_mode) {
|
switch (session.emoji_mode) {
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
PrintAndLogEx(NORMAL, " %s emoji.................. "_GREEN_("alias"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("alias"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case EMOJI:
|
case EMOJI:
|
||||||
PrintAndLogEx(NORMAL, " %s emoji.................. "_GREEN_("emoji"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("emoji"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case ALTTEXT:
|
case ALTTEXT:
|
||||||
PrintAndLogEx(NORMAL, " %s emoji.................. "_GREEN_("alttext"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("alttext"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case ERASE:
|
case ERASE:
|
||||||
PrintAndLogEx(NORMAL, " %s emoji.................. "_GREEN_("erase"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("erase"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(NORMAL, " %s emoji.................. "_RED_("unknown"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s emoji.................. "_RED_("unknown"), prefShowMsg(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showColorState(prefShowOpt_t Opt) {
|
static void showColorState(prefShowOpt_t opt) {
|
||||||
|
|
||||||
if (session.supports_colors)
|
if (session.supports_colors)
|
||||||
PrintAndLogEx(NORMAL, " %s color.................. "_GREEN_("ansi"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s color.................. "_GREEN_("ansi"), prefShowMsg(opt));
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, " %s color.................. "_WHITE_("off"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s color.................. "_WHITE_("off"), prefShowMsg(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showClientDebugState(prefShowOpt_t Opt) {
|
static void showClientDebugState(prefShowOpt_t opt) {
|
||||||
|
|
||||||
switch (session.client_debug_level) {
|
switch (session.client_debug_level) {
|
||||||
case cdbOFF:
|
case cdbOFF:
|
||||||
PrintAndLogEx(NORMAL, " %s client debug........... "_WHITE_("off"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s client debug........... "_WHITE_("off"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case cdbSIMPLE:
|
case cdbSIMPLE:
|
||||||
PrintAndLogEx(NORMAL, " %s client debug........... "_GREEN_("simple"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s client debug........... "_GREEN_("simple"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case cdbFULL:
|
case cdbFULL:
|
||||||
PrintAndLogEx(NORMAL, " %s client debug........... "_GREEN_("full"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s client debug........... "_GREEN_("full"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(NORMAL, " %s client debug........... "_RED_("unknown"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s client debug........... "_RED_("unknown"), prefShowMsg(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
static void showDeviceDebugState(prefShowOpt_t Opt) {
|
static void showDeviceDebugState(prefShowOpt_t opt) {
|
||||||
switch (session.device_debug_level) {
|
switch (session.device_debug_level) {
|
||||||
case ddbOFF:
|
case ddbOFF:
|
||||||
PrintAndLogEx(NORMAL, " %s device debug........... "_WHITE_("off"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s device debug........... "_WHITE_("off"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case ddbERROR:
|
case ddbERROR:
|
||||||
PrintAndLogEx(NORMAL, " %s device debug........... "_GREEN_("error"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("error"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case ddbINFO:
|
case ddbINFO:
|
||||||
PrintAndLogEx(NORMAL, " %s device debug........... "_GREEN_("info"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("info"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case ddbDEBUG:
|
case ddbDEBUG:
|
||||||
PrintAndLogEx(NORMAL, " %s device debug........... "_GREEN_("debug"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("debug"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
case ddbEXTENDED:
|
case ddbEXTENDED:
|
||||||
PrintAndLogEx(NORMAL, " %s device debug........... "_GREEN_("extended"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("extended"), prefShowMsg(opt));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(NORMAL, " %s device debug........... "_RED_("unknown"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s device debug........... "_RED_("unknown"), prefShowMsg(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
static void showSavePathState(savePaths_t pathIndex, prefShowOpt_t Opt) {
|
static void showSavePathState(savePaths_t pathIndex, prefShowOpt_t opt) {
|
||||||
|
|
||||||
char tempStr[50];
|
char tempStr[50];
|
||||||
|
|
||||||
|
@ -470,29 +469,30 @@ static void showSavePathState(savePaths_t pathIndex, prefShowOpt_t Opt) {
|
||||||
strcpy (tempStr,_RED_("unknown")" save path......");
|
strcpy (tempStr,_RED_("unknown")" save path......");
|
||||||
}
|
}
|
||||||
if ((session.defaultPaths[pathIndex] == NULL) || (strcmp(session.defaultPaths[pathIndex],"") == 0))
|
if ((session.defaultPaths[pathIndex] == NULL) || (strcmp(session.defaultPaths[pathIndex],"") == 0))
|
||||||
PrintAndLogEx(NORMAL, " %s %s "_WHITE_("not set"), prefShowMsg(Opt),tempStr);
|
PrintAndLogEx(INFO, " %s %s "_WHITE_("not set"), prefShowMsg(opt),tempStr);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, " %s %s "_GREEN_("%s"), prefShowMsg(Opt), tempStr, session.defaultPaths[pathIndex]);
|
PrintAndLogEx(INFO, " %s %s "_GREEN_("%s"), prefShowMsg(opt), tempStr, session.defaultPaths[pathIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showPlotPosState(void) {
|
static void showPlotPosState(void) {
|
||||||
PrintAndLogEx(NORMAL, " Plot window............ X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"),
|
PrintAndLogEx(INFO, " Plot window............ X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"),
|
||||||
session.plot.x, session.plot.y, session.plot.h, session.plot.w);
|
session.plot.x, session.plot.y, session.plot.h, session.plot.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showOverlayPosState(void) {
|
static void showOverlayPosState(void) {
|
||||||
PrintAndLogEx(NORMAL, " Slider/Overlay window.. X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"),
|
PrintAndLogEx(INFO, " Slider/Overlay window.. X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"),
|
||||||
session.overlay.x, session.overlay.y, session.overlay.h, session.overlay.w);
|
session.overlay.x, session.overlay.y, session.overlay.h, session.overlay.w);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void showHintsState(prefShowOpt_t Opt) {
|
static void showHintsState(prefShowOpt_t opt) {
|
||||||
if (session.show_hints)
|
if (session.show_hints)
|
||||||
PrintAndLogEx(NORMAL, " %s hints.................. "_GREEN_("on"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s hints.................. "_GREEN_("on"), prefShowMsg(opt));
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, " %s hints.................. "_WHITE_("off"), prefShowMsg(Opt));
|
PrintAndLogEx(INFO, " %s hints.................. "_WHITE_("off"), prefShowMsg(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int setCmdEmoji(const char *Cmd) {
|
static int setCmdEmoji(const char *Cmd) {
|
||||||
uint8_t cmdp = 0;
|
uint8_t cmdp = 0;
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
|
@ -909,13 +909,14 @@ static int CmdPrefShow(const char *Cmd) {
|
||||||
if (session.preferences_loaded) {
|
if (session.preferences_loaded) {
|
||||||
char *fn = prefGetFilename();
|
char *fn = prefGetFilename();
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, _CYAN_("Preferences loaded from " _YELLOW_("%s")), fn);
|
PrintAndLogEx(INFO, "Using "_YELLOW_("%s"), fn);
|
||||||
free(fn);
|
free(fn);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(ERR, "Preferences not loaded");
|
PrintAndLogEx(ERR, "Preferences not loaded");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Current settings");
|
||||||
showEmojiState(prefShowNone);
|
showEmojiState(prefShowNone);
|
||||||
showHintsState(prefShowNone);
|
showHintsState(prefShowNone);
|
||||||
showColorState(prefShowNone);
|
showColorState(prefShowNone);
|
||||||
|
@ -927,6 +928,7 @@ static int CmdPrefShow(const char *Cmd) {
|
||||||
|
|
||||||
showClientDebugState(prefShowNone);
|
showClientDebugState(prefShowNone);
|
||||||
// showDeviceDebugState(prefShowNone);
|
// showDeviceDebugState(prefShowNone);
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -18,8 +18,10 @@
|
||||||
#ifdef HAVE_READLINE
|
#ifdef HAVE_READLINE
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "usart_defs.h"
|
#include "usart_defs.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "proxgui.h"
|
#include "proxgui.h"
|
||||||
|
@ -33,8 +35,8 @@
|
||||||
#include "preferences.h"
|
#include "preferences.h"
|
||||||
|
|
||||||
#define BANNERMSG1 " :snowflake: iceman@icesql.net"
|
#define BANNERMSG1 " :snowflake: iceman@icesql.net"
|
||||||
#define BANNERMSG2 " https://github.com/rfidresearchgroup/proxmark3/"
|
#define BANNERMSG2 " bleeding edge :coffee:"
|
||||||
#define BANNERMSG3 " bleeding edge :coffee:"
|
#define BANNERMSG3 " https://github.com/rfidresearchgroup/proxmark3/"
|
||||||
|
|
||||||
typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode;
|
typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode;
|
||||||
|
|
||||||
|
@ -56,11 +58,11 @@ static void showBanner_logo(LogoMode mode) {
|
||||||
sq, sq, tl, hl, hl, sq, sq, tr, sq, sq, sq, sq, tr, __, sq, sq, sq, sq, vl, bl, hl, hl, hl, sq, sq, tr);
|
sq, sq, tl, hl, hl, sq, sq, tr, sq, sq, sq, sq, tr, __, sq, sq, sq, sq, vl, bl, hl, hl, hl, sq, sq, tr);
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"),
|
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"),
|
||||||
sq, sq, sq, sq, sq, sq, tl, br, sq, sq, tl, sq, sq, sq, sq, tl, sq, sq, vl, __, sq, sq, sq, sq, tl, br);
|
sq, sq, sq, sq, sq, sq, tl, br, sq, sq, tl, sq, sq, sq, sq, tl, sq, sq, vl, __, sq, sq, sq, sq, tl, br);
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")" " BANNERMSG1,
|
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"),
|
||||||
sq, sq, tl, hl, hl, hl, br, __, sq, sq, vl, bl, sq, sq, tl, br, sq, sq, vl, __, bl, hl, hl, sq, sq, tr);
|
sq, sq, tl, hl, hl, hl, br, __, sq, sq, vl, bl, sq, sq, tl, br, sq, sq, vl, __, bl, hl, hl, sq, sq, tr);
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")" " BANNERMSG2,
|
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")" " BANNERMSG1,
|
||||||
sq, sq, vl, __, __, __, __, __, sq, sq, vl, __, bl, hl, br, __, sq, sq, vl, sq, sq, sq, sq, sq, tl, br);
|
sq, sq, vl, __, __, __, __, __, sq, sq, vl, __, bl, hl, br, __, sq, sq, vl, sq, sq, sq, sq, sq, tl, br);
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")" " BANNERMSG3,
|
PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")" " BANNERMSG2,
|
||||||
bl, hl, br, __, __, __, __, __, bl, hl, br, __, __, __, __, __, bl, hl, br, bl, hl, hl, hl, hl, br, __);
|
bl, hl, br, __, __, __, __, __, bl, hl, br, __, __, __, __, __, bl, hl, br, bl, hl, hl, hl, hl, br, __);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -68,21 +70,23 @@ static void showBanner_logo(LogoMode mode) {
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("██████╗ ███╗ ███╗█████╗ "));
|
PrintAndLogEx(NORMAL, " " _BLUE_("██████╗ ███╗ ███╗█████╗ "));
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("██╔══██╗████╗ ████║╚═══██╗"));
|
PrintAndLogEx(NORMAL, " " _BLUE_("██╔══██╗████╗ ████║╚═══██╗"));
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("██████╔╝██╔████╔██║ ████╔╝"));
|
PrintAndLogEx(NORMAL, " " _BLUE_("██████╔╝██╔████╔██║ ████╔╝"));
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ╚══██╗") " " BANNERMSG1);
|
PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ╚══██╗"));
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("██║ ██║ ╚═╝ ██║█████╔╝") " " BANNERMSG2);
|
PrintAndLogEx(NORMAL, " " _BLUE_("██║ ██║ ╚═╝ ██║█████╔╝") " " BANNERMSG1);
|
||||||
PrintAndLogEx(NORMAL, " " _BLUE_("╚═╝ ╚═╝ ╚═╝╚════╝ ") " " BANNERMSG3);
|
PrintAndLogEx(NORMAL, " " _BLUE_("╚═╝ ╚═╝ ╚═╝╚════╝ ") " " BANNERMSG2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ASCII: {
|
case ASCII: {
|
||||||
PrintAndLogEx(NORMAL, " ######. ###. ###.#####. ");
|
PrintAndLogEx(NORMAL, " ######. ###. ###.#####. ");
|
||||||
PrintAndLogEx(NORMAL, " ##...##.####. ####. ...##.");
|
PrintAndLogEx(NORMAL, " ##...##.####. ####. ...##.");
|
||||||
PrintAndLogEx(NORMAL, " ######..##.####.##. ####..");
|
PrintAndLogEx(NORMAL, " ######..##.####.##. ####..");
|
||||||
PrintAndLogEx(NORMAL, " ##..... ##..##..##. ..##." " " BANNERMSG1);
|
PrintAndLogEx(NORMAL, " ##..... ##..##..##. ..##.");
|
||||||
PrintAndLogEx(NORMAL, " ##. ##. .. ##.#####.." " " BANNERMSG2);
|
PrintAndLogEx(NORMAL, " ##. ##. .. ##.#####.. " BANNERMSG1);
|
||||||
PrintAndLogEx(NORMAL, " .. .. .. ..... " " " BANNERMSG3);
|
PrintAndLogEx(NORMAL, " .. .. .. ..... " BANNERMSG2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(NORMAL, BANNERMSG3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showBanner(void) {
|
static void showBanner(void) {
|
||||||
|
@ -134,6 +138,37 @@ static int check_comm(void) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static void flush_history(void) {
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
if (session.history_path) {
|
||||||
|
write_history(session.history_path);
|
||||||
|
free(session.history_path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_READLINE
|
||||||
|
|
||||||
|
# if defined(_WIN32)
|
||||||
|
/*
|
||||||
|
static bool WINAPI terminate_handler(DWORD t) {
|
||||||
|
if (t == CTRL_C_EVENT) {
|
||||||
|
flush_history();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
# else
|
||||||
|
struct sigaction old_action;
|
||||||
|
static void terminate_handler(int signum) {
|
||||||
|
sigaction(SIGINT, &old_action, NULL);
|
||||||
|
flush_history();
|
||||||
|
kill(0, SIGINT);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// first slot is always NULL, indicating absence of script when idx=0
|
// first slot is always NULL, indicating absence of script when idx=0
|
||||||
static FILE *cmdscriptfile[MAX_NESTED_CMDSCRIPT + 1] = {0};
|
static FILE *cmdscriptfile[MAX_NESTED_CMDSCRIPT + 1] = {0};
|
||||||
|
@ -211,16 +246,29 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
#ifdef HAVE_READLINE
|
||||||
char *my_history_path = NULL;
|
session.history_path = NULL;
|
||||||
if (searchHomeFilePath(&my_history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
|
if (searchHomeFilePath(&session.history_path, NULL, PROXHISTORY, true) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "No history will be recorded");
|
PrintAndLogEx(ERR, "No history will be recorded");
|
||||||
my_history_path = NULL;
|
session.history_path = NULL;
|
||||||
} else {
|
} else {
|
||||||
read_history(my_history_path);
|
|
||||||
|
# if defined(_WIN32)
|
||||||
|
// SetConsoleCtrlHandler((PHANDLER_ROUTINE)terminate_handler, true);
|
||||||
|
# else
|
||||||
|
struct sigaction action;
|
||||||
|
memset(&action, 0, sizeof(action));
|
||||||
|
action.sa_handler = &terminate_handler;
|
||||||
|
sigaction(SIGINT, &action, &old_action);
|
||||||
|
# endif
|
||||||
|
rl_catch_signals = 1;
|
||||||
|
rl_set_signals();
|
||||||
|
read_history(session.history_path);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// loops every time enter is pressed...
|
// loops every time enter is pressed...
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
bool printprompt = false;
|
bool printprompt = false;
|
||||||
if (session.pm3_present) {
|
if (session.pm3_present) {
|
||||||
if (conn.send_via_fpc_usart == false)
|
if (conn.send_via_fpc_usart == false)
|
||||||
|
@ -391,11 +439,9 @@ check_script:
|
||||||
pop_cmdscriptfile();
|
pop_cmdscriptfile();
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
#ifdef HAVE_READLINE
|
||||||
if (my_history_path) {
|
flush_history();
|
||||||
write_history(my_history_path);
|
|
||||||
free(my_history_path);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
free(cmd);
|
free(cmd);
|
||||||
cmd = NULL;
|
cmd = NULL;
|
||||||
|
@ -641,7 +687,6 @@ finish2:
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
static bool DetectWindowsAnsiSupport(void) {
|
static bool DetectWindowsAnsiSupport(void) {
|
||||||
bool ret = false;
|
|
||||||
HKEY hKey = NULL;
|
HKEY hKey = NULL;
|
||||||
bool virtualTerminalLevelSet = false;
|
bool virtualTerminalLevelSet = false;
|
||||||
bool forceV2Set = false;
|
bool forceV2Set = false;
|
||||||
|
@ -681,9 +726,15 @@ static bool DetectWindowsAnsiSupport(void) {
|
||||||
}
|
}
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
DWORD dwMode = 0;
|
||||||
|
GetConsoleMode(hOut, &dwMode);
|
||||||
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
SetConsoleMode(hOut, dwMode);
|
||||||
|
|
||||||
// If both VirtualTerminalLevel and ForceV2 is set, AnsiColor should work
|
// If both VirtualTerminalLevel and ForceV2 is set, AnsiColor should work
|
||||||
ret = virtualTerminalLevelSet && forceV2Set;
|
return virtualTerminalLevelSet && forceV2Set;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1022,7 +1073,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
#ifdef HAVE_GUI
|
#ifdef HAVE_GUI
|
||||||
|
|
||||||
# ifdef _WIN32
|
# if defined(_WIN32)
|
||||||
InitGraphics(argc, argv, script_cmds_file, script_cmd, stayInCommandLoop);
|
InitGraphics(argc, argv, script_cmds_file, script_cmd, stayInCommandLoop);
|
||||||
MainGraphics();
|
MainGraphics();
|
||||||
# else
|
# else
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef struct {
|
||||||
// char *defaultPaths[spItemCount]; // Array should allow loop searching for files
|
// char *defaultPaths[spItemCount]; // Array should allow loop searching for files
|
||||||
clientdebugLevel_t client_debug_level;
|
clientdebugLevel_t client_debug_level;
|
||||||
// uint8_t device_debug_level;
|
// uint8_t device_debug_level;
|
||||||
|
char *history_path;
|
||||||
} session_arg_t;
|
} session_arg_t;
|
||||||
|
|
||||||
extern session_arg_t session;
|
extern session_arg_t session;
|
||||||
|
|
|
@ -205,7 +205,7 @@ k <name> : key filename, if no <name> given, UID will be used as filename"
|
||||||
f <name> : data filename, if no <name> given, UID will be used as filename
|
f <name> : data filename, if no <name> given, UID will be used as filename
|
||||||
|
|
||||||
pm3 --> hf mf dump 1
|
pm3 --> hf mf dump 1
|
||||||
pm3 --> hf mf dump 1 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin
|
pm3 --> hf mf dump 1 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-dump.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
Convert .bin to .eml
|
Convert .bin to .eml
|
||||||
|
@ -275,7 +275,7 @@ Clone Mifare 1K Sequence
|
||||||
```
|
```
|
||||||
pm3 --> hf mf chk *1 ? d mfc_default_keys
|
pm3 --> hf mf chk *1 ? d mfc_default_keys
|
||||||
pm3 --> hf mf dump
|
pm3 --> hf mf dump
|
||||||
pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin
|
pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-dump.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
Read Mifare Ultralight EV1
|
Read Mifare Ultralight EV1
|
||||||
|
|
|
@ -11,9 +11,37 @@
|
||||||
#ifndef EM4X50_H__
|
#ifndef EM4X50_H__
|
||||||
#define EM4X50_H__
|
#define EM4X50_H__
|
||||||
|
|
||||||
|
#define EM4X50_NO_WORDS 34
|
||||||
|
|
||||||
|
// special words
|
||||||
|
#define EM4X50_DEVICE_PASSWORD 0
|
||||||
|
#define EM4X50_PROTECTION 1
|
||||||
|
#define EM4X50_CONTROL 2
|
||||||
|
#define EM4X50_DEVICE_SERIAL 32
|
||||||
|
#define EM4X50_DEVICE_ID 33
|
||||||
|
|
||||||
|
// control word (word = 4 bytes)
|
||||||
|
#define FIRST_WORD_READ 0 // first byte
|
||||||
|
#define LAST_WORD_READ 1 // second byte
|
||||||
|
#define CONFIG_BLOCK 2 // third byte
|
||||||
|
#define PASSWORD_CHECK 0x80 // first bit in third byte
|
||||||
|
#define READ_AFTER_WRITE 0x40 // second bit in third byte
|
||||||
|
|
||||||
|
// protection word
|
||||||
|
#define FIRST_WORD_READ_PROTECTED 0 // first byte
|
||||||
|
#define LAST_WORD_READ_PROTECTED 1 // second byte
|
||||||
|
#define FIRST_WORD_WRITE_INHIBITED 2 // third byte
|
||||||
|
#define LAST_WORD_WRITE_INHIBITED 3 // fourth byte
|
||||||
|
|
||||||
|
// misc
|
||||||
|
#define STATUS_NO_WORDS 0xfc
|
||||||
|
#define STATUS_SUCCESS 0x2
|
||||||
|
#define STATUS_LOGIN 0x1
|
||||||
|
#define NO_CHARS_MAX 400
|
||||||
|
#define TIMEOUT 2000
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool fwr_given;
|
bool addr_given;
|
||||||
bool lwr_given;
|
|
||||||
bool pwd_given;
|
bool pwd_given;
|
||||||
bool newpwd_given;
|
bool newpwd_given;
|
||||||
uint8_t password[4];
|
uint8_t password[4];
|
||||||
|
|
|
@ -405,6 +405,7 @@ typedef struct {
|
||||||
#define CMD_LF_EM4X50_INFO 0x0240
|
#define CMD_LF_EM4X50_INFO 0x0240
|
||||||
#define CMD_LF_EM4X50_WRITE 0x0241
|
#define CMD_LF_EM4X50_WRITE 0x0241
|
||||||
#define CMD_LF_EM4X50_WRITE_PASSWORD 0x0242
|
#define CMD_LF_EM4X50_WRITE_PASSWORD 0x0242
|
||||||
|
#define CMD_LF_EM4X50_READ 0x0243
|
||||||
// Sampling configuration for LF reader/sniffer
|
// Sampling configuration for LF reader/sniffer
|
||||||
#define CMD_LF_SAMPLING_SET_CONFIG 0x021D
|
#define CMD_LF_SAMPLING_SET_CONFIG 0x021D
|
||||||
#define CMD_LF_FSK_SIMULATE 0x021E
|
#define CMD_LF_FSK_SIMULATE 0x021E
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
# EML data var te get keys of
|
# EML data var te get keys of
|
||||||
EML_FILE_DATA = """PLACE RAW hf-mf-CARD_UID-data.eml FILE CONTENT OF CURRENTLY LOADED CARD HERE"""
|
EML_FILE_DATA = """PLACE RAW hf-mf-CARD_UID-dump.eml FILE CONTENT OF CURRENTLY LOADED CARD HERE"""
|
||||||
# Change your device name here if it differs from the default Proxmark3 RDV4.0
|
# Change your device name here if it differs from the default Proxmark3 RDV4.0
|
||||||
PROXMARK_BIN_EXEC_STRING = 'proxmark3 -c "%s" /dev/tty.usbmodemiceman1'
|
PROXMARK_BIN_EXEC_STRING = 'proxmark3 -c "%s" /dev/tty.usbmodemiceman1'
|
||||||
# Constants
|
# Constants
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue