mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 15:26:13 +08:00
Merge branch 'master' into allin
update
This commit is contained in:
commit
b0cfb28d40
|
@ -3,8 +3,11 @@ 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...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Add lf t55xx chk e <EM4100> option. Checks calculated password based on the EM4100 id from some white cloners forumla by paleopterix (@mwalker33)
|
||||
- Add lf t55xx sniff to allow extracting commands and passwords used be cloners. (@mwalker33)
|
||||
- Add low level support for 14b' aka Innovatron (@doegox)
|
||||
- Add doc/cliparser.md (@mwalker33)
|
||||
- Add `hf 14b apdu` - send APDU over ISO14443B (@iceman1001)
|
||||
- Add `lf t55xx chk e <EM4100> option` - Checks calculated password based on the EM4100 id from some white cloners forumla by paleopterix (@mwalker33)
|
||||
- Add `lf t55xx sniff` to allow extracting commands and passwords used be cloners. (@mwalker33)
|
||||
- Add options to `lf read`, `lf cmdread`, `lf sniff` for repeated acquisitions (@doegox)
|
||||
- Change options of `lf read` to match `lf cmdread`, this affects historical `d` and `s` options (@doegox)
|
||||
- Add `hf waveshare` to upload picture to Waveshare NFC-Powered e-Paper (@doegox)
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)|
|
||||
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic cards](/doc/magic_cards_notes.md)|
|
||||
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)|
|
||||
|
||||
|[Notes on cliparser usage](/doc/cliparser.md)|||
|
||||
|
||||
## Build for non-RDV4 Proxmark3 platforms
|
||||
|
||||
|
|
|
@ -292,6 +292,12 @@ void tosend_reset(void) {
|
|||
}
|
||||
|
||||
void tosend_stuffbit(int b) {
|
||||
|
||||
if (toSend.max >= TOSEND_BUFFER_SIZE - 1) {
|
||||
Dbprintf(_RED_("toSend overflow"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (toSend.bit >= 8) {
|
||||
toSend.max++;
|
||||
toSend.buf[toSend.max] = 0;
|
||||
|
@ -299,7 +305,7 @@ void tosend_stuffbit(int b) {
|
|||
}
|
||||
|
||||
if (b)
|
||||
toSend.buf[ toSend.max] |= (1 << (7 - toSend.bit));
|
||||
toSend.buf[toSend.max] |= (1 << (7 - toSend.bit));
|
||||
|
||||
toSend.bit++;
|
||||
|
||||
|
|
|
@ -1138,11 +1138,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443B_SIMULATE: {
|
||||
SimulateIso14443bTag(packet->oldarg[0]);
|
||||
SimulateIso14443bTag(packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443B_COMMAND: {
|
||||
//SendRawCommand14443B(packet->oldarg[0],packet->oldarg[1],packet->oldarg[2],packet->data.asBytes);
|
||||
SendRawCommand14443B_Ex(packet);
|
||||
break;
|
||||
}
|
||||
|
|
13
armsrc/epa.c
13
armsrc/epa.c
|
@ -118,7 +118,7 @@ static int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response, uint16_t re
|
|||
case 'a':
|
||||
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
|
||||
case 'b':
|
||||
return iso14443b_apdu(apdu, length, response, respmaxlen);
|
||||
return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -222,14 +222,13 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
|
|||
// since the card doesn't always care for the expected length we send it,
|
||||
// we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame)
|
||||
uint8_t response_apdu[262];
|
||||
int rapdu_length = 0;
|
||||
|
||||
// select the file EF.CardAccess
|
||||
rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess,
|
||||
sizeof(apdu_select_binary_cardaccess),
|
||||
response_apdu,
|
||||
sizeof(response_apdu)
|
||||
);
|
||||
int rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess,
|
||||
sizeof(apdu_select_binary_cardaccess),
|
||||
response_apdu,
|
||||
sizeof(response_apdu)
|
||||
);
|
||||
|
||||
if (rapdu_length < 6
|
||||
|| response_apdu[rapdu_length - 4] != 0x90
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "commonutil.h"
|
||||
#include "dbprint.h"
|
||||
#include "ticks.h"
|
||||
#include "mifare.h"
|
||||
#include "iso18.h"
|
||||
|
||||
// FeliCa timings
|
||||
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles
|
||||
|
|
|
@ -1747,6 +1747,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
|
||||
// init as reader
|
||||
lf_init(true, false);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
||||
// Tag specific configuration settings (sof, timings, etc.)
|
||||
// TODO HTS
|
||||
|
@ -1780,9 +1781,10 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
size_t max_nrzs = (8 * HITAG_FRAME_LEN + 5) * 2; // up to 2 nrzs per bit
|
||||
uint8_t nrz_samples[max_nrzs];
|
||||
size_t nrzs = 0;
|
||||
|
||||
int16_t checked = 0;
|
||||
uint32_t signal_size = 10000;
|
||||
bool turn_on = true;
|
||||
|
||||
while (bStop == false && BUTTON_PRESS() == false) {
|
||||
|
||||
// use malloc
|
||||
|
@ -1818,9 +1820,20 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
}
|
||||
}
|
||||
|
||||
// Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
|
||||
lf_wait_periods(t_wait_2);
|
||||
command_start += t_wait_2;
|
||||
if (bStop) break;
|
||||
if (turn_on) {
|
||||
// Wait 50ms with field off to be sure the transponder gets reset
|
||||
SpinDelay(50);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||
turn_on = false;
|
||||
// Wait with field on to be in "Wait for START_AUTH" timeframe
|
||||
lf_wait_periods(HITAG_T_WAIT_POWERUP + HITAG_T_WAIT_START_AUTH_MAX / 4);
|
||||
command_start += HITAG_T_WAIT_POWERUP + HITAG_T_WAIT_START_AUTH_MAX / 4;
|
||||
} else {
|
||||
// Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
|
||||
lf_wait_periods(t_wait_2);
|
||||
command_start += t_wait_2;
|
||||
}
|
||||
|
||||
// Transmit the reader frame
|
||||
command_duration = hitag_reader_send_frame(tx, txlen);
|
||||
|
|
|
@ -41,15 +41,18 @@
|
|||
|
||||
// defaults to 2000ms
|
||||
#ifndef FWT_TIMEOUT_14B
|
||||
# define FWT_TIMEOUT_14B 35312
|
||||
# define FWT_TIMEOUT_14B 35312
|
||||
#endif
|
||||
|
||||
// 1 tick == 1/13.56 mhz
|
||||
// 1 us = 1.5 tick
|
||||
|
||||
// 330/848kHz = 1558us / 4 == 400us,
|
||||
#define ISO14443B_READER_TIMEOUT 1700 //330
|
||||
#define ISO14443B_READER_TIMEOUT 10000 //330
|
||||
|
||||
// 1024/3.39MHz = 302.1us between end of tag response and next reader cmd
|
||||
#define DELAY_ISO14443B_VICC_TO_VCD_READER 600 // 1024
|
||||
#define DELAY_ISO14443B_VCD_TO_VICC_READER 600// 1056
|
||||
#define DELAY_ISO14443B_VICC_TO_VCD_READER (28*9) // 1024 ( counting from start of PICC EOF 14 ETU's)
|
||||
#define DELAY_ISO14443B_VCD_TO_VICC_READER (28*9) // 1056
|
||||
|
||||
#ifndef RECEIVE_MASK
|
||||
# define RECEIVE_MASK (DMA_BUFFER_SIZE - 1)
|
||||
|
@ -57,7 +60,7 @@
|
|||
|
||||
// Guard Time (per 14443-2)
|
||||
#ifndef TR0
|
||||
# define TR0 64 // TR0 max is 256/fs = 256/(848kHz) = 302us or 64 samples from FPGA
|
||||
# define TR0 32 // TR0 max is 151/fs = 151/(848kHz) = 302us or 64 samples from FPGA
|
||||
#endif
|
||||
|
||||
// Synchronization time (per 14443-2)
|
||||
|
@ -76,10 +79,9 @@ static void iso14b_set_timeout(uint32_t timeout);
|
|||
static void iso14b_set_maxframesize(uint16_t size);
|
||||
|
||||
// the block number for the ISO14443-4 PCB (used with APDUs)
|
||||
static uint8_t pcb_blocknum = 0;
|
||||
static uint8_t iso14b_pcb_blocknum = 0;
|
||||
static uint32_t iso14b_timeout = FWT_TIMEOUT_14B;
|
||||
|
||||
|
||||
/* ISO 14443 B
|
||||
*
|
||||
* Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig)
|
||||
|
@ -272,8 +274,7 @@ static struct {
|
|||
enum {
|
||||
DEMOD_UNSYNCD,
|
||||
DEMOD_PHASE_REF_TRAINING,
|
||||
DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
|
||||
DEMOD_GOT_FALLING_EDGE_OF_SOF,
|
||||
WAIT_FOR_RISING_EDGE_OF_SOF,
|
||||
DEMOD_AWAITING_START_BIT,
|
||||
DEMOD_RECEIVING_DATA
|
||||
} state;
|
||||
|
@ -306,7 +307,6 @@ static void Demod14bInit(uint8_t *data, uint16_t max_len) {
|
|||
Demod14bReset();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 9.4395 us = 1 ETU and clock is about 1.5 us
|
||||
* 13560000Hz
|
||||
|
@ -530,7 +530,7 @@ static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) {
|
|||
// Main loop of simulated tag: receive commands from reader, decide what
|
||||
// response to send, and send it.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SimulateIso14443bTag(uint32_t pupi) {
|
||||
void SimulateIso14443bTag(uint8_t *pupi) {
|
||||
|
||||
LED_A_ON();
|
||||
// the only commands we understand is WUPB, AFI=0, Select All, N=1:
|
||||
|
@ -553,15 +553,15 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
|||
0x5e, 0xd7
|
||||
};
|
||||
|
||||
// response to HLTB and ATTRIB
|
||||
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
|
||||
|
||||
// ...PUPI/UID supplied from user. Adjust ATQB response accordingly
|
||||
if (pupi > 0) {
|
||||
num_to_bytes(pupi, 4, respATQB + 1);
|
||||
if (memcmp("\x00\x00\x00\x00", pupi, 4) != 0) {
|
||||
memcpy(respATQB + 1, pupi, 4);
|
||||
AddCrc14B(respATQB, 12);
|
||||
}
|
||||
|
||||
// response to HLTB and ATTRIB
|
||||
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
|
||||
|
||||
// setup device.
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
|
@ -723,6 +723,13 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
|||
// tag's response, which we leave in the buffer to be demodulated on the
|
||||
// PC side.
|
||||
//=============================================================================
|
||||
// We support both 14b framing and 14b' framing.
|
||||
// 14b framing looks like:
|
||||
// xxxxxxxx1111111111111111-000000000011-0........1-0........1-0........1-1-0........1-0........1-1000000000011xxxxxx
|
||||
// TR1 SOF 10*0+2*1 start-stop ^^^^^^^^byte ^ occasional stuff bit EOF 10*0+N*1
|
||||
// 14b' framing looks like:
|
||||
// xxxxxxxxxxxxxxxx111111111111111111111-0........1-0........1-0........1-1-0........1-0........1-000000000000xxxxxxx
|
||||
// SOF? start-stop ^^^^^^^^byte ^ occasional stuff bit EOF
|
||||
|
||||
/*
|
||||
* Handles reception of a bit from the tag
|
||||
|
@ -740,7 +747,7 @@ void SimulateIso14443bTag(uint32_t pupi) {
|
|||
*/
|
||||
static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
||||
|
||||
int v;
|
||||
int v = 0;
|
||||
|
||||
// The soft decision on the bit uses an estimate of just the
|
||||
// quadrant of the reference angle, not the exact angle.
|
||||
|
@ -757,7 +764,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
} \
|
||||
}
|
||||
|
||||
#define SUBCARRIER_DETECT_THRESHOLD 8
|
||||
#define SUBCARRIER_DETECT_THRESHOLD 8
|
||||
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
|
||||
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
|
||||
|
||||
|
@ -773,57 +780,33 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
break;
|
||||
}
|
||||
case DEMOD_PHASE_REF_TRAINING: {
|
||||
if (Demod.posCount < 8) {
|
||||
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
|
||||
// note: synchronization time > 80 1/fs
|
||||
Demod.sumI += ci;
|
||||
Demod.sumQ += cq;
|
||||
Demod.posCount++;
|
||||
// While we get a constant signal
|
||||
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||
if (((ABS(Demod.sumI) > ABS(Demod.sumQ)) && (((ci > 0) && (Demod.sumI > 0)) || ((ci < 0) && (Demod.sumI < 0)))) || // signal closer to horizontal, polarity check based on on I
|
||||
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
|
||||
if (Demod.posCount < 10) { // refine signal approximation during first 10 samples
|
||||
Demod.sumI += ci;
|
||||
Demod.sumQ += cq;
|
||||
}
|
||||
Demod.posCount += 1;
|
||||
} else {
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
// transition
|
||||
if (Demod.posCount < 10) {
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
break;
|
||||
} else {
|
||||
// at this point it can be start of 14b' data or start of 14b SOF
|
||||
MAKE_SOFT_DECISION();
|
||||
Demod.posCount = 1; // this was the first half
|
||||
Demod.thisBit = v;
|
||||
Demod.shiftReg = 0;
|
||||
Demod.state = DEMOD_RECEIVING_DATA;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: {
|
||||
|
||||
MAKE_SOFT_DECISION();
|
||||
|
||||
if (v < 0) { // logic '0' detected
|
||||
Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
|
||||
Demod.posCount = 0; // start of SOF sequence
|
||||
} else {
|
||||
if (Demod.posCount > 200 / 4) { // maximum length of TR1 = 200 1/fs
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
}
|
||||
Demod.posCount++;
|
||||
break;
|
||||
}
|
||||
case DEMOD_GOT_FALLING_EDGE_OF_SOF: {
|
||||
|
||||
Demod.posCount++;
|
||||
MAKE_SOFT_DECISION();
|
||||
|
||||
if (v > 0) {
|
||||
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
} else {
|
||||
LED_C_ON(); // Got SOF
|
||||
Demod.posCount = 0;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
}
|
||||
} else {
|
||||
if (Demod.posCount > 14 * 2) { // low phase of SOF too long (> 12 etu)
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
LED_C_OFF();
|
||||
}
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -831,7 +814,7 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
Demod.posCount++;
|
||||
MAKE_SOFT_DECISION();
|
||||
if (v > 0) {
|
||||
if (Demod.posCount > 6 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
|
||||
if (Demod.posCount > 3 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
|
||||
LED_C_OFF();
|
||||
if (Demod.bitCount == 0 && Demod.len == 0) { // received SOF only, this is valid for iClass/Picopass
|
||||
return true;
|
||||
|
@ -847,6 +830,28 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case WAIT_FOR_RISING_EDGE_OF_SOF: {
|
||||
|
||||
Demod.posCount++;
|
||||
MAKE_SOFT_DECISION();
|
||||
if (v > 0) {
|
||||
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
} else {
|
||||
LED_C_ON(); // Got SOF
|
||||
Demod.posCount = 0;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
}
|
||||
} else {
|
||||
if (Demod.posCount > 12 * 2) { // low phase of SOF too long (> 12 etu)
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
LED_C_OFF();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DEMOD_RECEIVING_DATA: {
|
||||
|
||||
MAKE_SOFT_DECISION();
|
||||
|
@ -873,12 +878,35 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
Demod.bitCount = 0;
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
} else {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
LED_C_OFF();
|
||||
if (s == 0x000) {
|
||||
// This is EOF (start, stop and all data bits == '0'
|
||||
return true;
|
||||
if (Demod.len > 0) {
|
||||
LED_C_OFF();
|
||||
// This is EOF (start, stop and all data bits == '0'
|
||||
return true;
|
||||
} else {
|
||||
// Zeroes but no data acquired yet?
|
||||
// => Still in SOF of 14b, wait for raising edge
|
||||
Demod.posCount = 10 * 2;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = WAIT_FOR_RISING_EDGE_OF_SOF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AMPLITUDE(ci, cq) < SUBCARRIER_DETECT_THRESHOLD) {
|
||||
LED_C_OFF();
|
||||
// subcarrier lost
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
if (Demod.len > 0) { // no EOF but no signal anymore and we got data, e.g. ASK CTx
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// we have still signal but no proper byte or EOF? this shouldn't happen
|
||||
//Demod.posCount = 10 * 2;
|
||||
Demod.bitCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.state = WAIT_FOR_RISING_EDGE_OF_SOF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Demod.posCount = 0;
|
||||
|
@ -894,25 +922,18 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Demodulate the samples we received from the tag, also log to tracebuffer
|
||||
*/
|
||||
static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeout, uint32_t *eof_time) {
|
||||
|
||||
|
||||
int samples = 0, ret = 0;
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
Demod14bInit(response, max_len);
|
||||
|
||||
// wait for last transfer to complete
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) {};
|
||||
|
||||
// And put the FPGA in the appropriate mode
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_848_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
|
||||
|
||||
|
||||
// Setup and start DMA.
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
|
||||
//FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
|
||||
|
||||
// The DMA buffer, used to stream samples from the FPGA
|
||||
dmabuf16_t *dma = get_dma16();
|
||||
|
@ -924,6 +945,9 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
|||
uint32_t dma_start_time = 0;
|
||||
uint16_t *upTo = dma->buf;
|
||||
|
||||
// Put FPGA in the appropriate mode
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_848_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
|
||||
|
||||
for (;;) {
|
||||
|
||||
volatile uint16_t behindBy = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1);
|
||||
|
@ -971,7 +995,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
|||
|
||||
if (Handle14443bSamplesFromTag(ci, cq)) {
|
||||
|
||||
*eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM; // end of EOF
|
||||
*eof_time = dma_start_time + (samples ) - DELAY_TAG_TO_ARM; // end of EOF
|
||||
|
||||
if (Demod.len > Demod.max_len) {
|
||||
ret = -2; // overflow
|
||||
|
@ -986,19 +1010,17 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, int timeo
|
|||
}
|
||||
|
||||
FpgaDisableSscDma();
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (Demod.len > 0) {
|
||||
uint32_t sof_time = *eof_time
|
||||
- (Demod.len * 8 * 8 * 16) // time for byte transfers
|
||||
- (32 * 16) // time for SOF transfer
|
||||
- 0; // time for EOF transfer
|
||||
- (Demod.len * (8 + 2)) // time for byte transfers
|
||||
- (12) // time for SOF transfer
|
||||
- (12); // time for EOF transfer
|
||||
LogTrace(Demod.output, Demod.len, (sof_time * 4), (*eof_time * 4), NULL, false);
|
||||
}
|
||||
|
||||
return Demod.len;
|
||||
}
|
||||
|
||||
|
@ -1011,6 +1033,7 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
|||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_SHALLOW_MOD);
|
||||
|
||||
// TR2 minimum 14 ETUs
|
||||
if (*start_time < DELAY_ARM_TO_TAG) {
|
||||
*start_time = DELAY_ARM_TO_TAG;
|
||||
}
|
||||
|
@ -1018,21 +1041,20 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
|||
*start_time = (*start_time - DELAY_ARM_TO_TAG) & 0xfffffff0;
|
||||
|
||||
if (GetCountSspClk() > *start_time) { // we may miss the intended time
|
||||
*start_time = (GetCountSspClk() + 16) & 0xfffffff0; // next possible time
|
||||
*start_time = (GetCountSspClk() + 32) & 0xfffffff0; // next possible time
|
||||
}
|
||||
|
||||
|
||||
// wait
|
||||
while (GetCountSspClk() < *start_time) ;
|
||||
while (GetCountSspClk() < *start_time);
|
||||
|
||||
LED_B_ON();
|
||||
for (int c = 0; c < ts->max; c++) {
|
||||
volatile uint8_t data = ts->buf[c];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint16_t send_word = (data & 0x80) ? 0x0000 : 0xffff;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
volatile uint16_t send_word = (data & 0x80) ? 0x0000 : 0xFFFF;
|
||||
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ;
|
||||
|
||||
AT91C_BASE_SSC->SSC_THR = send_word;
|
||||
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ;
|
||||
|
@ -1045,6 +1067,9 @@ static void TransmitFor14443b_AsReader(uint32_t *start_time) {
|
|||
LED_B_OFF();
|
||||
|
||||
*start_time += DELAY_ARM_TO_TAG;
|
||||
|
||||
// wait for last transfer to complete
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) {};
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1061,32 +1086,38 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
|||
* - no modulation ONES
|
||||
*
|
||||
* 1 ETU == 1 BIT!
|
||||
* TR0 - 8 ETUS minimum.
|
||||
* TR0 - 8 ETU's minimum.
|
||||
* TR0 - 32 ETU's maximum for ATQB only
|
||||
* TR0 - FWT for all other commands
|
||||
*
|
||||
* QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode?
|
||||
* 1 "stuffbit" = 1ETU (9us)
|
||||
*
|
||||
* TR2 - After the PICC response, the PCD is required to wait the Frame Delay Time (TR2)
|
||||
before transmission of the next command. The minimum frame delay time required for
|
||||
all commands is 14 ETUs
|
||||
*
|
||||
*/
|
||||
|
||||
int i;
|
||||
tosend_reset();
|
||||
|
||||
|
||||
// Send SOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (i = 0; i < 10; i++) {
|
||||
tosend_stuffbit(0);
|
||||
|
||||
|
||||
}
|
||||
// 2-3 ETUs of ONE
|
||||
tosend_stuffbit(1);
|
||||
tosend_stuffbit(1);
|
||||
|
||||
// Sending cmd, LSB
|
||||
// from here we add BITS
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
// Start bit
|
||||
tosend_stuffbit(0);
|
||||
// Data bits
|
||||
uint8_t b = cmd[i];
|
||||
|
||||
// Data bits
|
||||
volatile uint8_t b = cmd[i];
|
||||
tosend_stuffbit(b & 1);
|
||||
tosend_stuffbit((b >> 1) & 1);
|
||||
tosend_stuffbit((b >> 2) & 1);
|
||||
|
@ -1098,31 +1129,29 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
|
|||
|
||||
// Stop bit
|
||||
tosend_stuffbit(1);
|
||||
// EGT extra guard time
|
||||
// For PCD it ranges 0-57us (1etu = 9us)
|
||||
// tosend_stuffbit(1);
|
||||
// tosend_stuffbit(1);
|
||||
// tosend_stuffbit(1);
|
||||
// EGT extra guard time 1 ETU = 9us
|
||||
// For PCD it ranges 0-57us === 0 - 6 ETU
|
||||
// FOR PICC it ranges 0-19us == 0 - 2 ETU
|
||||
|
||||
}
|
||||
|
||||
// Send EOF
|
||||
// 10-11 ETUs of ZERO
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (i = 0; i < 10; i++) {
|
||||
tosend_stuffbit(0);
|
||||
}
|
||||
|
||||
// Transition time. TR0 - guard time
|
||||
// 8ETUS minum?
|
||||
// Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF.
|
||||
// I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode
|
||||
tosend_stuffbit(1);
|
||||
/* Transition time. TR0 - guard time
|
||||
* TR0 - 8 ETU's minimum.
|
||||
* TR0 - 32 ETU's maximum for ATQB only
|
||||
* TR0 - FWT for all other commands
|
||||
* 32,64,128,256,512, ... , 262144, 524288 ETU
|
||||
*/
|
||||
int pad = (12 + (len * 10) + 11) & 0x7;
|
||||
|
||||
// ensure that last byte is filled up
|
||||
for (int i = 0; i < 8 ; ++i)
|
||||
for (i = 0; i < 16 - pad; ++i)
|
||||
tosend_stuffbit(1);
|
||||
|
||||
// TR1 - Synchronization time
|
||||
// Convert from last character reference to length
|
||||
tosend_t *ts = get_tosend();
|
||||
ts->max++;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1132,56 +1161,175 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t
|
|||
tosend_t *ts = get_tosend();
|
||||
CodeIso14443bAsReader(cmd, len);
|
||||
TransmitFor14443b_AsReader(start_time);
|
||||
*eof_time = *start_time + (32 * (8 * ts->max));
|
||||
*eof_time = *start_time + (10 * ts->max) + 10 + 2 + 10;
|
||||
LogTrace(cmd, len, *start_time, *eof_time, NULL, true);
|
||||
}
|
||||
|
||||
/* Sends an APDU to the tag
|
||||
* TODO: check CRC and preamble
|
||||
*/
|
||||
int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response, uint16_t respmaxlen) {
|
||||
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res) {
|
||||
|
||||
LED_A_ON();
|
||||
uint8_t message_frame[message_length + 4];
|
||||
// PCB
|
||||
message_frame[0] = 0x0A | pcb_blocknum;
|
||||
pcb_blocknum ^= 1;
|
||||
// CID
|
||||
message_frame[1] = 0;
|
||||
// INF
|
||||
memcpy(message_frame + 2, message, message_length);
|
||||
// EDC (CRC)
|
||||
AddCrc14B(message_frame, message_length + 2);
|
||||
uint8_t real_cmd[msg_len + 4];
|
||||
|
||||
if (msg_len) {
|
||||
// ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02
|
||||
real_cmd[0] = 0x02; // bnr, nad, cid, chn=0; i-block(0x00)
|
||||
if (send_chaining) {
|
||||
real_cmd[0] |= 0x10;
|
||||
}
|
||||
// put block number into the PCB
|
||||
real_cmd[0] |= iso14b_pcb_blocknum;
|
||||
memcpy(real_cmd + 1, msg, msg_len);
|
||||
} else {
|
||||
// R-block. ACK
|
||||
real_cmd[0] = 0xA2; // r-block + ACK
|
||||
real_cmd[0] |= iso14b_pcb_blocknum;
|
||||
}
|
||||
|
||||
AddCrc14B(real_cmd, msg_len + 1);
|
||||
|
||||
// send
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(message_frame, sizeof(message_frame), &start_time, &eof_time);
|
||||
|
||||
// Get response?
|
||||
if (response == NULL) {
|
||||
LED_A_OFF();
|
||||
return 0;
|
||||
}
|
||||
CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
int retlen = Get14443bAnswerFromTag(response, respmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen < 3) {
|
||||
LED_A_OFF();
|
||||
return -1;
|
||||
uint8_t *data_bytes = (uint8_t *) rxdata;
|
||||
|
||||
if (len <= 0) {
|
||||
return 0; //DATA LINK ERROR
|
||||
} else {
|
||||
// S-Block WTX
|
||||
while (len && ((data_bytes[0] & 0xF2) == 0xF2)) {
|
||||
uint32_t save_iso14b_timeout = iso14b_timeout;
|
||||
// temporarily increase timeout
|
||||
iso14b_set_timeout(MAX((data_bytes[1] & 0x3f) * save_iso14b_timeout, ISO14443B_READER_TIMEOUT));
|
||||
// Transmit WTX back
|
||||
// byte1 - WTXM [1..59]. command FWT = FWT * WTXM
|
||||
data_bytes[1] = data_bytes[1] & 0x3f; // 2 high bits mandatory set to 0b
|
||||
// now need to fix CRC.
|
||||
AddCrc14B(data_bytes, len - 2);
|
||||
|
||||
// transmit S-Block
|
||||
CodeAndTransmit14443bAsReader(data_bytes, len, &start_time, &eof_time);
|
||||
|
||||
// retrieve the result again (with increased timeout)
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
len = Get14443bAnswerFromTag(rxdata, rxmaxlen, ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
data_bytes = rxdata;
|
||||
// restore timeout
|
||||
iso14b_set_timeout(save_iso14b_timeout);
|
||||
}
|
||||
|
||||
// if we received an I- or R(ACK)-Block with a block number equal to the
|
||||
// current block number, toggle the current block number
|
||||
if (len >= 3 // PCB + CRC = 3 bytes
|
||||
&& ((data_bytes[0] & 0xC0) == 0 // I-Block
|
||||
|| (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
||||
&& (data_bytes[0] & 0x01) == iso14b_pcb_blocknum) { // equal block numbers
|
||||
iso14b_pcb_blocknum ^= 1;
|
||||
}
|
||||
|
||||
// if we received I-block with chaining we need to send ACK and receive another block of data
|
||||
if (res)
|
||||
*res = data_bytes[0];
|
||||
|
||||
// crc check
|
||||
if (len >= 3 && !check_crc(CRC_14443_B, data_bytes, len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// VALIDATE CRC
|
||||
if (!check_crc(CRC_14443_B, response, retlen)) {
|
||||
if (DBGLEVEL > DBG_DEBUG) DbpString("CRC fail");
|
||||
if (len) {
|
||||
// cut frame byte
|
||||
len -= 1;
|
||||
// memmove(data_bytes, data_bytes + 1, len);
|
||||
for (int i = 0; i < len; i++)
|
||||
data_bytes[i] = data_bytes[i + 1];
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* ASK CTS initialise.
|
||||
*/
|
||||
static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
|
||||
// INITIATE command: wake up the tag using the INITIATE
|
||||
uint8_t cmdINIT[] = {ASK_REQT, 0xF9, 0xE0};
|
||||
uint8_t cmdMSBUID[] = {ASK_SELECT, 0xFF, 0xFF, 0x00, 0x00};
|
||||
uint8_t cmdLSBUID[] = {0xC4, 0x00, 0x00};
|
||||
|
||||
AddCrc14B(cmdMSBUID, 3);
|
||||
AddCrc14B(cmdLSBUID, 1);
|
||||
|
||||
uint8_t r[8];
|
||||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(cmdINIT, sizeof(cmdINIT), &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
int retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen != 4) {
|
||||
return -1;
|
||||
}
|
||||
if (check_crc(CRC_14443_B, r, retlen) == false) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return retlen;
|
||||
}
|
||||
if (card) {
|
||||
// pc. fc Product code, Facility code
|
||||
card->pc = r[0];
|
||||
card->fc = r[1];
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
||||
CodeAndTransmit14443bAsReader(cmdMSBUID, sizeof(cmdMSBUID), &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen != 4) {
|
||||
return -1;
|
||||
}
|
||||
if (check_crc(CRC_14443_B, r, retlen) == false) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
memcpy(card->uid, r, 2);
|
||||
}
|
||||
|
||||
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
|
||||
CodeAndTransmit14443bAsReader(cmdLSBUID, sizeof(cmdLSBUID), &start_time, &eof_time);
|
||||
|
||||
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
|
||||
retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen != 4) {
|
||||
return -1;
|
||||
}
|
||||
if (check_crc(CRC_14443_B, r, retlen) == false) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (card) {
|
||||
memcpy(card->uid + 2, r, 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* SRx Initialise.
|
||||
*/
|
||||
|
@ -1200,8 +1348,9 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
int retlen = Get14443bAnswerFromTag(r_init, sizeof(r_init), ISO14443B_READER_TIMEOUT, &eof_time);
|
||||
FpgaDisableTracing();
|
||||
|
||||
if (retlen <= 0)
|
||||
if (retlen <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Randomly generated Chip ID
|
||||
if (card) {
|
||||
|
@ -1224,8 +1373,6 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
if (retlen != 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check the CRC of the answer:
|
||||
if (!check_crc(CRC_14443_B, r_select, retlen)) {
|
||||
return -2;
|
||||
}
|
||||
|
@ -1250,8 +1397,6 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
if (retlen != 10) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// The check the CRC of the answer
|
||||
if (!check_crc(CRC_14443_B, r_papid, retlen)) {
|
||||
return -2;
|
||||
}
|
||||
|
@ -1272,7 +1417,10 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
|
|||
int iso14443b_select_card(iso14b_card_select_t *card) {
|
||||
// WUPB command (including CRC)
|
||||
// Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state
|
||||
static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
|
||||
// WUTB or REQB is denoted in the third byte, lower nibble. 0 vs 8
|
||||
//static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
|
||||
static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xff };
|
||||
|
||||
// ATTRIB command (with space for CRC)
|
||||
uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
|
@ -1350,7 +1498,7 @@ int iso14443b_select_card(iso14b_card_select_t *card) {
|
|||
}
|
||||
}
|
||||
// reset PCB block number
|
||||
pcb_blocknum = 0;
|
||||
iso14b_pcb_blocknum = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1641,7 +1789,7 @@ void SniffIso14443b(void) {
|
|||
expect_tag_answer = false;
|
||||
tag_is_active = false;
|
||||
} else {
|
||||
tag_is_active = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF);
|
||||
tag_is_active = (Demod.state > WAIT_FOR_RISING_EDGE_OF_SOF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1683,6 +1831,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
size_t len = c->oldarg[1] & 0xffff;
|
||||
uint32_t timeout = c->oldarg[2];
|
||||
uint8_t *cmd = c->data.asBytes;
|
||||
uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00};
|
||||
|
||||
if (DBGLEVEL > DBG_DEBUG) Dbprintf("14b raw: param, %04x", param);
|
||||
|
||||
|
@ -1718,10 +1867,20 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
if (status > 0) goto out;
|
||||
}
|
||||
|
||||
if ((param & ISO14B_SELECT_CTS) == ISO14B_SELECT_CTS) {
|
||||
iso14b_cts_card_select_t cts;
|
||||
sendlen = sizeof(iso14b_cts_card_select_t);
|
||||
status = iso14443b_select_cts_card(&cts);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&cts, sendlen);
|
||||
// 0: OK 2: demod fail, 3:crc fail,
|
||||
if (status > 0) goto out;
|
||||
}
|
||||
|
||||
if ((param & ISO14B_APDU) == ISO14B_APDU) {
|
||||
uint8_t buf[100] = {0};
|
||||
status = iso14443b_apdu(cmd, len, buf, sizeof(buf));
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, status, 0, buf, status);
|
||||
uint8_t res;
|
||||
status = iso14443b_apdu(cmd, len, (param & ISO14B_SEND_CHAINING), buf, sizeof(buf), &res);
|
||||
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
|
||||
reply_mix(CMD_HF_ISO14443B_COMMAND, status, res, 0, buf, sendlen);
|
||||
}
|
||||
|
||||
if ((param & ISO14B_RAW) == ISO14B_RAW) {
|
||||
|
@ -1729,8 +1888,6 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
|
|||
AddCrc14B(cmd, len);
|
||||
len += 2;
|
||||
}
|
||||
uint8_t buf[100] = {0};
|
||||
|
||||
uint32_t start_time = 0;
|
||||
uint32_t eof_time = 0;
|
||||
CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#include "mifare.h"
|
||||
#include "iso14b.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
#ifndef AddCrc14A
|
||||
|
@ -27,12 +27,12 @@
|
|||
#endif
|
||||
|
||||
void iso14443b_setup(void);
|
||||
int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response, uint16_t respmaxlen);
|
||||
int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res);
|
||||
|
||||
int iso14443b_select_card(iso14b_card_select_t *card);
|
||||
int iso14443b_select_card_srx(iso14b_card_select_t *card);
|
||||
|
||||
void SimulateIso14443bTag(uint32_t pupi);
|
||||
void SimulateIso14443bTag(uint8_t *pupi);
|
||||
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
|
||||
void ReadSTMemoryIso14443b(uint16_t numofblocks);
|
||||
void SniffIso14443b(void);
|
||||
|
|
|
@ -465,7 +465,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint16_t period_0, uint
|
|||
} else if (*command == '1') {
|
||||
TurnReadLFOn(period_1);
|
||||
} else {
|
||||
for (uint8_t i=0; i < LF_CMDREAD_MAX_EXTRA_SYMBOLS; i++) {
|
||||
for (uint8_t i = 0; i < LF_CMDREAD_MAX_EXTRA_SYMBOLS; i++) {
|
||||
if (*command == symbol_extra[i]) {
|
||||
TurnReadLFOn(period_extra[i]);
|
||||
break;
|
||||
|
|
|
@ -332,7 +332,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
|||
if (verbose) {
|
||||
if (checked == -1) {
|
||||
Dbprintf("lf sampling aborted");
|
||||
} else if ((cancel_counter == cancel_after) && (cancel_after > 0)){
|
||||
} else if ((cancel_counter == cancel_after) && (cancel_after > 0)) {
|
||||
Dbprintf("lf sampling cancelled after %u", cancel_counter);
|
||||
}
|
||||
|
||||
|
|
|
@ -253,6 +253,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdlfguard.c
|
||||
${PM3_ROOT}/client/src/cmdlfhid.c
|
||||
${PM3_ROOT}/client/src/cmdlfhitag.c
|
||||
${PM3_ROOT}/client/src/cmdlfidteck.c
|
||||
${PM3_ROOT}/client/src/cmdlfindala.c
|
||||
${PM3_ROOT}/client/src/cmdlfio.c
|
||||
${PM3_ROOT}/client/src/cmdlfjablotron.c
|
||||
|
|
|
@ -447,6 +447,7 @@ SRCS = aidsearch.c \
|
|||
cmdlfgallagher.c \
|
||||
cmdlfhid.c \
|
||||
cmdlfhitag.c \
|
||||
cmdlfidteck.c \
|
||||
cmdlfindala.c \
|
||||
cmdlfio.c \
|
||||
cmdlfjablotron.c \
|
||||
|
|
|
@ -132,6 +132,7 @@ add_library(pm3rrg_rdv4 SHARED
|
|||
${PM3_ROOT}/client/src/cmdlfguard.c
|
||||
${PM3_ROOT}/client/src/cmdlfhid.c
|
||||
${PM3_ROOT}/client/src/cmdlfhitag.c
|
||||
${PM3_ROOT}/client/src/cmdlfidteck.c
|
||||
${PM3_ROOT}/client/src/cmdlfindala.c
|
||||
${PM3_ROOT}/client/src/cmdlfio.c
|
||||
${PM3_ROOT}/client/src/cmdlfjablotron.c
|
||||
|
@ -209,4 +210,4 @@ target_link_libraries(pm3rrg_rdv4
|
|||
pm3rrg_rdv4_reveng
|
||||
pm3rrg_rdv4_whereami
|
||||
android
|
||||
log)
|
||||
log)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env -S pm3 -s
|
||||
|
||||
mem load f mfc_default_keys m
|
||||
mem load f t55xx_default_pwds t
|
||||
mem load f iclass_default_keys i
|
||||
mem load -f mfc_default_keys --mfc
|
||||
mem load -f t55xx_default_pwds --t55xx
|
||||
mem load -f iclass_default_keys --iclass
|
||||
lf t55xx deviceconfig z p
|
||||
|
|
|
@ -4195,7 +4195,8 @@ static void arg_cat_option(char *dest,
|
|||
#endif
|
||||
|
||||
if (datatype) {
|
||||
arg_cat(&dest, "=", &ndest);
|
||||
// arg_cat(&dest, "=", &ndest);
|
||||
arg_cat(&dest, " ", &ndest);
|
||||
if (optvalue) {
|
||||
arg_cat(&dest, "[", &ndest);
|
||||
arg_cat(&dest, datatype, &ndest);
|
||||
|
@ -4270,10 +4271,15 @@ static void arg_cat_optionv(char *dest,
|
|||
}
|
||||
|
||||
if (datatype) {
|
||||
if (longopts)
|
||||
/* if (longopts)
|
||||
arg_cat(&dest, "=", &ndest);
|
||||
else if (shortopts)
|
||||
arg_cat(&dest, " ", &ndest);
|
||||
*/
|
||||
if (longopts)
|
||||
arg_cat(&dest, " ", &ndest);
|
||||
else if (shortopts)
|
||||
arg_cat(&dest, " ", &ndest);
|
||||
|
||||
if (optvalue) {
|
||||
arg_cat(&dest, "[", &ndest);
|
||||
|
|
|
@ -11,10 +11,25 @@
|
|||
#include "cliparser.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h> // Get color constants
|
||||
#include <ui.h> // get PrintAndLogEx
|
||||
|
||||
#ifndef ARRAYLEN
|
||||
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
// Custom Colors
|
||||
// To default the color return s
|
||||
#define _SectionTagColor_(s) _GREEN_(s)
|
||||
#define _ExampleColor_(s) _YELLOW_(s)
|
||||
#define _CommandColor_(s) _RED_(s)
|
||||
#define _DescriptionColor_(s) _CYAN_(s)
|
||||
#define _ArgColor_(s) s
|
||||
#define _ArgHelpColor_(s) s
|
||||
// End Custom Colors
|
||||
// Option width set to 30 to allow option descriptions to align. approx line 74
|
||||
// Example width set to 50 to allow help descriptions to align. approx line 93
|
||||
|
||||
int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) {
|
||||
*ctx = malloc(sizeof(CLIParserContext));
|
||||
if (!*ctx) {
|
||||
|
@ -40,7 +55,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
/* verify the argtable[] entries were allocated sucessfully */
|
||||
if (arg_nullcheck(ctx->argtable) != 0) {
|
||||
/* NULL entries were detected, some allocations must have failed */
|
||||
printf("ERROR: Insufficient memory\n");
|
||||
PrintAndLogEx(ERR, "ERROR: Insufficient memory\n");
|
||||
fflush(stdout);
|
||||
return 2;
|
||||
}
|
||||
|
@ -49,14 +64,50 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
|
||||
/* special case: '--help' takes precedence over error reporting */
|
||||
if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)(ctx->argtable)[0])->count > 0) { // help must be the first record
|
||||
printf("Usage: %s", ctx->programName);
|
||||
arg_print_syntaxv(stdout, ctx->argtable, "\n");
|
||||
if (ctx->programHint)
|
||||
printf("%s\n\n", ctx->programHint);
|
||||
arg_print_glossary(stdout, ctx->argtable, " %-20s %s\n");
|
||||
printf("\n");
|
||||
if (ctx->programHelp)
|
||||
printf("%s \n", ctx->programHelp);
|
||||
PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint);
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:"));
|
||||
PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName);
|
||||
arg_print_syntax(stdout, ctx->argtable, "\n\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, _SectionTagColor_("options:"));
|
||||
|
||||
arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
if (ctx->programHelp) {
|
||||
PrintAndLogEx(NORMAL, _SectionTagColor_("examples/notes:"));
|
||||
char *buf = NULL;
|
||||
int idx = 0;
|
||||
buf = realloc(buf, strlen(ctx->programHelp) + 1); // more then enough as we are splitting
|
||||
|
||||
char *p2; // pointer to split example from comment.
|
||||
int egWidth = 30;
|
||||
for (int i = 0; i <= strlen(ctx->programHelp); i++) { // <= so to get string terminator.
|
||||
buf[idx++] = ctx->programHelp[i];
|
||||
if ((ctx->programHelp[i] == '\n') || (ctx->programHelp[i] == 0x00)) {
|
||||
buf[idx - 1] = 0x00;
|
||||
p2 = strstr(buf, "->"); // See if the example has a comment.
|
||||
if (p2 != NULL) {
|
||||
*(p2 - 1) = 0x00;
|
||||
|
||||
if (strlen(buf) > 28)
|
||||
egWidth = strlen(buf) + 5;
|
||||
else
|
||||
egWidth = 30;
|
||||
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, buf, p2);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, buf);
|
||||
}
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
return 1;
|
||||
|
@ -66,7 +117,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
if (nerrors > 0) {
|
||||
/* Display the error details contained in the arg_end struct.*/
|
||||
arg_print_errors(stdout, ((struct arg_end *)(ctx->argtable)[vargtableLen - 1]), ctx->programName);
|
||||
printf("Try '%s --help' for more information.\n", ctx->programName);
|
||||
PrintAndLogEx(WARNING, "Try '%s --help' for more information.\n", ctx->programName);
|
||||
fflush(stdout);
|
||||
return 3;
|
||||
}
|
||||
|
@ -74,6 +125,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum ParserState {
|
||||
PS_FIRST,
|
||||
PS_ARGUMENT,
|
||||
|
@ -152,7 +204,7 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
|||
*datalen = 0;
|
||||
|
||||
int ibuf = 0;
|
||||
uint8_t tmp_buf[256] = {0};
|
||||
uint8_t tmp_buf[512] = {0};
|
||||
int res = CLIParamStrToBuf(argstr, tmp_buf, maxdatalen * 2, &ibuf); // *2 because here HEX
|
||||
if (res) {
|
||||
printf("Parameter error: buffer overflow.\n");
|
||||
|
@ -186,7 +238,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
|||
if (!argstr->count)
|
||||
return 0;
|
||||
|
||||
uint8_t tmp_buf[256] = {0};
|
||||
uint8_t tmp_buf[512] = {0};
|
||||
int ibuf = 0;
|
||||
|
||||
for (int i = 0; i < argstr->count; i++) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
|
||||
#define arg_param_begin arg_lit0("hH", "help", "This help")
|
||||
#define arg_param_begin arg_lit0("h", "help", "This help")
|
||||
#define arg_param_end arg_end(20)
|
||||
|
||||
#define arg_getsize(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
|
|
@ -93,8 +93,10 @@ Command = {
|
|||
o.data = data
|
||||
return o
|
||||
end,
|
||||
parse = function (packet)
|
||||
local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet)
|
||||
parse = function(packet)
|
||||
local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLL', packet)
|
||||
local length = #packet - count + 1
|
||||
count, data = bin.unpack('H'..length, packet, count)
|
||||
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
|
||||
end
|
||||
}
|
||||
|
@ -121,26 +123,28 @@ end
|
|||
-- @param command - the usb packet to send
|
||||
-- @param ignoreresponse - if set to true, we don't read the device answer packet
|
||||
-- which is usually recipe for fail. If not sent, the host will wait 2s for a
|
||||
-- response of type CMD_ACK
|
||||
-- response of type CMD_ACK or like NG use the CMD as ack..
|
||||
-- @return packet,nil if successful
|
||||
-- nil, errormessage if unsuccessful
|
||||
function Command:sendMIX( ignore_response, timeout )
|
||||
function Command:sendMIX( ignore_response, timeout, use_cmd_ack)
|
||||
if timeout == nil then timeout = TIMEOUT end
|
||||
local data = self.data
|
||||
local cmd = self.cmd
|
||||
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
|
||||
|
||||
local err, msg = core.SendCommandMIX(cmd, arg1, arg2, arg3, data)
|
||||
if err == nil then return err, msg end
|
||||
|
||||
if ignore_response then return true, nil end
|
||||
|
||||
if timeout == nil then timeout = TIMEOUT end
|
||||
local ack = _commands.CMD_ACK
|
||||
if use_cmd_ack then
|
||||
ack = cmd
|
||||
end
|
||||
|
||||
local response, msg = core.WaitForResponseTimeout(_commands.CMD_ACK, timeout)
|
||||
local response, msg = core.WaitForResponseTimeout(ack, timeout)
|
||||
if response == nil then
|
||||
return nil, 'Error, waiting for response timed out :: '..msg
|
||||
end
|
||||
|
||||
-- lets digest
|
||||
data = nil
|
||||
cmd = nil
|
||||
|
@ -157,15 +161,13 @@ function Command:sendMIX( ignore_response, timeout )
|
|||
return packed, nil;
|
||||
end
|
||||
function Command:sendNG( ignore_response, timeout )
|
||||
if timeout == nil then timeout = TIMEOUT end
|
||||
local data = self.data
|
||||
local cmd = self.cmd
|
||||
local err, msg = core.SendCommandNG(cmd, data)
|
||||
if err == nil then return nil, msg end
|
||||
|
||||
if ignore_response then return true, nil end
|
||||
|
||||
if timeout == nil then timeout = TIMEOUT end
|
||||
|
||||
local response, msg = core.WaitForResponseTimeout(cmd, timeout)
|
||||
if response == nil then
|
||||
return nil, 'Error, waiting for response timed out :: '..msg
|
||||
|
|
|
@ -15,17 +15,18 @@ local cmds = require('commands')
|
|||
local utils = require('utils')
|
||||
|
||||
-- Shouldn't take longer than 2.5 seconds
|
||||
local TIMEOUT = 2500
|
||||
local TIMEOUT = 2000
|
||||
|
||||
local ISO14B_COMMAND = {
|
||||
ISO14B_CONNECT = 1,
|
||||
ISO14B_DISCONNECT = 2,
|
||||
ISO14B_APDU = 4,
|
||||
ISO14B_RAW = 8,
|
||||
ISO14B_CONNECT = 0x1,
|
||||
ISO14B_DISCONNECT = 0x2,
|
||||
ISO14B_APDU = 0x4,
|
||||
ISO14B_RAW = 0x8,
|
||||
ISO14B_REQUEST_TRIGGER = 0x10,
|
||||
ISO14B_APPEND_CRC = 0x20,
|
||||
ISO14B_SELECT_STD = 0x40,
|
||||
ISO14B_SELECT_SR = 0x80,
|
||||
ISO14B_SET_TIMEOUT = 0x100,
|
||||
}
|
||||
|
||||
local function parse14443b(data)
|
||||
|
@ -74,9 +75,11 @@ local function read14443b(disconnect)
|
|||
arg1 = flags
|
||||
}
|
||||
|
||||
local result, err = command:sendMIX()
|
||||
info = nil
|
||||
|
||||
local result, err = command:sendMIX(false, TIMEOUT, true)
|
||||
if result then
|
||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result)
|
||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result)
|
||||
if arg0 == 0 then
|
||||
data = string.sub(result, count)
|
||||
info, err = parse14443b(data)
|
||||
|
@ -88,12 +91,10 @@ local function read14443b(disconnect)
|
|||
end
|
||||
|
||||
if err then
|
||||
print(err)
|
||||
return nil, err
|
||||
end
|
||||
return info
|
||||
return info, nil
|
||||
end
|
||||
|
||||
---
|
||||
-- Waits for a mifare card to be placed within the vicinity of the reader.
|
||||
-- @return if successful: an table containing card info
|
||||
|
@ -102,12 +103,11 @@ local function waitFor14443b()
|
|||
print('Waiting for card... press Enter to quit')
|
||||
while not core.kbd_enter_pressed() do
|
||||
res, err = read14443b(false)
|
||||
if res then return res end
|
||||
if res then return res, err end
|
||||
-- err means that there was no response from card
|
||||
end
|
||||
return nil, 'Aborted by user'
|
||||
end
|
||||
|
||||
---
|
||||
-- turns on the HF field.
|
||||
local function connect14443b()
|
||||
|
|
|
@ -11,10 +11,10 @@ This is a script to allow raw 14443a commands to be sent and received.
|
|||
]]
|
||||
example = [[
|
||||
# 1. Connect and don't disconnect
|
||||
script run hf_14a_raw -p
|
||||
script run hf_14a_raw -k
|
||||
|
||||
# 2. Send mf auth, read response (nonce)
|
||||
script run hf_14a_raw -o -x 6000F57b -p
|
||||
script run hf_14a_raw -o -x 6000F57b -k
|
||||
|
||||
# 3. disconnect
|
||||
script run hf_14a_raw -o
|
||||
|
@ -26,10 +26,10 @@ usage = [[
|
|||
script run hf_14a_raw -x 6000F57b
|
||||
]]
|
||||
arguments = [[
|
||||
-o do not connect - use this only if you previously used -p to stay connected
|
||||
-o do not connect - use this only if you previously used -k to stay connected
|
||||
-r do not read response
|
||||
-c calculate and append CRC
|
||||
-p stay connected - dont inactivate the field
|
||||
-k stay connected - dont inactivate the field
|
||||
-x <payload> Data to send (NO SPACES!)
|
||||
-d Debug flag
|
||||
-t Topaz mode
|
||||
|
@ -187,8 +187,8 @@ function selftest()
|
|||
DEBUG = true
|
||||
dbg('Performing test')
|
||||
main()
|
||||
main('-p')
|
||||
main(' -o -x 6000F57b -p')
|
||||
main('-k')
|
||||
main(' -o -x 6000F57b -k')
|
||||
main('-o')
|
||||
main('-x 6000F57b')
|
||||
dbg('Tests done')
|
||||
|
|
|
@ -135,13 +135,13 @@ function main(args)
|
|||
end
|
||||
|
||||
-- Original loop
|
||||
-- core.console("hf 14a raw -a -p -b 7 45")
|
||||
-- local cmd_select = string.format("hf 14a raw -c -p 9370%s", serial_number)
|
||||
-- core.console("hf 14a raw -a -k -b 7 45")
|
||||
-- local cmd_select = string.format("hf 14a raw -c -k 9370%s", serial_number)
|
||||
-- core.console(cmd_select)
|
||||
-- for i = 0, 254 do
|
||||
-- local cmd_rd_blk = string.format("hf 14a raw -c -p 30 %02x", i)
|
||||
-- local cmd_rd_blk = string.format("hf 14a raw -c -k 30 %02x", i)
|
||||
-- core.console(cmd_rd_blk)
|
||||
-- core.console("hf 14a raw -p 80")
|
||||
-- core.console("hf 14a raw -k 80")
|
||||
-- end
|
||||
-- core.console("hf 14a raw -r")
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ local ansicolors = require('ansicolors')
|
|||
|
||||
copyright = ''
|
||||
author = 'Iceman'
|
||||
version = 'v1.0.2'
|
||||
version = 'v1.0.4'
|
||||
desc = [[
|
||||
This is a script to communicate with a CALYSPO / 14443b tag using the '14b raw' commands
|
||||
]]
|
||||
|
@ -31,11 +31,12 @@ device-side.
|
|||
|
||||
local function calypso_parse(result)
|
||||
local r = Command.parse(result)
|
||||
local len = r.arg2 * 2
|
||||
r.data = string.sub(r.data, 0, len);
|
||||
print('GOT:', r.data)
|
||||
if r.arg1 == 0 then
|
||||
return r, nil
|
||||
if r.arg1 >= 0 then
|
||||
local len = r.arg2 * 2
|
||||
if len > 0 then
|
||||
r.data = string.sub(r.data, 0, len);
|
||||
return r, nil
|
||||
end
|
||||
end
|
||||
return nil,nil
|
||||
end
|
||||
|
@ -123,12 +124,19 @@ local function calypso_send_cmd_raw(data, ignoreresponse )
|
|||
arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string
|
||||
data = data} -- data bytes (commands etc)
|
||||
|
||||
result, err = command:sendMIX(ignoreresponse)
|
||||
local use_cmd_ack = true
|
||||
result, err = command:sendMIX(ignoreresponse, 2000, use_cmd_ack)
|
||||
if result then
|
||||
local r = calypso_parse(result)
|
||||
return r, nil
|
||||
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result)
|
||||
if arg0 >= 0 then
|
||||
return calypso_parse(result)
|
||||
else
|
||||
err = 'card response failed'
|
||||
end
|
||||
else
|
||||
err = 'No response from card'
|
||||
end
|
||||
return respone, err
|
||||
return result, err
|
||||
end
|
||||
---
|
||||
-- calypso_card_num : Reads card number from ATR and
|
||||
|
@ -136,23 +144,22 @@ end
|
|||
local function calypso_card_num(card)
|
||||
if not card then return end
|
||||
local card_num = tonumber( card.uid:sub(1,8),16 )
|
||||
print('Card UID', card.uid)
|
||||
print('Card Number', card_num)
|
||||
print('')
|
||||
print('Card UID ' ..ansicolors.green..card.uid:format('%x')..ansicolors.reset)
|
||||
print('Card Number ' ..ansicolors.green..string.format('%u', card_num)..ansicolors.reset)
|
||||
print('-----------------------')
|
||||
end
|
||||
---
|
||||
-- analyse CALYPSO apdu status bytes.
|
||||
local function calypso_apdu_status(apdu)
|
||||
-- last two is CRC
|
||||
-- next two is APDU status bytes.
|
||||
local status = false
|
||||
local mess = 'FAIL'
|
||||
local sw = apdu:sub( #apdu-7, #apdu-4)
|
||||
desc, err = iso7816.tostring(sw)
|
||||
print ('SW', sw, desc, err )
|
||||
|
||||
status = ( sw == '9000' )
|
||||
|
||||
return status
|
||||
--print ('SW', sw, desc, err )
|
||||
local status = ( sw == '9000' )
|
||||
return status, desc, err
|
||||
end
|
||||
|
||||
local _calypso_cmds = {
|
||||
|
@ -215,7 +222,7 @@ function main(args)
|
|||
if o == 'b' then bytes = a end
|
||||
end
|
||||
|
||||
lib14b.connect()
|
||||
-- lib14b.connect()
|
||||
|
||||
-- Select 14b tag.
|
||||
card, err = lib14b.waitFor14443b()
|
||||
|
@ -241,14 +248,23 @@ function main(args)
|
|||
--for i = 1,10 do
|
||||
--result, err = calypso_send_cmd_raw('0294a40800043f000002',false) --select ICC file
|
||||
for i, apdu in spairs(_calypso_cmds) do
|
||||
print('>>', i )
|
||||
print('>> '..ansicolors.yellow..i..ansicolors.reset)
|
||||
apdu = apdu:gsub('%s+', '')
|
||||
result, err = calypso_send_cmd_raw(apdu , false)
|
||||
if result then
|
||||
calypso_apdu_status(result.data)
|
||||
print('<<', result.data )
|
||||
if err then
|
||||
print('<< '..err)
|
||||
else
|
||||
print('<< no answer')
|
||||
if result then
|
||||
local status, desc, err = calypso_apdu_status(result.data)
|
||||
local d = result.data:sub(3, (#result.data - 8))
|
||||
if status then
|
||||
print('<< '..d..' ('..ansicolors.green..'ok'..ansicolors.reset..')')
|
||||
else
|
||||
print('<< '..d..' '..ansicolors.red..err..ansicolors.reset )
|
||||
end
|
||||
else
|
||||
print('<< no answer')
|
||||
end
|
||||
end
|
||||
end
|
||||
lib14b.disconnect()
|
||||
|
|
|
@ -59,24 +59,24 @@ end
|
|||
|
||||
local function cmdUltralight()
|
||||
return {
|
||||
[0] = 'hf 14a raw -p -a -b 7 40',
|
||||
[1] = 'hf 14a raw -p -a 43',
|
||||
[0] = 'hf 14a raw -k -a -b 7 40',
|
||||
[1] = 'hf 14a raw -k -a 43',
|
||||
[2] = 'hf 14a raw -c -a A2005380712A',
|
||||
[3] = 'hf 14a raw -p -a -b 7 40',
|
||||
[4] = 'hf 14a raw -p -a 43',
|
||||
[3] = 'hf 14a raw -k -a -b 7 40',
|
||||
[4] = 'hf 14a raw -k -a 43',
|
||||
[5] = 'hf 14a raw -c -a A2010200D980',
|
||||
[6] = 'hf 14a raw -p -a -b 7 40',
|
||||
[7] = 'hf 14a raw -p -a 43',
|
||||
[6] = 'hf 14a raw -k -a -b 7 40',
|
||||
[7] = 'hf 14a raw -k -a 43',
|
||||
[8] = 'hf 14a raw -c -a A2025B480000',
|
||||
[9] = 'hf 14a raw -c -a 5000',
|
||||
}
|
||||
end
|
||||
local function cmdClassic()
|
||||
return {
|
||||
[0] = 'hf 14a raw -p -a -b 7 40',
|
||||
[1] = 'hf 14a raw -p -a 43',
|
||||
[2] = 'hf 14a raw -c -p -a A000',
|
||||
[3] = 'hf 14a raw -c -p -a 01020304049802000000000000001001',
|
||||
[0] = 'hf 14a raw -k -a -b 7 40',
|
||||
[1] = 'hf 14a raw -k -a 43',
|
||||
[2] = 'hf 14a raw -c -k -a A000',
|
||||
[3] = 'hf 14a raw -c -k -a 01020304049802000000000000001001',
|
||||
[4] = 'hf 14a raw -c -a 5000',
|
||||
}
|
||||
end
|
||||
|
|
|
@ -70,18 +70,18 @@ function magicUID(b0, b1, b2)
|
|||
print('Using backdoor Magic tag function')
|
||||
|
||||
-- write block 0
|
||||
core.console('hf 14a raw -p -a -b 7 40')
|
||||
core.console('hf 14a raw -p -a 43')
|
||||
core.console('hf 14a raw -k -a -b 7 40')
|
||||
core.console('hf 14a raw -k -a 43')
|
||||
core.console('hf 14a raw -c -a A200'..b0)
|
||||
|
||||
-- write block 1
|
||||
core.console('hf 14a raw -p -a -b 7 40')
|
||||
core.console('hf 14a raw -p -a 43')
|
||||
core.console('hf 14a raw -k -a -b 7 40')
|
||||
core.console('hf 14a raw -k -a 43')
|
||||
core.console('hf 14a raw -c -a A201'..b1)
|
||||
|
||||
-- write block 2
|
||||
core.console('hf 14a raw -p -a -b 7 40')
|
||||
core.console('hf 14a raw -p -a 43')
|
||||
core.console('hf 14a raw -k -a -b 7 40')
|
||||
core.console('hf 14a raw -k -a 43')
|
||||
core.console('hf 14a raw -c -a A202'..b2)
|
||||
end
|
||||
--
|
||||
|
@ -90,16 +90,16 @@ function brickableUID(b0, b1, b2)
|
|||
|
||||
print('Using BRICKABLE Magic tag function')
|
||||
|
||||
core.console('hf 14a raw -p -s -3')
|
||||
core.console('hf 14a raw -k -s -3')
|
||||
|
||||
-- write block 0
|
||||
core.console('hf 14a raw -p -c A200'..b0)
|
||||
core.console('hf 14a raw -k -c A200'..b0)
|
||||
|
||||
-- write block 1
|
||||
core.console('hf 14a raw -p -c A201'..b1)
|
||||
core.console('hf 14a raw -k -c A201'..b1)
|
||||
|
||||
-- write block 2
|
||||
core.console('hf 14a raw -p -c A202'..b2)
|
||||
core.console('hf 14a raw -k -c A202'..b2)
|
||||
end
|
||||
---
|
||||
-- The main entry point
|
||||
|
|
|
@ -74,9 +74,9 @@ function main(args)
|
|||
-- Upload dictionaries
|
||||
print('Uploading dictionaries to RDV4 flashmemory')
|
||||
print(dash)
|
||||
core.console('mem load f mfc_default_keys m')
|
||||
core.console('mem load f t55xx_default_pwds t')
|
||||
core.console('mem load f iclass_default_keys i')
|
||||
core.console('mem load -f mfc_default_keys --mfc')
|
||||
core.console('mem load -f t55xx_default_pwds --t55xx')
|
||||
core.console('mem load -f iclass_default_keys --iclass')
|
||||
print(dash)
|
||||
|
||||
-- T55x7 Device configuration
|
||||
|
|
|
@ -557,27 +557,11 @@ static int CmdConvertBitStream(const char *Cmd) {
|
|||
//verbose will print results and demoding messages
|
||||
//emSearch will auto search for EM410x format in bitstream
|
||||
//askType switches decode: ask/raw = 0, ask/manchester = 1
|
||||
int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
|
||||
int invert = 0;
|
||||
int clk = 0;
|
||||
int maxErr = 100;
|
||||
size_t maxLen = 0;
|
||||
int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
|
||||
uint8_t askamp = 0;
|
||||
char amp = tolower(param_getchar(Cmd, 0));
|
||||
|
||||
sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &);
|
||||
|
||||
if (!maxLen) maxLen = pm3_capabilities.bigbuf_size;
|
||||
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
return PM3_EMALLOC;
|
||||
|
@ -597,7 +581,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType,
|
|||
int foundclk = 0;
|
||||
|
||||
//amplify signal before ST check
|
||||
if (amp == 'a') {
|
||||
if (amplify) {
|
||||
askAmp(bits, BitLen);
|
||||
}
|
||||
|
||||
|
@ -658,9 +642,9 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType,
|
|||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
|
||||
int ASKDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType) {
|
||||
bool st = false;
|
||||
return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st);
|
||||
return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, verbose, emSearch, askType, &st);
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
|
@ -670,19 +654,36 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
|
|||
static int Cmdaskmandemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 45 || cmdp == 'h') return usage_data_rawdemod_am();
|
||||
|
||||
bool st = true;
|
||||
if (Cmd[0] == 's')
|
||||
return ASKDemod_ext(Cmd++, true, true, 1, &st);
|
||||
else if (Cmd[1] == 's')
|
||||
return ASKDemod_ext(Cmd += 2, true, true, 1, &st);
|
||||
|
||||
return ASKDemod(Cmd, true, true, 1);
|
||||
bool st = false;
|
||||
if (Cmd[0] == 's') {
|
||||
st = true;
|
||||
Cmd++;
|
||||
} else if (Cmd[1] == 's') {
|
||||
st = true;
|
||||
Cmd += 2;
|
||||
}
|
||||
int clk = 0;
|
||||
int invert = 0;
|
||||
int maxErr = 100;
|
||||
size_t maxLen = 0;
|
||||
bool amplify = false;
|
||||
char amp = tolower(param_getchar(Cmd, 0));
|
||||
sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &);
|
||||
amplify = amp == 'a';
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, true, true, 1, &st);
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//manchester decode
|
||||
//stricktly take 10 and 01 and convert to 0 and 1
|
||||
//strictly take 10 and 01 and convert to 0 and 1
|
||||
static int Cmdmandecoderaw(const char *Cmd) {
|
||||
size_t size = 0;
|
||||
int high = 0, low = 0;
|
||||
|
@ -785,10 +786,8 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) {
|
|||
|
||||
//by marshmellow
|
||||
// - ASK Demod then Biphase decode GraphBuffer samples
|
||||
int ASKbiphaseDemod(const char *Cmd, bool verbose) {
|
||||
int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
||||
//ask raw demod GraphBuffer first
|
||||
int offset = 0, clk = 0, invert = 0, maxErr = 50;
|
||||
sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
|
||||
|
||||
uint8_t BitStream[MAX_DEMOD_BUF_LEN];
|
||||
size_t size = getFromGraphBuf(BitStream);
|
||||
|
@ -828,16 +827,33 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) {
|
|||
static int Cmdaskbiphdemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab();
|
||||
|
||||
return ASKbiphaseDemod(Cmd, true);
|
||||
int offset = 0, clk = 0, invert = 0, maxErr = 50;
|
||||
sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
|
||||
return ASKbiphaseDemod(offset, clk, invert, maxErr, true);
|
||||
}
|
||||
|
||||
//by marshmellow - see ASKDemod
|
||||
static int Cmdaskrawdemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar();
|
||||
|
||||
return ASKDemod(Cmd, true, false, 0);
|
||||
bool st = false;
|
||||
int clk = 0;
|
||||
int invert = 0;
|
||||
int maxErr = 100;
|
||||
size_t maxLen = 0;
|
||||
bool amplify = false;
|
||||
char amp = tolower(param_getchar(Cmd, 0));
|
||||
sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &);
|
||||
amplify = amp == 'a';
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, true, false, 0, &st);
|
||||
}
|
||||
|
||||
int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveGrph, bool verbose) {
|
||||
|
@ -1140,24 +1156,8 @@ static char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) {
|
|||
//fsk raw demod and print binary
|
||||
//takes 4 arguments - Clock, invert, fchigh, fclow
|
||||
//defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a))
|
||||
int FSKrawDemod(const char *Cmd, bool verbose) {
|
||||
int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bool verbose) {
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint8_t rfLen, invert, fchigh, fclow;
|
||||
|
||||
//set defaults
|
||||
//set options from parameters entered with the command
|
||||
rfLen = param_get8(Cmd, 0);
|
||||
invert = param_get8(Cmd, 1);
|
||||
fchigh = param_get8(Cmd, 2);
|
||||
fclow = param_get8(Cmd, 3);
|
||||
|
||||
if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) {
|
||||
if (rfLen == 1) {
|
||||
invert = 1; //if invert option only is used
|
||||
rfLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (getSignalProperties()->isnoise)
|
||||
return PM3_ESOFT;
|
||||
|
||||
|
@ -1218,26 +1218,27 @@ out:
|
|||
static int CmdFSKrawdemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs();
|
||||
uint8_t rfLen, invert, fchigh, fclow;
|
||||
|
||||
return FSKrawDemod(Cmd, true);
|
||||
//set defaults
|
||||
//set options from parameters entered with the command
|
||||
rfLen = param_get8(Cmd, 0);
|
||||
invert = param_get8(Cmd, 1);
|
||||
fchigh = param_get8(Cmd, 2);
|
||||
fclow = param_get8(Cmd, 3);
|
||||
|
||||
if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) {
|
||||
if (rfLen == 1) {
|
||||
invert = 1; //if invert option only is used
|
||||
rfLen = 0;
|
||||
}
|
||||
}
|
||||
return FSKrawDemod(rfLen, invert, fchigh, fclow, true);
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//attempt to psk1 demod graph buffer
|
||||
int PSKDemod(const char *Cmd, bool verbose) {
|
||||
int invert = 0, clk = 0, maxErr = 100;
|
||||
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
if (invert != 0 && invert != 1) {
|
||||
if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
int PSKDemod(int clk, int invert, int maxErr, bool verbose) {
|
||||
if (getSignalProperties()->isnoise)
|
||||
return PM3_ESOFT;
|
||||
|
||||
|
@ -1276,91 +1277,13 @@ int PSKDemod(const char *Cmd, bool verbose) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int demodIdteck(void) {
|
||||
|
||||
if (PSKDemod("", false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
size_t size = DemodBufferLen;
|
||||
|
||||
//get binary from PSK1 wave
|
||||
int idx = detectIdteck(DemodBuffer, &size);
|
||||
if (idx < 0) {
|
||||
|
||||
if (idx == -1)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples");
|
||||
else if (idx == -2)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise");
|
||||
else if (idx == -3)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found");
|
||||
else if (idx == -4)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %zu", size);
|
||||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d", idx);
|
||||
|
||||
// if didn't find preamble try again inverting
|
||||
if (PSKDemod("1", false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
idx = detectIdteck(DemodBuffer, &size);
|
||||
if (idx < 0) {
|
||||
|
||||
if (idx == -1)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples");
|
||||
else if (idx == -2)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise");
|
||||
else if (idx == -3)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found");
|
||||
else if (idx == -4)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %zu", size);
|
||||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d", idx);
|
||||
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
setDemodBuff(DemodBuffer, 64, idx);
|
||||
|
||||
//got a good demod
|
||||
uint32_t id = 0;
|
||||
uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
|
||||
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
|
||||
|
||||
//parity check (TBD)
|
||||
//checksum check (TBD)
|
||||
|
||||
//output
|
||||
PrintAndLogEx(SUCCESS, "IDTECK Tag Found: Card ID %u , Raw: %08X%08X", id, raw1, raw2);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
static int CmdIdteckDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodIdteck();
|
||||
}
|
||||
*/
|
||||
|
||||
// by marshmellow
|
||||
// takes 3 arguments - clock, invert, maxErr as integers
|
||||
// attempts to demodulate nrz only
|
||||
// prints binary found and saves in demodbuffer for further commands
|
||||
int NRZrawDemod(const char *Cmd, bool verbose) {
|
||||
int NRZrawDemod(int clk, int invert, int maxErr, bool verbose) {
|
||||
|
||||
int errCnt = 0, clkStartIdx = 0;
|
||||
int invert = 0, clk = 0, maxErr = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (getSignalProperties()->isnoise)
|
||||
return PM3_ESOFT;
|
||||
|
@ -1409,8 +1332,18 @@ int NRZrawDemod(const char *Cmd, bool verbose) {
|
|||
static int CmdNRZrawDemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_nr();
|
||||
int invert = 0, clk = 0, maxErr = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
|
||||
return NRZrawDemod(Cmd, true);
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
return NRZrawDemod(clk, invert, maxErr, true);
|
||||
}
|
||||
|
||||
// by marshmellow
|
||||
|
@ -1420,8 +1353,17 @@ static int CmdNRZrawDemod(const char *Cmd) {
|
|||
int CmdPSK1rawDemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1();
|
||||
|
||||
int ans = PSKDemod(Cmd, true);
|
||||
int clk = 0, invert = 0, maxErr = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
int ans = PSKDemod(clk, invert, maxErr, true);
|
||||
//output
|
||||
if (ans != PM3_SUCCESS) {
|
||||
if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans);
|
||||
|
@ -1438,8 +1380,17 @@ int CmdPSK1rawDemod(const char *Cmd) {
|
|||
static int CmdPSK2rawDemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2();
|
||||
|
||||
int ans = PSKDemod(Cmd, true);
|
||||
int clk = 0, invert = 0, maxErr = 100;
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
int ans = PSKDemod(clk, invert, maxErr, true);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans);
|
||||
return PM3_ESOFT;
|
||||
|
@ -2313,15 +2264,14 @@ static int CmdDataNDEF(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "data ndef",
|
||||
"Decode and print NFC Data Exchange Format (NDEF)",
|
||||
"Samples:\n"
|
||||
_YELLOW_("\tdata ndef -d 9101085402656e48656c6c6f5101085402656e576f726c64\n")
|
||||
_YELLOW_("\tdata ndef -d 0103d020240203e02c040300fe\n")
|
||||
"data ndef -d 9101085402656e48656c6c6f5101085402656e576f726c64\n"
|
||||
"data ndef -d 0103d020240203e02c040300fe\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("dD", "data", "<hex>", "NDEF data to decode"),
|
||||
arg_lit0("vV", "verbose", "verbose mode"),
|
||||
arg_strx0("d", "data", "<hex>", "NDEF data to decode"),
|
||||
arg_lit0("v", "verbose", "verbose mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
|
|
@ -59,12 +59,13 @@ int CmdNorm(const char *Cmd);
|
|||
int CmdPlot(const char *Cmd); // used by cmd lf cotag
|
||||
int CmdSave(const char *Cmd); // used by cmd auto
|
||||
int CmdTuneSamples(const char *Cmd); // used by cmd lf hw
|
||||
int ASKbiphaseDemod(const char *Cmd, bool verbose); // used by cmd lf em4x, lf fdx, lf guard, lf jablotron, lf nedap, lf t55xx
|
||||
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType); // used by cmd lf em4x, lf t55xx, lf viking
|
||||
int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck); // used by cmd lf, lf em4x, lf noralsy, le presco, lf securekey, lf t55xx, lf visa2k
|
||||
int FSKrawDemod(const char *Cmd, bool verbose); // used by cmd lf, lf em4x, lf t55xx
|
||||
int PSKDemod(const char *Cmd, bool verbose); // used by cmd lf em4x, lf indala, lf keri, lf nexwatch, lf t55xx
|
||||
int NRZrawDemod(const char *Cmd, bool verbose); // used by cmd lf pac, lf t55xx
|
||||
|
||||
int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose); // used by cmd lf em4x, lf fdx, lf guard, lf jablotron, lf nedap, lf t55xx
|
||||
int ASKDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType); // used by cmd lf em4x, lf t55xx, lf viking
|
||||
int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck); // used by cmd lf, lf em4x, lf noralsy, le presco, lf securekey, lf t55xx, lf visa2k
|
||||
int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bool verbose); // used by cmd lf, lf em4x, lf t55xx
|
||||
int PSKDemod(int clk, int invert, int maxErr, bool verbose); // used by cmd lf em4x, lf indala, lf keri, lf nexwatch, lf t55xx
|
||||
int NRZrawDemod(int clk, int invert, int maxErr, bool verbose); // used by cmd lf pac, lf t55xx
|
||||
|
||||
|
||||
void printDemodBuff(void);
|
||||
|
@ -79,7 +80,6 @@ int getSamplesEx(uint32_t start, uint32_t end, bool verbose);
|
|||
void setClockGrid(uint32_t clk, int offset);
|
||||
int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down);
|
||||
int AskEdgeDetect(const int *in, int *out, int len, int threshold);
|
||||
int demodIdteck(void);
|
||||
|
||||
#define MAX_DEMOD_BUF_LEN (1024*128)
|
||||
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
|
||||
|
|
|
@ -8,16 +8,13 @@
|
|||
// Proxmark3 RDV40 Flash memory commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "cmdflashmem.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cliparser.h"
|
||||
#include "pmflash.h"
|
||||
#include "fileutils.h" //saveFile
|
||||
#include "comms.h" //getfromdevice
|
||||
#include "fileutils.h" // saveFile
|
||||
#include "comms.h" // getfromdevice
|
||||
#include "cmdflashmemspiffs.h" // spiffs commands
|
||||
|
||||
#include "rsa.h"
|
||||
#include "sha1.h"
|
||||
|
||||
|
@ -29,90 +26,34 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_flashmem_spibaud(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] <baudrate>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, " <baudrate> SPI baudrate in MHz [24|48]");
|
||||
PrintAndLogEx(NORMAL, " ");
|
||||
PrintAndLogEx(NORMAL, " If >= 24MHz, FASTREADS instead of READS instruction will be used.");
|
||||
PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48MHz setting");
|
||||
PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24MHz");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem spibaud 48");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_flashmem_load(void) {
|
||||
PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem load [o <offset>] f <file name> [m|t|i]");
|
||||
PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first");
|
||||
PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)");
|
||||
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
|
||||
PrintAndLogEx(NORMAL, " f <filename> : file name");
|
||||
PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)");
|
||||
PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)");
|
||||
PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0
|
||||
PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024
|
||||
PrintAndLogEx(NORMAL, " mem load f mfc_default_keys m");
|
||||
PrintAndLogEx(NORMAL, " mem load f t55xx_default_pwds t");
|
||||
PrintAndLogEx(NORMAL, " mem load f iclass_default_keys i");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_flashmem_dump(void) {
|
||||
PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console");
|
||||
PrintAndLogEx(NORMAL, " Usage: mem dump [o <offset>] [l <length>] [f <file name>] [p]");
|
||||
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
|
||||
PrintAndLogEx(NORMAL, " l <length> : length");
|
||||
PrintAndLogEx(NORMAL, " f <filename> : file name");
|
||||
PrintAndLogEx(NORMAL, " p : print dump in console");
|
||||
PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem dump f myfile"); // download whole flashmem to file myfile
|
||||
PrintAndLogEx(NORMAL, " mem dump p o 262015 l 128"); // display 128 bytes from offset 262015 (RSA sig)
|
||||
PrintAndLogEx(NORMAL, " mem dump p f myfile o 241664 l 58"); // download and display 58 bytes from offset 241664 to file myfile
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_flashmem_wipe(void) {
|
||||
|
||||
PrintAndLogEx(WARNING, "[OBS] use with caution.");
|
||||
PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n");
|
||||
|
||||
PrintAndLogEx(NORMAL, " Usage: mem wipe p <page>");
|
||||
PrintAndLogEx(NORMAL, " p <page> : 0,1,2 page memory");
|
||||
// PrintAndLogEx(NORMAL, " i : inital total wipe");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page.
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_flashmem_info(void) {
|
||||
PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n");
|
||||
PrintAndLogEx(NORMAL, " Usage: mem info");
|
||||
// PrintAndLogEx(NORMAL, " s : create a signature");
|
||||
// PrintAndLogEx(NORMAL, " w : write signature to flash memory");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem info");
|
||||
// PrintAndLogEx(NORMAL, " mem info s");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem baudrate",
|
||||
"Set the baudrate for the SPI flash memory communications.\n"
|
||||
"Reading Flash ID will virtually always fail under 48MHz setting.\n"
|
||||
"Unless you know what you are doing, please stay at 24MHz.\n"
|
||||
"If >= 24MHz, FASTREADS instead of READS instruction will be used.",
|
||||
"mem baudrate --mhz 48"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int1(NULL, "mhz", "<24|48>", "SPI baudrate in MHz"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int br = arg_get_int_def(ctx, 1, -1);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
char ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) < 1 || ctmp == 'h') {
|
||||
return usage_flashmem_spibaud();
|
||||
if (br == -1) {
|
||||
PrintAndLogEx(ERR, "failed to get baudrate");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10);
|
||||
baudrate = baudrate * 1000000;
|
||||
uint32_t baudrate = br * 1000000;
|
||||
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) {
|
||||
usage_flashmem_spibaud();
|
||||
PrintAndLogEx(ERR, "wrong baudrate. Only 24 or 48 is allowed");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
SendCommandNG(CMD_FLASHMEM_SET_SPIBAUDRATE, (uint8_t *)&baudrate, sizeof(uint32_t));
|
||||
|
@ -121,52 +62,50 @@ static int CmdFlashmemSpiBaudrate(const char *Cmd) {
|
|||
|
||||
static int CmdFlashMemLoad(const char *Cmd) {
|
||||
|
||||
uint32_t start_index = 0;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem load",
|
||||
"Loads binary file into flash memory on device\n"
|
||||
"Warning: mem area to be written must have been wiped first\n"
|
||||
"( this is already taken care when loading dictionaries )",
|
||||
"mem load -f myfile -> upload file myfile values at default offset 0\n"
|
||||
"mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n"
|
||||
"mem load -f mfc_default_keys -m -> upload MFC keys\n"
|
||||
"mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n"
|
||||
"mem load -f iclass_default_keys -i -> upload iCLASS keys\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int0("o", "offset", "<dec>", "offset in memory"),
|
||||
arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"),
|
||||
arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"),
|
||||
arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"),
|
||||
arg_strx0("f", "file", "<filename>", "file name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int offset = arg_get_int_def(ctx, 1, 0);
|
||||
bool is_mfc = arg_get_lit(ctx, 2);
|
||||
bool is_iclass = arg_get_lit(ctx, 3);
|
||||
bool is_t55xx = arg_get_lit(ctx, 4);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
Dictionary_t d = DICTIONARY_NONE;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_load();
|
||||
case 'f':
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'o':
|
||||
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'm':
|
||||
d = DICTIONARY_MIFARE;
|
||||
cmdp++;
|
||||
break;
|
||||
case 't':
|
||||
d = DICTIONARY_T55XX;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'i':
|
||||
d = DICTIONARY_ICLASS;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
if (is_mfc) {
|
||||
d = DICTIONARY_MIFARE;
|
||||
PrintAndLogEx(INFO, "treating file as MIFARE Classic keys");
|
||||
} else if (is_iclass) {
|
||||
d = DICTIONARY_ICLASS;
|
||||
PrintAndLogEx(INFO, "treating file as iCLASS keys");
|
||||
} else if (is_t55xx) {
|
||||
d = DICTIONARY_T55XX;
|
||||
PrintAndLogEx(INFO, "treating file as T55xx passwords");
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmem_load();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
size_t datalen = 0;
|
||||
uint32_t keycount = 0;
|
||||
int res = 0;
|
||||
|
@ -174,7 +113,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
switch (d) {
|
||||
case DICTIONARY_MIFARE:
|
||||
start_index = DEFAULT_MF_KEYS_OFFSET;
|
||||
offset = DEFAULT_MF_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -189,7 +128,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
datalen += 2;
|
||||
break;
|
||||
case DICTIONARY_T55XX:
|
||||
start_index = DEFAULT_T55XX_KEYS_OFFSET;
|
||||
offset = DEFAULT_T55XX_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -204,7 +143,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
datalen += 2;
|
||||
break;
|
||||
case DICTIONARY_ICLASS:
|
||||
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||
offset = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -253,13 +192,13 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
clearCommandBuffer();
|
||||
|
||||
SendCommandOLD(CMD_FLASHMEM_WRITE, start_index + bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
|
||||
SendCommandOLD(CMD_FLASHMEM_WRITE, offset + bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
|
||||
|
||||
bytes_remaining -= bytes_in_packet;
|
||||
bytes_sent += bytes_in_packet;
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
conn.block_after_ACK = false;
|
||||
free(data);
|
||||
|
@ -276,54 +215,37 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
conn.block_after_ACK = false;
|
||||
free(data);
|
||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, start_index);
|
||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, offset);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemDump(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem dump",
|
||||
"Dumps flash memory on device into a file or view in console",
|
||||
"mem dump -f myfile -> download all flashmem to file\n"
|
||||
"mem dump --view -o 262015 --len 128 -> display 128 bytes from offset 262015 (RSA sig)\n"
|
||||
"mem dump --view -f myfile -o 241664 --len 58 -> display 58 bytes from offset 241664 and save to file"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int0("o", "offset", "<dec>", "offset in memory"),
|
||||
arg_int0("l", "len", "<dec>", "length"),
|
||||
arg_lit0("v", "view", "view dump"),
|
||||
arg_strx0("f", "file", "<filename>", "file name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int offset = arg_get_int_def(ctx, 1, 0);
|
||||
int len = arg_get_int_def(ctx, 2, FLASH_MEM_MAX_SIZE);
|
||||
bool view = arg_get_lit(ctx, 3);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
bool print = false;
|
||||
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_dump();
|
||||
case 'l':
|
||||
len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'o':
|
||||
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'p':
|
||||
print = true;
|
||||
cmdp += 1;
|
||||
break;
|
||||
case 'f':
|
||||
//File handling
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmem_dump();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||
if (!dump) {
|
||||
|
@ -331,14 +253,15 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flashmem", len);
|
||||
if (!GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, 0, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; downloading from flashmemory");
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flash memory", len);
|
||||
if (!GetFromDevice(FLASH_MEM, dump, len, offset, NULL, 0, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; downloading from flash memory");
|
||||
free(dump);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
if (print) {
|
||||
if (view) {
|
||||
PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------");
|
||||
print_hex_break(dump, len, 32);
|
||||
}
|
||||
|
||||
|
@ -350,39 +273,32 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemWipe(const char *Cmd) {
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
bool initalwipe = false;
|
||||
uint8_t page = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_wipe();
|
||||
case 'p':
|
||||
page = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
||||
if (page > 2) {
|
||||
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'i':
|
||||
initalwipe = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem wipe",
|
||||
"Wipe flash memory on device, which fills it with 0xFF\n"
|
||||
_WHITE_("[ ") _RED_("!!! OBS") " ] use with caution",
|
||||
"mem wipe -p 0 -> wipes first page"
|
||||
// "mem wipe -i -> inital total wipe"
|
||||
);
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmem_wipe();
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int0("p", NULL, "<dec>", "0,1,2 page memory"),
|
||||
// arg_lit0("i", NULL, "inital total wipe"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool initalwipe = false;
|
||||
int page = arg_get_int_def(ctx, 1, -1);
|
||||
// initalwipe = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (page < 0 || page > 2 ) {
|
||||
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -393,59 +309,51 @@ static int CmdFlashMemWipe(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
const char* msg = "Flash WIPE ";
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (isok)
|
||||
PrintAndLogEx(SUCCESS, "Flash WIPE ok");
|
||||
PrintAndLogEx(SUCCESS, "%s ( " _GREEN_("ok")" )", msg);
|
||||
else {
|
||||
PrintAndLogEx(FAILED, "Flash WIPE failed");
|
||||
PrintAndLogEx(FAILED, "%s ( " _RED_("failed") " )", msg);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemInfo(const char *Cmd) {
|
||||
|
||||
uint8_t sha_hash[20] = {0};
|
||||
mbedtls_rsa_context rsa;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem info",
|
||||
"Collect signature and verify it from flash memory",
|
||||
"mem info"
|
||||
// "mem info -s"
|
||||
);
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false, shall_write = false, shall_sign = false;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_info();
|
||||
case 's': {
|
||||
shall_sign = true;
|
||||
cmdp++;
|
||||
break;
|
||||
}
|
||||
case 'w':
|
||||
shall_write = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
// arg_lit0("s", NULL, "create a signature"),
|
||||
// arg_lit0("w", NULL, "write signature to flash memory"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
//Validations
|
||||
if (errors) {
|
||||
usage_flashmem_info();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
bool shall_sign = false, shall_write = false;
|
||||
// shall_sign = arg_get_lit(ctx, 1);
|
||||
// shall_write = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (!isok) {
|
||||
if (isok == false) {
|
||||
PrintAndLogEx(FAILED, "failed");
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
@ -455,15 +363,20 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
memcpy(&mem, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
|
||||
|
||||
// Flash ID hash (sha1)
|
||||
uint8_t sha_hash[20] = {0};
|
||||
mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
|
||||
|
||||
// print header
|
||||
PrintAndLogEx(INFO, "\n--- Flash memory Information ---------");
|
||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid)));
|
||||
PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash)));
|
||||
PrintAndLogEx(INFO, "RSA SIGNATURE |");
|
||||
print_hex_break(mem.signature, sizeof(mem.signature), 32);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
||||
// PrintAndLogEx(INFO, "-----------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
|
||||
PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------");
|
||||
for (int i = 0; i < (sizeof(mem.signature) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// RRG Public RSA Key
|
||||
|
@ -473,7 +386,10 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
#define RSA_E "010001"
|
||||
|
||||
// public key modulus N
|
||||
#define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
|
||||
#define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
|
||||
"4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
|
||||
"9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
|
||||
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
|
||||
|
@ -516,9 +432,9 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
||||
"A74206CEC169D74BF5A8C50D6F48EA08"
|
||||
|
||||
|
||||
#define KEY_LEN 128
|
||||
|
||||
mbedtls_rsa_context rsa;
|
||||
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||
|
||||
rsa.len = KEY_LEN;
|
||||
|
@ -532,13 +448,31 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
|
||||
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
|
||||
|
||||
PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN);
|
||||
|
||||
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
|
||||
|
||||
char str_exp[10];
|
||||
char str_pk[261];
|
||||
size_t exlen = 0, pklen = 0;
|
||||
mbedtls_mpi_write_string(&rsa.E, 16, str_exp, sizeof(str_exp), &exlen);
|
||||
mbedtls_mpi_write_string(&rsa.N, 16, str_pk, sizeof(str_pk), &pklen);
|
||||
|
||||
PrintAndLogEx(INFO, "Len.................. %u", rsa.len);
|
||||
PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
|
||||
PrintAndLogEx(INFO, "Public key modulus N");
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
||||
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
const char *msgkey = "RSA key validation... ";
|
||||
if (is_keyok)
|
||||
PrintAndLogEx(SUCCESS, "RSA key validation ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgkey);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA key validation failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgkey);
|
||||
|
||||
//
|
||||
uint8_t from_device[KEY_LEN];
|
||||
|
@ -554,10 +488,11 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
if (shall_sign) {
|
||||
|
||||
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
||||
const char *msgsign = "RSA signing.......... ";
|
||||
if (is_signed == 0)
|
||||
PrintAndLogEx(SUCCESS, "RSA Signing ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgsign);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA Signing failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgsign);
|
||||
|
||||
if (shall_write) {
|
||||
// save to mem
|
||||
|
@ -574,29 +509,33 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(INFO, "Signed | ");
|
||||
print_hex_break(sign, sizeof(sign), 32);
|
||||
PrintAndLogEx(INFO, "Signed");
|
||||
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
||||
}
|
||||
}
|
||||
|
||||
// Verify (public key)
|
||||
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device);
|
||||
const char *msgverify = "RSA verification..... ";
|
||||
if (is_verified == 0)
|
||||
PrintAndLogEx(SUCCESS, "RSA Verification ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgverify);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA Verification failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgverify);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation [rdv40]"},
|
||||
{"spibaud", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate [rdv40]"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information [rdv40]"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory [rdv40]"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory [rdv40]"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory [rdv40]"},
|
||||
{"baudrate", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -236,8 +236,8 @@ static int usage_hf_14a_sim(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14a_sniff(void) {
|
||||
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
|
||||
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'");
|
||||
PrintAndLogEx(NORMAL, "Collect data from the field and save into command buffer.");
|
||||
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf 14a list'");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]");
|
||||
PrintAndLogEx(NORMAL, "c - triggered by first data from card");
|
||||
PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)");
|
||||
|
@ -246,11 +246,11 @@ static int usage_hf_14a_sniff(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_14a_raw(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-p] [-a] [-T] [-t] <milliseconds> [-b] <number of bits> <0A 0B 0C ... hex>");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-k] [-a] [-T] [-t] <milliseconds> [-b] <number of bits> <0A 0B 0C ... hex>");
|
||||
PrintAndLogEx(NORMAL, " -h this help");
|
||||
PrintAndLogEx(NORMAL, " -r do not read response");
|
||||
PrintAndLogEx(NORMAL, " -c calculate and append CRC");
|
||||
PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive");
|
||||
PrintAndLogEx(NORMAL, " -k keep signal field ON after receive");
|
||||
PrintAndLogEx(NORMAL, " -a active signal field ON without select");
|
||||
PrintAndLogEx(NORMAL, " -s active signal field ON with select");
|
||||
PrintAndLogEx(NORMAL, " -b number of bits to send. Useful for send partial byte");
|
||||
|
@ -563,13 +563,13 @@ static int CmdHF14AInfo(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a info",
|
||||
"This command makes more extensive tests against a ISO14443a tag in order to collect information",
|
||||
"Sample:\n\thf 14a info -nsv - shows full information about the card\n");
|
||||
"hf 14a info -nsv -> shows full information about the card\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "adds some information to results"),
|
||||
arg_lit0("nN", "nacktest", "test for nack bug"),
|
||||
arg_lit0("sS", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
|
||||
arg_lit0("v", "verbose", "adds some information to results"),
|
||||
arg_lit0("n", "nacktest", "test for nack bug"),
|
||||
arg_lit0("s", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -1080,20 +1080,20 @@ static int CmdHF14AAPDU(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a apdu",
|
||||
"Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013",
|
||||
"Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"
|
||||
"\thf 14a apdu -sd 00A404000E325041592E5359532E444446303100 - decode apdu\n"
|
||||
"\thf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 - encode standard apdu\n"
|
||||
"\thf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 - encode extended apdu\n");
|
||||
"hf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"
|
||||
"hf 14a apdu -sd 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
|
||||
"hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
|
||||
"hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("sS", "select", "activate field and select card"),
|
||||
arg_lit0("kK", "keep", "leave the signal field ON after receive response"),
|
||||
arg_lit0("tT", "tlv", "executes TLV decoder if it possible"),
|
||||
arg_lit0("dD", "decapdu", "decode apdu request if it possible"),
|
||||
arg_str0("mM", "make", "<head (CLA INS P1 P2) hex>", "make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
|
||||
arg_lit0("eE", "extended", "make extended length apdu if `m` parameter included"),
|
||||
arg_int0("lL", "le", "<Le (int)>", "Le apdu parameter if `m` parameter included"),
|
||||
arg_lit0("s", "select", "activate field and select card"),
|
||||
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
|
||||
arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
|
||||
arg_lit0("d", "decapdu", "decode apdu request if it possible"),
|
||||
arg_str0("m", "make", "<head (CLA INS P1 P2) hex>", "make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
|
||||
arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
|
||||
arg_int0("l", "le", "<Le (int)>", "Le apdu parameter if `m` parameter included"),
|
||||
arg_strx1(NULL, NULL, "<APDU (hex) | data (hex)>", "data if `m` parameter included"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -1186,7 +1186,7 @@ static int CmdHF14AAPDU(const char *Cmd) {
|
|||
static int CmdHF14ACmdRaw(const char *Cmd) {
|
||||
bool reply = 1;
|
||||
bool crc = false;
|
||||
bool power = false;
|
||||
bool keep_field_on = false;
|
||||
bool active = false;
|
||||
bool active_select = false;
|
||||
bool no_rats = false;
|
||||
|
@ -1218,8 +1218,8 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
|||
case 'c':
|
||||
crc = true;
|
||||
break;
|
||||
case 'p':
|
||||
power = true;
|
||||
case 'k':
|
||||
keep_field_on = true;
|
||||
break;
|
||||
case 'a':
|
||||
active = true;
|
||||
|
@ -1306,7 +1306,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
|||
argtimeout = 13560000 / 1000 / (8 * 16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
||||
}
|
||||
|
||||
if (power) {
|
||||
if (keep_field_on) {
|
||||
flags |= ISO14A_NO_DISCONNECT;
|
||||
}
|
||||
|
||||
|
@ -1369,8 +1369,7 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a antifuzz",
|
||||
"Tries to fuzz the ISO14443a anticollision phase",
|
||||
"Usage:\n"
|
||||
"\thf 14a antifuzz -4\n");
|
||||
"hf 14a antifuzz -4\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -1398,9 +1397,8 @@ static int CmdHF14AChaining(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 14a chaining",
|
||||
"Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
|
||||
"Usage:\n"
|
||||
"\thf 14a chaining disable -> disable chaining\n"
|
||||
"\thf 14a chaining -> show chaining enable/disable state\n");
|
||||
"hf 14a chaining disable -> disable chaining\n"
|
||||
"hf 14a chaining -> show chaining enable/disable state\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -1425,38 +1423,10 @@ static int CmdHF14AChaining(const char *Cmd) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"},
|
||||
{"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"},
|
||||
{"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"},
|
||||
{"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "<n> Collect n>0 ISO14443-a UIDs in one go"},
|
||||
{"sim", CmdHF14ASim, IfPm3Iso14443a, "<UID> -- Simulate ISO 14443-a tag"},
|
||||
{"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"},
|
||||
{"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"},
|
||||
{"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
|
||||
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
|
||||
{"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
|
||||
{"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int CmdHelp(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
CmdsHelp(CommandTable);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdHF14A(const char *Cmd) {
|
||||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
static void printTag(const char *tag) {
|
||||
PrintAndLogEx(SUCCESS, " " _YELLOW_("%s"), tag);
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
MTNONE = 0,
|
||||
MTCLASSIC = 1,
|
||||
|
@ -2032,3 +2002,30 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
DropField();
|
||||
return select_status;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"},
|
||||
{"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"},
|
||||
{"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"},
|
||||
{"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "<n> Collect n>0 ISO14443-a UIDs in one go"},
|
||||
{"sim", CmdHF14ASim, IfPm3Iso14443a, "<UID> -- Simulate ISO 14443-a tag"},
|
||||
{"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"},
|
||||
{"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"},
|
||||
{"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
|
||||
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
|
||||
{"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
|
||||
{"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int CmdHelp(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
CmdsHelp(CommandTable);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdHF14A(const char *Cmd) {
|
||||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -315,10 +315,10 @@ static int usage_15_raw(void) {
|
|||
{"-r", "do not read response" },
|
||||
{"-2", "use slower '1 out of 256' mode" },
|
||||
{"-c", "calculate and append CRC" },
|
||||
{"-p", "leave the signal field ON" },
|
||||
{"-k", "keep signal field ON after receive" },
|
||||
{"", "Tip: turn on debugging for verbose output"},
|
||||
};
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 raw [-r] [-2] [-c] <0A 0B 0C ... hex>\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 15 raw [-r] [-2] [-k] [-c] <0A 0B 0C ... hex>\n");
|
||||
PrintAndLogOptions(options, 4, 3);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -381,7 +381,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
|||
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
|
||||
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
|
||||
{"MIKRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"},
|
||||
{"Spark1 Public key", "04d64bb732c0d214e7ec580736acf847284b502c25c0f7f2fa86aace1dada4387a"},
|
||||
{"VivoKey Spark1 Public key", "04d64bb732c0d214e7ec580736acf847284b502c25c0f7f2fa86aace1dada4387a"},
|
||||
};
|
||||
/*
|
||||
uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = {
|
||||
|
@ -431,7 +431,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
|||
for (i = 0; i < sizeof(revsign); i++) {
|
||||
revsign[i] = signature[31 - i];
|
||||
}
|
||||
|
||||
|
||||
int reason = 0;
|
||||
bool is_valid = false;
|
||||
for (i = 0; i < ARRAYLEN(nxp_15693_public_keys); i++) {
|
||||
|
@ -446,7 +446,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
|||
reason = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// try with sha256
|
||||
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 8, signature, 32, true);
|
||||
is_valid = (res == 0);
|
||||
|
@ -463,7 +463,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// try with sha256
|
||||
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, revuid, sizeof(revuid), revsign, sizeof(revsign), true);
|
||||
is_valid = (res == 0);
|
||||
|
@ -487,7 +487,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
|||
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
|
||||
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
|
||||
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
|
||||
switch(reason) {
|
||||
switch (reason) {
|
||||
case 1:
|
||||
PrintAndLogEx(INFO, " Params used: UID and signature, plain");
|
||||
break;
|
||||
|
@ -497,7 +497,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
|||
case 3:
|
||||
PrintAndLogEx(INFO, " Params used: reversed UID and signature, plain");
|
||||
break;
|
||||
case 4:
|
||||
case 4:
|
||||
PrintAndLogEx(INFO, " Params used: reversed UID and signature, SHA256");
|
||||
break;
|
||||
}
|
||||
|
@ -1353,7 +1353,7 @@ static int CmdHF15Raw(const char *Cmd) {
|
|||
if (strlen(Cmd) < 3 || cmdp == 'h') return usage_15_raw();
|
||||
|
||||
int reply = 1, fast = 1, i = 0;
|
||||
bool crc = false, leaveSignalON = false;
|
||||
bool crc = false, keep_field_on = false;
|
||||
char buf[5] = "";
|
||||
uint8_t data[100];
|
||||
uint32_t datalen = 0, temp;
|
||||
|
@ -1364,21 +1364,18 @@ static int CmdHF15Raw(const char *Cmd) {
|
|||
while (Cmd[i] != '\0') {
|
||||
if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; }
|
||||
if (Cmd[i] == '-') {
|
||||
switch (Cmd[i + 1]) {
|
||||
switch (tolower(Cmd[i + 1])) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
reply = 0;
|
||||
break;
|
||||
case '2':
|
||||
fast = 0;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
crc = true;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
leaveSignalON = true;
|
||||
case 'k':
|
||||
keep_field_on = true;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Invalid option");
|
||||
|
@ -1429,7 +1426,7 @@ static int CmdHF15Raw(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
if (leaveSignalON == false)
|
||||
if (keep_field_on == false)
|
||||
DropField();
|
||||
|
||||
return PM3_SUCCESS;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "crc16.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "protocols.h" // definitions of ISO14B protocol
|
||||
#include "iso14b.h"
|
||||
|
||||
#define TIMEOUT 2000
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "crc16.h"
|
||||
#include "util.h"
|
||||
#include "ui.h"
|
||||
#include "mifare.h" // felica_card_select_t struct
|
||||
#include "iso18.h" // felica_card_select_t struct
|
||||
#include "des.h"
|
||||
#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))
|
||||
|
||||
|
@ -84,11 +84,11 @@ static int usage_hf_felica_dumplite(void) {
|
|||
}
|
||||
|
||||
static int usage_hf_felica_raw(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-k] [-a] <0A 0B 0C ... hex>");
|
||||
PrintAndLogEx(NORMAL, " -h this help");
|
||||
PrintAndLogEx(NORMAL, " -r do not read response");
|
||||
PrintAndLogEx(NORMAL, " -c calculate and append CRC");
|
||||
PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive");
|
||||
PrintAndLogEx(NORMAL, " -k keep signal field ON after receive");
|
||||
PrintAndLogEx(NORMAL, " -a active signal field ON without select");
|
||||
PrintAndLogEx(NORMAL, " -s active signal field ON with select");
|
||||
return PM3_SUCCESS;
|
||||
|
@ -1687,7 +1687,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
|
|||
static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||
bool reply = 1;
|
||||
bool crc = false;
|
||||
bool power = false;
|
||||
bool keep_field_on = false;
|
||||
bool active = false;
|
||||
bool active_select = false;
|
||||
uint16_t numbits = 0;
|
||||
|
@ -1714,8 +1714,8 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
|||
case 'c':
|
||||
crc = true;
|
||||
break;
|
||||
case 'p':
|
||||
power = true;
|
||||
case 'k':
|
||||
keep_field_on = true;
|
||||
break;
|
||||
case 'a':
|
||||
active = true;
|
||||
|
@ -1771,7 +1771,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
|||
flags |= FELICA_NO_SELECT;
|
||||
}
|
||||
|
||||
if (power) {
|
||||
if (keep_field_on) {
|
||||
flags |= FELICA_NO_DISCONNECT;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define CMDHFFELICA_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "mifare.h"
|
||||
#include "iso18.h"
|
||||
|
||||
int CmdHFFelica(const char *Cmd);
|
||||
int readFelicaUid(bool verbose);
|
||||
|
|
|
@ -160,17 +160,17 @@ static int CmdHFFidoRegister(const char *cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido reg",
|
||||
"Initiate a U2F token registration. Needs two 32-byte hash numbers. \nchallenge parameter (32b) and application parameter (32b).",
|
||||
"Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n"
|
||||
"\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"
|
||||
"\thf fido reg -p s0 s1 -> execute command with plain parameters");
|
||||
"hf fido reg -> execute command with 2 parameters, filled 0x00\n"
|
||||
"hf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters\n"
|
||||
"hf fido reg -p s0 s1 -> execute command with plain parameters");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("aA", "apdu", "show APDU requests and responses"),
|
||||
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"),
|
||||
arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"),
|
||||
arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."),
|
||||
arg_lit0("a", "apdu", "show APDU requests and responses"),
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("p", "plain", "send plain ASCII to challenge and application parameters instead of HEX"),
|
||||
arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"),
|
||||
arg_str0("j", "json", "fido.json", "JSON input / output file name for parameters."),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII challenge parameter (32b HEX/1..16 chars)>", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL),
|
||||
arg_param_end
|
||||
|
@ -397,20 +397,20 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido auth",
|
||||
"Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).",
|
||||
"Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n"
|
||||
"\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f "
|
||||
"hf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n"
|
||||
"hf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f "
|
||||
"000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("vV", "verbose", "show technical data"),
|
||||
arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"),
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_lit0("p", "plain", "send plain ASCII to challenge and application parameters instead of HEX"),
|
||||
arg_rem("default mode:", "dont-enforce-user-presence-and-sign"),
|
||||
arg_lit0("uU", "user", "mode: enforce-user-presence-and-sign"),
|
||||
arg_lit0("cC", "check", "mode: check-only"),
|
||||
arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."),
|
||||
arg_str0("kK", "key", "public key to verify signature", NULL),
|
||||
arg_lit0("u", "user", "mode: enforce-user-presence-and-sign"),
|
||||
arg_lit0("c", "check", "mode: check-only"),
|
||||
arg_str0("j", "json", "fido.json", "JSON input / output file name for parameters."),
|
||||
arg_str0("k", "key", "public key to verify signature", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX key handle (var 0..255b)>", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII challenge parameter (32b HEX/1..16 chars)>", NULL),
|
||||
arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL),
|
||||
|
@ -658,16 +658,16 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido make",
|
||||
"Execute a FIDO2 Make Credential command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.",
|
||||
"Usage:\n\thf fido make -> execute command with default parameters file `fido2.json`\n"
|
||||
"\thf fido make test.json -> execute command with parameters file `text.json`");
|
||||
"Execute a FIDO2 Make Credential command. Needs json file with parameters. Sample file `fido2.json` in `resources/`.",
|
||||
"hf fido make -> execute command with default parameters file `fido2.json`\n"
|
||||
"hf fido make test.json -> execute command with parameters file `text.json`");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"),
|
||||
arg_lit0("cC", "cbor", "show CBOR decoded data"),
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"),
|
||||
arg_lit0("c", "cbor", "show CBOR decoded data"),
|
||||
arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -783,16 +783,16 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf fido assert",
|
||||
"Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.",
|
||||
"Usage:\n\thf fido assert -> execute command with default parameters file `fido2.json`\n"
|
||||
"\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId");
|
||||
"Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json` in `resources/`.",
|
||||
"hf fido assert -> execute command with default parameters file `fido2.json`\n"
|
||||
"hf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("cC", "cbor", "show CBOR decoded data"),
|
||||
arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator doesn't store credential to its memory)"),
|
||||
arg_lit0("a", "apdu", "show APDU reqests and responses"),
|
||||
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"),
|
||||
arg_lit0("c", "cbor", "show CBOR decoded data"),
|
||||
arg_lit0("l", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator doesn't store credential to its memory)"),
|
||||
arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"),
|
||||
arg_param_end
|
||||
};
|
||||
|
|
|
@ -641,9 +641,8 @@ static int CmdHFiClassSniff(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf iclass sniff",
|
||||
"Sniff the communication reader and tag",
|
||||
"Usage:\n"
|
||||
_YELLOW_("\thf iclass sniff") "\n"
|
||||
_YELLOW_("\thf iclass sniff -j") " -> jam e-purse updates\n"
|
||||
"hf iclass sniff\n"
|
||||
"hf iclass sniff -j -> jam e-purse updates\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
|
|
|
@ -4120,15 +4120,14 @@ static int CmdHF14AMfCWipe(const char *cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf cwipe",
|
||||
"Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.",
|
||||
"Usage:\n"
|
||||
_YELLOW_("\thf mf cwipe") " -> wipe card\n"
|
||||
_YELLOW_("\thf mf cwipe -u 09080706 -a 0004 -s 18") " -- set UID, ATQA and SAK and wipe card");
|
||||
"hf mf cwipe -> wipe card\n"
|
||||
"hf mf cwipe -u 09080706 -a 0004 -s 18 -> set UID, ATQA and SAK and wipe card");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("uU", "uid", "<UID (hex 4b)>", "UID for card"),
|
||||
arg_str0("aA", "atqa", "<ATQA (hex 2b)>", "ATQA for card"),
|
||||
arg_str0("sS", "sak", "<SAK (hex 1b)>", "SAK for card"),
|
||||
arg_str0("u", "uid", "<UID (hex 4b)>", "UID for card"),
|
||||
arg_str0("a", "atqa", "<ATQA (hex 2b)>", "ATQA for card"),
|
||||
arg_str0("s", "sak", "<SAK (hex 1b)>", "SAK for card"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, cmd, argtable, true);
|
||||
|
@ -4799,9 +4798,8 @@ static int CmdHF14AMfAuth4(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf auth4",
|
||||
"Executes AES authentication command in ISO14443-4",
|
||||
"Usage:\n"
|
||||
_YELLOW_("\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f") " -> executes authentication\n"
|
||||
_YELLOW_("\thf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") " -> executes authentication\n");
|
||||
"hf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
|
||||
"hf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -4834,19 +4832,18 @@ static int CmdHF14AMfMAD(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf mad",
|
||||
"Checks and prints MIFARE Application Directory (MAD)",
|
||||
"Usage:\n"
|
||||
_YELLOW_("\thf mf mad") " -> shows MAD if exists\n"
|
||||
_YELLOW_("\thf mf mad --aid e103 -k ffffffffffff -b") " -> shows NDEF data if exists. read card with custom key and key B\n"
|
||||
_YELLOW_("\thf mf mad --dch -k ffffffffffff") " -> decode CardHolder information\n");
|
||||
"hf mf mad -> shows MAD if exists\n"
|
||||
"hf mf mad --aid e103 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"
|
||||
"hf mf mad --dch -k ffffffffffff -> decode CardHolder information\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show technical data"),
|
||||
arg_str0("", "aid", "<aid>", "print all sectors with specified aid"),
|
||||
arg_str0("kK", "key", "<key>", "key for printing sectors"),
|
||||
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
|
||||
arg_lit0("", "be", "(optional, BigEndian)"),
|
||||
arg_lit0("", "dch", "decode Card Holder information"),
|
||||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_str0(NULL, "aid", "<aid>", "print all sectors with specified aid"),
|
||||
arg_str0("k", "key", "<key>", "key for printing sectors"),
|
||||
arg_lit0("b", "keyb", "use key B for access printing sectors (by default: key A)"),
|
||||
arg_lit0(NULL, "be", "(optional, BigEndian)"),
|
||||
arg_lit0(NULL, "dch", "decode Card Holder information"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -4976,17 +4973,16 @@ static int CmdHFMFNDEF(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf ndef",
|
||||
"Prints NFC Data Exchange Format (NDEF)",
|
||||
"Usage:\n"
|
||||
_YELLOW_("\thf mf ndef") " -> shows NDEF parsed data\n"
|
||||
_YELLOW_("\thf mf ndef -vv") " -> shows NDEF parsed and raw data\n"
|
||||
_YELLOW_("\thf mf ndef --aid e103 -k ffffffffffff -b") " -> shows NDEF data with custom AID, key and with key B\n");
|
||||
"hf mf ndef -> shows NDEF parsed data\n"
|
||||
"hf mf ndef -vv -> shows NDEF parsed and raw data\n"
|
||||
"hf mf ndef --aid e103 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\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_litn("v", "verbose", 0, 2, "show technical data"),
|
||||
arg_str0(NULL, "aid", "<aid>", "replace default aid for NDEF"),
|
||||
arg_str0("k", "key", "<key>", "replace default key for NDEF"),
|
||||
arg_lit0("b", "keyb", "use key B for access sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -5092,17 +5088,16 @@ static int CmdHFMFPersonalize(const char *cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf personalize",
|
||||
"Personalize the UID of a MIFARE Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.",
|
||||
"Usage:\n"
|
||||
_YELLOW_("\thf mf personalize UIDF0") " -> double size UID according to ISO/IEC14443-3\n"
|
||||
_YELLOW_("\thf mf personalize UIDF1") " -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"
|
||||
_YELLOW_("\thf mf personalize UIDF2") " -> single size random ID according to ISO/IEC14443-3\n"
|
||||
_YELLOW_("\thf mf personalize UIDF3") " -> single size NUID according to ISO/IEC14443-3\n"
|
||||
_YELLOW_("\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3") " -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n");
|
||||
"hf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n"
|
||||
"hf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"
|
||||
"hf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n"
|
||||
"hf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n"
|
||||
"hf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("tT", "keytype", "<A|B>", "key type (A or B) to authenticate sector 0 (default: A)"),
|
||||
arg_str0("kK", "key", "<key (hex 6 Bytes)>", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"),
|
||||
arg_str0("t", "keytype", "<A|B>", "key type (A or B) to authenticate sector 0 (default: A)"),
|
||||
arg_str0("k", "key", "<key (hex 6 Bytes)>", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"),
|
||||
arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -5276,7 +5271,7 @@ static command_t CommandTable[] = {
|
|||
{"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill simulator memory with help of keys from simulator"},
|
||||
{"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear simulator memory"},
|
||||
{"egetblk", CmdHF14AMfEGetBlk, IfPm3Iso14443a, "Get simulator memory block"},
|
||||
{"egetsc", CmdHF14AMfEGetSc, IfPm3Iso14443a, "Get simulator memory sector"},
|
||||
{"egetsc", CmdHF14AMfEGetSc, IfPm3Iso14443a, "Get simulator memory sector"},
|
||||
{"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from simulator memory"},
|
||||
{"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Load from file emul dump"},
|
||||
{"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"},
|
||||
|
|
|
@ -488,7 +488,7 @@ static const char *getstatus(uint16_t *sw) {
|
|||
return "Current authentication status does not allow the requested command";
|
||||
|
||||
case MFDES_E_BOUNDARY:
|
||||
return "Attempted to read/write data from/to beyong the file's/record's limit";
|
||||
return "Attempted to read/write data from/to beyond the file's/record's limit";
|
||||
|
||||
case MFDES_E_PICC_INTEGRITY:
|
||||
return "PICC integrity error, PICC will be disabled";
|
||||
|
@ -653,7 +653,7 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
|||
return DESFIRE_EV3;
|
||||
if (major == 0x30 && minor == 0x00)
|
||||
return DESFIRE_LIGHT;
|
||||
if (major == 0x11 && minor == 0x00)
|
||||
if (major == 0x11 && minor == 0x00)
|
||||
return PLUS_EV1;
|
||||
if (major == 0x10 && minor == 0x00)
|
||||
return NTAG413DNA;
|
||||
|
@ -2079,12 +2079,12 @@ static int CmdHF14ADesSelectApp(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes selectaid",
|
||||
"Select Application ID",
|
||||
"Usage:\n\thf mfdes selectaid -a 123456\n"
|
||||
"hf mfdes selectaid -a 123456"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -2114,16 +2114,16 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes createaid",
|
||||
"Create Application ID",
|
||||
"Usage:\n\thf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E -n Test\n"
|
||||
"hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E -n Test"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to create as hex bytes ("),
|
||||
arg_strx0("fF", "fid", "<fid>", "File ID to create (optional)"),
|
||||
arg_strx0("kK", "keysetting1", "<keysetting1>", "Key Setting 1 (Application Master Key Settings)"),
|
||||
arg_strx0("lL", "keysetting2", "<keysetting2>", "Key Setting 2"),
|
||||
arg_str0("nN", "name", "<name>", "App ISO-4 Name (optional)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to create as hex bytes (3 hex bytes)"),
|
||||
arg_strx0("f", "fid", "<fid>", "File ID to create (optional)"),
|
||||
arg_strx0("k", "ks1", "<keysetting1>", "Key Setting 1 (Application Master Key Settings)"),
|
||||
arg_strx0("l", "ks2", "<keysetting2>", "Key Setting 2"),
|
||||
arg_str0("n", "name", "<name>", "App ISO-4 Name (optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -2242,13 +2242,13 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes deleteaid",
|
||||
"Delete Application ID",
|
||||
"Usage:\n\t-a aid (3 hex bytes, big endian)\n\n"
|
||||
"Example:\n\thf mfdes deleteaid -a 123456\n"
|
||||
// "Usage:\n\t-a aid (3 hex bytes, big endian)\n\n"
|
||||
"hf mfdes deleteaid -a 123456"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to delete"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID (3 hex bytes, big endian) to delete"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -2305,17 +2305,15 @@ static int selectfile(uint8_t *aid, uint32_t fileno, uint8_t *cs) {
|
|||
|
||||
static int CmdHF14ADesClearRecordFile(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes clearrecord",
|
||||
"Clear record file",
|
||||
"Usage:\n\t"
|
||||
"hf mfdes clearrecord -n 01\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
CLIParserInit(&ctx, "hf mfdes clearfile",
|
||||
"Clear record file\nMake sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes clearfile -n 01"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes, big endian, optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -2369,15 +2367,13 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes deletefile",
|
||||
"Delete File",
|
||||
"Usage:\n\t"
|
||||
"hf mfdes deletefile -n 01\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"hf mfdes deletefile -n 01 -> Make sure to select aid or authenticate aid before running this command."
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -2431,19 +2427,19 @@ static int CmdHF14ADesCreateFile(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes createfile",
|
||||
"Create Standard/Backup File",
|
||||
"Usage:"
|
||||
"\n\thf mfdes createfile -f 0001 -n 01 -c 0 -r EEEE -s 000100 -a 123456\n"
|
||||
"hf mfdes createfile -f 0001 -n 01 -c 0 -r EEEE -s 000100 -a 123456"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("fF", "fileid", "<fileid>", "ISO FID (2 hex bytes, big endian)"),
|
||||
arg_int0("cC", "com.set", "<comset>", "Communication setting (0=Plain,1=Plain+MAC,3=Enciphered)"),
|
||||
arg_strx0("rR", "accessrights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
arg_strx0("sS", "filesize", "<filesize>", "File size (3 hex bytes, big endian)"),
|
||||
arg_lit0("bB", "backup", "Create backupfile instead of standard file"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("f", "fileid", "<fileid>", "ISO FID (2 hex bytes, big endian)"),
|
||||
arg_int0("c", "com.set", "<comset>", "Communication setting (0=Plain,1=Plain+MAC,3=Enciphered)"),
|
||||
// arg_strx0("r", "accessrights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
arg_strx0("r", "rights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
arg_strx0("s", "filesize", "<filesize>", "File size (3 hex bytes, big endian)"),
|
||||
arg_lit0("b", "backup", "Create backupfile instead of standard file"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -2548,16 +2544,15 @@ static int CmdHF14ADesCreateFile(const char *Cmd) {
|
|||
static int CmdHF14ADesGetValueData(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes getvalue",
|
||||
"Get value from value file",
|
||||
"Usage:"
|
||||
"\n\thf mfdes getvalue -n 03\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"Get value from value file\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes getvalue -n 03"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -2620,21 +2615,19 @@ static int CmdHF14ADesGetValueData(const char *Cmd) {
|
|||
static int CmdHF14ADesReadData(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes readdata",
|
||||
"Read data from File",
|
||||
"Usage:"
|
||||
"\n\thf mfdes readdata -n 01 -t 0 -o 000000 -l 000000 -a 123456\n"
|
||||
"\thf mfdes readdata -n 01 -t 0 (Read all data from standard file, fileno 01)\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"Read data from File\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes readdata -n 01 -t 0 -o 000000 -l 000000 -a 123456\n"
|
||||
"hf mfdes readdata -n 01 -t 0 -> Read all data from standard file, fileno 01"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("oO", "offset", "<offset>", "File Offset (3 hex bytes, big endian), optional"),
|
||||
arg_strx0("lL", "length", "<length>",
|
||||
"Length to read (3 hex bytes, big endian -> 000000 = Read all data),optional"),
|
||||
arg_int0("tT", "type", "<type>", "File Type (0=Standard/Backup, 1=Record)"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("o", "offset", "<offset>", "File Offset (3 hex bytes, big endian), optional"),
|
||||
arg_strx0("l", "length", "<length>", "Length to read (3 hex bytes, big endian -> 000000 = Read all data),optional"),
|
||||
arg_int0("t", "type", "<type>", "File Type (0=Standard/Backup, 1=Record)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -2743,18 +2736,17 @@ static int CmdHF14ADesReadData(const char *Cmd) {
|
|||
static int CmdHF14ADesChangeValue(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes changevalue",
|
||||
"Change value (credit/limitedcredit/debit)",
|
||||
"Usage:"
|
||||
"\n\thf mfdes changevalue -n 03 -m 0 -d 00000001\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"Change value (credit/limitedcredit/debit)\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes changevalue -n 03 -m 0 -d 00000001"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("dD", "value", "<value>", "Value to increase (4 hex bytes, big endian)"),
|
||||
arg_int0("mM", "mode", "<mode>", "Mode (0=Credit, 1=LimitedCredit, 2=Debit)"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("d", "value", "<value>", "Value to increase (4 hex bytes, big endian)"),
|
||||
arg_int0("m", "mode", "<mode>", "Mode (0=Credit, 1=LimitedCredit, 2=Debit)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -2841,19 +2833,18 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
|||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes writedata",
|
||||
"Write data to File",
|
||||
"Usage:"
|
||||
"\n\thf mfdes writedata -n 01 -t 0 -o 000000 -d 3132333435363738\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"Write data to File\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes writedata -n 01 -t 0 -o 000000 -d 3132333435363738"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("oO", "offset", "<offset>", "File Offset (3 hex bytes, big endian), optional"),
|
||||
arg_strx0("dD", "data", "<data>", "Data to write (hex bytes, 0xFFFF bytes max.)"),
|
||||
arg_int0("type", "type", "<type>", "File Type (0=Standard/Backup, 1=Record)"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian, optional)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("o", "offset", "<offset>", "File Offset (3 hex bytes, big endian), optional"),
|
||||
arg_strx0("d", "data", "<data>", "Data to write (hex bytes, 256 bytes max)"),
|
||||
arg_int0("t", "type", "<type>", "File Type (0=Standard/Backup, 1=Record)"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes, big endian, optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -2947,22 +2938,23 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
|
|||
static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes createrecordfile",
|
||||
"Create Linear/Cyclic Record File",
|
||||
"Usage:"
|
||||
"\n\thf mfdes createrecordfile -f 1122 -n 02 -c 0 -r EEEE -s 000010 -m 000005 -a 123456\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"Create Linear/Cyclic Record File\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes createrecordfile -f 1122 -n 02 -c 0 -r EEEE -s 000010 -m 000005 -a 123456"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("fF", "fileid", "<fileid>", "ISO FID (2 hex bytes, big endian)"),
|
||||
arg_int0("cC", "com.set", "<comset>", "Communication setting (0=Plain,1=Plain+MAC,3=Enciphered)"),
|
||||
arg_strx0("rR", "accessrights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
arg_strx0("sS", "recordsize", "<recordsize>", "Record size (3 hex bytes, big endian, 000001 to FFFFFF)"),
|
||||
arg_strx0("mM", "maxnumrecord", "<maxnumrecord>", "Max. Number of Records (3 hex bytes, big endian)"),
|
||||
arg_lit0("bB", "cyclic", "Create cyclic record file instead of linear record file"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_strx0("f", "fileid", "<fileid>", "ISO FID (2 hex bytes, big endian)"),
|
||||
arg_int0("c", "com.set", "<comset>", "Communication setting (0=Plain,1=Plain+MAC,3=Enciphered)"),
|
||||
// arg_strx0("r", "accessrights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
// arg_strx0("s", "recordsize", "<recordsize>", "Record size (3 hex bytes, big endian, 000001 to FFFFFF)"),
|
||||
arg_strx0("r", "rights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
arg_strx0("s", "size", "<recordsize>", "Record size (3 hex bytes, big endian, 000001 to FFFFFF)"),
|
||||
arg_strx0("m", "maxrecord", "<maxrecord>", "Max. Number of Records (3 hex bytes, big endian)"),
|
||||
arg_lit0("b", "cyclic", "Create cyclic record file instead of linear record file"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -3082,22 +3074,21 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
|
|||
static int CmdHF14ADesCreateValueFile(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes createvaluefile",
|
||||
"Create Value File",
|
||||
"Usage:"
|
||||
"\n\thf mfdes createvaluefile -n 03 -c 0 -r EEEE -l 00000000 -u 00002000 -v 00000001 -m 02 -a 123456\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"Create Value File\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes createvaluefile -n 03 -c 0 -r EEEE -l 00000000 -u 00002000 -v 00000001 -m 02 -a 123456\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_int0("cC", "com.set", "<comset>", "Communication setting (0=Plain,1=Plain+MAC,3=Enciphered)"),
|
||||
arg_strx0("rR", "accessrights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
arg_strx0("lL", "lowerlimit", "<lowerlimit>", "Lower limit (4 hex bytes, big endian)"),
|
||||
arg_strx0("uU", "upperlimit", "<upperlimit>", "Upper limit (4 hex bytes, big endian)"),
|
||||
arg_strx0("vV", "value", "<value>", "Value (4 hex bytes, big endian)"),
|
||||
arg_strx0("mM", "limitcredit", "<limitcredit>", "Limited Credit enabled (1 hex byte [Bit 0=LimitedCredit, 1=FreeValue])"),
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_strx0("n", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
|
||||
arg_int0("c", "com.set", "<comset>", "Communication setting (0=Plain,1=Plain+MAC,3=Enciphered)"),
|
||||
arg_strx0("r", "rights", "<accessrights>", "Access rights (2 hex bytes -> RW/Chg/R/W, 0-D Key, E Free, F Denied)"),
|
||||
arg_strx0("l", "lowerlimit", "<lowerlimit>", "Lower limit (4 hex bytes, big endian)"),
|
||||
arg_strx0("u", "upperlimit", "<upperlimit>", "Upper limit (4 hex bytes, big endian)"),
|
||||
arg_strx0("v", "value", "<value>", "Value (4 hex bytes, big endian)"),
|
||||
arg_strx0("m", "limitcredit", "<limitcredit>", "Limited Credit enabled (1 hex byte [Bit 0=LimitedCredit, 1=FreeValue])"),
|
||||
arg_strx0("a", "aid", "<aid>", "App ID to select as hex bytes (3 bytes,big endian,optional)"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
|
@ -3215,11 +3206,15 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) {
|
|||
static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes formatpicc",
|
||||
"Formats MIFARE DESFire PICC to factory state",
|
||||
"Usage:"
|
||||
"\n\thf mfdes formatpicc\n"
|
||||
"Make sure to authenticate picc before running this command.\n"
|
||||
"Formats MIFARE DESFire PICC to factory state\n"
|
||||
"Make sure to authenticate picc before running this command.",
|
||||
"hf mfdes formatpicc"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
sAPDU apdu = {0x90, MFDES_FORMAT_PICC, 0x00, 0x00, 0, NULL}; // 0xDF
|
||||
uint16_t sw = 0;
|
||||
|
@ -3324,10 +3319,10 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
|||
if (major == 0 && minor == 2)
|
||||
PrintAndLogEx(INFO, "\t0.2 - DESFire Light, Originality check, ");
|
||||
|
||||
if (cardtype == DESFIRE_EV2 ||
|
||||
cardtype == DESFIRE_LIGHT ||
|
||||
cardtype == DESFIRE_EV3 ||
|
||||
cardtype == NTAG413DNA) {
|
||||
if (cardtype == DESFIRE_EV2 ||
|
||||
cardtype == DESFIRE_LIGHT ||
|
||||
cardtype == DESFIRE_EV3 ||
|
||||
cardtype == NTAG413DNA) {
|
||||
// Signature originality check
|
||||
uint8_t signature[56] = {0};
|
||||
size_t signature_len = 0;
|
||||
|
@ -3761,20 +3756,19 @@ static int CmdHF14ADesChangeKey(const char *Cmd) {
|
|||
uint8_t newkeylength = 8;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes changekey",
|
||||
"Changes Mifare DESFire Key",
|
||||
"Usage:"
|
||||
"\n\thf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 (DES,keynumber 0)\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.\n"
|
||||
"Changes Mifare DESFire Key\n"
|
||||
"Make sure to select aid or authenticate aid before running this command.",
|
||||
"hf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 -> DES,keynumber 0"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int0("nN", "keyno", "<keyno>", "Key number used for authentification"),
|
||||
arg_int0("tT", "algo", "<algo>", "Current key algo (1=DES, 2=3DES(2K2DES), 3=3K3DES, 4=AES)"),
|
||||
arg_str0("kK", "key", "<Key>", "Current Key (HEX 8-24 bytes)"),
|
||||
arg_int0("uU", "newalgo", "<newalgo>", "New key algo (1=DES, 2=3DES(2K2DES), 3=3K3DES, 4=AES)"),
|
||||
arg_str0("jJ", "newkey", "<newkey>", "New Key (HEX 8-24 bytes)"),
|
||||
arg_int0("vV", "aesversion", "<aesversion>", "Aes version (if aes is used)"),
|
||||
arg_int0("n", "keyno", "<keyno>", "Key number used for authentification"),
|
||||
arg_int0("t", "algo", "<algo>", "Current key algo (1=DES, 2=3DES(2K2DES), 3=3K3DES, 4=AES)"),
|
||||
arg_str0("k", "key", "<Key>", "Current Key (HEX 8-24 bytes)"),
|
||||
arg_int0("u", "newalgo", "<newalgo>", "New key algo (1=DES, 2=3DES(2K2DES), 3=3K3DES, 4=AES)"),
|
||||
arg_str0("j", "newkey", "<newkey>", "New Key (HEX 8-24 bytes)"),
|
||||
arg_int0("v", "aesversion", "<aesversion>", "Aes version (if aes is used)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -3860,23 +3854,22 @@ static int CmdHF14ADesAuth(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes auth",
|
||||
"Authenticates Mifare DESFire using Key",
|
||||
"Usage:"
|
||||
"\n\thf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 (AES,keynumber 0, aid 0x803201)"
|
||||
"\n\thf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 (3DES,keynumber 1, aid 0x000000)"
|
||||
"\n\thf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 (DES,keynumber 2, aid 0x000000)"
|
||||
"\n\thf mfdes auth -m 1 -t 1 -a 000000 -n 0 (DES, defaultkey, aid 0x000000)"
|
||||
"\n\thf mfdes auth -m 2 -t 2 -a 000000 -n 0 (3DES, defaultkey, aid 0x000000)"
|
||||
"\n\thf mfdes auth -m 3 -t 4 -a 000000 -n 0 (3K3DES, defaultkey, aid 0x000000)"
|
||||
"\n\thf mfdes auth -m 3 -t 4 -a 000000 -n 0 (AES, defaultkey, aid 0x000000)"
|
||||
"hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> AES,keynumber 0, aid 0x803201\n"
|
||||
"hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3DES,keynumber 1, aid 0x000000\n"
|
||||
"hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> DES,keynumber 2, aid 0x000000\n"
|
||||
"hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> DES, defaultkey, aid 0x000000\n"
|
||||
"hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3DES, defaultkey, aid 0x000000\n"
|
||||
"hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3K3DES, defaultkey, aid 0x000000\n"
|
||||
"hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> AES, defaultkey, aid 0x000000"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int0("mM", "type", "<type>", "Auth type (1=normal, 2=iso, 3=aes)"),
|
||||
arg_int0("tT", "algo", "<algo>", "Crypt algo (1=DES, 2=3DES(2K2DES), 3=3K3DES, 4=AES)"),
|
||||
arg_strx0("aA", "aid", "<aid>", "AID used for authentification (HEX 3 bytes)"),
|
||||
arg_int0("nN", "keyno", "<keyno>", "Key number used for authentification"),
|
||||
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 8-24 bytes)"),
|
||||
arg_int0("m", "type", "<type>", "Auth type (1=normal, 2=iso, 3=aes)"),
|
||||
arg_int0("t", "algo", "<algo>", "Crypt algo (1=DES, 2=3DES(2K2DES), 3=3K3DES, 4=AES)"),
|
||||
arg_strx0("a", "aid", "<aid>", "AID used for authentification (HEX 3 bytes)"),
|
||||
arg_int0("n", "keyno", "<keyno>", "Key number used for authentification"),
|
||||
arg_str0("k", "key", "<Key>", "Key for checking (HEX 8-24 bytes)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -4222,23 +4215,22 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes chk",
|
||||
"Checks keys with Mifare Desfire card.",
|
||||
"Usage:\n"
|
||||
" hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n"
|
||||
" hf mfdes chk -d mfdes_default_keys -> check keys from dictionary against all existing aid on card\n"
|
||||
" hf mfdes chk -d mfdes_default_keys -a 123456 -> check keys from dictionary against aid 0x123456\n"
|
||||
" hf mfdes chk -a 123456 --pattern1b -j keys -> check all 1-byte keys pattern on aid 0x123456 and save found keys to json\n"
|
||||
" hf mfdes chk -a 123456 --pattern2b --startp2b FA00 -> check all 2-byte keys pattern on aid 0x123456. Start from key FA00FA00...FA00\n");
|
||||
"hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n"
|
||||
"hf mfdes chk -d mfdes_default_keys -> check keys from dictionary against all existing aid on card\n"
|
||||
"hf mfdes chk -d mfdes_default_keys -a 123456 -> check keys from dictionary against aid 0x123456\n"
|
||||
"hf mfdes chk -a 123456 --pattern1b -j keys -> check all 1-byte keys pattern on aid 0x123456 and save found keys to json\n"
|
||||
"hf mfdes chk -a 123456 --pattern2b --startp2b FA00 -> check all 2-byte keys pattern on aid 0x123456. Start from key FA00FA00...FA00");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "Use specific AID (3 hex bytes, big endian)"),
|
||||
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
|
||||
arg_str0("dD", "dict", "<file>", "File with keys dictionary"),
|
||||
arg_strx0("a", "aid", "<aid>", "Use specific AID (3 hex bytes, big endian)"),
|
||||
arg_str0("k", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
|
||||
arg_str0("d", "dict", "<file>", "File with keys dictionary"),
|
||||
arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"),
|
||||
arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"),
|
||||
arg_str0(NULL, "startp2b", "<Pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"),
|
||||
arg_str0("jJ", "json", "<file>", "Json file to save keys"),
|
||||
arg_lit0("vV", "verbose", "Verbose mode."),
|
||||
arg_str0("j", "json", "<file>", "Json file to save keys"),
|
||||
arg_lit0("v", "verbose", "Verbose mode."),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -4489,17 +4481,16 @@ static int CmdHF14aDesNDEF(const char *Cmd) {
|
|||
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");
|
||||
"hf mfdes ndef -> shows NDEF data\n"
|
||||
"hf mfdes ndef -v -> shows NDEF parsed and raw data\n"
|
||||
"hf mfdes ndef -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data with custom AID and key");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_litn("vV", "verbose", 0, 2, "show technical data"),
|
||||
arg_litn("v", "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_str0("k", "key", "<key>", "replace default key for NDEF"),
|
||||
arg_lit0("b", "keyb", "use key B for access sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
|
|
@ -371,19 +371,22 @@ static int CmdHFMFPInfo(const char *Cmd) {
|
|||
int res = ExchangeRAW14a(cmd, sizeof(cmd), true, false, data, sizeof(data), &datalen, false);
|
||||
|
||||
// DESFire answers 0x1C or 67 00
|
||||
// Plus answers 0x0B, 0x09
|
||||
if ( data[0] != 0x0b && data[0] != 0x09 && data[0] != 0x1C && data[0] != 0x67) {
|
||||
// Plus answers 0x0B, 0x09, 0x06
|
||||
// Which tag answers 6D 00 ??
|
||||
if (data[0] != 0x0b && data[0] != 0x09 && data[0] != 0x1C && data[0] != 0x67) {
|
||||
PrintAndLogEx(INFO, _RED_("Send copy to iceman of this command output!"));
|
||||
PrintAndLogEx(INFO, "data: %s", sprint_hex(data, datalen));
|
||||
}
|
||||
|
||||
|
||||
if ((memcmp(data, "\x67\x00", 2) == 0) ||
|
||||
(memcmp(data, "\x1C\x83\x0C", 3) == 0)
|
||||
) {
|
||||
(memcmp(data, "\x1C\x83\x0C", 3) == 0)
|
||||
) {
|
||||
PrintAndLogEx(INFO, " result: " _RED_("MIFARE DESFire"));
|
||||
PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf mfdes info`"));
|
||||
DropField();
|
||||
return PM3_SUCCESS;
|
||||
} else if (memcmp(data, "\x6D\x00", 2) == 0) {
|
||||
isPlus = false;
|
||||
} else {
|
||||
PrintAndLogEx(INFO, " result: " _GREEN_("MIFARE Plus SL0/SL3"));
|
||||
}
|
||||
|
@ -436,12 +439,12 @@ static int CmdHFMFPWritePerso(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp wrp",
|
||||
"Executes Write Perso command. Can be used in SL0 mode only.",
|
||||
"Usage:\n\thf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n"
|
||||
"\thf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000");
|
||||
"hf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n"
|
||||
"hf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show internal data."),
|
||||
arg_lit0("v", "verbose", "show internal data."),
|
||||
arg_str1(NULL, NULL, "<HEX key number (2b)>", NULL),
|
||||
arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL),
|
||||
arg_param_end
|
||||
|
@ -503,12 +506,12 @@ static int CmdHFMFPInitPerso(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp initp",
|
||||
"Executes Write Perso command for all card's keys. Can be used in SL0 mode only.",
|
||||
"Usage:\n\thf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n"
|
||||
"\thf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange");
|
||||
"hf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n"
|
||||
"hf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_litn("vV", "verbose", 0, 2, "show internal data."),
|
||||
arg_litn("v", "verbose", 0, 2, "show internal data."),
|
||||
arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -571,11 +574,11 @@ static int CmdHFMFPCommitPerso(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp commitp",
|
||||
"Executes Commit Perso command. Can be used in SL0 mode only.",
|
||||
"Usage:\n\thf mfp commitp -> \n");
|
||||
"hf mfp commitp");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show internal data."),
|
||||
arg_lit0("v", "verbose", "show internal data."),
|
||||
arg_int0(NULL, NULL, "SL mode", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -618,12 +621,12 @@ static int CmdHFMFPAuth(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp auth",
|
||||
"Executes AES authentication command for Mifare Plus card",
|
||||
"Usage:\n\thf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
|
||||
"\thf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data\n");
|
||||
"hf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
|
||||
"hf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show internal data."),
|
||||
arg_lit0("v", "verbose", "show internal data."),
|
||||
arg_str1(NULL, NULL, "<Key Num (HEX 2 bytes)>", NULL),
|
||||
arg_str1(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
|
||||
arg_param_end
|
||||
|
@ -656,15 +659,15 @@ static int CmdHFMFPRdbl(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp rdbl",
|
||||
"Reads several blocks from Mifare Plus card.",
|
||||
"Usage:\n\thf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n"
|
||||
"\thf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n");
|
||||
"hf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n"
|
||||
"hf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show internal data."),
|
||||
arg_int0("nN", "count", "blocks count (by default 1).", NULL),
|
||||
arg_lit0("bB", "keyb", "use key B (by default keyA)."),
|
||||
arg_lit0("pP", "plain", "plain communication mode between reader and card."),
|
||||
arg_lit0("v", "verbose", "show internal data."),
|
||||
arg_int0("n", "count", "blocks count (by default 1).", NULL),
|
||||
arg_lit0("b", "keyb", "use key B (by default keyA)."),
|
||||
arg_lit0("p", "plain", "plain communication mode between reader and card."),
|
||||
arg_int1(NULL, NULL, "<Block Num (0..255)>", NULL),
|
||||
arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
|
||||
arg_param_end
|
||||
|
@ -769,14 +772,14 @@ static int CmdHFMFPRdsc(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp rdsc",
|
||||
"Reads one sector from Mifare Plus card.",
|
||||
"Usage:\n\thf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n"
|
||||
"\thf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n");
|
||||
"hf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n"
|
||||
"hf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show internal data."),
|
||||
arg_lit0("bB", "keyb", "use key B (by default keyA)."),
|
||||
arg_lit0("pP", "plain", "plain communication mode between reader and card."),
|
||||
arg_lit0("v", "verbose", "show internal data."),
|
||||
arg_lit0("b", "keyb", "use key B (by default keyA)."),
|
||||
arg_lit0("p", "plain", "plain communication mode between reader and card."),
|
||||
arg_int1(NULL, NULL, "<Sector Num (0..255)>", NULL),
|
||||
arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
|
||||
arg_param_end
|
||||
|
@ -868,13 +871,13 @@ static int CmdHFMFPWrbl(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp wrbl",
|
||||
"Writes one block to Mifare Plus card.",
|
||||
"Usage:\n\thf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n"
|
||||
"\thf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data\n");
|
||||
"hf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n"
|
||||
"hf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show internal data."),
|
||||
arg_lit0("bB", "keyb", "use key B (by default keyA)."),
|
||||
arg_lit0("v", "verbose", "show internal data."),
|
||||
arg_lit0("b", "keyb", "use key B (by default keyA)."),
|
||||
arg_int1(NULL, NULL, "<Block Num (0..255)>", NULL),
|
||||
arg_str1(NULL, NULL, "<Data (HEX 16 bytes)>", NULL),
|
||||
arg_str0(NULL, NULL, "<Key (HEX 16 bytes)>", NULL),
|
||||
|
@ -1070,26 +1073,25 @@ static int CmdHFMFPChk(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp chk",
|
||||
"Checks keys with Mifare Plus card.",
|
||||
"Usage:\n"
|
||||
" hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n"
|
||||
" hf mfp chk -s 2 -a -> check default key list on sector 2, key A\n"
|
||||
" hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n"
|
||||
" hf mfp chk --pattern1b -j keys -> check all 1-byte keys pattern and save found keys to json\n"
|
||||
" hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00\n");
|
||||
"hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n"
|
||||
"hf mfp chk -s 2 -a -> check default key list on sector 2, key A\n"
|
||||
"hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n"
|
||||
"hf mfp chk --pattern1b -j keys -> check all 1-byte keys pattern and save found keys to json\n"
|
||||
"hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("aA", "keya", "check only key A (by default check all keys)."),
|
||||
arg_lit0("bB", "keyb", "check only key B (by default check all keys)."),
|
||||
arg_int0("sS", "startsec", "Start sector Num (0..255)", NULL),
|
||||
arg_int0("eE", "endsec", "End sector Num (0..255)", NULL),
|
||||
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
|
||||
arg_str0("dD", "dict", "<file>", "file with keys dictionary"),
|
||||
arg_lit0("a", "keya", "check only key A (by default check all keys)."),
|
||||
arg_lit0("b", "keyb", "check only key B (by default check all keys)."),
|
||||
arg_int0("s", "startsec", "Start sector Num (0..255)", NULL),
|
||||
arg_int0("e", "endsec", "End sector Num (0..255)", NULL),
|
||||
arg_str0("k", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
|
||||
arg_str0("d", "dict", "<file>", "file with keys dictionary"),
|
||||
arg_lit0(NULL, "pattern1b", "check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"),
|
||||
arg_lit0(NULL, "pattern2b", "check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"),
|
||||
arg_str0(NULL, "startp2b", "<Pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"),
|
||||
arg_str0("jJ", "json", "<file>", "json file to save keys"),
|
||||
arg_lit0("vV", "verbose", "verbose mode."),
|
||||
arg_str0("j", "json", "<file>", "json file to save keys"),
|
||||
arg_lit0("v", "verbose", "verbose mode."),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -1303,17 +1305,17 @@ static int CmdHFMFPMAD(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp mad",
|
||||
"Checks and prints Mifare Application Directory (MAD)",
|
||||
"Usage:\n\thf mfp mad -> shows MAD if exists\n"
|
||||
"\thf mfp mad -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data if exists\n");
|
||||
"hf mfp mad -> shows MAD if exists\n"
|
||||
"hf mfp mad -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data if exists");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("vV", "verbose", "show technical data"),
|
||||
arg_str0("", "aid", "<aid>", "print all sectors with aid"),
|
||||
arg_str0("kK", "key", "<key>", "key for printing sectors"),
|
||||
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
|
||||
arg_lit0("", "be", "(optional, BigEndian)"),
|
||||
arg_lit0("", "dch", "decode Card Holder information"),
|
||||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_str0(NULL, "aid", "<aid>", "print all sectors with aid"),
|
||||
arg_str0("k", "key", "<key>", "key for printing sectors"),
|
||||
arg_lit0("b", "keyb", "use key B for access printing sectors (by default: key A)"),
|
||||
arg_lit0(NULL, "be", "(optional, BigEndian)"),
|
||||
arg_lit0(NULL, "dch", "decode Card Holder information"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -1443,17 +1445,16 @@ static int CmdHFMFPNDEF(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfp ndef",
|
||||
"Prints NFC Data Exchange Format (NDEF)",
|
||||
"Usage:\n"
|
||||
_YELLOW_("\thf mfp ndef") " -> shows NDEF data\n"
|
||||
_YELLOW_("\thf mfp ndef -vv") " -> shows NDEF parsed and raw data\n"
|
||||
_YELLOW_("\thf mfp ndef -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7") " -> shows NDEF data with custom AID and key\n");
|
||||
"hf mfp ndef -> shows NDEF data\n"
|
||||
"hf mfp ndef -vv -> shows NDEF parsed and raw data\n"
|
||||
"hf mfp ndef -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data with custom AID and key");
|
||||
|
||||
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_litn("v", "verbose", 0, 2, "show technical data"),
|
||||
arg_str0(NULL, "aid", "<aid>", "replace default aid for NDEF"),
|
||||
arg_str0("k", "key", "<key>", "replace default key for NDEF"),
|
||||
arg_lit0("b", "keyb", "use key B for access sectors (by default: key A)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
|
|
@ -814,7 +814,7 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st
|
|||
break;
|
||||
}
|
||||
// valid mirror start page and byte position within start page.
|
||||
if ((tagtype & NTAG_213_F)||(tagtype & NTAG_213_TT)) {
|
||||
if ((tagtype & NTAG_213_F) || (tagtype & NTAG_213_TT)) {
|
||||
switch (mirror_conf) {
|
||||
case 1:
|
||||
{ PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x24) ? "OK" : "Invalid value"); break;}
|
||||
|
@ -1116,7 +1116,7 @@ uint32_t GetHF14AMfU_Type(void) {
|
|||
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype = NTAG_210; break; }
|
||||
else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype = NTAG_212; break; }
|
||||
else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = NTAG_213; break; }
|
||||
else if (memcmp(version, "\x00\x04\x04\x02\x01\x01\x0F", 7) == 0) { tagtype = NTAG_213_C; break; }
|
||||
else if (memcmp(version, "\x00\x04\x04\x02\x01\x01\x0F", 7) == 0) { tagtype = NTAG_213_C; break; }
|
||||
else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x11", 7) == 0) { tagtype = NTAG_215; break; }
|
||||
else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x13", 7) == 0) { tagtype = NTAG_216; break; }
|
||||
else if (memcmp(version, "\x00\x04\x04\x04\x01\x00\x0F", 7) == 0) { tagtype = NTAG_213_F; break; }
|
||||
|
@ -1466,7 +1466,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
if (len < 1) {
|
||||
if (len < 1) {
|
||||
PrintAndLogEx(WARNING, _YELLOW_("password not known"));
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen r`") " to get see known pwd gen algo suggestions");
|
||||
}
|
||||
|
@ -2954,13 +2954,13 @@ static int CmdHF14MfuNDEF(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfu ndef",
|
||||
"Prints NFC Data Exchange Format (NDEF)",
|
||||
"Usage:\n\thf mfu ndef -> shows NDEF data\n"
|
||||
"\thf mfu ndef -k ffffffff -> shows NDEF data with key\n");
|
||||
"hf mfu ndef -> shows NDEF data\n"
|
||||
"hf mfu ndef -k ffffffff -> shows NDEF data with key");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("kK", "key", "replace default key for NDEF", NULL),
|
||||
arg_lit0("lL", "key", "(optional) swap entered key's endianness"),
|
||||
arg_str0("k", "key", "replace default key for NDEF", NULL),
|
||||
arg_lit0("l", "key", "(optional) swap entered key's endianness"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "cmdparser.h" // command_t
|
||||
#include "comms.h" // clearCommandBuffer
|
||||
#include "cmdtrace.h"
|
||||
#include "cliparser.h"
|
||||
#include "crc16.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "protocols.h" // definitions of ISO14A/7816 protocol
|
||||
|
@ -21,65 +22,9 @@
|
|||
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
|
||||
|
||||
#define TIMEOUT 2000
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_hf_st_info(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf st info [h]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, "Example:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf st info"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_st_sim(void) {
|
||||
PrintAndLogEx(NORMAL, "\n Emulating ST25TA512B tag with 7 byte UID\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf st sim [h] u <uid> ");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h : This help");
|
||||
PrintAndLogEx(NORMAL, " u : 7 byte UID");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf st sim u 02E2007D0FCA4C"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_hf_st_ndef(void) {
|
||||
PrintAndLogEx(NORMAL, "\n Print NFC Data Exchange Format (NDEF)\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf st ndef [h] p <pwd> ");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h : This help");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> : 16 byte password");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf st ndef p 82E80053D4CA5C0B656D852CC696C8A1"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_hf_st_protect(void) {
|
||||
PrintAndLogEx(NORMAL, "\n Change R/W protection for NFC Data Exchange Format (NDEF)\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf st protect [h] p <pwd> r|w [0|1]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h : This help");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> : 16 byte write password");
|
||||
PrintAndLogEx(NORMAL, " r|w : Change (r)ead or (w)rite protection");
|
||||
PrintAndLogEx(NORMAL, " [0|1] : Enable / Disable protection");
|
||||
PrintAndLogEx(NORMAL, " 0 = Disable (default)");
|
||||
PrintAndLogEx(NORMAL, " 1 = Enable");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf st protect p 82E80053D4CA5C0B656D852CC696C8A1 r 0"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_hf_st_pwd(void) {
|
||||
PrintAndLogEx(NORMAL, "\n Change R/W password for NFC Data Exchange Format (NDEF)\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf st pwd [h] p <pwd> r|w n <newpwd>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h : This help");
|
||||
PrintAndLogEx(NORMAL, " p <pwd> : 16 byte write password");
|
||||
PrintAndLogEx(NORMAL, " r|w : Change (r)ead or (w)rite password");
|
||||
PrintAndLogEx(NORMAL, " n <newpwd> : New 16 byte password");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf st pwd p 82E80053D4CA5C0B656D852CC696C8A1 r n 00000000000000000000000000000000"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// get ST Microelectronics chip model (from UID)
|
||||
static char *get_st_chip_model(uint8_t pc) {
|
||||
static char model[40];
|
||||
|
@ -348,26 +293,44 @@ int infoHF_ST(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// menu command to get and print all info known about any known 14b tag
|
||||
// menu command to get and print all info known about any known ST25TA tag
|
||||
static int cmd_hf_st_info(const char *Cmd) {
|
||||
char c = tolower(param_getchar(Cmd, 0));
|
||||
if (c == 'h') return usage_hf_st_info();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf st info",
|
||||
"Get info about ST25TA tag",
|
||||
"hf st info"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
return infoHF_ST();
|
||||
}
|
||||
|
||||
static int cmd_hf_st_sim(const char *Cmd) {
|
||||
char c = tolower(param_getchar(Cmd, 0));
|
||||
if (c == 'h' || c == 0x00) return usage_hf_st_sim();
|
||||
|
||||
int uidlen = 0;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t uid[7] = {0};
|
||||
if (c == 'u') {
|
||||
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
|
||||
uidlen >>= 1;
|
||||
if (uidlen != 7) {
|
||||
return usage_hf_st_sim();
|
||||
}
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf st sim",
|
||||
"Emulating ST25TA512B tag with 7 byte UID",
|
||||
"hf st sim -u 02E2007D0FCA4C\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("u", "uid", "<hex>", "7 byte UID"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||
|
||||
if (uidlen != 7) {
|
||||
PrintAndLogEx(ERR, "UID must be 7 hex bytes");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
char param[40];
|
||||
|
@ -376,18 +339,32 @@ static int cmd_hf_st_sim(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int cmd_hf_st_ndef(const char *Cmd) {
|
||||
char c = tolower(param_getchar(Cmd, 0));
|
||||
if (c == 'h' || c == 0x00) return usage_hf_st_ndef();
|
||||
|
||||
int pwdlen = 0;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t pwd[16] = {0};
|
||||
if (c == 'p') {
|
||||
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
|
||||
pwdlen >>= 1;
|
||||
bool with_pwd = false;
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf st ndef",
|
||||
"Read NFC Data Exchange Format (NDEF) file on ST25TA",
|
||||
"hf st ndef -p 82E80053D4CA5C0B656D852CC696C8A1\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("p", "password", "<hex>", "16 byte read password"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 1, pwd, &pwdlen);
|
||||
|
||||
if (pwdlen == 0) {
|
||||
with_pwd = false;
|
||||
} else {
|
||||
if (pwdlen != 16) {
|
||||
return usage_hf_st_ndef();
|
||||
PrintAndLogEx(ERR, "Password must be 16 hex bytes");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
with_pwd = true;
|
||||
}
|
||||
|
||||
bool activate_field = true;
|
||||
|
@ -429,27 +406,29 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// --------------- VERIFY ----------------
|
||||
uint8_t aVERIFY[30];
|
||||
int aVERIFY_n = 0;
|
||||
param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw == 0x6300) {
|
||||
// need to provide 16byte password
|
||||
param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (with_pwd) {
|
||||
// --------------- VERIFY ----------------
|
||||
uint8_t aVERIFY[30];
|
||||
int aVERIFY_n = 0;
|
||||
param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
return PM3_ESOFT;
|
||||
if (sw == 0x6300) {
|
||||
// need to provide 16byte password
|
||||
param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
|
||||
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
|
||||
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
sw = get_sw(response, resplen);
|
||||
if (sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -473,57 +452,72 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
|||
|
||||
static int cmd_hf_st_protect(const char *Cmd) {
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
int pwdlen = 0;
|
||||
uint8_t pwd[16] = {0};
|
||||
int statelen = 3;
|
||||
uint8_t state[3] = {0x26, 0, 0};
|
||||
uint8_t state[3] = {0x26, 0, 0x02};
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_hf_st_protect();
|
||||
case '0':
|
||||
state[0] = 0x26; //Disable protection
|
||||
cmdp++;
|
||||
break;
|
||||
case '1':
|
||||
state[0] = 0x28; //Enable protection
|
||||
cmdp++;
|
||||
break;
|
||||
case 'r':
|
||||
state[2] = 0x01;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'w':
|
||||
state[2] = 0x02;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'p':
|
||||
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
|
||||
pwdlen >>= 1;
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool disable_protection = false;
|
||||
bool enable_protection = false;
|
||||
bool read_protection = false;
|
||||
bool write_protection = false;
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf st protect",
|
||||
"Change read or write protection for NFC Data Exchange Format (NDEF) file on ST25TA",
|
||||
"hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -r -e -> enable read protection\n"
|
||||
"hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -w -d -> disable write protection\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("e", "enable", "enable protection"),
|
||||
arg_lit0("d", "disable", "disable protection (default)"),
|
||||
arg_lit0("r", "read", "change read protection"),
|
||||
arg_lit0("w", "write", "change write protection (default)"),
|
||||
arg_str1("p", "password", "<hex>", "16 byte write password"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
enable_protection = arg_get_lit(ctx, 1);
|
||||
disable_protection = arg_get_lit(ctx, 2);
|
||||
read_protection = arg_get_lit(ctx, 3);
|
||||
write_protection = arg_get_lit(ctx, 4);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 5, pwd, &pwdlen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
//Validations
|
||||
|
||||
if (state[2] == 0x00) {
|
||||
PrintAndLogEx(WARNING, "Missing action (r)ead or (w)rite");
|
||||
errors = true;
|
||||
}
|
||||
if (pwdlen != 16) {
|
||||
PrintAndLogEx(WARNING, "Missing 16 byte password");
|
||||
errors = true;
|
||||
if (enable_protection && disable_protection) {
|
||||
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
if (enable_protection) {
|
||||
state[0] = 0x28;
|
||||
}
|
||||
if (disable_protection) {
|
||||
state[0] = 0x26;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors || cmdp == 0) return usage_hf_st_protect();
|
||||
if (read_protection && write_protection) {
|
||||
PrintAndLogEx(ERR, "Must specify either read or write protection, not both");
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
if (read_protection) {
|
||||
state[2] = 0x01;
|
||||
}
|
||||
if (write_protection) {
|
||||
state[2] = 0x02;
|
||||
}
|
||||
}
|
||||
|
||||
if (pwdlen != 16) {
|
||||
PrintAndLogEx(ERR, "Missing 16 byte password");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool activate_field = true;
|
||||
bool keep_field_on = true;
|
||||
|
@ -603,63 +597,63 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int cmd_hf_st_pwd(const char *Cmd) {
|
||||
char c = tolower(param_getchar(Cmd, 0));
|
||||
if (c == 'h' || c == 0x00) return usage_hf_st_pwd();
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
int pwdlen = 0;
|
||||
uint8_t pwd[16] = {0};
|
||||
int newpwdlen = 0;
|
||||
uint8_t newpwd[16] = {0};
|
||||
int changePwdlen = 4;
|
||||
uint8_t changePwd[4] = {0x24, 0x00, 0x00, 0x10};
|
||||
uint8_t changePwd[4] = {0x24, 0x00, 0x01, 0x10};
|
||||
bool change_read_password = false;
|
||||
bool change_write_password = false;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_hf_st_pwd();
|
||||
case 'r':
|
||||
changePwd[2] = 0x01;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'w':
|
||||
changePwd[2] = 0x02;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'p':
|
||||
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
|
||||
pwdlen >>= 1;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'n':
|
||||
param_gethex_ex(Cmd, cmdp + 1, newpwd, &newpwdlen);
|
||||
newpwdlen >>= 1;
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf st pwd",
|
||||
"Change read or write password for NFC Data Exchange Format (NDEF) file on ST25TA",
|
||||
"hf st pwd -p 82E80053D4CA5C0B656D852CC696C8A1 -r -n 00000000000000000000000000000000 -> change read password\n"
|
||||
"hf st pwd -p 82E80053D4CA5C0B656D852CC696C8A1 -w -n 00000000000000000000000000000000 -> change write password\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("r", "read", "change the read password (default)"),
|
||||
arg_lit0("w", "write", "change the write password"),
|
||||
arg_str1("p", "password", "<hex>", "current 16 byte write password"),
|
||||
arg_str1("n", "new", "<hex>", "new 16 byte password"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
change_read_password = arg_get_lit(ctx, 1);
|
||||
change_write_password = arg_get_lit(ctx, 2);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 3, pwd, &pwdlen);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 4, newpwd, &newpwdlen);
|
||||
|
||||
if (change_read_password && change_write_password) {
|
||||
PrintAndLogEx(ERR, "Must specify either read or write, not both");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
} else {
|
||||
if (change_read_password) {
|
||||
changePwd[2] = 0x01;
|
||||
}
|
||||
if (change_write_password) {
|
||||
changePwd[2] = 0x02;
|
||||
}
|
||||
}
|
||||
|
||||
//Validations
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (changePwd[2] == 0x00) {
|
||||
PrintAndLogEx(WARNING, "Missing password specification: (r)ead or (w)rite");
|
||||
errors = true;
|
||||
}
|
||||
if (pwdlen != 16) {
|
||||
PrintAndLogEx(WARNING, "Missing original 16 byte password");
|
||||
errors = true;
|
||||
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (newpwdlen != 16) {
|
||||
PrintAndLogEx(WARNING, "Missing new 16 byte password");
|
||||
errors = true;
|
||||
PrintAndLogEx(ERR, "New password must be 16 hex bytes");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (errors || cmdp == 0) return usage_hf_st_pwd();
|
||||
|
||||
|
||||
bool activate_field = true;
|
||||
bool keep_field_on = true;
|
||||
uint8_t response[PM3_CMD_DATA_SIZE];
|
||||
|
@ -745,13 +739,13 @@ static int cmd_hf_st_list(const char *Cmd) {
|
|||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"},
|
||||
{"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"},
|
||||
{"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"},
|
||||
{"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"},
|
||||
{"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"},
|
||||
{"protect", cmd_hf_st_protect, IfPm3Iso14443a, "change protection on tag"},
|
||||
{"pwd", cmd_hf_st_pwd, IfPm3Iso14443a, "change password on tag"},
|
||||
{"sim", cmd_hf_st_sim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"},
|
||||
{"pwd", cmd_hf_st_pwd, IfPm3Iso14443a, "change password on tag"},
|
||||
{"sim", cmd_hf_st_sim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -565,7 +565,7 @@ static int transceive_blocking(uint8_t *txBuf, uint16_t txBufLen, uint8_t *rxBuf
|
|||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (resp.oldarg[0] > rxBufLen) {
|
||||
PrintAndLogEx(WARNING, "Received %u bytes, rxBuf too small (%u)", resp.oldarg[0], rxBufLen);
|
||||
PrintAndLogEx(WARNING, "Received %"PRIu32 " bytes, rxBuf too small (%u)", resp.oldarg[0], rxBufLen);
|
||||
memcpy(rxBuf, resp.data.asBytes, rxBufLen);
|
||||
*actLen = rxBufLen;
|
||||
return PM3_ESOFT;
|
||||
|
|
|
@ -716,7 +716,7 @@ void pm3_version(bool verbose, bool oneliner) {
|
|||
PrintAndLogEx(NORMAL, " compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH);
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("PROXMARK3") " ]");
|
||||
if (IfPm3Rdv4Fw() == false ){
|
||||
if (IfPm3Rdv4Fw() == false) {
|
||||
PrintAndLogEx(NORMAL, " firmware.........................%s", _GREEN_("PM3OTHER"));
|
||||
if (IfPm3FpcUsartHost()) {
|
||||
PrintAndLogEx(NORMAL, " FPC USART for BT add-on..........%s", _GREEN_("present"));
|
||||
|
|
|
@ -33,28 +33,29 @@
|
|||
#include "cmdlfem4x50.h" // for em4x50
|
||||
#include "cmdlfhid.h" // for hid menu
|
||||
#include "cmdlfhitag.h" // for hitag menu
|
||||
#include "cmdlfidteck.h" // for idteck menu
|
||||
#include "cmdlfio.h" // for ioprox menu
|
||||
#include "cmdlft55xx.h" // for t55xx menu
|
||||
#include "cmdlfti.h" // for ti menu
|
||||
#include "cmdlfpresco.h" // for presco menu
|
||||
#include "cmdlfpcf7931.h" // for pcf7931 menu
|
||||
#include "cmdlfpyramid.h" // for pyramid menu
|
||||
#include "cmdlfviking.h" // for viking menu
|
||||
#include "cmdlfnedap.h" // for NEDAP menu
|
||||
#include "cmdlfjablotron.h" // for JABLOTRON menu
|
||||
#include "cmdlfvisa2000.h" // for VISA2000 menu
|
||||
#include "cmdlfnoralsy.h" // for NORALSY meny
|
||||
#include "cmdlfcotag.h" // for COTAG meny
|
||||
#include "cmdlfindala.h" // for indala menu
|
||||
#include "cmdlfguard.h" // for gproxii menu
|
||||
#include "cmdlffdx.h" // for fdx-b menu
|
||||
#include "cmdlfparadox.h" // for paradox menu
|
||||
#include "cmdlfnexwatch.h" // for nexwatch menu
|
||||
#include "cmdlfsecurakey.h" // for securakey menu
|
||||
#include "cmdlfpac.h" // for pac menu
|
||||
#include "cmdlfgallagher.h" // for GALLAGHER menu
|
||||
#include "cmdlfguard.h" // for gproxii menu
|
||||
#include "cmdlfindala.h" // for indala menu
|
||||
#include "cmdlfjablotron.h" // for JABLOTRON menu
|
||||
#include "cmdlfkeri.h" // for keri menu
|
||||
#include "cmdlfmotorola.h" // for Motorola menu
|
||||
#include "cmdlfgallagher.h" // for GALLAGHER menu
|
||||
#include "cmdlfnedap.h" // for NEDAP menu
|
||||
#include "cmdlfnexwatch.h" // for nexwatch menu
|
||||
#include "cmdlfnoralsy.h" // for NORALSY meny
|
||||
#include "cmdlfpac.h" // for pac menu
|
||||
#include "cmdlfparadox.h" // for paradox menu
|
||||
#include "cmdlfpcf7931.h" // for pcf7931 menu
|
||||
#include "cmdlfpresco.h" // for presco menu
|
||||
#include "cmdlfpyramid.h" // for pyramid menu
|
||||
#include "cmdlfsecurakey.h" // for securakey menu
|
||||
#include "cmdlft55xx.h" // for t55xx menu
|
||||
#include "cmdlfti.h" // for ti menu
|
||||
#include "cmdlfviking.h" // for viking menu
|
||||
#include "cmdlfvisa2000.h" // for VISA2000 menu
|
||||
|
||||
#define LF_CMDREAD_MAX_EXTRA_SYMBOLS 4
|
||||
static bool g_lf_threshold_set = false;
|
||||
|
@ -77,14 +78,14 @@ static int usage_lf_cmdread(void) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in decimal and in microseconds (us)"));
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, "- probing for Hitag 1/Hitag S:");
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" probing for Hitag 1/Hitag S") ":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf cmdread d 50 z 116 o 166 e W 3000 c W00110"));
|
||||
PrintAndLogEx(NORMAL, "- probing for Hitag 2:");
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" probing for Hitag 2") ":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf cmdread d 50 z 116 o 166 e W 3000 c W11000"));
|
||||
PrintAndLogEx(NORMAL, "- probing for Hitag 2, oscilloscope style:");
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" probing for Hitag 2, oscilloscope style") ":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" data plot"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf cmdread d 50 z 116 o 166 e W 3000 c W11000 q s 2000 @"));
|
||||
PrintAndLogEx(NORMAL, "- probing for Hitag (us):");
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" probing for Hitag (us)") ":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf cmdread d 48 z 112 o 176 e W 3000 e S 240 e E 336 c W0S00000010000E"));
|
||||
PrintAndLogEx(NORMAL, "Extras:");
|
||||
PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters.");
|
||||
|
@ -116,8 +117,8 @@ static int usage_lf_sim(void) {
|
|||
PrintAndLogEx(NORMAL, " h This help");
|
||||
PrintAndLogEx(NORMAL, " <gap> Start gap (in microseconds)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf sim 240 - start simulating with 240ms gap");
|
||||
PrintAndLogEx(NORMAL, " lf sim");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf sim 240") " - start simulating with 240ms gap");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf sim"));
|
||||
PrintAndLogEx(NORMAL, "Extras:");
|
||||
PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters.");
|
||||
return PM3_SUCCESS;
|
||||
|
@ -132,9 +133,9 @@ static int usage_lf_sniff(void) {
|
|||
PrintAndLogEx(NORMAL, " @ run continuously until a key is pressed (optional)");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf sniff");
|
||||
PrintAndLogEx(NORMAL, "- oscilloscope style:");
|
||||
PrintAndLogEx(NORMAL, " data plot");
|
||||
PrintAndLogEx(NORMAL, " lf sniff q s 3000 @");
|
||||
PrintAndLogEx(NORMAL, _CYAN_(" oscilloscope style") ":");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" data plot"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf sniff q s 3000 @"));
|
||||
PrintAndLogEx(NORMAL, "Extras:");
|
||||
PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters.");
|
||||
PrintAndLogEx(NORMAL, " use " _YELLOW_("'data plot'")" to look at it");
|
||||
|
@ -154,12 +155,12 @@ static int usage_lf_config(void) {
|
|||
PrintAndLogEx(NORMAL, " t <threshold> Sets trigger threshold. 0 means no threshold (range: 0-128)");
|
||||
PrintAndLogEx(NORMAL, " s <samplestoskip> Sets a number of samples to skip before capture. Default: 0");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf config - shows current config");
|
||||
PrintAndLogEx(NORMAL, " lf config b 8 L - samples at 125 kHz, 8bps.");
|
||||
PrintAndLogEx(NORMAL, " lf config H b 4 d 3 - samples at 134 kHz, averages three samples into one, stored with ");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf config") " - shows current config");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf config b 8 L") " - samples at 125 kHz, 8bps.");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf config H b 4 d 3") " - samples at 134 kHz, averages three samples into one, stored with ");
|
||||
PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample.");
|
||||
PrintAndLogEx(NORMAL, " lf read - performs a read (active field)");
|
||||
PrintAndLogEx(NORMAL, " lf sniff - performs a sniff (no active field)");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf read") " - performs a read (active field)");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf sniff") " - performs a sniff (no active field)");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_simfsk(void) {
|
||||
|
@ -180,10 +181,10 @@ static int usage_lf_simfsk(void) {
|
|||
PrintAndLogEx(NORMAL, "\n NOTE: if you set one clock manually set them all manually");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf simfsk c 40 H 8 L 5 d 010203 - FSK1 rf/40 data 010203");
|
||||
PrintAndLogEx(NORMAL, " lf simfsk c 40 H 5 L 8 d 010203 - FSK1a rf/40 data 010203");
|
||||
PrintAndLogEx(NORMAL, " lf simfsk c 64 H 10 L 8 d 010203 - FSK2 rf/64 data 010203");
|
||||
PrintAndLogEx(NORMAL, " lf simfsk c 64 H 8 L 10 d 010203 - FSK2a rf/64 data 010203");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf simfsk c 40 H 8 L 5 d 010203") " - FSK1 rf/40 data 010203");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf simfsk c 40 H 5 L 8 d 010203") " - FSK1a rf/40 data 010203");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf simfsk c 64 H 10 L 8 d 010203") " - FSK2 rf/64 data 010203");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf simfsk c 64 H 8 L 10 d 010203") " - FSK2a rf/64 data 010203");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -221,10 +222,10 @@ static int usage_lf_find(void) {
|
|||
PrintAndLogEx(NORMAL, " <0|1> Use data from Graphbuffer, if not set, try reading data from tag.");
|
||||
PrintAndLogEx(NORMAL, " u Search for Unknown tags, if not set, reads only known tags.");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf search = try reading data from tag & search for known tags");
|
||||
PrintAndLogEx(NORMAL, " lf search 1 = use data from GraphBuffer & search for known tags");
|
||||
PrintAndLogEx(NORMAL, " lf search u = try reading data from tag & search for known and unknown tags");
|
||||
PrintAndLogEx(NORMAL, " lf search 1 u = use data from GraphBuffer & search for known and unknown tags");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf search") " - try reading data from tag & search for known tags");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf search 1") " - use data from GraphBuffer & search for known tags");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf search u") " - try reading data from tag & search for known and unknown tags");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf search 1 u") " - use data from GraphBuffer & search for known and unknown tags");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_tune(void) {
|
||||
|
@ -1445,27 +1446,27 @@ int CmdLFfind(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
if (demodVisa2k() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Visa2000 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 (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 (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 (demodVisa2k(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Visa2000 ID") " found!"); goto out;}
|
||||
if (demodHID(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;}
|
||||
if (demodAWID(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;}
|
||||
if (demodIOProx(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;}
|
||||
if (demodParadox(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;}
|
||||
if (demodNexWatch(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); goto out;}
|
||||
if (demodIndala(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;}
|
||||
if (demodEM410x(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;}
|
||||
if (demodFDX(true) == 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 (demodIdteck() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck 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 (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 (demodPac() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;}
|
||||
if (demodPresco() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;}
|
||||
if (demodPyramid() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;}
|
||||
if (demodSecurakey() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;}
|
||||
if (demodViking() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Viking ID") " found!"); goto out;}
|
||||
if (demodGallagher() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") " found!"); goto out;}
|
||||
if (demodGuard(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; }
|
||||
if (demodIdteck(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
|
||||
if (demodJablotron(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;}
|
||||
if (demodNedap(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!"); goto out;}
|
||||
if (demodNoralsy(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;}
|
||||
if (demodKeri(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;}
|
||||
if (demodPac(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;}
|
||||
if (demodPresco(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;}
|
||||
if (demodPyramid(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;}
|
||||
if (demodSecurakey(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;}
|
||||
if (demodViking(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Viking ID") " found!"); goto out;}
|
||||
if (demodGallagher(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") " found!"); goto out;}
|
||||
|
||||
// if (demodTI() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") " found!"); goto out;}
|
||||
// if (demodFermax() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") " found!"); goto out;}
|
||||
|
@ -1486,14 +1487,14 @@ int CmdLFfind(const char *Cmd) {
|
|||
|
||||
//fsk
|
||||
if (GetFskClock("", false)) {
|
||||
if (FSKrawDemod("", true) == PM3_SUCCESS) {
|
||||
if (FSKrawDemod(0, 0, 0, 0, true) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(NORMAL, "\nUnknown FSK Modulated Tag found!");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
bool st = true;
|
||||
if (ASKDemod_ext("0 0 0", true, false, 1, &st) == PM3_SUCCESS) {
|
||||
if (ASKDemod_ext(0, 0, 0, 0, false, true, false, 1, &st) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(NORMAL, "\nUnknown ASK Modulated and Manchester encoded Tag found!");
|
||||
PrintAndLogEx(NORMAL, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'"));
|
||||
goto out;
|
||||
|
@ -1531,6 +1532,7 @@ static command_t CommandTable[] = {
|
|||
{"gproxii", CmdLFGuard, AlwaysAvailable, "{ Guardall Prox II RFIDs... }"},
|
||||
{"hid", CmdLFHID, AlwaysAvailable, "{ HID Prox RFIDs... }"},
|
||||
{"hitag", CmdLFHitag, AlwaysAvailable, "{ Hitag CHIPs... }"},
|
||||
{"idteck", CmdLFIdteck, AlwaysAvailable, "{ Idteck RFIDs... }"},
|
||||
{"indala", CmdLFINDALA, AlwaysAvailable, "{ Indala RFIDs... }"},
|
||||
{"io", CmdLFIO, AlwaysAvailable, "{ ioProx RFIDs... }"},
|
||||
{"jablotron", CmdLFJablotron, AlwaysAvailable, "{ Jablotron RFIDs... }"},
|
||||
|
|
|
@ -196,9 +196,8 @@ static int CmdAWIDWatch(const char *Cmd) {
|
|||
//by marshmellow
|
||||
//AWID Prox demod - FSK2a RF/50 with preamble of 00000001 (always a 96 bit data stream)
|
||||
//print full AWID Prox ID and some bit format details if found
|
||||
static int CmdAWIDDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
|
||||
int demodAWID(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - AWID failed to allocate memory");
|
||||
|
@ -337,10 +336,16 @@ static int CmdAWIDDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdAWIDDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodAWID(true);
|
||||
}
|
||||
|
||||
// this read is the "normal" read, which download lf signal and tries to demod here.
|
||||
static int CmdAWIDRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 12000);
|
||||
return CmdAWIDDemod(Cmd);
|
||||
return demodAWID(true);
|
||||
}
|
||||
|
||||
static int CmdAWIDSim(const char *Cmd) {
|
||||
|
@ -605,7 +610,3 @@ int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits) {
|
|||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int demodAWID(void) {
|
||||
return CmdAWIDDemod("");
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
int CmdLFAWID(const char *Cmd);
|
||||
|
||||
int demodAWID(void);
|
||||
int demodAWID(bool verbose);
|
||||
int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,7 +37,8 @@ static int usage_lf_cotag_read(void) {
|
|||
|
||||
// COTAG demod should be able to use GraphBuffer,
|
||||
// when data load samples
|
||||
int demodCOTAG(void) {
|
||||
int demodCOTAG(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
|
||||
uint8_t bits[COTAG_BITS] = {0};
|
||||
size_t bitlen = COTAG_BITS;
|
||||
|
@ -73,8 +74,8 @@ int demodCOTAG(void) {
|
|||
}
|
||||
|
||||
static int CmdCOTAGDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodCOTAG();
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodCOTAG(true);
|
||||
}
|
||||
// When reading a COTAG.
|
||||
// 0 = HIGH/LOW signal - maxlength bigbuff
|
||||
|
@ -118,7 +119,7 @@ static int CmdCOTAGRead(const char *Cmd) {
|
|||
case 1: {
|
||||
memcpy(DemodBuffer, resp.data.asBytes, resp.length);
|
||||
DemodBufferLen = resp.length;
|
||||
return demodCOTAG();
|
||||
return demodCOTAG(true);
|
||||
}
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
#endif
|
||||
|
||||
int CmdLFCOTAG(const char *Cmd);
|
||||
int demodCOTAG(void);
|
||||
int demodCOTAG(bool verbose);
|
||||
int readCOTAGUid(void);
|
||||
#endif
|
||||
|
|
|
@ -63,17 +63,17 @@ static int usage_lf_em410x_watch(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_lf_em410x_write(void) {
|
||||
static int usage_lf_em410x_clone(void) {
|
||||
PrintAndLogEx(NORMAL, "Writes EM410x ID to a T55x7 or Q5/T5555 tag");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf em 410x_write [h] <id> <card> [clock]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf em 410x_clone [h] <id> <card> [clock]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " <id> - ID number");
|
||||
PrintAndLogEx(NORMAL, " <card> - 0|1 0 = Q5/T5555, 1 = T55x7");
|
||||
PrintAndLogEx(NORMAL, " <clock> - 16|32|40|64, optional, set R/F clock rate, defaults to 64");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_write 0F0368568B 1") " = write ID to t55x7 card");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf em 410x_clone 0F0368568B 1") " = write ID to t55x7 card");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_em410x_ws(void) {
|
||||
|
@ -390,15 +390,14 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose) {
|
||||
int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose) {
|
||||
bool st = true;
|
||||
|
||||
// em410x simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
|
||||
if (isGraphBitstream()) {
|
||||
convertGraphFromBitstream();
|
||||
}
|
||||
|
||||
if (ASKDemod_ext(Cmd, false, false, 1, &st) != PM3_SUCCESS)
|
||||
if (ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, false, false, 1, &st) != PM3_SUCCESS)
|
||||
return PM3_ESOFT;
|
||||
return AskEm410xDecode(verbose, hi, lo);
|
||||
}
|
||||
|
@ -423,14 +422,27 @@ static int CmdEM410xWatch(const char *Cmd) {
|
|||
//takes 3 arguments - clock, invert and maxErr as integers
|
||||
//attempts to demodulate ask while decoding manchester
|
||||
//prints binary found and saves in graphbuffer for further commands
|
||||
int demodEM410x(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
uint32_t hi = 0;
|
||||
uint64_t lo = 0;
|
||||
return AskEm410xDemod(0, 0, 100, 0, false, &hi, &lo, true);
|
||||
}
|
||||
|
||||
static int CmdEM410xDemod(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod();
|
||||
|
||||
uint32_t hi = 0;
|
||||
uint64_t lo = 0;
|
||||
|
||||
if (AskEm410xDemod(Cmd, &hi, &lo, true) != PM3_SUCCESS)
|
||||
int clk = 0;
|
||||
int invert = 0;
|
||||
int maxErr = 100;
|
||||
size_t maxLen = 0;
|
||||
char amp = tolower(param_getchar(Cmd, 0));
|
||||
sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &);
|
||||
bool amplify = amp == 'a';
|
||||
if (AskEm410xDemod(clk, invert, maxErr, maxLen, amplify, &hi, &lo, true) != PM3_SUCCESS)
|
||||
return PM3_ESOFT;
|
||||
|
||||
g_em410xid = lo;
|
||||
|
@ -439,8 +451,20 @@ static int CmdEM410xDemod(const char *Cmd) {
|
|||
|
||||
// this read is the "normal" read, which download lf signal and tries to demod here.
|
||||
static int CmdEM410xRead(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod();
|
||||
|
||||
uint32_t hi = 0;
|
||||
uint64_t lo = 0;
|
||||
int clk = 0;
|
||||
int invert = 0;
|
||||
int maxErr = 100;
|
||||
size_t maxLen = 0;
|
||||
char amp = tolower(param_getchar(Cmd, 0));
|
||||
sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &);
|
||||
bool amplify = amp == 'a';
|
||||
lf_read(false, 12288);
|
||||
return CmdEM410xDemod(Cmd);
|
||||
return AskEm410xDemod(clk, invert, maxErr, maxLen, amplify, &hi, &lo, true);
|
||||
}
|
||||
|
||||
// emulate an EM410X tag
|
||||
|
@ -591,9 +615,9 @@ static int CmdEM410xWatchnSpoof(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdEM410xWrite(const char *Cmd) {
|
||||
static int CmdEM410xClone(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 0x00 || cmdp == 'h') return usage_lf_em410x_write();
|
||||
if (cmdp == 0x00 || cmdp == 'h') return usage_lf_em410x_clone();
|
||||
|
||||
uint64_t id = param_get64ex(Cmd, 0, -1, 16);
|
||||
uint8_t card = param_get8ex(Cmd, 1, 0xFF, 10);
|
||||
|
@ -602,19 +626,19 @@ static int CmdEM410xWrite(const char *Cmd) {
|
|||
// Check ID
|
||||
if (id == 0xFFFFFFFFFFFFFFFF) {
|
||||
PrintAndLogEx(ERR, "error, ID is required\n");
|
||||
usage_lf_em410x_write();
|
||||
usage_lf_em410x_clone();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (id >= 0x10000000000) {
|
||||
PrintAndLogEx(ERR, "error, given EM410x ID is longer than 40 bits\n");
|
||||
usage_lf_em410x_write();
|
||||
usage_lf_em410x_clone();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// Check Card
|
||||
if (card > 1) {
|
||||
PrintAndLogEx(FAILED, "error, bad card type selected\n");
|
||||
usage_lf_em410x_write();
|
||||
usage_lf_em410x_clone();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -626,7 +650,7 @@ static int CmdEM410xWrite(const char *Cmd) {
|
|||
if ((clock1 != 16) && (clock1 != 32) && (clock1 != 64) && (clock1 != 40)) {
|
||||
PrintAndLogEx(FAILED, "error, clock rate" _RED_("%d")" not valid", clock1);
|
||||
PrintAndLogEx(INFO, "supported clock rates: " _YELLOW_("16, 32, 40, 60") "\n");
|
||||
usage_lf_em410x_write();
|
||||
usage_lf_em410x_clone();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -735,7 +759,7 @@ static bool detectFSK(void) {
|
|||
return false;
|
||||
}
|
||||
// demod
|
||||
int ans = FSKrawDemod("0 0", false);
|
||||
int ans = FSKrawDemod(0, 0, 0, 0, false);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: FSK Demod failed");
|
||||
return false;
|
||||
|
@ -751,12 +775,12 @@ static bool detectPSK(void) {
|
|||
}
|
||||
//demod
|
||||
//try psk1 -- 0 0 6 (six errors?!?)
|
||||
ans = PSKDemod("0 0 6", false);
|
||||
ans = PSKDemod(0, 0, 6, false);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: PSK1 Demod failed");
|
||||
|
||||
//try psk1 inverted
|
||||
ans = PSKDemod("0 1 6", false);
|
||||
ans = PSKDemod(0, 1, 6, false);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: PSK1 inverted Demod failed");
|
||||
return false;
|
||||
|
@ -769,7 +793,7 @@ static bool detectPSK(void) {
|
|||
// try manchester - NOTE: ST only applies to T55x7 tags.
|
||||
static bool detectASK_MAN(void) {
|
||||
bool stcheck = false;
|
||||
if (ASKDemod_ext("0 0 0", false, false, 1, &stcheck) != PM3_SUCCESS) {
|
||||
if (ASKDemod_ext(0, 0, 0, 0, false, false, false, 1, &stcheck) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/Manchester Demod failed");
|
||||
return false;
|
||||
}
|
||||
|
@ -777,11 +801,11 @@ static bool detectASK_MAN(void) {
|
|||
}
|
||||
|
||||
static bool detectASK_BI(void) {
|
||||
int ans = ASKbiphaseDemod("0 0 1", false);
|
||||
int ans = ASKbiphaseDemod(0, 0, 1, 50, false);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/biphase normal demod failed");
|
||||
|
||||
ans = ASKbiphaseDemod("0 1 1", false);
|
||||
ans = ASKbiphaseDemod(0, 1, 1, 50, false);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/biphase inverted demod failed");
|
||||
return false;
|
||||
|
@ -790,11 +814,11 @@ static bool detectASK_BI(void) {
|
|||
return true;
|
||||
}
|
||||
static bool detectNRZ(void) {
|
||||
int ans = NRZrawDemod("0 0 1", false);
|
||||
int ans = NRZrawDemod(0, 0, 1, false);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: NRZ normal demod failed");
|
||||
|
||||
ans = NRZrawDemod("0 1 1", false);
|
||||
ans = NRZrawDemod(0, 1, 1, false);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - EM: NRZ inverted demod failed");
|
||||
return false;
|
||||
|
@ -1383,7 +1407,7 @@ static command_t CommandTable[] = {
|
|||
{"410x_brute", CmdEM410xBrute, IfPm3Lf, "reader bruteforce attack by simulating EM410x tags"},
|
||||
{"410x_watch", CmdEM410xWatch, IfPm3Lf, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
{"410x_spoof", CmdEM410xWatchnSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||
{"410x_write", CmdEM410xWrite, IfPm3Lf, "write EM410x UID to T55x7 or Q5/T5555 tag"},
|
||||
{"410x_clone", CmdEM410xClone, IfPm3Lf, "write EM410x UID to T55x7 or Q5/T5555 tag"},
|
||||
{"----------", CmdHelp, AlwaysAvailable, "-------------------- " _CYAN_("EM 4x05 / 4x69") " -------------------"},
|
||||
{"4x05_demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"},
|
||||
{"4x05_dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"},
|
||||
|
@ -1414,7 +1438,3 @@ int CmdLFEM4X(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
int demodEM410x(void) {
|
||||
return CmdEM410xDemod("");
|
||||
}
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
|
||||
int CmdLFEM4X(const char *Cmd);
|
||||
|
||||
int demodEM410x(void);
|
||||
int demodEM410x(bool verbose);
|
||||
bool EM4x05IsBlock0(uint32_t *word);
|
||||
|
||||
void printEM410x(uint32_t hi, uint64_t id);
|
||||
int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo);
|
||||
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose);
|
||||
int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -597,6 +597,8 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) {
|
|||
int CmdEM4x50Read(const char *Cmd) {
|
||||
|
||||
em4x50_data_t etd;
|
||||
memset(&etd, 0x00, sizeof(em4x50_data_t));
|
||||
|
||||
etd.pwd_given = false;
|
||||
etd.addr_given = false;
|
||||
etd.newpwd_given = false;
|
||||
|
|
|
@ -220,7 +220,7 @@ static int CmdFDXBdemodBI(const char *Cmd) {
|
|||
int demodFDX(bool verbose) {
|
||||
//Differential Biphase / di-phase (inverted biphase)
|
||||
//get binary from ask wave
|
||||
if (ASKbiphaseDemod("0 32 1 100", false) != PM3_SUCCESS) {
|
||||
if (ASKbiphaseDemod(0, 32, 1, 100, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - FDX-B ASKbiphaseDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
|
|
@ -67,11 +67,10 @@ static void descramble(uint8_t *arr, uint8_t len) {
|
|||
}
|
||||
|
||||
//see ASK/MAN Demod for what args are accepted
|
||||
static int CmdGallagherDemod(const char *Cmd) {
|
||||
|
||||
(void)Cmd;
|
||||
int demodGallagher(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
bool st = true;
|
||||
if (ASKDemod_ext("32 0 0 0", false, false, 1, &st) != PM3_SUCCESS) {
|
||||
if (ASKDemod_ext(32, 0, 100, 0, false, false, false, 1, &st) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - GALLAGHER: ASKDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -134,9 +133,15 @@ static int CmdGallagherDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdGallagherDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodGallagher(true);
|
||||
}
|
||||
|
||||
static int CmdGallagherRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 4096 * 2 + 20);
|
||||
return CmdGallagherDemod(Cmd);
|
||||
return demodGallagher(true);
|
||||
}
|
||||
|
||||
static int CmdGallagherClone(const char *Cmd) {
|
||||
|
@ -222,8 +227,3 @@ int detectGallagher(uint8_t *dest, size_t *size) {
|
|||
//return start position
|
||||
return (int)startIdx;
|
||||
}
|
||||
|
||||
int demodGallagher(void) {
|
||||
return CmdGallagherDemod("");
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
int CmdLFGallagher(const char *Cmd);
|
||||
|
||||
int demodGallagher(void);
|
||||
int demodGallagher(bool verbose);
|
||||
int detectGallagher(uint8_t *dest, size_t *size);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -65,12 +65,11 @@ static int usage_lf_guard_sim(void) {
|
|||
//WARNING: if it fails during some points it will destroy the DemodBuffer data
|
||||
// but will leave the GraphBuffer intact.
|
||||
//if successful it will push askraw data back to demod buffer ready for emulation
|
||||
static int CmdGuardDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
|
||||
int demodGuard(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//Differential Biphase
|
||||
//get binary from ask wave
|
||||
if (ASKbiphaseDemod("0 64 0 0", false) != PM3_SUCCESS) {
|
||||
if (ASKbiphaseDemod(0, 64, 0, 0, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII ASKbiphaseDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -150,9 +149,15 @@ static int CmdGuardDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdGuardDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodGuard(true);
|
||||
}
|
||||
|
||||
static int CmdGuardRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 10000);
|
||||
return CmdGuardDemod(Cmd);
|
||||
return demodGuard(true);
|
||||
}
|
||||
|
||||
static int CmdGuardClone(const char *Cmd) {
|
||||
|
@ -290,10 +295,6 @@ int detectGProxII(uint8_t *bits, size_t *size) {
|
|||
return -5; //spacer bits not found - not a valid gproxII
|
||||
}
|
||||
|
||||
int demodGuard(void) {
|
||||
return CmdGuardDemod("");
|
||||
}
|
||||
|
||||
// Works for 26bits.
|
||||
int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) {
|
||||
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
|
||||
int CmdLFGuard(const char *Cmd);
|
||||
int detectGProxII(uint8_t *bits, size_t *size);
|
||||
int demodGuard(void);
|
||||
int demodGuard(bool verbose);
|
||||
int getGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits);
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "cmdparser.h" // command_t
|
||||
#include "comms.h"
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "cliparser.h"
|
||||
#include "ui.h"
|
||||
#include "graph.h"
|
||||
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
||||
|
@ -43,70 +44,6 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_lf_hid_watch(void) {
|
||||
PrintAndLogEx(NORMAL, "Enables HID compatible reader mode printing details.");
|
||||
PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued.");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf hid watch");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid watch"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_hid_sim(void) {
|
||||
PrintAndLogEx(NORMAL, "Enables simulation of HID card with card number.");
|
||||
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf hid sim [h] [ID]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - This help");
|
||||
PrintAndLogEx(NORMAL, " ID - HID id");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid sim 2006ec0c86"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_hid_clone(void) {
|
||||
PrintAndLogEx(NORMAL, "Clone HID to T55x7. " _BLUE_("Tag must be on antenna!"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf hid clone [h] [l] ID");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - This help");
|
||||
PrintAndLogEx(NORMAL, " l - 84bit ID");
|
||||
PrintAndLogEx(NORMAL, " ID - HID id");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone 2006ec0c86"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf hid clone l 2006ec0c86"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_hid_brute(void) {
|
||||
PrintAndLogEx(NORMAL, "Enables bruteforce of HID readers with specified facility code.");
|
||||
PrintAndLogEx(NORMAL, "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step");
|
||||
PrintAndLogEx(NORMAL, "if cardnumber is not given, it starts with 1 and goes up to 65535");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] w <format> [<field> (decimal)>] [up|down] {...}");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h : This help");
|
||||
PrintAndLogEx(NORMAL, " w <format> : see " _YELLOW_("`wiegand list`") " for available formats");
|
||||
PrintAndLogEx(NORMAL, " f <facility-code> : facility code");
|
||||
PrintAndLogEx(NORMAL, " c <cardnumber> : card number to start with");
|
||||
PrintAndLogEx(NORMAL, " i <issuelevel> : issue level");
|
||||
PrintAndLogEx(NORMAL, " o <oem> : OEM code");
|
||||
PrintAndLogEx(NORMAL, " d <delay> : delay betweens attempts in ms. Default 1000ms");
|
||||
PrintAndLogEx(NORMAL, " v : verbose logging, show all tries");
|
||||
PrintAndLogEx(NORMAL, " up : direction to increment card number. (default is both directions)");
|
||||
PrintAndLogEx(NORMAL, " down : direction to decrement card number. (default is both directions)");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
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 v w H10301 f 21 c 200 d 2000"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// sending three times. Didn't seem to break the previous sim?
|
||||
static int sendPing(void) {
|
||||
SendCommandNG(CMD_PING, NULL, 0);
|
||||
|
@ -152,8 +89,8 @@ static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, boo
|
|||
//by marshmellow (based on existing demod + holiman's refactor)
|
||||
//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
|
||||
//print full HID Prox ID and some bit format details if found
|
||||
static int CmdHIDDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
int demodHID(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
|
||||
// HID simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
|
||||
if (isGraphBitstream()) {
|
||||
|
@ -261,17 +198,35 @@ static int CmdHIDDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHIDDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodHID(true);
|
||||
}
|
||||
|
||||
// this read is the "normal" read, which download lf signal and tries to demod here.
|
||||
static int CmdHIDRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 12000);
|
||||
return CmdHIDDemod(Cmd);
|
||||
return demodHID(true);
|
||||
}
|
||||
|
||||
// this read loops on device side.
|
||||
// uses the demod in lfops.c
|
||||
static int CmdHIDWatch(const char *Cmd) {
|
||||
uint8_t c = tolower(param_getchar(Cmd, 0));
|
||||
if (c == 'h') return usage_lf_hid_watch();
|
||||
CLIParserContext *ctx;
|
||||
|
||||
CLIParserInit(&ctx, "lf hid watch",
|
||||
"Enables HID compatible reader mode printing details.\n"
|
||||
"By default, values are printed and logged until the button is pressed or another USB command is issued.\n",
|
||||
"lf hid watch"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Watching for HID Prox cards - place tag on antenna");
|
||||
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
|
||||
|
@ -284,28 +239,52 @@ static int CmdHIDWatch(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHIDSim(const char *Cmd) {
|
||||
int idlen = 0;
|
||||
uint8_t id[10] = {0};
|
||||
lf_hidsim_t payload;
|
||||
payload.longFMT = 0;
|
||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||
uint32_t n = 0, i = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_hid_sim();
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf hid sim",
|
||||
"Enables simulation of HID card with card number.",
|
||||
"lf hid sim 2006ec0c86"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("l", "long", "Simulate HID tag with long ID"),
|
||||
arg_str1(NULL, NULL, "<hex>", "HID tag ID"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
if (strchr(Cmd, 'l') != 0) {
|
||||
i++;
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
bool long_id = arg_get_lit(ctx, 1);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 2, id, &idlen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (long_id) {
|
||||
for (i=0; i < idlen; ++i) {
|
||||
hi2 = (hi2 << 4) | (hi >> 28);
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (n & 0xf);
|
||||
}
|
||||
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||
|
||||
hi2 = (hi2 << 4) | (hi >> 28);
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||
}
|
||||
PrintAndLogEx(INFO, "Simulating HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
|
||||
payload.longFMT = 1;
|
||||
} else {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
for (i=0; i < idlen; ++i) {
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (n & 0xf);
|
||||
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Simulating HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
|
||||
hi2 = 0;
|
||||
|
@ -328,28 +307,55 @@ static int CmdHIDSim(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdHIDClone(const char *Cmd) {
|
||||
int idlen = 0;
|
||||
uint8_t id[10] = {0};
|
||||
|
||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||
uint32_t n = 0, i = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf hid clone",
|
||||
"Clone HID to T55x7. Tag must be on antenna!",
|
||||
"lf hid clone 2006ec0c86\n"
|
||||
"lf hid clone -l 2006ec0c86"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("l", "long", "84bit HID long ID"),
|
||||
arg_str1(NULL, NULL, "<hex>", "HID tag ID"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool long_id = arg_get_lit(ctx, 1);
|
||||
|
||||
CLIGetHexWithReturn(ctx, 2, id, &idlen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_hid_clone();
|
||||
uint8_t longid[1] = {0};
|
||||
if (strchr(Cmd, 'l') != 0) {
|
||||
i++;
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
|
||||
if (long_id) {
|
||||
for (i=0; i < idlen; ++i) {
|
||||
hi2 = (hi2 << 4) | (hi >> 28);
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (n & 0xf);
|
||||
}
|
||||
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||
|
||||
hi2 = (hi2 << 4) | (hi >> 28);
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||
}
|
||||
PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID: " _GREEN_("%x%08x%08x"), hi2, hi, lo);
|
||||
|
||||
longid[0] = 1;
|
||||
} else {
|
||||
while (sscanf(&Cmd[i++], "%1x", &n) == 1) {
|
||||
for (i=0; i < idlen; ++i) {
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (n & 0xf);
|
||||
lo = (lo << 4) | (id[i] >> 4); //get first 4 bits
|
||||
|
||||
hi = (hi << 4) | (lo >> 28);
|
||||
lo = (lo << 4) | (id[i] & 0xf); //get last 4 bits
|
||||
}
|
||||
PrintAndLogEx(INFO, "Preparing to clone HID tag with ID: " _GREEN_("%x%08x"), hi, lo);
|
||||
hi2 = 0;
|
||||
|
@ -379,82 +385,63 @@ static int CmdHIDClone(const char *Cmd) {
|
|||
|
||||
static int CmdHIDBrute(const char *Cmd) {
|
||||
|
||||
bool errors = false, verbose = false;
|
||||
uint32_t delay = 1000;
|
||||
uint8_t cmdp = 0;
|
||||
int format_idx = -1;
|
||||
int direction = 0;
|
||||
char format[16] = {0};
|
||||
uint8_t format[16] = {0};
|
||||
int formatLen;
|
||||
|
||||
wiegand_card_t cn_hi, cn_low;
|
||||
memset(&cn_hi, 0, sizeof(wiegand_card_t));
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf hid brute",
|
||||
"Enables bruteforce of HID readers with specified facility code.\n"
|
||||
"This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step\n"
|
||||
"if cardnumber is not given, it starts with 1 and goes up to 65535",
|
||||
"lf hid brute -w H10301 -f 224\n"
|
||||
"lf hid brute -w H10301 -f 21 -d 2000\n"
|
||||
"lf hid brute -v -w H10301 -f 21 -c 200 -d 2000\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("v", "verbose", "verbose logging, show all tries"),
|
||||
arg_str1("w", "wiegand", "format", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
||||
arg_int0("f", "fn", "dec", "facility code"),
|
||||
arg_int0("c", "cn", "dec", "card number to start with"),
|
||||
arg_int0("i", NULL, "dec", "issue level"),
|
||||
arg_int0("o", "oem", "dec", "OEM code"),
|
||||
arg_int0("d", "delay", "dec", "delay betweens attempts in ms. Default 1000ms"),
|
||||
arg_lit0(NULL, "up", "direction to increment card number. (default is both directions)"),
|
||||
arg_lit0(NULL, "down", "direction to decrement card number. (default is both directions)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
char s[10] = {0};
|
||||
if (param_getstr(Cmd, cmdp, s, sizeof(s)) > 0) {
|
||||
if (strlen(s) > 1) {
|
||||
str_lower((char *)s);
|
||||
if (str_startswith(s, "up")) {
|
||||
direction = 1;
|
||||
} else if (str_startswith(s, "do")) {
|
||||
direction = 2;
|
||||
}
|
||||
cmdp++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_lf_hid_brute();
|
||||
case 'w':
|
||||
param_getstr(Cmd, cmdp + 1, format, sizeof(format));
|
||||
format_idx = HIDFindCardFormat(format);
|
||||
if (format_idx == -1) {
|
||||
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
||||
errors = true;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'c':
|
||||
cn_hi.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'd':
|
||||
// delay between attemps, defaults to 1000ms.
|
||||
delay = param_get32ex(Cmd, cmdp + 1, 1000, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'f':
|
||||
cn_hi.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'i':
|
||||
cn_hi.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'o':
|
||||
cn_hi.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter: " _YELLOW_("'%c'"), param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool verbose = arg_get_lit(ctx, 1);
|
||||
|
||||
CLIGetStrWithReturn(ctx, 2, format, &formatLen);
|
||||
|
||||
format_idx = HIDFindCardFormat((char*) format);
|
||||
if (format_idx == -1) {
|
||||
PrintAndLogEx(ERR, "You must select a wiegand format. See " _YELLOW_("`wiegand list`") " for available formats\n");
|
||||
errors = true;
|
||||
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (errors) return usage_lf_hid_brute();
|
||||
cn_hi.FacilityCode = arg_get_int_def(ctx, 3, 0);
|
||||
cn_hi.CardNumber = arg_get_int_def(ctx, 4, 0);
|
||||
cn_hi.IssueLevel = arg_get_int_def(ctx, 5, 0);
|
||||
cn_hi.OEM = arg_get_int_def(ctx, 6, 0);
|
||||
delay = arg_get_int_def(ctx, 7, 1000);
|
||||
|
||||
if (arg_get_lit(ctx, 8) && arg_get_lit(ctx, 9)) {
|
||||
direction = 0;
|
||||
} else if (arg_get_lit(ctx, 8)) {
|
||||
direction = 1;
|
||||
} else if (arg_get_lit(ctx, 9)) {
|
||||
direction = 2;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx);
|
||||
|
@ -562,7 +549,3 @@ int CmdLFHID(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
int demodHID(void) {
|
||||
return CmdHIDDemod("");
|
||||
}
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
|
||||
int CmdLFHID(const char *Cmd);
|
||||
|
||||
int demodHID(void);
|
||||
int demodHID(bool verbose);
|
||||
|
||||
#endif
|
||||
|
|
136
client/src/cmdlfidteck.c
Normal file
136
client/src/cmdlfidteck.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Iceman,
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Low frequency Idteck tag commands
|
||||
// PSK
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "cmdlfidteck.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "comms.h"
|
||||
#include "ui.h"
|
||||
#include "cmddata.h"
|
||||
#include "cmdlf.h"
|
||||
#include "lfdemod.h"
|
||||
#include "commonutil.h" // num_to_bytes
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
int demodIdteck(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
if (PSKDemod(0, 0, 100, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
size_t size = DemodBufferLen;
|
||||
|
||||
//get binary from PSK1 wave
|
||||
int idx = detectIdteck(DemodBuffer, &size);
|
||||
if (idx < 0) {
|
||||
|
||||
if (idx == -1)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples");
|
||||
else if (idx == -2)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise");
|
||||
else if (idx == -3)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found");
|
||||
else if (idx == -4)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %zu", size);
|
||||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d", idx);
|
||||
|
||||
// if didn't find preamble try again inverting
|
||||
if (PSKDemod(0, 1, 100, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
idx = detectIdteck(DemodBuffer, &size);
|
||||
if (idx < 0) {
|
||||
|
||||
if (idx == -1)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples");
|
||||
else if (idx == -2)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise");
|
||||
else if (idx == -3)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found");
|
||||
else if (idx == -4)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %zu", size);
|
||||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d", idx);
|
||||
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
setDemodBuff(DemodBuffer, 64, idx);
|
||||
|
||||
//got a good demod
|
||||
uint32_t id = 0;
|
||||
uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
|
||||
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
|
||||
|
||||
//parity check (TBD)
|
||||
//checksum check (TBD)
|
||||
|
||||
//output
|
||||
PrintAndLogEx(SUCCESS, "IDTECK Tag Found: Card ID %u , Raw: %08X%08X", id, raw1, raw2);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdIdteckDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodIdteck(true);
|
||||
}
|
||||
|
||||
static int CmdIdteckRead(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
lf_read(false, 5000);
|
||||
return demodIdteck(true);
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"demod", CmdIdteckDemod, AlwaysAvailable, "Demodulate an Idteck tag from the GraphBuffer"},
|
||||
{"read", CmdIdteckRead, IfPm3Lf, "Attempt to read and Extract tag data from the antenna"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int CmdHelp(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
CmdsHelp(CommandTable);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdLFIdteck(const char *Cmd) {
|
||||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
// Find IDTEC PSK1, RF Preamble == 0x4944544B, Demodsize 64bits
|
||||
// by iceman
|
||||
int detectIdteck(uint8_t *dest, size_t *size) {
|
||||
//make sure buffer has data
|
||||
if (*size < 64 * 2) return -1;
|
||||
|
||||
if (getSignalProperties()->isnoise) return -2;
|
||||
|
||||
size_t start_idx = 0;
|
||||
uint8_t preamble[] = {0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1};
|
||||
|
||||
//preamble not found
|
||||
if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx))
|
||||
return -3;
|
||||
|
||||
// wrong demoded size
|
||||
if (*size != 64) return -4;
|
||||
return (int)start_idx;
|
||||
}
|
19
client/src/cmdlfidteck.h
Normal file
19
client/src/cmdlfidteck.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Low frequency Idteck tag commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef CMDLFIDTECK_H__
|
||||
#define CMDLFIDTECK_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int CmdLFIdteck(const char *Cmd);
|
||||
|
||||
int demodIdteck(bool verbose);
|
||||
int detectIdteck(uint8_t *dest, size_t *size);
|
||||
|
||||
#endif
|
|
@ -151,25 +151,17 @@ static void decodeHeden2L(uint8_t *bits) {
|
|||
// Indala 26 bit decode
|
||||
// by marshmellow, martinbeier
|
||||
// optional arguments - same as PSKDemod (clock & invert & maxerr)
|
||||
static int CmdIndalaDemod(const char *Cmd) {
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_lf_indala_demod();
|
||||
|
||||
int ans;
|
||||
if (strlen(Cmd) > 0)
|
||||
ans = PSKDemod(Cmd, true);
|
||||
else
|
||||
ans = PSKDemod("32", true);
|
||||
|
||||
int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
int ans = PSKDemod(clk, invert, maxErr, true);
|
||||
if (ans != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Indala can't demod signal: %d", ans);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t invert = 0;
|
||||
uint8_t inv = 0;
|
||||
size_t size = DemodBufferLen;
|
||||
int idx = detectIndala(DemodBuffer, &size, &invert);
|
||||
int idx = detectIndala(DemodBuffer, &size, &inv);
|
||||
if (idx < 0) {
|
||||
if (idx == -1)
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: not enough samples");
|
||||
|
@ -281,6 +273,29 @@ static int CmdIndalaDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int demodIndala(bool verbose) {
|
||||
return demodIndalaEx(32, 0, 100, verbose);
|
||||
}
|
||||
|
||||
static int CmdIndalaDemod(const char *Cmd) {
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_lf_indala_demod();
|
||||
|
||||
int clk = 32, invert = 0, maxErr = 100;
|
||||
if (strlen(Cmd) > 0) {
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
}
|
||||
if (clk == 1) {
|
||||
invert = 1;
|
||||
clk = 0;
|
||||
}
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
return demodIndalaEx(clk, invert, maxErr, true);
|
||||
}
|
||||
// older alternative indala demodulate (has some positives and negatives)
|
||||
// returns false positives more often - but runs against more sets of samples
|
||||
// poor psk signal can be difficult to demod this approach might succeed when the other fails
|
||||
|
@ -485,8 +500,15 @@ static int CmdIndalaDemodAlt(const char *Cmd) {
|
|||
|
||||
// this read is the "normal" read, which download lf signal and tries to demod here.
|
||||
static int CmdIndalaRead(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_lf_indala_demod();
|
||||
|
||||
int clk = 32, invert = 0, maxErr = 100;
|
||||
if (strlen(Cmd) > 0) {
|
||||
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
|
||||
}
|
||||
lf_read(false, 30000);
|
||||
return CmdIndalaDemod(Cmd);
|
||||
return demodIndalaEx(clk, invert, maxErr, true);
|
||||
}
|
||||
|
||||
static int CmdIndalaSim(const char *Cmd) {
|
||||
|
@ -558,20 +580,19 @@ static int CmdIndalaClone(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf indala clone",
|
||||
"clone INDALA UID to T55x7 or Q5/T5555 tag",
|
||||
"Examples:\n"
|
||||
_YELLOW_("\tlf indala clone --heden 888\n")
|
||||
_YELLOW_("\tlf indala clone --fc 123 --cn 1337\n")
|
||||
_YELLOW_("\tlf indala clone -r a0000000a0002021\n")
|
||||
_YELLOW_("\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"));
|
||||
"lf indala clone --heden 888\n"
|
||||
"lf indala clone --fc 123 --cn 1337\n"
|
||||
"lf indala clone -r a0000000a0002021\n"
|
||||
"lf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("lL", "long", "optional - long UID 224 bits"),
|
||||
arg_int0("cC", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
||||
arg_strx0("rR", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0("qQ", "Q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_int0("", "fc", "<decimal>", "Facility Code (26 bit format)"),
|
||||
arg_int0("", "cn", "<decimal>", "Cardnumber (26 bit format)"),
|
||||
arg_lit0("l", "long", "optional - long UID 224 bits"),
|
||||
arg_int0("c", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
|
||||
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
||||
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
|
||||
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit format)"),
|
||||
arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit format)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -865,7 +886,3 @@ out:
|
|||
return (int) idx;
|
||||
|
||||
}
|
||||
|
||||
int demodIndala(void) {
|
||||
return CmdIndalaDemod("");
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
int CmdLFINDALA(const char *Cmd);
|
||||
|
||||
int detectIndala(uint8_t *dest, size_t *size, uint8_t *invert);
|
||||
int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
int demodIndala(void);
|
||||
//int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
//int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
//int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
int demodIndalaEx(int clk, int invert, int maxErr, bool verbose);
|
||||
int demodIndala(bool verbose);
|
||||
int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -95,8 +95,8 @@ static int CmdIOProxWatch(const char *Cmd) {
|
|||
//by marshmellow
|
||||
//IO-Prox demod - FSK RF/64 with preamble of 000000001
|
||||
//print ioprox ID and some format details
|
||||
static int CmdIOProxDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
int demodIOProx(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
int idx = 0, retval = PM3_SUCCESS;
|
||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
|
@ -190,10 +190,15 @@ static int CmdIOProxDemod(const char *Cmd) {
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int CmdIOProxDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodIOProx(true);
|
||||
}
|
||||
// this read is the "normal" read, which download lf signal and tries to demod here.
|
||||
static int CmdIOProxRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 12000);
|
||||
return CmdIOProxDemod(Cmd);
|
||||
return demodIOProx(true);
|
||||
}
|
||||
static int CmdIOProxSim(const char *Cmd) {
|
||||
uint16_t cn = 0;
|
||||
|
@ -311,10 +316,6 @@ int CmdLFIO(const char *Cmd) {
|
|||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
int demodIOProx(void) {
|
||||
return CmdIOProxDemod("");
|
||||
}
|
||||
|
||||
//Index map
|
||||
//0 10 20 30 40 50 60
|
||||
//| | | | | | |
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
int CmdLFIO(const char *Cmd);
|
||||
|
||||
int demodIOProx(void);
|
||||
int demodIOProx(bool verbose);
|
||||
int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,16 +78,11 @@ static uint64_t getJablontronCardId(uint64_t rawcode) {
|
|||
return id;
|
||||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdJablotronDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodJablotron();
|
||||
}
|
||||
|
||||
int demodJablotron(void) {
|
||||
int demodJablotron(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//Differential Biphase / di-phase (inverted biphase)
|
||||
//get binary from ask wave
|
||||
if (ASKbiphaseDemod("0 64 1 0", false) != PM3_SUCCESS) {
|
||||
if (ASKbiphaseDemod(0, 64, 1, 0, false) != PM3_SUCCESS) {
|
||||
if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Jablotron ASKbiphaseDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -137,9 +132,16 @@ int demodJablotron(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdJablotronDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodJablotron(true);
|
||||
}
|
||||
|
||||
static int CmdJablotronRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 16000);
|
||||
return demodJablotron();
|
||||
return demodJablotron(true);
|
||||
}
|
||||
|
||||
static int CmdJablotronClone(const char *Cmd) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFJablotron(const char *Cmd);
|
||||
|
||||
int demodJablotron(void);
|
||||
int demodJablotron(bool verbose);
|
||||
int detectJablotron(uint8_t *bits, size_t *size);
|
||||
int getJablotronBits(uint64_t fullcode, uint8_t *bits);
|
||||
|
||||
|
|
|
@ -135,14 +135,10 @@ static int CmdKeriMSScramble(KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdKeriDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodKeri();
|
||||
}
|
||||
int demodKeri(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
|
||||
int demodKeri(void) {
|
||||
|
||||
if (PSKDemod("", false) != PM3_SUCCESS) {
|
||||
if (PSKDemod(0, 0, 100, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - KERI: PSK1 Demod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -212,9 +208,15 @@ int demodKeri(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdKeriDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodKeri(true);
|
||||
}
|
||||
|
||||
static int CmdKeriRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 10000);
|
||||
return CmdKeriDemod(Cmd);
|
||||
return demodKeri(true);
|
||||
}
|
||||
|
||||
static int CmdKeriClone(const char *Cmd) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFKeri(const char *Cmd);
|
||||
|
||||
int demodKeri(void);
|
||||
int demodKeri(bool verbose);
|
||||
int detectKeri(uint8_t *dest, size_t *size, bool *invert);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,16 +28,10 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
//see PSKDemod for what args are accepted
|
||||
static int CmdMotorolaDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodMotorola();
|
||||
}
|
||||
|
||||
int demodMotorola(void) {
|
||||
|
||||
int demodMotorola(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//PSK1
|
||||
if (PSKDemod("32 1", true) != PM3_SUCCESS) {
|
||||
if (PSKDemod(32, 1, 100, true) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Motorola: PSK Demod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -124,6 +118,12 @@ int demodMotorola(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
//see PSKDemod for what args are accepted
|
||||
static int CmdMotorolaDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodMotorola(true);
|
||||
}
|
||||
|
||||
static int CmdMotorolaRead(const char *Cmd) {
|
||||
// Motorola Flexpass seem to work at 74 kHz
|
||||
// and take about 4400 samples to befor modulating
|
||||
|
@ -145,7 +145,7 @@ static int CmdMotorolaRead(const char *Cmd) {
|
|||
sc.divisor = LF_DIVISOR_125;
|
||||
sc.samples_to_skip = 0;
|
||||
lf_config(&sc);
|
||||
return demodMotorola();
|
||||
return demodMotorola(true);
|
||||
}
|
||||
|
||||
static int CmdMotorolaClone(const char *Cmd) {
|
||||
|
@ -155,12 +155,10 @@ static int CmdMotorolaClone(const char *Cmd) {
|
|||
int datalen = 0;
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf indala clone",
|
||||
CLIParserInit(&ctx, "lf motorola clone",
|
||||
"Enables cloning of Motorola card with specified uid onto T55x7\n"
|
||||
"defaults to 64.\n",
|
||||
"\n"
|
||||
"Samples:\n"
|
||||
_YELLOW_("\tlf motorola clone a0000000a0002021") "\n"
|
||||
"defaults to 64.",
|
||||
"lf motorola clone a0000000a0002021"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
int CmdLFMotorola(const char *Cmd);
|
||||
|
||||
int demodMotorola(void);
|
||||
int demodMotorola(bool verbose);
|
||||
int detectMotorola(uint8_t *dest, size_t *size);
|
||||
int readMotorolaUid(void);
|
||||
#endif
|
||||
|
|
|
@ -107,15 +107,14 @@ static uint8_t isEven_64_63(const uint8_t *data) { // 8
|
|||
}
|
||||
|
||||
//NEDAP demod - ASK/Biphase (or Diphase), RF/64 with preamble of 1111111110 (always a 128 bit data stream)
|
||||
static int CmdLFNedapDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
|
||||
int demodNedap(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
uint8_t data[16], buffer[7], r0, r1, r2, r3, r4, r5, idxC1, idxC2, idxC3, idxC4, idxC5, fixed0, fixed1, unk1, unk2, subtype; // 4 bits
|
||||
size_t size, offset = 0;
|
||||
uint16_t checksum, customerCode; // 12 bits
|
||||
uint32_t badgeId; // max 99999
|
||||
|
||||
if (ASKbiphaseDemod("0 64 1 0", false) != PM3_SUCCESS) {
|
||||
if (ASKbiphaseDemod(0, 64, 1, 0, false) != PM3_SUCCESS) {
|
||||
if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - NEDAP: ASK/Biphase Demod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -262,6 +261,10 @@ static int CmdLFNedapDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdLFNedapDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodNedap(true);
|
||||
}
|
||||
/* Index map E E
|
||||
preamble enc tag type encrypted uid P d 33 d 90 d 04 d 71 d 40 d 45 d E7 P
|
||||
1111111110 00101101000001011010001100100100001011010100110101100 1 0 00110011 0 10010000 0 00000100 0 01110001 0 01000000 0 01000101 0 11100111 1
|
||||
|
@ -307,8 +310,9 @@ lf t55xx wr b 4 d 4c0003ff
|
|||
*/
|
||||
|
||||
static int CmdLFNedapRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 16000);
|
||||
return CmdLFNedapDemod(Cmd);
|
||||
return demodNedap(true);
|
||||
}
|
||||
|
||||
static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data) { // 8 or 16
|
||||
|
@ -554,8 +558,3 @@ int CmdLFNedap(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
int demodNedap(void) {
|
||||
return CmdLFNedapDemod("");
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFNedap(const char *Cmd);
|
||||
|
||||
int demodNedap(void);
|
||||
int demodNedap(bool verbose);
|
||||
int detectNedap(uint8_t *dest, size_t *size);
|
||||
int getNedapBits(uint32_t cn, uint8_t *nedapBits);
|
||||
|
||||
|
|
|
@ -150,8 +150,9 @@ static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *s
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int demodNexWatch(void) {
|
||||
if (PSKDemod("", false) != PM3_SUCCESS) {
|
||||
int demodNexWatch(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
if (PSKDemod(0, 0, 100, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch can't demod signal");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -259,14 +260,15 @@ int demodNexWatch(void) {
|
|||
|
||||
static int CmdNexWatchDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodNexWatch();
|
||||
return demodNexWatch(true);
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdNexWatchRead(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
lf_read(false, 20000);
|
||||
return CmdNexWatchDemod(Cmd);
|
||||
return demodNexWatch(true);
|
||||
}
|
||||
|
||||
static int CmdNexWatchClone(const char *Cmd) {
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
|
||||
int CmdLFNEXWATCH(const char *Cmd);
|
||||
|
||||
int demodNexWatch(void);
|
||||
int demodNexWatch(bool verbose);
|
||||
int detectNexWatch(uint8_t *dest, size_t *size, bool *invert);
|
||||
#endif
|
||||
|
|
|
@ -62,12 +62,11 @@ static uint8_t noralsy_chksum(uint8_t *bits, uint8_t len) {
|
|||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdNoralsyDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
|
||||
int demodNoralsy(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//ASK / Manchester
|
||||
bool st = true;
|
||||
if (ASKDemod_ext("32 0 0", false, false, 1, &st) != PM3_SUCCESS) {
|
||||
if (ASKDemod_ext(32, 0, 0, 0, false, false, false, 1, &st) != PM3_SUCCESS) {
|
||||
if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Noralsy: ASK/Manchester Demod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -132,9 +131,15 @@ static int CmdNoralsyDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdNoralsyDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodNoralsy(true);
|
||||
}
|
||||
|
||||
static int CmdNoralsyRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 8000);
|
||||
return CmdNoralsyDemod(Cmd);
|
||||
return demodNoralsy(true);
|
||||
}
|
||||
|
||||
static int CmdNoralsyClone(const char *Cmd) {
|
||||
|
@ -291,7 +296,3 @@ int detectNoralsy(uint8_t *dest, size_t *size) {
|
|||
* * = unknown
|
||||
*
|
||||
**/
|
||||
|
||||
int demodNoralsy(void) {
|
||||
return CmdNoralsyDemod("");
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFNoralsy(const char *Cmd);
|
||||
|
||||
int demodNoralsy(void);
|
||||
int demodNoralsy(bool verbose);
|
||||
int detectNoralsy(uint8_t *dest, size_t *size);
|
||||
int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits);
|
||||
|
||||
|
|
|
@ -144,14 +144,10 @@ static void pacCardIdToRaw(uint8_t *outRawBytes, const char *cardId) {
|
|||
}
|
||||
|
||||
//see NRZDemod for what args are accepted
|
||||
static int CmdPacDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodPac();
|
||||
}
|
||||
|
||||
int demodPac(void) {
|
||||
int demodPac(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//NRZ
|
||||
if (NRZrawDemod("", false) != PM3_SUCCESS) {
|
||||
if (NRZrawDemod(0, 0, 100, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: NRZ Demod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -188,9 +184,15 @@ int demodPac(void) {
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int CmdPacDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodPac(true);
|
||||
}
|
||||
|
||||
static int CmdPacRead(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
lf_read(false, 4096 * 2 + 20);
|
||||
return CmdPacDemod(Cmd);
|
||||
return demodPac(true);
|
||||
}
|
||||
|
||||
static int CmdPacClone(const char *Cmd) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFPac(const char *Cmd);
|
||||
|
||||
int demodPac(void);
|
||||
int demodPac(bool verbose);
|
||||
int detectPac(uint8_t *dest, size_t *size);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -71,16 +71,12 @@ const uint8_t paradox_lut[] = {
|
|||
|
||||
#define PARADOX_PREAMBLE_LEN 8
|
||||
|
||||
static int CmdParadoxDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodParadox();
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//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
|
||||
|
||||
int demodParadox(void) {
|
||||
int demodParadox(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
|
@ -201,11 +197,18 @@ int demodParadox(void) {
|
|||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdParadoxDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodParadox(true);
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdParadoxRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 10000);
|
||||
return CmdParadoxDemod(Cmd);
|
||||
return demodParadox(true);
|
||||
}
|
||||
|
||||
static int CmdParadoxClone(const char *Cmd) {
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
|
||||
int CmdLFParadox(const char *Cmd);
|
||||
|
||||
int demodParadox(void);
|
||||
int demodParadox(bool verbose);
|
||||
int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx);
|
||||
#endif
|
||||
|
|
|
@ -57,10 +57,10 @@ static int usage_lf_presco_sim(void) {
|
|||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdPrescoDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
int demodPresco(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
bool st = true;
|
||||
if (ASKDemod_ext("32 0 0 0 0 a", false, false, 1, &st) != PM3_SUCCESS) {
|
||||
if (ASKDemod_ext(32, 0, 0, 0, false, false, false, 1, &st) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error Presco ASKDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -97,11 +97,17 @@ static int CmdPrescoDemod(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdPrescoDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodPresco(true);
|
||||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdPrescoRead(const char *Cmd) {
|
||||
// Presco Number: 123456789 --> Sitecode 30 | usercode 8665
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 12000);
|
||||
return CmdPrescoDemod(Cmd);
|
||||
return demodPresco(true);
|
||||
}
|
||||
|
||||
// takes base 12 ID converts to hex
|
||||
|
@ -178,6 +184,7 @@ static int CmdPrescoSim(const char *Cmd) {
|
|||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"demod", CmdPrescoDemod, AlwaysAvailable, "demodulate Presco tag from the GraphBuffer"},
|
||||
{"read", CmdPrescoRead, IfPm3Lf, "Attempt to read and Extract tag data"},
|
||||
{"clone", CmdPrescoClone, IfPm3Lf, "clone presco tag to T55x7 or Q5/T5555"},
|
||||
{"sim", CmdPrescoSim, IfPm3Lf, "simulate presco tag"},
|
||||
|
@ -277,8 +284,3 @@ int getPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
|
|||
num_to_bytebits(fullcode, 32, prescoBits + 96);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int demodPresco(void) {
|
||||
return CmdPrescoDemod("");
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFPresco(const char *Cmd);
|
||||
|
||||
int demodPresco(void);
|
||||
int demodPresco(bool verbose);
|
||||
int detectPresco(uint8_t *dest, size_t *size);
|
||||
int getPrescoBits(uint32_t fullcode, uint8_t *prescoBits);
|
||||
int getWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5);
|
||||
|
|
|
@ -64,14 +64,10 @@ static int usage_lf_pyramid_sim(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdPyramidDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodPyramid();
|
||||
}
|
||||
|
||||
//Pyramid Prox demod - FSK RF/50 with preamble of 0000000000000001 (always a 128 bit data stream)
|
||||
//print full Farpointe Data/Pyramid Prox ID and some bit format details if found
|
||||
int demodPyramid(void) {
|
||||
int demodPyramid(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
|
@ -213,9 +209,15 @@ int demodPyramid(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdPyramidDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodPyramid(true);
|
||||
}
|
||||
|
||||
static int CmdPyramidRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 15000);
|
||||
return CmdPyramidDemod(Cmd);
|
||||
return demodPyramid(true);
|
||||
}
|
||||
|
||||
static int CmdPyramidClone(const char *Cmd) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFPyramid(const char *Cmd);
|
||||
|
||||
int demodPyramid(void);
|
||||
int demodPyramid(bool verbose);
|
||||
int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx);
|
||||
int getPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits);
|
||||
#endif
|
||||
|
|
|
@ -38,17 +38,13 @@ static int usage_lf_securakey_clone(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdSecurakeyDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodSecurakey();
|
||||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
int demodSecurakey(void) {
|
||||
int demodSecurakey(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
|
||||
//ASK / Manchester
|
||||
bool st = false;
|
||||
if (ASKDemod_ext("40 0 0", false, false, 1, &st) != PM3_SUCCESS) {
|
||||
if (ASKDemod_ext(40, 0, 0, 0, false, false, false, 1, &st) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Securakey: ASK/Manchester Demod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -128,9 +124,15 @@ int demodSecurakey(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdSecurakeyDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodSecurakey(true);
|
||||
}
|
||||
|
||||
static int CmdSecurakeyRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 8000);
|
||||
return CmdSecurakeyDemod(Cmd);
|
||||
return demodSecurakey(true);
|
||||
}
|
||||
|
||||
static int CmdSecurakeyClone(const char *Cmd) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFSecurakey(const char *Cmd);
|
||||
|
||||
int demodSecurakey(void);
|
||||
int demodSecurakey(bool verbose);
|
||||
int detectSecurakey(uint8_t *dest, size_t *size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -354,8 +354,8 @@ static int usage_t55xx_protect(void) {
|
|||
print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx protect n 01020304") " - sets new password to 01020304");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx protect p 11223344") " - use pwd 11223344 to set newpwd to 00000000");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx protect n 01020304") " - sets new password to 01020304");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx protect p 11223344 n 00000000") " - use pwd 11223344 to set newpwd to 00000000");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ static int usage_t55xx_clonehelp(void) {
|
|||
PrintAndLogEx(NORMAL, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:");
|
||||
PrintAndLogEx(NORMAL, _GREEN_("lf awid clone"));
|
||||
// todo: rename to clone
|
||||
PrintAndLogEx(NORMAL, _GREEN_("lf em 410x_write"));
|
||||
PrintAndLogEx(NORMAL, _GREEN_("lf em 410x_clone"));
|
||||
// todo: implement restore
|
||||
// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x05_write"));
|
||||
// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x50_write"));
|
||||
|
@ -407,7 +407,7 @@ static int usage_t55xx_sniff(void) {
|
|||
PrintAndLogEx(NORMAL, "Usage: lf t55xx sniff [w <width 0> <width 1>] [l <min level>] [s <level>] [t <level>] [1] [h]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " w <0> <1> - Set samples width for 0 and 1 matching (default auto detect)");
|
||||
// PrintAndLogEx(NORMAL, " s <level> - Set minimum signal level (default 20)");
|
||||
// PrintAndLogEx(NORMAL, " s <level> - Set minimum signal level (default 20)");
|
||||
PrintAndLogEx(NORMAL, " t <level> - Set tolerance level (default 5). lower means tighter");
|
||||
PrintAndLogEx(NORMAL, " 1 - Extract from current sample buffer (default will get new samples)");
|
||||
PrintAndLogEx(NORMAL, " h - This help");
|
||||
|
@ -944,8 +944,6 @@ static int CmdT55xxReadBlock(const char *Cmd) {
|
|||
|
||||
bool DecodeT55xxBlock(void) {
|
||||
|
||||
char buf[30] = {0x00};
|
||||
char *cmdStr = buf;
|
||||
int ans = 0;
|
||||
bool ST = config.ST;
|
||||
uint8_t bitRate[8] = {8, 16, 32, 40, 50, 64, 100, 128};
|
||||
|
@ -953,41 +951,33 @@ bool DecodeT55xxBlock(void) {
|
|||
|
||||
switch (config.modulation) {
|
||||
case DEMOD_FSK:
|
||||
snprintf(cmdStr, sizeof(buf), "%d %d", bitRate[config.bitrate], config.inverted);
|
||||
ans = FSKrawDemod(cmdStr, false);
|
||||
ans = FSKrawDemod(bitRate[config.bitrate], config.inverted, 0, 0, false);
|
||||
break;
|
||||
case DEMOD_FSK1:
|
||||
case DEMOD_FSK1a:
|
||||
snprintf(cmdStr, sizeof(buf), "%d %d 8 5", bitRate[config.bitrate], config.inverted);
|
||||
ans = FSKrawDemod(cmdStr, false);
|
||||
ans = FSKrawDemod(bitRate[config.bitrate], config.inverted, 8, 5, false);
|
||||
break;
|
||||
case DEMOD_FSK2:
|
||||
case DEMOD_FSK2a:
|
||||
snprintf(cmdStr, sizeof(buf), "%d %d 10 8", bitRate[config.bitrate], config.inverted);
|
||||
ans = FSKrawDemod(cmdStr, false);
|
||||
ans = FSKrawDemod(bitRate[config.bitrate], config.inverted, 10, 8, false);
|
||||
break;
|
||||
case DEMOD_ASK:
|
||||
snprintf(cmdStr, sizeof(buf), "%d %d 1", bitRate[config.bitrate], config.inverted);
|
||||
ans = ASKDemod_ext(cmdStr, false, false, 1, &ST);
|
||||
ans = ASKDemod_ext(bitRate[config.bitrate], config.inverted, 1, 0, false, false, false, 1, &ST);
|
||||
break;
|
||||
case DEMOD_PSK1:
|
||||
snprintf(cmdStr, sizeof(buf), "%d %d 6", bitRate[config.bitrate], config.inverted);
|
||||
ans = PSKDemod(cmdStr, false);
|
||||
ans = PSKDemod(bitRate[config.bitrate], config.inverted, 6, false);
|
||||
break;
|
||||
case DEMOD_PSK2: //inverted won't affect this
|
||||
case DEMOD_PSK3: //not fully implemented
|
||||
snprintf(cmdStr, sizeof(buf), "%d 0 6", bitRate[config.bitrate]);
|
||||
ans = PSKDemod(cmdStr, false);
|
||||
ans = PSKDemod(bitRate[config.bitrate], 0, 6, false);
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
break;
|
||||
case DEMOD_NRZ:
|
||||
snprintf(cmdStr, sizeof(buf), "%d %d 1", bitRate[config.bitrate], config.inverted);
|
||||
ans = NRZrawDemod(cmdStr, false);
|
||||
ans = NRZrawDemod(bitRate[config.bitrate], config.inverted, 1, false);
|
||||
break;
|
||||
case DEMOD_BI:
|
||||
case DEMOD_BIa:
|
||||
snprintf(cmdStr, sizeof(buf), "0 %d %d 1", bitRate[config.bitrate], config.inverted);
|
||||
ans = ASKbiphaseDemod(cmdStr, false);
|
||||
ans = ASKbiphaseDemod(0, bitRate[config.bitrate], config.inverted, 1, false);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -999,7 +989,8 @@ static bool DecodeT5555TraceBlock(void) {
|
|||
DemodBufferLen = 0x00;
|
||||
|
||||
// According to datasheet. Always: RF/64, not inverted, Manchester
|
||||
return (ASKDemod("64 0 1", false, false, 1) == PM3_SUCCESS);
|
||||
bool st = false;
|
||||
return (ASKDemod_ext(64, 0, 1, 0, false, false, false, 1, &st) == PM3_SUCCESS);
|
||||
}
|
||||
|
||||
// sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf
|
||||
|
@ -1139,7 +1130,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge);
|
||||
|
||||
if (ans && ((fc1 == 10 && fc2 == 8) || (fc1 == 8 && fc2 == 5))) {
|
||||
if ((FSKrawDemod("0 0", false) == PM3_SUCCESS) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((FSKrawDemod(0, 0, 0, 0, false) == PM3_SUCCESS) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_FSK;
|
||||
if (fc1 == 8 && fc2 == 5)
|
||||
tests[hits].modulation = DEMOD_FSK1a;
|
||||
|
@ -1152,7 +1143,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
tests[hits].downlink_mode = downlink_mode;
|
||||
++hits;
|
||||
}
|
||||
if ((FSKrawDemod("0 1", false) == PM3_SUCCESS) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((FSKrawDemod(0, 1, 0, 0, false) == PM3_SUCCESS) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_FSK;
|
||||
if (fc1 == 8 && fc2 == 5)
|
||||
tests[hits].modulation = DEMOD_FSK1;
|
||||
|
@ -1174,7 +1165,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
// false = no emSearch
|
||||
// 1 = Ask/Man
|
||||
// st = true
|
||||
if ((ASKDemod_ext("0 0 1", false, false, 1, &tests[hits].ST) == PM3_SUCCESS) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((ASKDemod_ext(0, 0, 1, 0, false, false, false, 1, &tests[hits].ST) == PM3_SUCCESS) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_ASK;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = false;
|
||||
|
@ -1188,7 +1179,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
// false = no emSearch
|
||||
// 1 = Ask/Man
|
||||
// st = true
|
||||
if ((ASKDemod_ext("0 1 1", false, false, 1, &tests[hits].ST) == PM3_SUCCESS) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((ASKDemod_ext(0, 1, 1, 0, false, false, false, 1, &tests[hits].ST) == PM3_SUCCESS) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_ASK;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = true;
|
||||
|
@ -1196,7 +1187,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
tests[hits].downlink_mode = downlink_mode;
|
||||
++hits;
|
||||
}
|
||||
if ((ASKbiphaseDemod("0 0 0 2", false) == PM3_SUCCESS) && test(DEMOD_BI, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((ASKbiphaseDemod(0, 0, 0, 2, false) == PM3_SUCCESS) && test(DEMOD_BI, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_BI;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = false;
|
||||
|
@ -1205,7 +1196,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
tests[hits].downlink_mode = downlink_mode;
|
||||
++hits;
|
||||
}
|
||||
if ((ASKbiphaseDemod("0 0 1 2", false) == PM3_SUCCESS) && test(DEMOD_BIa, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((ASKbiphaseDemod(0, 0, 1, 2, false) == PM3_SUCCESS) && test(DEMOD_BIa, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_BIa;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = true;
|
||||
|
@ -1217,7 +1208,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
}
|
||||
clk = GetNrzClock("", false);
|
||||
if (clk > 8) { //clock of rf/8 is likely a false positive, so don't use it.
|
||||
if ((NRZrawDemod("0 0 1", false) == PM3_SUCCESS) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((NRZrawDemod(0, 0, 1, false) == PM3_SUCCESS) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_NRZ;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = false;
|
||||
|
@ -1227,7 +1218,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
++hits;
|
||||
}
|
||||
|
||||
if ((NRZrawDemod("0 1 1", false) == PM3_SUCCESS) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((NRZrawDemod(0, 1, 1, false) == PM3_SUCCESS) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_NRZ;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = true;
|
||||
|
@ -1244,7 +1235,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
save_restoreGB(GRAPH_SAVE);
|
||||
// skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
|
||||
CmdLtrim("160");
|
||||
if ((PSKDemod("0 0 6", false) == PM3_SUCCESS) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_PSK1;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = false;
|
||||
|
@ -1253,7 +1244,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
tests[hits].downlink_mode = downlink_mode;
|
||||
++hits;
|
||||
}
|
||||
if ((PSKDemod("0 1 6", false) == PM3_SUCCESS) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
if ((PSKDemod(0, 1, 6, false) == PM3_SUCCESS) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_PSK1;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = true;
|
||||
|
@ -1264,7 +1255,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
}
|
||||
//ICEMAN: are these PSKDemod calls needed?
|
||||
// PSK2 - needs a call to psk1TOpsk2.
|
||||
if (PSKDemod("0 0 6", false) == PM3_SUCCESS) {
|
||||
if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS) {
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
if (test(DEMOD_PSK2, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_PSK2;
|
||||
|
@ -1277,7 +1268,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
|||
}
|
||||
} // inverse waves does not affect this demod
|
||||
// PSK3 - needs a call to psk1TOpsk2.
|
||||
if (PSKDemod("0 0 6", false) == PM3_SUCCESS) {
|
||||
if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS) {
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
if (test(DEMOD_PSK3, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
|
||||
tests[hits].modulation = DEMOD_PSK3;
|
||||
|
@ -3037,9 +3028,9 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
case 'e':
|
||||
// White cloner password based on EM4100 ID
|
||||
useCardPassword = true;
|
||||
cardID = param_get64ex(Cmd,cmdp + 1,0,16);
|
||||
cardID = param_get64ex(Cmd, cmdp + 1, 0, 16);
|
||||
uint32_t card32Bit = cardID & 0xFFFFFFFF;
|
||||
cardPassword = lf_t55xx_white_pwdgen (card32Bit);
|
||||
cardPassword = lf_t55xx_white_pwdgen(card32Bit);
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
|
@ -3414,12 +3405,12 @@ bool tryDetectP1(bool getData) {
|
|||
// try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...)
|
||||
ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge);
|
||||
if (ans && ((fc1 == 10 && fc2 == 8) || (fc1 == 8 && fc2 == 5))) {
|
||||
if ((FSKrawDemod("0 0", false) == PM3_SUCCESS) &&
|
||||
if ((FSKrawDemod(0, 0, 0, 0, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
}
|
||||
if ((FSKrawDemod("0 1", false) == PM3_SUCCESS) &&
|
||||
if ((FSKrawDemod(0, 1, 0, 0, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
|
@ -3430,26 +3421,26 @@ bool tryDetectP1(bool getData) {
|
|||
// try ask clock detect. it could be another type even if successful.
|
||||
clk = GetAskClock("", false);
|
||||
if (clk > 0) {
|
||||
if ((ASKDemod_ext("0 0 1", false, false, 1, &st) == PM3_SUCCESS) &&
|
||||
if ((ASKDemod_ext(0, 0, 1, 0, false, false, false, 1, &st) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
st = true;
|
||||
if ((ASKDemod_ext("0 1 1", false, false, 1, &st) == PM3_SUCCESS) &&
|
||||
if ((ASKDemod_ext(0, 1, 1, 0, false, false, false, 1, &st) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((ASKbiphaseDemod("0 0 0 2", false) == PM3_SUCCESS) &&
|
||||
if ((ASKbiphaseDemod(0, 0, 0, 2, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((ASKbiphaseDemod("0 0 1 2", false) == PM3_SUCCESS) &&
|
||||
if ((ASKbiphaseDemod(0, 0, 1, 2, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
|
@ -3459,12 +3450,12 @@ bool tryDetectP1(bool getData) {
|
|||
// try NRZ clock detect. it could be another type even if successful.
|
||||
clk = GetNrzClock("", false); //has the most false positives :(
|
||||
if (clk > 0) {
|
||||
if ((NRZrawDemod("0 0 1", false) == PM3_SUCCESS) &&
|
||||
if ((NRZrawDemod(0, 0, 1, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
}
|
||||
if ((NRZrawDemod("0 1 1", false) == PM3_SUCCESS) &&
|
||||
if ((NRZrawDemod(0, 1, 1, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
return true;
|
||||
|
@ -3479,20 +3470,20 @@ bool tryDetectP1(bool getData) {
|
|||
// save_restoreGB(GRAPH_SAVE);
|
||||
// skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
|
||||
//CmdLtrim("160");
|
||||
if ((PSKDemod("0 0 6", false) == PM3_SUCCESS) &&
|
||||
if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
//save_restoreGB(GRAPH_RESTORE);
|
||||
return true;
|
||||
}
|
||||
if ((PSKDemod("0 1 6", false) == PM3_SUCCESS) &&
|
||||
if ((PSKDemod(0, 1, 6, false) == PM3_SUCCESS) &&
|
||||
preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
//save_restoreGB(GRAPH_RESTORE);
|
||||
return true;
|
||||
}
|
||||
// PSK2 - needs a call to psk1TOpsk2.
|
||||
if (PSKDemod("0 0 6", false) == PM3_SUCCESS) {
|
||||
if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS) {
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) &&
|
||||
(DemodBufferLen == 32 || DemodBufferLen == 64)) {
|
||||
|
@ -3775,7 +3766,7 @@ static uint8_t t55sniffGetPacket(int *pulseBuffer, char *data, uint8_t width0, u
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (approxEq(width1, pulseBuffer[i], tolerance)) {
|
||||
if (approxEq(width1, pulseBuffer[i], tolerance)) {
|
||||
data[dataLen++] = '1';
|
||||
i++;
|
||||
continue;
|
||||
|
@ -3792,7 +3783,7 @@ static uint8_t t55sniffTrimSamples(int *pulseBuffer, int *pulseIdx, uint8_t len)
|
|||
for (uint8_t ii = 0; ii < (80 - len); ii++) {
|
||||
pulseBuffer[ii] = pulseBuffer[ii + len];
|
||||
}
|
||||
|
||||
|
||||
*pulseIdx -= len;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -3815,7 +3806,7 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
char pwdText [100];
|
||||
char dataText [100];
|
||||
int pulseBuffer[80] = { 0 }; // max should be 73 +/- - Holds Pulse widths
|
||||
char data[80]; // linked to pulseBuffer. - Holds 0/1 from pulse widths
|
||||
char data[80]; // linked to pulseBuffer. - Holds 0/1 from pulse widths
|
||||
|
||||
|
||||
/*
|
||||
|
@ -3832,7 +3823,7 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
| Regular Read | 2 | 3 | 3 | 4 |
|
||||
| Reset | 2 | 3 | 3 | 4 |
|
||||
----------------------------------------------------------------
|
||||
|
||||
|
||||
T55xx bit widths (decimation 1) - Expected, but may vary a little
|
||||
Reference 0 for LL0 and Leading 0 can be longer
|
||||
-----------------------------------------------
|
||||
|
@ -3856,20 +3847,20 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
width1 = param_get8ex(Cmd, cmdp + 2, 0, 10);
|
||||
cmdp += 3;
|
||||
|
||||
if (width0 == 0) PrintAndLogEx (ERR,"need both sample widths! "_RED_("Missing sample width for 0"));
|
||||
if (width1 == 0) PrintAndLogEx (ERR,"need both sample widths! "_RED_("Missing sample width for 1"));
|
||||
if (width0 == 0) PrintAndLogEx(ERR, "need both sample widths! "_RED_("Missing sample width for 0"));
|
||||
if (width1 == 0) PrintAndLogEx(ERR, "need both sample widths! "_RED_("Missing sample width for 1"));
|
||||
if ((width0 == 0) || (width1 == 0)) {
|
||||
PrintAndLogEx (NORMAL,"");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return usage_t55xx_sniff();
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
case 't':
|
||||
tolerance = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
cmdp++;
|
||||
PrintAndLogEx (ERR,"Invalid options supplied!");
|
||||
PrintAndLogEx(ERR, "Invalid options supplied!");
|
||||
return usage_t55xx_sniff();
|
||||
}
|
||||
}
|
||||
|
@ -3877,12 +3868,12 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
// setup and sample data from Proxmark
|
||||
// if not directed to existing sample/graphbuffer
|
||||
if (sampleData) {
|
||||
CmdLFSniff ("");
|
||||
CmdLFSniff("");
|
||||
}
|
||||
|
||||
// Headings
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO,_CYAN_("T55xx command detection"));
|
||||
PrintAndLogEx(INFO, _CYAN_("T55xx command detection"));
|
||||
PrintAndLogEx(SUCCESS, "Downlink mode | password | Data | blk | page | 0 | 1 | raw");
|
||||
PrintAndLogEx(SUCCESS, "----------------------+----------+----------+-----+------+-----+-----+-------------------------------------------------------------------------------");
|
||||
|
||||
|
@ -3918,13 +3909,13 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
if (pulseSamples > 0) {
|
||||
pulseBuffer[pulseIdx++] = pulseSamples;
|
||||
if (pulseIdx > 79) { // make room for next sample - if not used by now, it wont be.
|
||||
t55sniffTrimSamples (pulseBuffer, &pulseIdx, 1);
|
||||
t55sniffTrimSamples(pulseBuffer, &pulseIdx, 1);
|
||||
}
|
||||
|
||||
// Check Samples for valid packets;
|
||||
// We should find (outside of leading bits) we have a packet of "1" and "0" at same widths.
|
||||
if (pulseIdx >= 6) {// min size for a read - ignoring 1of4 10 0 <adr>
|
||||
|
||||
|
||||
// We auto find widths
|
||||
if ((width0 == 0) && (width1 == 0)) {
|
||||
// We ignore bit 0 for the moment as it may be a ref. pulse, so check last
|
||||
|
@ -3932,13 +3923,13 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
minWidth = pulseBuffer[1];
|
||||
maxWidth = pulseBuffer[1];
|
||||
bool done = false;
|
||||
|
||||
while ((!done) && (ii < pulseIdx) && ((maxWidth <= minWidth) || (approxEq(minWidth,maxWidth,tolerance)))) { // min should be 8, 16-32 more normal
|
||||
if (pulseBuffer[ii]+3 < minWidth) {
|
||||
|
||||
while ((!done) && (ii < pulseIdx) && ((maxWidth <= minWidth) || (approxEq(minWidth, maxWidth, tolerance)))) { // min should be 8, 16-32 more normal
|
||||
if (pulseBuffer[ii] + 3 < minWidth) {
|
||||
minWidth = pulseBuffer[ii];
|
||||
done = true;
|
||||
}
|
||||
if (pulseBuffer[ii]-1 > maxWidth) {
|
||||
if (pulseBuffer[ii] - 1 > maxWidth) {
|
||||
maxWidth = pulseBuffer[ii];
|
||||
done = true;
|
||||
}
|
||||
|
@ -3951,44 +3942,44 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
}
|
||||
|
||||
// out of bounds... min max far enough appart and minWidth is large enough
|
||||
if (((maxWidth - minWidth) < 6) || (minWidth < 6)) // min 8 +/-
|
||||
if (((maxWidth - minWidth) < 6) || (minWidth < 6)) // min 8 +/-
|
||||
continue;
|
||||
|
||||
// At this point we should have
|
||||
|
||||
// At this point we should have
|
||||
// - a min of 6 samples
|
||||
// - the 0 and 1 sample widths
|
||||
// - min 0 and min seperations (worst case)
|
||||
// No max checks done (yet) as have seen samples > then specs in use.
|
||||
|
||||
|
||||
// Check first bit.
|
||||
|
||||
|
||||
// Long leading 0
|
||||
if (haveData == false && (approxEq(pulseBuffer[0],136+minWidth,tolerance) && approxEq(pulseBuffer[1],maxWidth,tolerance))) {
|
||||
printf ("Long Leading 0 - not yet hanled | have 1 Fisrt bit | Min : %-3d - Max : %-3d : diff : %d\n",minWidth,maxWidth, maxWidth-minWidth);
|
||||
if (haveData == false && (approxEq(pulseBuffer[0], 136 + minWidth, tolerance) && approxEq(pulseBuffer[1], maxWidth, tolerance))) {
|
||||
// printf ("Long Leading 0 - not yet hanled | have 1 Fisrt bit | Min : %-3d - Max : %-3d : diff : %d\n",minWidth,maxWidth, maxWidth-minWidth);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fixed bit - Default
|
||||
if (haveData == false && (approxEq(pulseBuffer[0], maxWidth, tolerance))) {
|
||||
dataLen = t55sniffGetPacket (pulseBuffer, data, minWidth, maxWidth, tolerance);
|
||||
dataLen = t55sniffGetPacket(pulseBuffer, data, minWidth, maxWidth, tolerance);
|
||||
|
||||
// if ((dataLen == 39) )
|
||||
// printf ("Fixed | Data end of 80 samples | offset : %llu - datalen %-2d - data : %s --- - Bit 0 width : %d\n",idx,dataLen,data,pulseBuffer[0]);
|
||||
// if ((dataLen == 39) )
|
||||
// printf ("Fixed | Data end of 80 samples | offset : %llu - datalen %-2d - data : %s --- - Bit 0 width : %d\n",idx,dataLen,data,pulseBuffer[0]);
|
||||
|
||||
if (data[0] == '0') { // should never get here..
|
||||
dataLen = 0;
|
||||
dataLen = 0;
|
||||
data[0] = 0;
|
||||
} else {
|
||||
|
||||
// Default Read
|
||||
if (dataLen == 6) {
|
||||
t55sniffTrimSamples (pulseBuffer, &pulseIdx,4); // left 1 or 2 samples seemed to help
|
||||
t55sniffTrimSamples(pulseBuffer, &pulseIdx, 4); // left 1 or 2 samples seemed to help
|
||||
|
||||
page = data[1] - '0';
|
||||
blockAddr = 0;
|
||||
for (uint8_t i = 3; i < 6; i++) {
|
||||
blockAddr <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
blockAddr |= 1;
|
||||
}
|
||||
blockData = 0;
|
||||
|
@ -3998,92 +3989,92 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
|
||||
// Password Write
|
||||
if (dataLen == 70) {
|
||||
t55sniffTrimSamples (pulseBuffer, &pulseIdx,70);
|
||||
t55sniffTrimSamples(pulseBuffer, &pulseIdx, 70);
|
||||
|
||||
page = data[1] - '0';
|
||||
usedPassword = 0;
|
||||
for (uint8_t i = 2; i <= 33; i++) {
|
||||
usedPassword <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
usedPassword |= 1;
|
||||
}
|
||||
// Lock bit 34
|
||||
blockData = 0;
|
||||
for (uint8_t i = 35; i <= 66; i++) {
|
||||
blockData <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
blockData |= 1;
|
||||
}
|
||||
blockAddr = 0;
|
||||
for (uint8_t i = 67; i <= 69; i++) {
|
||||
blockAddr <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
blockAddr |= 1;
|
||||
}
|
||||
haveData = true;
|
||||
sprintf(modeText, "Default pwd write");
|
||||
sprintf(pwdText, "%08X", usedPassword);
|
||||
sprintf(dataText, "%08X",blockData );
|
||||
sprintf(dataText, "%08X", blockData);
|
||||
}
|
||||
|
||||
// Default Write (or password read ??)
|
||||
if (dataLen == 38) {
|
||||
t55sniffTrimSamples (pulseBuffer, &pulseIdx,38);
|
||||
t55sniffTrimSamples(pulseBuffer, &pulseIdx, 38);
|
||||
|
||||
page = data[1] - '0';
|
||||
usedPassword = 0;
|
||||
blockData = 0;
|
||||
for (uint8_t i = 3; i <= 34; i++) {
|
||||
blockData <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
blockData |= 1;
|
||||
}
|
||||
blockAddr = 0;
|
||||
for (uint8_t i = 35; i <= 37; i++) {
|
||||
blockAddr <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
blockAddr |= 1;
|
||||
}
|
||||
haveData = true;
|
||||
sprintf(modeText, "Default write");
|
||||
sprintf(dataText, "%08X",blockData );
|
||||
sprintf(dataText, "%08X", blockData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Leading 0
|
||||
if (haveData == false && (approxEq(pulseBuffer[0], minWidth, tolerance))) {
|
||||
// leading 0 (should = 0 width)
|
||||
// leading 0 (should = 0 width)
|
||||
// 1 of 4 (leads with 00)
|
||||
dataLen = t55sniffGetPacket (pulseBuffer,data,minWidth,maxWidth,tolerance);
|
||||
dataLen = t55sniffGetPacket(pulseBuffer, data, minWidth, maxWidth, tolerance);
|
||||
// **** Should check to 0 to be actual 0 as well i.e. 01 .... data ....
|
||||
if ((data[0] == '0') && (data[1] == '1')) {
|
||||
if (dataLen == 73) {
|
||||
t55sniffTrimSamples (pulseBuffer, &pulseIdx, 73);
|
||||
t55sniffTrimSamples(pulseBuffer, &pulseIdx, 73);
|
||||
|
||||
page = data[2] - '0';
|
||||
usedPassword = 0;
|
||||
for (uint8_t i = 5; i <= 36; i++) {
|
||||
usedPassword <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
usedPassword |= 1;
|
||||
}
|
||||
blockData = 0;
|
||||
for (uint8_t i = 38; i <= 69; i++) {
|
||||
blockData <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
blockData |= 1;
|
||||
}
|
||||
blockAddr = 0;
|
||||
for (uint8_t i = 70; i <= 72; i++) {
|
||||
blockAddr <<= 1;
|
||||
if (data[i] == '1')
|
||||
if (data[i] == '1')
|
||||
blockAddr |= 1;
|
||||
}
|
||||
haveData = true;
|
||||
sprintf(modeText, "Leading 0 pwd write");
|
||||
sprintf(pwdText, "%08X", usedPassword);
|
||||
sprintf(dataText, "%08X",blockData );
|
||||
sprintf(dataText, "%08X", blockData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4092,16 +4083,16 @@ static int CmdT55xxSniff(const char *Cmd) {
|
|||
// Print results
|
||||
if (haveData) { //&& (minWidth > 1) && (maxWidth > minWidth)){
|
||||
if (blockAddr == 7)
|
||||
PrintAndLogEx (SUCCESS, "%-20s | "_GREEN_("%8s")" | "_YELLOW_("%8s")" | "_YELLOW_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText, pwdText, dataText, blockAddr, page, minWidth, maxWidth, data);
|
||||
PrintAndLogEx(SUCCESS, "%-20s | "_GREEN_("%8s")" | "_YELLOW_("%8s")" | "_YELLOW_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText, pwdText, dataText, blockAddr, page, minWidth, maxWidth, data);
|
||||
else
|
||||
PrintAndLogEx (SUCCESS, "%-20s | "_GREEN_("%8s")" | "_GREEN_("%8s")" | "_GREEN_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText, pwdText, dataText, blockAddr, page, minWidth, maxWidth, data);
|
||||
PrintAndLogEx(SUCCESS, "%-20s | "_GREEN_("%8s")" | "_GREEN_("%8s")" | "_GREEN_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText, pwdText, dataText, blockAddr, page, minWidth, maxWidth, data);
|
||||
}
|
||||
}
|
||||
|
||||
// footer
|
||||
PrintAndLogEx (SUCCESS, "-----------------------------------------------------------------------------------------------------------------------------------------------------");
|
||||
PrintAndLogEx (NORMAL, "");
|
||||
|
||||
PrintAndLogEx(SUCCESS, "-----------------------------------------------------------------------------------------------------------------------------------------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int CmdTIDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
int demodTI(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
/* MATLAB as follows:
|
||||
f_s = 2000000; % sampling frequency
|
||||
f_l = 123200; % low FSK tone
|
||||
|
@ -271,6 +271,11 @@ out:
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int CmdTIDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodTI(true);
|
||||
}
|
||||
|
||||
// read a TI tag and return its ID
|
||||
static int CmdTIRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
|
@ -317,8 +322,3 @@ int CmdLFTI(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
int demodTI(void) {
|
||||
return CmdTIDemod("");
|
||||
}
|
||||
|
||||
|
|
|
@ -15,5 +15,5 @@
|
|||
|
||||
int CmdLFTI(const char *Cmd);
|
||||
|
||||
int demodTI(void);
|
||||
int demodTI(bool verbose);
|
||||
#endif
|
||||
|
|
|
@ -38,14 +38,10 @@ static int usage_lf_verichip_clone(void) {
|
|||
}
|
||||
|
||||
//see NRZDemod for what args are accepted
|
||||
static int CmdVerichipDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodVerichip();
|
||||
}
|
||||
|
||||
int demodVerichip(void) {
|
||||
int demodVerichip(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//NRZ
|
||||
if (NRZrawDemod("", false) != PM3_SUCCESS) {
|
||||
if (NRZrawDemod(0, 0, 100, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - VERICHIP: NRZ Demod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -81,9 +77,15 @@ int demodVerichip(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdVerichipDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodVerichip(true);
|
||||
}
|
||||
|
||||
static int CmdVerichipRead(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
lf_read(false, 4096 * 2 + 20);
|
||||
return CmdVerichipDemod(Cmd);
|
||||
return demodVerichip(true);
|
||||
}
|
||||
|
||||
static int CmdVerichipClone(const char *Cmd) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFVerichip(const char *Cmd);
|
||||
|
||||
int demodVerichip(void);
|
||||
int demodVerichip(bool verbose);
|
||||
int detectVerichip(uint8_t *dest, size_t *size);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -53,14 +53,12 @@ static int usage_lf_viking_sim(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdVikingDemod(const char *Cmd) {
|
||||
return demodViking();
|
||||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
int demodViking(void) {
|
||||
int demodViking(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
|
||||
if (ASKDemod("", false, false, 1) != PM3_SUCCESS) {
|
||||
bool st = false;
|
||||
if (ASKDemod_ext(0, 0, 100, 0, false, false, false, 1, &st) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Viking ASKDemod failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -84,10 +82,16 @@ int demodViking(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdVikingDemod(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
return demodViking(true);
|
||||
}
|
||||
|
||||
//see ASKDemod for what args are accepted
|
||||
static int CmdVikingRead(const char *Cmd) {
|
||||
(void)Cmd;
|
||||
lf_read(false, 10000);
|
||||
return CmdVikingDemod(Cmd);
|
||||
return demodViking(true);
|
||||
}
|
||||
|
||||
static int CmdVikingClone(const char *Cmd) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
int CmdLFViking(const char *Cmd);
|
||||
|
||||
int demodViking(void);
|
||||
int demodViking(bool verbose);
|
||||
int detectViking(uint8_t *src, size_t *size);
|
||||
uint64_t getVikingBits(uint32_t id);
|
||||
|
||||
|
|
|
@ -87,10 +87,6 @@ static uint8_t visa_parity(uint32_t id) {
|
|||
return par;
|
||||
}
|
||||
|
||||
static int CmdVisa2kDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodVisa2k();
|
||||
}
|
||||
/**
|
||||
*
|
||||
* 56495332 00096ebd 00000077 —> tag id 618173
|
||||
|
@ -103,14 +99,15 @@ static int CmdVisa2kDemod(const char *Cmd) {
|
|||
*
|
||||
**/
|
||||
//see ASKDemod for what args are accepted
|
||||
int demodVisa2k(void) {
|
||||
int demodVisa2k(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
save_restoreGB(GRAPH_SAVE);
|
||||
|
||||
//CmdAskEdgeDetect("");
|
||||
|
||||
//ASK / Manchester
|
||||
bool st = true;
|
||||
if (ASKDemod_ext("64 0 0", false, false, 1, &st) != PM3_SUCCESS) {
|
||||
if (ASKDemod_ext(64, 0, 0, 0, false, false, false, 1, &st) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Visa2k: ASK/Manchester Demod failed");
|
||||
save_restoreGB(GRAPH_RESTORE);
|
||||
return PM3_ESOFT;
|
||||
|
@ -160,10 +157,16 @@ int demodVisa2k(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdVisa2kDemod(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
return demodVisa2k(true);
|
||||
}
|
||||
|
||||
// 64*96*2=12288 samples just in case we just missed the first preamble we can still catch 2 of them
|
||||
static int CmdVisa2kRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
lf_read(false, 20000);
|
||||
return CmdVisa2kDemod(Cmd);
|
||||
return demodVisa2k(true);
|
||||
}
|
||||
|
||||
static int CmdVisa2kClone(const char *Cmd) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
int CmdLFVisa2k(const char *Cmd);
|
||||
|
||||
int getvisa2kBits(uint64_t fullcode, uint8_t *bits);
|
||||
int demodVisa2k(void);
|
||||
int demodVisa2k(bool verbose);
|
||||
int detectVisa2k(uint8_t *dest, size_t *size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -196,7 +196,7 @@ int CmdsParse(const command_t Commands[], const char *Cmd) {
|
|||
dumpCommandsRecursive(Commands, 1);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
if (strcmp(Cmd, "coffee") == 0) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, " ((\n ))\n" _YELLOW_(" .______.\n | |]\n \\ /\n `----´\n\n"));
|
||||
|
|
|
@ -203,7 +203,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
data_len = hdr->data_len;
|
||||
|
||||
if (tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr) > traceLen) {
|
||||
PrintAndLogEx(DEBUG, "trace pos offset %u larger than reported tracelen %u", tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr), traceLen);
|
||||
PrintAndLogEx(DEBUG, "trace pos offset %"PRIu32 " larger than reported tracelen %u", tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr), traceLen);
|
||||
return traceLen;
|
||||
}
|
||||
|
||||
|
|
|
@ -638,7 +638,7 @@ void Plot::closeEvent(QCloseEvent *event) {
|
|||
}
|
||||
|
||||
void Plot::Zoom(float factor, int refX) {
|
||||
if (factor >=1) { // Zoom in
|
||||
if (factor >= 1) { // Zoom in
|
||||
if (GraphPixelsPerPoint <= 25 * factor) {
|
||||
GraphPixelsPerPoint *= factor;
|
||||
GraphStart += (refX - GraphStart) - ((refX - GraphStart) / factor);
|
||||
|
@ -664,7 +664,7 @@ void Plot::Move(int offset) {
|
|||
}
|
||||
} else { // Move left
|
||||
if (GraphPixelsPerPoint < 20) {
|
||||
if (GraphStart >= (uint)-offset) {
|
||||
if (GraphStart >= (uint) - offset) {
|
||||
GraphStart += offset;
|
||||
} else {
|
||||
GraphStart = 0;
|
||||
|
@ -697,15 +697,15 @@ void Plot::wheelEvent(QWheelEvent *event) {
|
|||
x += GraphStart;
|
||||
// event->angleDelta doesn't exist in QT4, both exist in 5.12.8 and 5.14.2 and event->delta doesn't exist in 5.15.0
|
||||
#if QT_VERSION >= 0x050d00
|
||||
Zoom(1.0-(float)event->angleDelta().y()/(120/zoom_offset), x);
|
||||
Zoom(1.0 - (float)event->angleDelta().y() / (120 / zoom_offset), x);
|
||||
#else
|
||||
Zoom(1.0-(float)event->delta()/(120/zoom_offset), x);
|
||||
Zoom(1.0 - (float)event->delta() / (120 / zoom_offset), x);
|
||||
#endif
|
||||
} else {
|
||||
#if QT_VERSION >= 0x050d00
|
||||
Move(PageWidth*(-(float)event->angleDelta().y()/(120/move_offset)));
|
||||
Move(PageWidth * (-(float)event->angleDelta().y() / (120 / move_offset)));
|
||||
#else
|
||||
Move(PageWidth*(-(float)event->delta()/(120/move_offset)));
|
||||
Move(PageWidth * (-(float)event->delta() / (120 / move_offset)));
|
||||
#endif
|
||||
}
|
||||
this->update();
|
||||
|
|
|
@ -129,6 +129,7 @@ static int l_SendCommandOLD(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(cmd, arg0, arg1, arg2, data, len);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
|
@ -176,6 +177,7 @@ static int l_SendCommandMIX(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(cmd, arg0, arg1, arg2, data, len);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
|
@ -215,6 +217,7 @@ static int l_SendCommandNG(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(cmd, data, len);
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
|
@ -387,8 +390,9 @@ static int l_WaitForResponseTimeout(lua_State *L) {
|
|||
ms_timeout = luaL_checkunsigned(L, 2);
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(cmd, &resp, ms_timeout) == false)
|
||||
if (WaitForResponseTimeout(cmd, &resp, ms_timeout) == false) {
|
||||
return returnToLuaWithError(L, "No response from the device");
|
||||
}
|
||||
|
||||
char foo[sizeof(PacketResponseNG)];
|
||||
n = 0;
|
||||
|
@ -426,7 +430,6 @@ static int l_WaitForResponseTimeout(lua_State *L) {
|
|||
|
||||
//Push it as a string
|
||||
lua_pushlstring(L, (const char *)&foo, sizeof(foo));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue