Merge branch 'master' into apdufuzz

This commit is contained in:
ikarus
2020-12-13 00:14:34 +01:00
35 changed files with 657 additions and 361 deletions
+10 -10
View File
@@ -88,7 +88,7 @@ static int get_input_data_from_file(uint32_t *words, char *inputfile) {
uint32_t size = size_in_spiffs(inputfile);
uint8_t *mem = BigBuf_malloc(size);
Dbprintf(_YELLOW_("found input file %s"), inputfile);
rdv40_spiffs_read_as_filetype(inputfile, mem, size, RDV40_SPIFFS_SAFETY_SAFE);
@@ -153,7 +153,7 @@ void RunMod(void) {
if (button_pressed == BUTTON_SINGLE_CLICK) {
SpinUp(100);
switch (state) {
case STATE_SIM:
@@ -168,7 +168,7 @@ void RunMod(void) {
default:
break;
}
state_change = true;
} else if (button_pressed == BUTTON_HOLD) {
@@ -261,9 +261,9 @@ void RunMod(void) {
log_exists = exists_in_spiffs(LF_EM4X50BRUTE_LOGFILE);
now = get_input_data_from_file(passwords, LF_EM4X50BRUTE_INPUTFILE);
if (now == 2) {
// print some information
int no_iter = passwords[1] - passwords[0] + 1;
int dur_s = no_iter / EM4X50_PWD_SPEED;
@@ -277,7 +277,7 @@ void RunMod(void) {
no_iter, passwords[0], passwords[1]);
Dbprintf(_YELLOW_("estimated duration: %ih%im%is"),
dur_h, dur_m, dur_s);
} else {
Dbprintf(_RED_("error in input data"));
break;
@@ -287,7 +287,7 @@ void RunMod(void) {
}
pwd_found = em4x50_standalone_brute(passwords[0], passwords[1], &pwd);
if (pwd_found == PM3_ETIMEOUT) {
// timeout -> no EM4x50 tag on reader?
@@ -313,15 +313,15 @@ void RunMod(void) {
strcat((char *)entry, "\n");
append(LF_EM4X50BRUTE_LOGFILE, entry, strlen((char *)entry));
} else {
// stopped -> write to logfile
sprintf((char *)entry, "stopped search - last password: 0x%08"PRIx32, pwd);
Dbprintf(_YELLOW_("%s"), entry);
strcat((char *)entry, "\n");
append(LF_EM4X50BRUTE_LOGFILE, entry, strlen((char *)entry));
// replace start password by last tested password in
// inputfile (spiffs) so that brute forcing process will
// be continued when envoking brute force mode again
+8
View File
@@ -1174,6 +1174,14 @@ static void PacketReceived(PacketCommandNG *packet) {
em4x70_write((em4x70_data_t *)packet->data.asBytes);
break;
}
case CMD_LF_EM4X70_UNLOCK: {
em4x70_unlock((em4x70_data_t *)packet->data.asBytes);
break;
}
case CMD_LF_EM4X70_AUTH: {
em4x70_auth((em4x70_data_t *)packet->data.asBytes);
break;
}
#endif
#ifdef WITH_ISO15693
+41 -41
View File
@@ -37,11 +37,11 @@
#define EM4X50_T_TAG_WAITING_FOR_SIGNAL 75
#define EM4X50_T_WAITING_FOR_DBLLIW 1550
#define EM4X50_T_WAITING_FOR_SNGLLIW 140 // this value seems to be
// critical;
// if it's too low
// (e.g. < 120) some cards
// are no longer readable
// although they're ok
// critical;
// if it's too low
// (e.g. < 120) some cards
// are no longer readable
// although they're ok
#define EM4X50_TAG_TOLERANCE 8
#define EM4X50_TAG_WORD 45
@@ -65,18 +65,18 @@ static void wait_timer(uint32_t period) {
// extract and check parities
// return result of parity check and extracted plain data
static bool extract_parities(uint64_t word, uint32_t *data) {
uint8_t row_parities = 0x0, col_parities = 0x0;
uint8_t row_parities_calculated = 0x0, col_parities_calculated = 0x0;
*data = 0x0;
// extract plain data (32 bits) from raw word (45 bits)
for (int i = 0; i < 4; i++) {
*data <<= 8;
*data |= (word >> ((4 - i) * 9 + 1)) & 0xFF;
}
// extract row parities (4 bits + stop bit) from raw word (45 bits)
for (int i = 0; i < 5; i++) {
row_parities <<= 1;
@@ -106,7 +106,7 @@ static bool extract_parities(uint64_t word, uint32_t *data) {
col_parities_calculated ^= (*data >> ((3 - j) * 8 + (7 - i))) & 0x1;
}
}
if ((row_parities == row_parities_calculated) && (col_parities == col_parities_calculated))
return true;
@@ -191,7 +191,7 @@ static bool get_signalproperties(void) {
// about 2 samples per bit period
wait_timer(T0 * EM4X50_T_TAG_HALF_PERIOD);
// ignore first samples
if ((i > SIGNAL_IGNORE_FIRST_SAMPLES) && (AT91C_BASE_SSC->SSC_RHR > noise)) {
signal_found = true;
@@ -229,7 +229,7 @@ static bool get_signalproperties(void) {
gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100;
LED_A_OFF();
return true;
}
@@ -290,7 +290,7 @@ static uint32_t get_pulse_length(void) {
// check if pulse length <pl> corresponds to given length <length>
static bool check_pulse_length(uint32_t pl, int length) {
return ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) && (pl <= T0 * (length + EM4X50_TAG_TOLERANCE)));
return ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) && (pl <= T0 * (length + EM4X50_TAG_TOLERANCE)));
}
// send single bit according to EM4x50 application note and datasheet
@@ -346,12 +346,12 @@ static void em4x50_reader_send_byte_with_parity(uint8_t byte) {
// word hast be sent in msb notation
static void em4x50_reader_send_word(const uint32_t word) {
uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0};
for (int i = 0; i < 4; i++) {
bytes[i] = (word >> (24 - (8 * i))) & 0xFF;
em4x50_reader_send_byte_with_parity(bytes[i]);
}
// send column parities
em4x50_reader_send_byte(bytes[0] ^ bytes[1] ^ bytes[2] ^ bytes[3]);
@@ -362,7 +362,7 @@ static void em4x50_reader_send_word(const uint32_t word) {
// find single listen window
static bool find_single_listen_window(void) {
int cnt_pulses = 0;
LED_B_ON();
while (cnt_pulses < EM4X50_T_WAITING_FOR_SNGLLIW) {
@@ -392,7 +392,7 @@ static bool find_single_listen_window(void) {
// -> 34 words + 34 single listen windows -> about 1600 pulses
static int find_double_listen_window(bool bcommand) {
int cnt_pulses = 0;
LED_B_ON();
while (cnt_pulses < EM4X50_T_WAITING_FOR_DBLLIW) {
@@ -452,7 +452,7 @@ static int find_double_listen_window(bool bcommand) {
cnt_pulses++;
}
LED_B_OFF();
LED_B_OFF();
return PM3_EFAILED;
}
@@ -480,7 +480,7 @@ static bool check_ack(bool bliw) {
if (BUTTON_PRESS())
return false;
if (check_pulse_length(get_pulse_length(), 2 * EM4X50_T_TAG_FULL_PERIOD)) {
// The received signal is either ACK or NAK.
@@ -531,9 +531,9 @@ static int get_word_from_bitstream(uint32_t *data) {
int cnt = 0;
uint32_t pl = 0;
uint64_t word = 0x0;
LED_C_ON();
*data = 0x0;
// initial bit value depends on last pulse length of listen window
@@ -561,7 +561,7 @@ static int get_word_from_bitstream(uint32_t *data) {
cnt++;
word <<= 1;
pl = get_pulse_length();
if (check_pulse_length(pl, EM4X50_T_TAG_FULL_PERIOD)) {
@@ -612,9 +612,9 @@ static int get_word_from_bitstream(uint32_t *data) {
return (extract_parities(word, data)) ? --cnt : 0;
}
}
LED_C_OFF();
return PM3_EOPABORTED;
}
@@ -696,7 +696,7 @@ bool em4x50_sim_send_word(uint32_t word) {
// word has tobe sent in msb, not lsb
word = reflect32(word);
// 4 bytes each with even row parity bit
for (int i = 0; i < 4; i++) {
if (em4x50_sim_send_byte_with_parity((word >> ((3 - i) * 8)) & 0xFF) == false) {
@@ -776,7 +776,7 @@ static bool login(uint32_t password) {
// send password
em4x50_reader_send_word(password);
wait_timer(T0 * EM4X50_T_TAG_TPP);
// check if ACK is returned
@@ -799,7 +799,7 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
for (*pwd = start; *pwd <= stop; (*pwd)++) {
if (login(*pwd) == PM3_SUCCESS) {
pwd_found = true;
// to be safe login 5 more times
@@ -809,11 +809,11 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
break;
}
}
if (pwd_found)
break;
}
// print password every 500 iterations
if ((++cnt % 500) == 0) {
@@ -827,10 +827,10 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
// print data
Dbprintf("|%8i | 0x%08x | 0x%08x |", cnt, reflect32(*pwd), *pwd);
}
if (BUTTON_PRESS())
break;
}
// print footer
@@ -852,7 +852,7 @@ void em4x50_login(uint32_t *password) {
reply_ng(CMD_LF_EM4X50_LOGIN, status, NULL, 0);
}
// envoke password search
// envoke password search
void em4x50_brute(em4x50_data_t *etd) {
em4x50_setup_read();
@@ -903,7 +903,7 @@ void em4x50_chk(uint8_t *filename) {
pwd = 0x0;
for (int j = 0; j < 4; j++)
pwd |= (*(pwds + 4 * i + j)) << ((3 - j) * 8);
if ((status = login(pwd)) == PM3_SUCCESS)
break;
}
@@ -1063,7 +1063,7 @@ void em4x50_reader(void) {
// writes <word> to specified <addresses>
static int write(uint32_t word, uint32_t addresses) {
if (request_receive_mode() == PM3_SUCCESS) {
// send write command
@@ -1079,7 +1079,7 @@ static int write(uint32_t word, uint32_t addresses) {
reply_ng(CMD_LF_EM4X50_WRITE, PM3_ETEAROFF, NULL, 0);
return PM3_ETEAROFF;
} else {
// wait for T0 * EM4X50_T_TAG_TWA (write access time)
wait_timer(T0 * EM4X50_T_TAG_TWA);
@@ -1175,7 +1175,7 @@ void em4x50_write(em4x50_data_t *etd) {
// if password is given renew login after reset
if (etd->pwd_given)
status = login(etd->password1);
if (status == PM3_SUCCESS) {
// call a selective read
@@ -1225,11 +1225,11 @@ void em4x50_sim(uint8_t *filename) {
int status = PM3_SUCCESS;
uint8_t *em4x50_mem = BigBuf_get_EM_addr();
uint32_t words[EM4X50_NO_WORDS] = {0x0};
#ifdef WITH_FLASH
if (strlen((char *)filename) != 0) {
BigBuf_free();
int changed = rdv40_spiffs_lazy_mount();
@@ -1246,7 +1246,7 @@ void em4x50_sim(uint8_t *filename) {
for (int i = 0; i < EM4X50_NO_WORDS; i++)
words[i] = reflect32(bytes_to_num(em4x50_mem + (i * 4), 4));
// only if valid em4x50 data (e.g. uid == serial)
if (words[EM4X50_DEVICE_SERIAL] != words[EM4X50_DEVICE_ID]) {
@@ -1261,7 +1261,7 @@ void em4x50_sim(uint8_t *filename) {
// iceman, will need a usb cmd check to break as well
while (BUTTON_PRESS() == false) {
WDT_HIT();
em4x50_sim_send_listen_window();
for (int i = fwr; i <= lwr; i++) {
@@ -1277,7 +1277,7 @@ void em4x50_sim(uint8_t *filename) {
} else {
status = PM3_ENODATA;
}
BigBuf_free();
lf_finalize();
reply_ng(CMD_LF_EM4X50_SIM, status, NULL, 0);
+208 -68
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -19,5 +19,7 @@ typedef struct {
void em4x70_info(em4x70_data_t *etd);
void em4x70_write(em4x70_data_t *etd);
void em4x70_unlock(em4x70_data_t *etd);
void em4x70_auth(em4x70_data_t *etd);
#endif /* EM4x70_H */
+17 -17
View File
@@ -1727,7 +1727,7 @@ void SimTagIso15693(uint8_t *uid) {
if ((cmd_len >= 5) && (cmd[0] & ISO15_REQ_INVENTORY) && (cmd[1] == ISO15_CMD_INVENTORY)) {
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
// Build INVENTORY command
uint8_t resp_inv[CMD_INV_RESP] = {0};
@@ -1743,30 +1743,30 @@ void SimTagIso15693(uint8_t *uid) {
resp_inv[7] = uid[2];
resp_inv[8] = uid[1];
resp_inv[9] = uid[0];
// CRC
AddCrc15(resp_inv, 10);
CodeIso15693AsTag(resp_inv, CMD_INV_RESP);
tosend_t *ts = get_tosend();
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
LogTrace_ISO15693(resp_inv, CMD_INV_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
chip_state = SELECTED;
}
// GET_SYSTEM_INFO
if ((cmd[1] == ISO15_CMD_SYSINFO)) {
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
// Build GET_SYSTEM_INFO command
uint8_t resp_sysinfo[CMD_SYSINFO_RESP] = {0};
resp_sysinfo[0] = 0; // Response flags.
resp_sysinfo[1] = 0x0F; // Information flags (0x0F - DSFID, AFI, Mem size, IC)
// 64-bit UID
resp_sysinfo[2] = uid[7];
resp_sysinfo[3] = uid[6];
@@ -1776,42 +1776,42 @@ void SimTagIso15693(uint8_t *uid) {
resp_sysinfo[7] = uid[2];
resp_sysinfo[8] = uid[1];
resp_sysinfo[9] = uid[0];
resp_sysinfo[10] = 0; // DSFID
resp_sysinfo[11] = 0; // AFI
resp_sysinfo[12] = 0x1B; // Memory size.
resp_sysinfo[13] = 0x03; // Memory size.
resp_sysinfo[14] = 0x01; // IC reference.
// CRC
AddCrc15(resp_sysinfo, 15);
CodeIso15693AsTag(resp_sysinfo, CMD_SYSINFO_RESP);
tosend_t *ts = get_tosend();
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
LogTrace_ISO15693(resp_sysinfo, CMD_SYSINFO_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
}
// READ_BLOCK
if ((cmd[1] == ISO15_CMD_READ)) {
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
// Build GET_SYSTEM_INFO command
uint8_t resp_readblock[CMD_READBLOCK_RESP] = {0};
resp_readblock[0] = 0; // Response flags.
resp_readblock[1] = 0; // Block data.
resp_readblock[2] = 0; // Block data.
resp_readblock[3] = 0; // Block data.
resp_readblock[4] = 0; // Block data.
// CRC
AddCrc15(resp_readblock, 5);
CodeIso15693AsTag(resp_readblock, CMD_READBLOCK_RESP);
tosend_t *ts = get_tosend();
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
+1 -1
View File
@@ -515,7 +515,7 @@ void doCotagAcquisition(void) {
if (BUTTON_PRESS())
break;
if (checker == 4000) {
if (data_available())
break;
+8 -8
View File
@@ -624,7 +624,7 @@ static int CmdHFiClassReader(const char *Cmd) {
CLIParserInit(&ctx, "hf iclass reader",
"Act as a iCLASS reader. Look for iCLASS tags until Enter or the pm3 button is pressed",
"hf iclass reader -@ -> continuous reader mode"
);
);
void *argtable[] = {
arg_param_begin,
@@ -1700,7 +1700,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
"hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 6 --last 18 --ki 0\n"
"hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 6 --last 18 --ki 0 --elite\n"
"hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 6 --last 18 -k 1122334455667788 --elite\n"
);
);
void *argtable[] = {
arg_param_begin,
@@ -3318,12 +3318,12 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
static int CmdHFiClassEncode(const char *Cmd) {
CLIParserContext *ctx;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass encode",
"Encode binary wiegand to block 7",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337\n"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337, writing w elite key"
);
);
void *argtable[] = {
arg_param_begin,
@@ -3422,7 +3422,7 @@ static int CmdHFiClassEncode(const char *Cmd) {
}
// add binary sentinel bit.
pushBit(&bout, 1);
// convert binary string to hex bytes
for (int i = 0; i < bin_len; i++) {
char c = bin[i];
@@ -3449,11 +3449,11 @@ static int CmdHFiClassEncode(const char *Cmd) {
int isok = PM3_SUCCESS;
// write
for (uint8_t i=0; i<4; i++) {
isok = iclass_write_block(6 + i, credential + (i*8), key, use_credit_key, elite, rawkey, false, false, auth);
for (uint8_t i = 0; i < 4; i++) {
isok = iclass_write_block(6 + i, credential + (i * 8), key, use_credit_key, elite, rawkey, false, false, auth);
switch (isok) {
case PM3_SUCCESS:
PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _GREEN_("ok") " ) --> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i*8), 8));
PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _GREEN_("ok") " ) --> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i * 8), 8));
break;
default:
PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _RED_("fail") " )", 6 + i, 6 + i);
+1 -1
View File
@@ -276,7 +276,7 @@ static int CmdHFMFPInfo(const char *Cmd) {
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
PrintAndLogEx(INFO, "-------------------------------------------------------------");
+2 -2
View File
@@ -510,7 +510,7 @@ static int CmdAWIDBrute(const char *Cmd) {
break;
}
// truncate card number
if ((cn & 0xFFFF) != cn) {
cn &= 0xFFFF;
@@ -550,7 +550,7 @@ static int CmdAWIDBrute(const char *Cmd) {
if (cn > 1) {
if (down > 1) {
if (sendTry(fmtlen, fc, --down, delay, bits, size, verbose) != PM3_SUCCESS) {
return PM3_ESOFT;
return PM3_ESOFT;
}
}
}
+3 -3
View File
@@ -190,9 +190,9 @@ static int CmdDestronClone(const char *Cmd) {
blocks[1] = (blocks[1] & 0xFFFF) | 0xAAE20000;
PrintAndLogEx(INFO, "Preparing to clone Destron tag to " _YELLOW_("%s") " with ID: " _YELLOW_("%s")
, cardtype
, sprint_hex_inrow(data, datalen)
);
, cardtype
, sprint_hex_inrow(data, datalen)
);
print_blocks(blocks, ARRAYLEN(blocks));
+12 -12
View File
@@ -118,7 +118,7 @@ void printEM410x(uint32_t hi, uint64_t id, bool verbose) {
if (hi) {
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%06X%016" PRIX64), hi, id);
} else {
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
}
return;
}
@@ -395,7 +395,7 @@ static int CmdEM410xReader(const char *Cmd) {
// emulate an EM410X tag
static int CmdEM410xSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 410x sim",
"Enables simulation of EM 410x card.\n"
@@ -433,7 +433,7 @@ static int CmdEM410xSim(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdEM410xBrute(const char *Cmd) {
static int CmdEM410xBrute(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 410x brute",
"bruteforcing by emulating EM 410x tag",
@@ -452,10 +452,10 @@ static int CmdEM410xBrute(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
// clock default 64 in EM410x
// clock default 64 in EM410x
uint32_t clk = arg_get_u32_def(ctx, 1, 64);
// default pause time: 1 second
// default pause time: 1 second
uint32_t delay = arg_get_u32_def(ctx, 2, 1000);
int fnlen = 0;
@@ -467,7 +467,7 @@ static int CmdEM410xBrute(const char *Cmd) {
PrintAndLogEx(ERR, "Error: Please specify a filename");
return PM3_EINVARG;
}
uint32_t uidcnt = 0;
uint8_t stUidBlock = 20;
uint8_t *p = NULL;
@@ -543,10 +543,10 @@ static int CmdEM410xBrute(const char *Cmd) {
memcpy(testuid, uidblock + 5 * c, 5);
PrintAndLogEx(INFO, "Bruteforce %d / %d: simulating UID " _YELLOW_("%s")
, c + 1
, uidcnt
, sprint_hex_inrow(testuid, sizeof(testuid))
);
, c + 1
, uidcnt
, sprint_hex_inrow(testuid, sizeof(testuid))
);
em410x_construct_emul_graph(testuid, clk);
@@ -585,7 +585,7 @@ static int CmdEM410xClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 410x clone",
"Writes EM410x ID to a T55x7 or Q5/T5555 tag",
"lf em 410x clone --id 0F0368568B -> write id to T55x7 tag\n"
"lf em 410x clone --id 0F0368568B -> write id to T55x7 tag\n"
"lf em 410x clone --id 0F0368568B --q5 -> write id to Q5/T5555 tag"
);
@@ -598,7 +598,7 @@ static int CmdEM410xClone(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
// clock default 64 in EM410x
// clock default 64 in EM410x
uint32_t clk = arg_get_u32_def(ctx, 1, 64);
int uid_len = 0;
uint8_t uid[5] = {0};
+15 -15
View File
@@ -773,7 +773,7 @@ int CmdEM4x05Write(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_int0("a", "addr", "<dec>", "memory address to write to. (0-13)"),
arg_str1("d", "data", "<hex>", "data to write, 4 bytes hex"),
arg_str1("d", "data", "<hex>", "data to write, 4 bytes hex"),
arg_str0("p", "pwd", "<hex>", "optional - password, 4 bytes hex"),
arg_lit0(NULL, "po", "protect operation"),
arg_param_end
@@ -784,14 +784,14 @@ int CmdEM4x05Write(const char *Cmd) {
uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 3, 0xFFFFFFFFFFFFFFFF);
bool protect_operation = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if ((addr > 13) && (protect_operation == false)) {
PrintAndLogEx(WARNING, "Address must be between 0 and 13");
return PM3_EINVARG;
}
bool use_pwd = false;
uint32_t pwd = ( inputpwd != 0xFFFFFFFFFFFFFFFF) ? (inputpwd & 0xFFFFFFFF) : 0;
bool use_pwd = false;
uint32_t pwd = (inputpwd != 0xFFFFFFFFFFFFFFFF) ? (inputpwd & 0xFFFFFFFF) : 0;
if (pwd == 0xFFFFFFFF) {
if (protect_operation)
PrintAndLogEx(INFO, "Writing protection words data %08X", data);
@@ -807,14 +807,14 @@ int CmdEM4x05Write(const char *Cmd) {
int res = PM3_SUCCESS;
// set Protect Words
if (protect_operation) {
if (protect_operation) {
res = em4x05_protect(pwd, use_pwd, data);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
return res;
}
} else {
res = em4x05_write_word_ext(addr, pwd, use_pwd, data);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
return res;
}
}
@@ -888,25 +888,25 @@ int CmdEM4x05Wipe(const char *Cmd) {
bool use_pwd = false;
uint32_t pwd = 0;
if ( inputpwd != 0xFFFFFFFFFFFFFFFF) {
if (inputpwd != 0xFFFFFFFFFFFFFFFF) {
pwd = (inputpwd & 0xFFFFFFFF);
use_pwd = true;
}
// block 0 : User Data or Chip Info
int res = em4x05_write_word_ext(0, pwd, use_pwd, chip_info);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
return res;
}
// block 1 : UID - this should be read only for EM4205 and EM4305 not sure about others
res = em4x05_write_word_ext(1, pwd, use_pwd, chip_UID);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
PrintAndLogEx(INFO, "UID block write failed");
}
// block 2 : password
res = em4x05_write_word_ext(2, pwd, use_pwd, block_data);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
return res;
}
@@ -914,20 +914,20 @@ int CmdEM4x05Wipe(const char *Cmd) {
pwd = block_data;
// block 3 : user data
res = em4x05_write_word_ext(3, pwd, use_pwd, block_data);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
return res;
}
// block 4 : config
res = em4x05_write_word_ext(4, pwd, use_pwd, config);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
return res;
}
// Remainder of user/data blocks
for (addr = 5; addr < 14; addr++) {// Clear user data blocks
res = em4x05_write_word_ext(addr, pwd, use_pwd, block_data);
if ( res != PM3_SUCCESS) {
if (res != PM3_SUCCESS) {
return res;
}
}
@@ -2146,4 +2146,4 @@ static int CmdHelp(const char *Cmd) {
int CmdLFEM4X05(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}
}
+54 -54
View File
@@ -28,7 +28,7 @@ static void prepare_result(const uint8_t *data, int fwr, int lwr, em4x50_word_t
// restructure received result in "em4x50_word_t" structure
for (int i = fwr; i <= lwr; i++) {
for (int j = 0; j < 4; j++) {
words[i].byte[j] = data[i * 4 + (3 - j)];
words[i].byte[j] = data[i * 4 + (3 - j)];
}
}
}
@@ -131,7 +131,7 @@ static int em4x50_load_file(const char *filename, uint8_t *data, size_t data_len
int res = 0;
uint32_t serial = 0x0, device_id = 0x0;
if (str_endswith(filename, ".eml"))
res = loadFileEML(filename, data, bytes_read) != PM3_SUCCESS;
else if (str_endswith(filename, ".json"))
@@ -202,7 +202,7 @@ int CmdEM4x50ELoad(const char *Cmd) {
// upload to emulator memory
PrintAndLogEx(INFO, "Uploading dump " _YELLOW_("%s") " to emulator memory", filename);
em4x50_seteml(data, 0, DUMP_FILESIZE);
PrintAndLogEx(INFO, "Done");
return PM3_SUCCESS;
}
@@ -236,7 +236,7 @@ int CmdEM4x50ESave(const char *Cmd) {
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
return PM3_ETIMEOUT;
}
// valid em4x50 data?
uint32_t serial = bytes_to_num(data + 4 * EM4X50_DEVICE_SERIAL, 4);
uint32_t device_id = bytes_to_num(data + 4 * EM4X50_DEVICE_ID, 4);
@@ -244,7 +244,7 @@ int CmdEM4x50ESave(const char *Cmd) {
PrintAndLogEx(WARNING, "No valid em4x50 data in flash memory.");
return PM3_ENODATA;
}
// user supplied filename?
if (fnlen == 0) {
PrintAndLogEx(INFO, "Using UID as filename");
@@ -272,7 +272,7 @@ int CmdEM4x50Login(const char *Cmd) {
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIExecWithReturn(ctx, Cmd, argtable, true);
int pwd_len = 0;
uint8_t pwd[4] = {0x0};
CLIGetHexWithReturn(ctx, 1, pwd, &pwd_len);
@@ -281,7 +281,7 @@ int CmdEM4x50Login(const char *Cmd) {
if (pwd_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes");
return PM3_EINVARG;
}
}
uint32_t password = BYTES2UINT32(pwd);
@@ -315,30 +315,30 @@ int CmdEM4x50Brute(const char *Cmd) {
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIExecWithReturn(ctx, Cmd, argtable, true);
int first_len = 0;
uint8_t first[4] = {0,0,0,0};
uint8_t first[4] = {0, 0, 0, 0};
CLIGetHexWithReturn(ctx, 1, first, &first_len);
int last_len = 0;
uint8_t last[4] = {0,0,0,0};
uint8_t last[4] = {0, 0, 0, 0};
CLIGetHexWithReturn(ctx, 2, last, &last_len);
CLIParserFree(ctx);
if (first_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes");
return PM3_EINVARG;
}
if (last_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes");
return PM3_EINVARG;
}
}
if (last_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes");
return PM3_EINVARG;
}
em4x50_data_t etd;
etd.password1 = BYTES2UINT32(first);
etd.password2 = BYTES2UINT32(last);
// 27 passwords/second (empirical value)
const int speed = 27;
const int speed = 27;
// print some information
int no_iter = etd.password2 - etd.password1 + 1;
@@ -348,10 +348,10 @@ int CmdEM4x50Brute(const char *Cmd) {
dur_s -= dur_h * 3600 + dur_m * 60;
PrintAndLogEx(INFO, "Trying %i passwords in range [0x%08x, 0x%08x]"
, no_iter
, etd.password1
, etd.password2
);
, no_iter
, etd.password1
, etd.password2
);
PrintAndLogEx(INFO, "Estimated duration: %ih%im%is", dur_h, dur_m, dur_s);
// start
@@ -390,7 +390,7 @@ int CmdEM4x50Chk(const char *Cmd) {
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
if (IfPm3Flash() == false) {
PrintAndLogEx(WARNING, "no flash memory available");
return PM3_EFLASH;
@@ -410,17 +410,17 @@ int CmdEM4x50Chk(const char *Cmd) {
int res = loadFileDICTIONARY(filename, data, &datalen, 4, &key_count);
if (res || !key_count)
return PM3_EFILE;
PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button");
int status = PM3_EFAILED;
int keyblock = 2000; // block with 2000 bytes -> 500 keys
uint8_t destfn[32] = "em4x50_chk.bin";
PacketResponseNG resp;
PacketResponseNG resp;
int bytes_remaining = datalen;
while (bytes_remaining > 0) {
PrintAndLogEx(INPLACE, "Remaining keys: %i ", bytes_remaining / 4);
// upload to flash.
@@ -434,7 +434,7 @@ int CmdEM4x50Chk(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X50_CHK, destfn, sizeof(destfn));
WaitForResponseTimeoutW(CMD_LF_EM4X50_CHK, &resp, -1, false);
status = resp.status;
if ((status == PM3_SUCCESS) || (status == PM3_EOPABORTED))
break;
@@ -444,7 +444,7 @@ int CmdEM4x50Chk(const char *Cmd) {
}
PrintAndLogEx(NORMAL, "");
// print response
if (status == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Key " _GREEN_("found: %02x %02x %02x %02x"),
@@ -452,7 +452,7 @@ int CmdEM4x50Chk(const char *Cmd) {
resp.data.asBytes[2],
resp.data.asBytes[1],
resp.data.asBytes[0]
);
);
} else {
PrintAndLogEx(FAILED, "No key found");
}
@@ -536,7 +536,7 @@ int CmdEM4x50Read(const char *Cmd) {
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int addr = arg_get_int_def(ctx, 1, 0);
int pwd_len = 0;
uint8_t pwd[4] = {0x0};
@@ -545,7 +545,7 @@ int CmdEM4x50Read(const char *Cmd) {
if (addr <= 0 || addr >= EM4X50_NO_WORDS) {
return PM3_EINVARG;
}
}
em4x50_data_t etd;
@@ -587,11 +587,11 @@ int CmdEM4x50Info(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, true);
int pwd_len = 0;
uint8_t pwd[4] = {0x0};
uint8_t pwd[4] = {0x0};
CLIGetHexWithReturn(ctx, 1, pwd, &pwd_len);
CLIParserFree(ctx);
em4x50_data_t etd = {.pwd_given = false};
em4x50_data_t etd = {.pwd_given = false};
if (pwd_len) {
if (pwd_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len);
@@ -610,7 +610,7 @@ int CmdEM4x50Info(const char *Cmd) {
return PM3_ETIMEOUT;
}
if ( resp.status == PM3_SUCCESS)
if (resp.status == PM3_SUCCESS)
print_info_result(resp.data.asBytes);
else
PrintAndLogEx(FAILED, "Reading tag " _RED_("failed"));
@@ -666,7 +666,7 @@ int CmdEM4x50Reader(const char *Cmd) {
PrintAndLogEx(INFO, _GREEN_(" %s") "| %s", sprint_hex(words[i].byte, 4), r);
}
PrintAndLogEx(INFO, "-------------+-------------");
}
} while (cm && !kbd_enter_pressed());
@@ -771,11 +771,11 @@ int CmdEM4x50Write(const char *Cmd) {
arg_str0("p", "pwd", "<hex>", "password, 4 bytes, lsb"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int addr = arg_get_int_def(ctx, 1, 0);
int word_len = 0;
uint8_t word[4] = {0x0};
CLIGetHexWithReturn(ctx, 2, word, &word_len);
@@ -784,18 +784,18 @@ int CmdEM4x50Write(const char *Cmd) {
uint8_t pwd[4] = {0x0};
CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len);
CLIParserFree(ctx);
if (addr <= 0 || addr >= EM4X50_NO_WORDS) {
PrintAndLogEx(FAILED, "address has to be within range [0, 31]");
return PM3_EINVARG;
}
}
if (word_len != 4) {
PrintAndLogEx(FAILED, "word/data length must be 4 bytes instead of %d", word_len);
return PM3_EINVARG;
}
em4x50_data_t etd = {.pwd_given = false};
em4x50_data_t etd = {.pwd_given = false};
if (pwd_len) {
if (pwd_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len);
@@ -853,7 +853,7 @@ int CmdEM4x50WritePwd(const char *Cmd) {
arg_str1("n", "new", "<hex>", "new password, 4 hex bytes, lsb"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int pwd_len = 0;
uint8_t pwd[4] = {0x0};
@@ -865,7 +865,7 @@ int CmdEM4x50WritePwd(const char *Cmd) {
CLIParserFree(ctx);
em4x50_data_t etd;
em4x50_data_t etd;
if (pwd_len != 4) {
PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len);
return PM3_EINVARG;
@@ -898,9 +898,9 @@ int CmdEM4x50WritePwd(const char *Cmd) {
}
PrintAndLogEx(SUCCESS, "Writing new password %s (%s)"
, sprint_hex_inrow(npwd, sizeof(npwd))
, _GREEN_("ok")
);
, sprint_hex_inrow(npwd, sizeof(npwd))
, _GREEN_("ok")
);
return PM3_SUCCESS;
}
@@ -919,7 +919,7 @@ int CmdEM4x50Wipe(const char *Cmd) {
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIExecWithReturn(ctx, Cmd, argtable, true);
int pwd_len = 0;
uint8_t pwd[4] = {0x0};
CLIGetHexWithReturn(ctx, 1, pwd, &pwd_len);
@@ -935,7 +935,7 @@ int CmdEM4x50Wipe(const char *Cmd) {
etd.password1 = BYTES2UINT32(pwd);
etd.pwd_given = true;
// clear password
PacketResponseNG resp;
clearCommandBuffer();
@@ -954,13 +954,13 @@ int CmdEM4x50Wipe(const char *Cmd) {
// from now on new password 0x0
etd.password1 = 0x0;
// clear data (words 1 to 31)
for (int i = 1; i < EM4X50_DEVICE_SERIAL; i++) {
// no login necessary for blocks 3 to 31
etd.pwd_given = (i <= EM4X50_CONTROL);
PrintAndLogEx(INPLACE, "Wiping block %i", i);
etd.addresses = i << 8 | i;
@@ -971,7 +971,7 @@ int CmdEM4x50Wipe(const char *Cmd) {
return PM3_ETIMEOUT;
}
if ( resp.status != PM3_SUCCESS) {
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(FAILED, "Wiping data " _RED_("failed"));
return PM3_ESOFT;
@@ -1002,7 +1002,7 @@ int CmdEM4x50Restore(const char *Cmd) {
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIExecWithReturn(ctx, Cmd, argtable, true);
int uidLen = 0;
uint8_t uid[4] = {0x0};
@@ -1057,7 +1057,7 @@ int CmdEM4x50Restore(const char *Cmd) {
etd.addresses = i << 8 | i;
etd.word = reflect32(BYTES2UINT32((data + 4 * i)));
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X50_WRITE, (uint8_t *)&etd, sizeof(etd));
@@ -1074,7 +1074,7 @@ int CmdEM4x50Restore(const char *Cmd) {
}
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Done");
return PM3_SUCCESS;
}
@@ -1118,10 +1118,10 @@ static command_t CommandTable[] = {
{"login", CmdEM4x50Login, IfPm3EM4x50, "login into EM4x50"},
{"rdbl", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"},
{"wrbl", CmdEM4x50Write, IfPm3EM4x50, "write word data to EM4x50"},
{"writepwd",CmdEM4x50WritePwd, IfPm3EM4x50, "change password of EM4x50"},
{"writepwd", CmdEM4x50WritePwd, IfPm3EM4x50, "change password of EM4x50"},
{"wipe", CmdEM4x50Wipe, IfPm3EM4x50, "wipe EM4x50 tag"},
{"reader", CmdEM4x50Reader, IfPm3EM4x50, "show standard read mode data of EM4x50"},
{"restore",CmdEM4x50Restore, IfPm3EM4x50, "restore EM4x50 dump to tag"},
{"restore", CmdEM4x50Restore, IfPm3EM4x50, "restore EM4x50 dump to tag"},
{"sim", CmdEM4x50Sim, IfPm3EM4x50, "simulate EM4x50 tag"},
{"eload", CmdEM4x50ELoad, IfPm3EM4x50, "upload dump of EM4x50 to flash memory"},
{"esave", CmdEM4x50ESave, IfPm3EM4x50, "save flash memory to file"},
+150 -25
View File
@@ -31,26 +31,26 @@ static void print_info_result(uint8_t *data) {
// data section
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, _YELLOW_("EM4x70 data:"));
for(int i=1; i <= 32; i+=2) {
PrintAndLogEx(NORMAL, "%02X %02X", data[32-i], data[32-i-1]);
for (int i = 1; i <= 32; i += 2) {
PrintAndLogEx(NORMAL, "%02X %02X", data[32 - i], data[32 - i - 1]);
}
PrintAndLogEx(NORMAL, "Tag ID: %02X %02X %02X %02X", data[7], data[6], data[5], data[4]);
PrintAndLogEx(NORMAL, "Lockbit 0: %d %s", (data[3] & 0x40) ? 1:0, (data[3] & 0x40) ? "LOCKED":"UNLOCKED");
PrintAndLogEx(NORMAL, "Lockbit 1: %d", (data[3] & 0x80) ? 1:0);
PrintAndLogEx(NORMAL, "Lockbit 0: %d %s", (data[3] & 0x40) ? 1 : 0, (data[3] & 0x40) ? "LOCKED" : "UNLOCKED");
PrintAndLogEx(NORMAL, "Lockbit 1: %d", (data[3] & 0x80) ? 1 : 0);
PrintAndLogEx(NORMAL, "");
}
int em4x70_info(void) {
em4x70_data_t edata = {
.parity = false // TODO: try both? or default to true
};
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X70_INFO, (uint8_t *)&edata, sizeof(edata));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X70_INFO, &resp, TIMEOUT)) {
PrintAndLogEx(WARNING, "(em4x70) timeout while waiting for reply.");
@@ -80,18 +80,18 @@ int CmdEM4x70Info(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x10 info",
CLIParserInit(&ctx, "lf em 4x70 info",
"Tag Information EM4x70\n"
" Tag variants include ID48 automotive transponder.\n"
" ID48 does not use command parity (default).\n"
" V4070 and EM4170 do require parity bit.",
"lf em 4x70 info\n"
"lf em 4x70 info -p -> adds parity bit to command\n"
);
"lf em 4x70 info --par -> adds parity bit to command\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("p", "parity", "Add parity bit when sending commands"),
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
arg_param_end
};
@@ -104,7 +104,7 @@ int CmdEM4x70Info(const char *Cmd) {
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X70_INFO, &resp, TIMEOUT)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
PrintAndLogEx(WARNING, "Timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
@@ -113,7 +113,7 @@ int CmdEM4x70Info(const char *Cmd) {
return PM3_SUCCESS;
}
PrintAndLogEx(FAILED, "reading tag " _RED_("failed"));
PrintAndLogEx(FAILED, "Reading " _RED_("Failed"));
return PM3_ESOFT;
}
@@ -124,26 +124,26 @@ int CmdEM4x70Write(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x10 write",
CLIParserInit(&ctx, "lf em 4x70 write",
"Write EM4x70\n",
"lf em 4x70 write -b 15 d c0de -> write 'c0de' to block 15\n"
"lf em 4x70 write -p -b 15 -d c0de -> adds parity bit to commands\n"
);
"lf em 4x70 write -b 15 -d c0de -> write 'c0de' to block 15\n"
"lf em 4x70 write -b 15 -d c0de --par -> adds parity bit to commands\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("p", "parity", "Add parity bit when sending commands"),
arg_int1("b", "block", "<dec>", "block/word address, dec"),
arg_str1("d", "data", "<hex>", "data, 2 bytes"),
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
arg_int1("b", "block", "<dec>", "block/word address, dec"),
arg_str1("d", "data", "<hex>", "data, 2 bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
etd.parity = arg_get_lit(ctx, 1);
int addr = arg_get_int(ctx, 2);
int word_len = 0;
uint8_t word[2] = {0x0};
CLIGetHexWithReturn(ctx, 3, word, &word_len);
@@ -153,8 +153,8 @@ int CmdEM4x70Write(const char *Cmd) {
if (addr < 0 || addr >= EM4X70_NUM_BLOCKS) {
PrintAndLogEx(FAILED, "block has to be within range [0, 15]");
return PM3_EINVARG;
}
}
if (word_len != 2) {
PrintAndLogEx(FAILED, "word/data length must be 2 bytes instead of %d", word_len);
return PM3_EINVARG;
@@ -181,10 +181,135 @@ int CmdEM4x70Write(const char *Cmd) {
return PM3_ESOFT;
}
int CmdEM4x70Unlock(const char *Cmd) {
// send pin code to device, unlocking it for writing
em4x70_data_t etd = {0};
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x70 unlock",
"Unlock EM4x70 by sending PIN\n"
"Default pin may be:\n"
" AAAAAAAA\n"
" 00000000\n",
"lf em 4x70 unlock -p 11223344 -> Unlock with PIN\n"
"lf em 4x70 unlock -p 11223344 --par -> Unlock with PIN using parity commands\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
arg_str1("p", "pin", "<hex>", "pin, 4 bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
etd.parity = arg_get_lit(ctx, 1);
int pin_len = 0;
uint8_t pin[4] = {0x0};
CLIGetHexWithReturn(ctx, 2, pin, &pin_len);
CLIParserFree(ctx);
if (pin_len != 4) {
PrintAndLogEx(FAILED, "PIN length must be 4 bytes instead of %d", pin_len);
return PM3_EINVARG;
}
etd.pin = BYTES2UINT32(pin);
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X70_UNLOCK, (uint8_t *)&etd, sizeof(etd));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X70_UNLOCK, &resp, TIMEOUT)) {
PrintAndLogEx(WARNING, "Timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
if (resp.status) {
print_info_result(resp.data.asBytes);
return PM3_SUCCESS;
}
PrintAndLogEx(FAILED, "Unlocking tag " _RED_("failed"));
return PM3_ESOFT;
}
int CmdEM4x70Auth(const char *Cmd) {
// Authenticate transponder
// Send 56-bit random number + pre-computed f(rnd, k) to transponder.
// Transponder will respond with a response
em4x70_data_t etd = {0};
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf em 4x70 auth",
"Authenticate against an EM4x70 by sending random number (RN) and F(RN)\n"
" If F(RN) is incorrect based on the tag crypt key, the tag will not respond",
"lf em 4x70 auth --rnd 11223344556677 --frn 11223344\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0(NULL, "par", "Add parity bit when sending commands"),
arg_str1(NULL, "rnd", "<hex>", "Random 56-bit"),
arg_str1(NULL, "frn", "<hex>", "F(RN) 28-bit as 4 hex bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
etd.parity = arg_get_lit(ctx, 1);
int rnd_len = 7;
CLIGetHexWithReturn(ctx, 2, etd.rnd, &rnd_len);
int frnd_len = 4;
CLIGetHexWithReturn(ctx, 3, etd.frnd, &frnd_len);
CLIParserFree(ctx);
if (rnd_len != 7) {
PrintAndLogEx(FAILED, "Random number length must be 7 bytes instead of %d", rnd_len);
return PM3_EINVARG;
}
if (frnd_len != 4) {
PrintAndLogEx(FAILED, "F(RN) length must be 4 bytes instead of %d", frnd_len);
return PM3_EINVARG;
}
clearCommandBuffer();
SendCommandNG(CMD_LF_EM4X70_AUTH, (uint8_t *)&etd, sizeof(etd));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_EM4X70_AUTH, &resp, TIMEOUT)) {
PrintAndLogEx(WARNING, "Timeout while waiting for reply.");
return PM3_ETIMEOUT;
}
if (resp.status) {
// Response is 20-bit from tag
PrintAndLogEx(INFO, "Tag Auth Response: %02X %02X %02X", resp.data.asBytes[2], resp.data.asBytes[1], resp.data.asBytes[0]);
return PM3_SUCCESS;
}
PrintAndLogEx(FAILED, "TAG Authentication " _RED_("Failed"));
return PM3_ESOFT;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"info", CmdEM4x70Info, IfPm3EM4x70, "Tag information EM4x70"},
{"write", CmdEM4x70Write, IfPm3EM4x70, "Write EM4x70"},
{"unlock", CmdEM4x70Unlock, IfPm3EM4x70, "Unlock EM4x70 for writing"},
{"auth", CmdEM4x70Auth, IfPm3EM4x70, "Authenticate EM4x70"},
{NULL, NULL, NULL, NULL}
};
+2
View File
@@ -19,6 +19,8 @@
int CmdLFEM4X70(const char *Cmd);
int CmdEM4x70Info(const char *Cmd);
int CmdEM4x70Write(const char *Cmd);
int CmdEM4x70Unlock(const char *Cmd);
int CmdEM4x70Auth(const char *Cmd);
int em4x70_info(void);
bool detect_4x70_block(void);
+6 -6
View File
@@ -727,7 +727,7 @@ static int CmdFdxBClone(const char *Cmd) {
}
uint32_t extended = 0;
bool has_extended = false;
bool has_extended = false;
if (extended_len) {
extended = bytes_to_num(edata, extended_len);
has_extended = true;
@@ -773,10 +773,10 @@ static int CmdFdxBClone(const char *Cmd) {
free(bs);
PrintAndLogEx(INFO, "Preparing to clone FDX-B to " _YELLOW_("%s") " with animal ID: " _GREEN_("%04u-%"PRIu64)
, cardtype
, country_code
, national_code
);
, cardtype
, country_code
, national_code
);
print_blocks(blocks, ARRAYLEN(blocks));
int res;
@@ -820,7 +820,7 @@ static int CmdFdxBSim(const char *Cmd) {
CLIParserFree(ctx);
uint32_t extended = 0;
bool has_extended = false;
bool has_extended = false;
if (extended_len) {
extended = bytes_to_num(edata, extended_len);
has_extended = true;
+1 -1
View File
@@ -233,7 +233,7 @@ static int CmdGallagherClone(const char *Cmd) {
static int CmdGallagherSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf gallagher sim",
"Enables simulation of GALLAGHER card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n",
+7 -7
View File
@@ -226,10 +226,10 @@ static int CmdGuardClone(const char *Cmd) {
free(bs);
PrintAndLogEx(INFO, "Preparing to clone Guardall to " _YELLOW_("%s") " with Facility Code: " _GREEN_("%u") " Card Number: " _GREEN_("%u")
, cardtype
, facilitycode
, cardnumber
);
, cardtype
, facilitycode
, cardnumber
);
print_blocks(blocks, ARRAYLEN(blocks));
int res;
@@ -281,9 +281,9 @@ static int CmdGuardSim(const char *Cmd) {
}
PrintAndLogEx(SUCCESS, "Simulating Guardall Prox - Facility Code: " _YELLOW_("%u") " CardNumber: " _YELLOW_("%u")
, facilitycode
, cardnumber
);
, facilitycode
, cardnumber
);
// Guard uses: clk: 64, invert: 0, encoding: 2 (ASK Biphase)
lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + sizeof(bs));
+6 -6
View File
@@ -60,16 +60,16 @@ static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, boo
if (HIDPack(format_idx, card, &packed) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
return PM3_ESOFT;
}
if (verbose) {
PrintAndLogEx(INFO, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%"PRIu64) " Issue level: " _YELLOW_("%u") " OEM: " _YELLOW_("%u")
, card->FacilityCode
, card->CardNumber
, card->IssueLevel
, card->OEM
);
, card->FacilityCode
, card->CardNumber
, card->IssueLevel
, card->OEM
);
}
lf_hidsim_t payload;

Some files were not shown because too many files have changed in this diff Show More