mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-08-28 03:04:18 +00:00
hooked up the new DSP code. Should improve the t55xx commands
This commit is contained in:
@@ -461,6 +461,7 @@ set (TARGET_SOURCES
|
||||
${PM3_ROOT}/client/src/cmdlfsecurakey.c
|
||||
${PM3_ROOT}/client/src/cmdlft55xx.c
|
||||
${PM3_ROOT}/client/src/cmdlfti.c
|
||||
${PM3_ROOT}/client/src/cmdlftrovan.c
|
||||
${PM3_ROOT}/client/src/cmdlfviking.c
|
||||
${PM3_ROOT}/client/src/cmdlfvisa2000.c
|
||||
${PM3_ROOT}/client/src/cmdlfzx8211.c
|
||||
@@ -491,6 +492,9 @@ set (TARGET_SOURCES
|
||||
${PM3_ROOT}/client/src/pm3.c
|
||||
${PM3_ROOT}/client/src/pm3_binlib.c
|
||||
${PM3_ROOT}/client/src/pm3_bitlib.c
|
||||
${PM3_ROOT}/client/src/pm3_dsp.c
|
||||
|
||||
${PM3_ROOT}/client/src/pm3_fit.c
|
||||
${PM3_ROOT}/client/src/pm3line.c
|
||||
${PM3_ROOT}/client/src/scandir.c
|
||||
${PM3_ROOT}/client/src/scripting.c
|
||||
|
||||
@@ -802,6 +802,7 @@ SRCS = mifare/aiddesfire.c \
|
||||
cmdlfsecurakey.c \
|
||||
cmdlft55xx.c \
|
||||
cmdlfti.c \
|
||||
cmdlftrovan.c \
|
||||
cmdlfviking.c \
|
||||
cmdlfvisa2000.c \
|
||||
cmdlfzx8211.c \
|
||||
@@ -888,6 +889,8 @@ SRCS = mifare/aiddesfire.c \
|
||||
pm3.c \
|
||||
pm3_binlib.c \
|
||||
pm3_bitlib.c \
|
||||
pm3_dsp.c \
|
||||
pm3_fit.c \
|
||||
preferences.c \
|
||||
pm3line.c \
|
||||
proxmark3.c \
|
||||
|
||||
+1733
-112
File diff suppressed because it is too large
Load Diff
@@ -467,7 +467,7 @@ static int CmdFlashMemSpiFFSWipe(const char *Cmd) {
|
||||
CLIParserInit(&ctx, "mem spiffs wipe",
|
||||
_RED_("* * * Warning * * *") " \n"
|
||||
_CYAN_("This command wipes all files on the device SPIFFS file system"),
|
||||
"mem spiffs wipe");
|
||||
"mem spiffs wipe");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
@@ -512,11 +512,11 @@ static int CmdFlashMemSpiFFSUpload(const char *Cmd) {
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, FILE_PATH_SIZE, &slen);
|
||||
|
||||
int dlen = 0;
|
||||
char dest[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen);
|
||||
char dst[32] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dst, 32, &dlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
PrintAndLogEx(DEBUG, "Upload `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dest);
|
||||
PrintAndLogEx(DEBUG, "Upload `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dst);
|
||||
|
||||
size_t datalen = 0;
|
||||
uint8_t *data = NULL;
|
||||
@@ -527,11 +527,12 @@ static int CmdFlashMemSpiFFSUpload(const char *Cmd) {
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
res = flashmem_spiffs_load(dest, data, datalen);
|
||||
res = flashmem_spiffs_load(dst, data, datalen);
|
||||
free(data);
|
||||
|
||||
if (res == PM3_SUCCESS)
|
||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, dest);
|
||||
if (res == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, dst);
|
||||
}
|
||||
|
||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("mem spiffs tree") "` to verify");
|
||||
return res;
|
||||
|
||||
+1
-1
@@ -395,7 +395,7 @@ int CmdHFTune(const char *Cmd) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for Proxmark HF shutdown, aborting");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "\x1b%c[2K\r", 30);
|
||||
PrintAndLogEx(NORMAL, _CLR_LINE_ "\r");
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Min....... %u mV", v_min);
|
||||
|
||||
+37
-5
@@ -49,6 +49,7 @@
|
||||
#include "cmdlfidteck.h" // for idteck menu
|
||||
#include "cmdlfio.h" // for ioprox menu
|
||||
#include "cmdlfcotag.h" // for COTAG menu
|
||||
#include "pm3_dsp.h" // pm3_extract, pm3_is_switched_carrier
|
||||
#include "cmdlfdestron.h" // for FDX-A FECAVA Destron menu
|
||||
#include "cmdlffdxb.h" // for FDX-B menu
|
||||
#include "cmdlfgallagher.h" // for GALLAGHER menu
|
||||
@@ -68,6 +69,7 @@
|
||||
#include "cmdlfsecurakey.h" // for securakey menu
|
||||
#include "cmdlft55xx.h" // for t55xx menu
|
||||
#include "cmdlfti.h" // for ti menu
|
||||
#include "cmdlftrovan.h" // for trovan menu
|
||||
#include "cmdlfviking.h" // for viking menu
|
||||
#include "cmdlfvisa2000.h" // for VISA2000 menu
|
||||
#include "cmdlfzx8211.h" // for ZX8211 menu
|
||||
@@ -239,7 +241,7 @@ static int CmdLFTune(const char *Cmd) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "\x1b%c[2K\r", 30);
|
||||
PrintAndLogEx(NORMAL, _CLR_LINE_ "\r");
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Min....... %u mV", v_min);
|
||||
PrintAndLogEx(INFO, "Max....... %u mV", v_max);
|
||||
@@ -1834,11 +1836,11 @@ int CmdLFRelay(const char *Cmd) {
|
||||
" --rdr : Reading device, act as IP client and reads LF tag and sends data\n"
|
||||
" --tag : Simulation device, act as IP server and simulates relayed data\n",
|
||||
_WHITE_("Device A, reading LF tag, client") "\n"
|
||||
"lf relay --rdr --ip 192.168.1.141 -> Client, connect to IP 192.168.1.141:8000\n"
|
||||
"lf relay --rdr --ip 192.168.1.141 -p 18111 -> Client, connect to IP 192.168.1.141:18111 \n\n"
|
||||
"lf relay --rdr --ip 192.168.1.141 -> Client, connect to IP 192.168.1.141:8000\n"
|
||||
"lf relay --rdr --ip 192.168.1.141 -p 18111 -> Client, connect to IP 192.168.1.141:18111 \n\n"
|
||||
_WHITE_("Device B, simulate LF tag, server") "\n"
|
||||
"lf relay --tag -p 8111 -> Server listening port 8111, recv 40000 samples\n"
|
||||
"lf relay --tag -s 10000 -> Server listening port 8000, recv 10000 samples\n"
|
||||
"lf relay --tag -p 8111 -> Server listening port 8111, recv 40000 samples\n"
|
||||
"lf relay --tag -s 10000 -> Server listening port 8000, recv 10000 samples\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
@@ -2211,6 +2213,35 @@ int CmdLFfind(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (demodTrovan(false) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Trovan ID") " found!");
|
||||
if (search_cont) {
|
||||
found++;
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
// COTAG last, and only when the capture actually looks like one.
|
||||
if (found == 0) {
|
||||
|
||||
double *sig = pm3_extract(g_GraphBuffer, g_GraphTraceLen, 0, g_GraphTraceLen);
|
||||
if (sig != NULL) {
|
||||
|
||||
const bool switched = pm3_is_switched_carrier(sig, g_GraphTraceLen);
|
||||
free(sig);
|
||||
|
||||
if (switched && demodCOTAG(false, -1, -1) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!");
|
||||
if (search_cont) {
|
||||
found++;
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!"));
|
||||
}
|
||||
@@ -2351,6 +2382,7 @@ static command_t CommandTable[] = {
|
||||
{"securakey", CmdLFSecurakey, AlwaysAvailable, "{ Securakey RFIDs... }"},
|
||||
{"ti", CmdLFTI, AlwaysAvailable, "{ TI CHIPs... }"},
|
||||
{"t55xx", CmdLFT55XX, AlwaysAvailable, "{ T55xx CHIPs... }"},
|
||||
{"trovan", CmdLFTrovan, AlwaysAvailable, "{ Trovan animal IDs... }"},
|
||||
{"viking", CmdLFViking, AlwaysAvailable, "{ Viking RFIDs... }"},
|
||||
{"visa2000", CmdLFVisa2k, AlwaysAvailable, "{ Visa2000 RFIDs... }"},
|
||||
// {"zx", CmdLFZx8211, AlwaysAvailable, "{ ZX8211 RFIDs... }"},
|
||||
|
||||
+163
-245
@@ -54,75 +54,6 @@ static void find_avg_high_low(const int32_t *samples, int num_samples,
|
||||
double *out_high_level, double *out_low_level);
|
||||
static double trimmed_mean_abs(const int32_t *samples, int start, int count);
|
||||
|
||||
#if 0
|
||||
// TODO: With the new cotag implementation shall we remove this old version
|
||||
// or is there anything we could use from it?
|
||||
// COTAG demod should be able to use g_GraphBuffer,
|
||||
// when data load samples
|
||||
int demodCOTAG(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
|
||||
uint8_t bits[COTAG_BITS] = {0};
|
||||
size_t bitlen = COTAG_BITS;
|
||||
memcpy(bits, g_DemodBuffer, COTAG_BITS);
|
||||
|
||||
uint8_t inv_bits[COTAG_BITS] = {0};
|
||||
memcpy(inv_bits, g_DemodBuffer, COTAG_BITS);
|
||||
|
||||
uint8_t alignPos = 0;
|
||||
uint16_t err = manrawdecode(bits, &bitlen, 1, &alignPos);
|
||||
if (err > 50) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - COTAG too many errors: %d", err);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
setDemodBuff(bits, bitlen, 0);
|
||||
|
||||
//got a good demod
|
||||
uint16_t cn = bytebits_to_byteLSBF(bits + 1, 16);
|
||||
uint32_t fc = bytebits_to_byteLSBF(bits + 1 + 16, 8);
|
||||
|
||||
uint32_t raw1 = bytebits_to_byteLSBF(bits, 32);
|
||||
uint32_t raw2 = bytebits_to_byteLSBF(bits + 32, 32);
|
||||
uint32_t raw3 = bytebits_to_byteLSBF(bits + 64, 32);
|
||||
uint32_t raw4 = bytebits_to_byteLSBF(bits + 96, 32);
|
||||
|
||||
|
||||
/*
|
||||
fc 161: 1010 0001 -> LSB 1000 0101
|
||||
cn 33593 1000 0011 0011 1001 -> LSB 1001 1100 1100 0001
|
||||
cccc cccc cccc cccc ffffffff
|
||||
0 1001 1100 1100 0001 1000 0101 0000 0000 100001010000000001111011100000011010000010000000000000000000000000000000000000000000000000000000100111001100000110000101000
|
||||
1001 1100 1100 0001 10000101
|
||||
|
||||
COTAG FC/272
|
||||
1 7 7 D E 2 0 0 8 0 0 0 3 9 2 0 D 0 4 0000000000000
|
||||
0001 0111 0111 1101 1110 0010 0000 0000 1000 0000 0000 0000 0011 1001 0010 0000 1101 0000 0100 0000000000000000000000000000000000000000000000000000000
|
||||
0001 0111 0111 1101 1110 001 0010 1001 0011 1000 0110 0100
|
||||
|
||||
*/
|
||||
PrintAndLogEx(SUCCESS, "COTAG Found: FC " _GREEN_("%u")", CN: " _GREEN_("%u")" Raw: %08X%08X%08X%08X", fc, cn, raw1, raw2, raw3, raw4);
|
||||
|
||||
bitlen = COTAG_BITS;
|
||||
err = manrawdecode(inv_bits, &bitlen, 0, &alignPos);
|
||||
if (err < 50) {
|
||||
uint32_t cn_large = bytebits_to_byte(inv_bits + 1, 23);
|
||||
cn_large = reflect32(cn_large) >> 9;
|
||||
uint8_t a = bytebits_to_byte(inv_bits + 48, 4);
|
||||
uint8_t b = bytebits_to_byte(inv_bits + 52, 4);
|
||||
uint8_t c = bytebits_to_byte(inv_bits + 56, 4);
|
||||
uint16_t fc_large = NIBBLE_LOW(c) << 8 | NIBBLE_LOW(b) << 4 | NIBBLE_LOW(a);
|
||||
|
||||
raw1 = bytebits_to_byte(inv_bits, 32);
|
||||
raw2 = bytebits_to_byte(inv_bits + 32, 32);
|
||||
raw3 = bytebits_to_byte(inv_bits + 64, 32);
|
||||
raw4 = bytebits_to_byte(inv_bits + 96, 32);
|
||||
PrintAndLogEx(SUCCESS, " FC " _GREEN_("%u")", CN: " _GREEN_("%u")" Raw: %08X%08X%08X%08X", fc_large, cn_large, raw1, raw2, raw3, raw4);
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Demodulate COTAG samples.
|
||||
*
|
||||
@@ -141,64 +72,80 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
uint8_t *manchester_demod = NULL;
|
||||
uint8_t *manchester_demod_reversed = NULL;
|
||||
|
||||
/* Calculate min, max, average */
|
||||
int manchester_count = 0;
|
||||
const char *fail = NULL;
|
||||
|
||||
int64_t sum = 0;
|
||||
min = max = samples[0];
|
||||
|
||||
for (int i = 0; i < num_samples; i++) {
|
||||
sum += samples[i];
|
||||
if (samples[i] < min) min = samples[i];
|
||||
if (samples[i] > max) max = samples[i];
|
||||
if (samples[i] < min) {
|
||||
min = samples[i];
|
||||
}
|
||||
|
||||
if (samples[i] > max) {
|
||||
max = samples[i];
|
||||
}
|
||||
}
|
||||
|
||||
avg = (double)sum / (double)num_samples;
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, " Clock: %d", clock);
|
||||
if (threshold < 0)
|
||||
if (threshold < 0) {
|
||||
PrintAndLogEx(INFO, " Threshold: auto");
|
||||
else
|
||||
} else {
|
||||
PrintAndLogEx(INFO, " Threshold: %.2f", threshold);
|
||||
}
|
||||
PrintAndLogEx(INFO, " Min : %" PRId32, min);
|
||||
PrintAndLogEx(INFO, " Max : %" PRId32, max);
|
||||
PrintAndLogEx(INFO, " Avg : %.2f\n", avg);
|
||||
printf("\n");
|
||||
PrintAndLogEx(INFO, " Avg : %.2f", avg);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
/* DC offset removal: subtract average from every sample */
|
||||
// DC offset removal: subtract average from every sample
|
||||
for (int i = 0; i < num_samples; i++) {
|
||||
double v = round((double)samples[i] - avg);
|
||||
samples[i] = (int32_t)v;
|
||||
}
|
||||
|
||||
/* Auto threshold estimation: */
|
||||
// Auto threshold estimation
|
||||
if (threshold < 0) {
|
||||
double high_level, low_level;
|
||||
find_avg_high_low(samples, num_samples, clock, &high_level, &low_level);
|
||||
threshold = (low_level + high_level) * 0.5;
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, " Auto threshold: low_level=%.2f, high_level=%.2f --> threshold=%.2f", low_level, high_level, threshold);
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, " Auto threshold: low_level = %.2f, high_level = %.2f --> threshold = %.2f", low_level, high_level, threshold);
|
||||
}
|
||||
}
|
||||
|
||||
/* Auto clock-start detection (first edge detection) */
|
||||
// Auto clock-start detection (first edge detection)
|
||||
if (clock_start == -1) {
|
||||
clock_start = detect_edge(samples, num_samples, 0, threshold);
|
||||
if (verbose)
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, " Detected clock start candidate: sample #%d", clock_start);
|
||||
}
|
||||
}
|
||||
|
||||
/* High/low raw demodulation of clock-half cycles */
|
||||
// High/low raw demodulation of clock-half cycles
|
||||
int high_low_demod_01_len = (num_samples - clock_start) / clock_half + 16;
|
||||
|
||||
high_low_demod_01 = calloc(high_low_demod_01_len, sizeof(uint8_t));
|
||||
if (!high_low_demod_01) {
|
||||
if (high_low_demod_01 == NULL) {
|
||||
PrintAndLogEx(ERR, "Error: out of memory");
|
||||
rv = PM3_EMALLOC;
|
||||
goto end;
|
||||
}
|
||||
|
||||
int high_low_demod_01_count = 0;
|
||||
|
||||
for (int idx = clock_start; idx + clock <= num_samples; idx += clock) {
|
||||
/* Trimmed mean of absolute values of first half: */
|
||||
|
||||
// Trimmed mean of absolute values of first half
|
||||
double clock_half1_val = trimmed_mean_abs(samples, idx, clock_half);
|
||||
/* Trimmed mean of absolute values of second half: */
|
||||
|
||||
// Trimmed mean of absolute values of second half
|
||||
double clock_half2_val = trimmed_mean_abs(samples, idx + clock_half, clock_half);
|
||||
|
||||
uint8_t half1 = (clock_half1_val >= threshold) ? 1 : 0;
|
||||
@@ -209,38 +156,52 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
high_low_demod_01_count += 2;
|
||||
}
|
||||
|
||||
/* Manchester demodulation buffer: */
|
||||
// Manchester demodulation buffer
|
||||
int manchester_demod_len = high_low_demod_01_count / 2;
|
||||
manchester_demod = calloc(manchester_demod_len, sizeof(uint8_t));
|
||||
if (!manchester_demod) {
|
||||
if (manchester_demod == NULL) {
|
||||
PrintAndLogEx(ERR, "Error: out of memory");
|
||||
rv = PM3_EMALLOC;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Manchester demodulation (Thomas) from raw high/low demod (high_low_demod_01) */
|
||||
// Manchester demodulation (Thomas) from raw high/low demod (high_low_demod_01)
|
||||
const int MAX_MANDEMOD_ERRORS = 64;
|
||||
bool demod_success = true;
|
||||
int manchester_count = 0;
|
||||
int mandemod_err_count = 0;
|
||||
|
||||
for (int i = 0; i + 1 < high_low_demod_01_count;) {
|
||||
|
||||
uint8_t half1 = high_low_demod_01[i];
|
||||
uint8_t half2 = high_low_demod_01[i + 1];
|
||||
|
||||
if (half1 == 0 && half2 == 1) {
|
||||
|
||||
manchester_demod[manchester_count++] = 0;
|
||||
i += 2;
|
||||
|
||||
} else if (half1 == 1 && half2 == 0) {
|
||||
|
||||
manchester_demod[manchester_count++] = 1;
|
||||
i += 2;
|
||||
|
||||
} else {
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, " Manchester demod error: index %d (sample #%" PRId32 "): half1=%u, half2=%u --> clock align by half cycle",
|
||||
i, (int32_t)(clock_start + i * clock_half), (unsigned)half1, (unsigned)half2);
|
||||
i += 1; /* re-align by one half-clock forward */
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, " Manchester demod error: index %d (sample #%" PRId32 "): half1=%u, half2=%u --> clock align by half cycle"
|
||||
, i
|
||||
, (int32_t)(clock_start + i * clock_half)
|
||||
, (unsigned)half1, (unsigned)half2
|
||||
);
|
||||
}
|
||||
|
||||
// re-align by one half-clock forward
|
||||
i += 1;
|
||||
|
||||
mandemod_err_count++;
|
||||
|
||||
if (mandemod_err_count >= MAX_MANDEMOD_ERRORS) {
|
||||
PrintAndLogEx(ERR, " Manchester demod: too many errors (%d), giving up", mandemod_err_count);
|
||||
fail = "too many Manchester errors";
|
||||
demod_success = false;
|
||||
break;
|
||||
}
|
||||
@@ -248,31 +209,34 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
}
|
||||
|
||||
if (demod_success) {
|
||||
if (verbose)
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, " Manchester demod: %d bits", manchester_count);
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
goto end;
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Reverse order of bits */
|
||||
// Reverse order of bits
|
||||
manchester_demod_reversed = calloc(manchester_demod_len, sizeof(uint8_t));
|
||||
if (!manchester_demod_reversed) {
|
||||
if (manchester_demod_reversed == NULL) {
|
||||
PrintAndLogEx(ERR, "Error: out of memory");
|
||||
rv = PM3_EMALLOC;
|
||||
goto end;
|
||||
}
|
||||
for (int i = 0; i < manchester_count; i++)
|
||||
manchester_demod_reversed[i] = manchester_demod[manchester_count - 1 - i];
|
||||
|
||||
{
|
||||
for (int i = 0; i < manchester_count; i++) {
|
||||
manchester_demod_reversed[i] = manchester_demod[manchester_count - 1 - i];
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
char manchester_demod_reversed_str[manchester_count + 1];
|
||||
for (int i = 0; i < manchester_count; i++)
|
||||
for (int i = 0; i < manchester_count; i++) {
|
||||
manchester_demod_reversed_str[i] = '0' + manchester_demod_reversed[i];
|
||||
}
|
||||
manchester_demod_reversed_str[manchester_count] = '\0';
|
||||
PrintAndLogEx(SUCCESS, " Manchester demod reversed:");
|
||||
PrintAndLogEx(SUCCESS, " %s", manchester_demod_reversed_str);
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
PrintAndLogEx(INFO, " Manchester demod reversed:");
|
||||
PrintAndLogEx(INFO, " %s", manchester_demod_reversed_str);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -284,21 +248,21 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
* Card number: 0x24A88F
|
||||
*/
|
||||
|
||||
/* Find preamble. */
|
||||
// Find preamble.
|
||||
static const uint8_t preamble_a[] = {
|
||||
/* type A: 62 zeros followed by 1,0,1,0,0,0 */
|
||||
// type A: 62 zeros followed by 1,0,1,0,0,0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||
1, 0, 0, 0
|
||||
};
|
||||
static const uint8_t preamble_p[] = {
|
||||
/* type P: 55 zeros followed by 1,0,0,0,0,0,1 */
|
||||
// type P: 55 zeros followed by 1,0,0,0,0,0,1
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 1
|
||||
};
|
||||
static const uint8_t preamble_p0[] = {
|
||||
/* type P-0: 61 zeros followed by 1 */
|
||||
// type P-0: 61 zeros followed by 1
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1
|
||||
@@ -320,8 +284,8 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
|
||||
for (int i = 0; i < manchester_count && preamble_index < 0; i++) {
|
||||
for (int p = 0; preamble_patterns[p].pat != NULL; p++) {
|
||||
if (i + preamble_patterns[p].len <= manchester_count &&
|
||||
memcmp(&manchester_demod_reversed[i], preamble_patterns[p].pat, preamble_patterns[p].len) == 0) {
|
||||
if ( ((i + preamble_patterns[p].len) <= manchester_count)
|
||||
&& (memcmp(&manchester_demod_reversed[i], preamble_patterns[p].pat, preamble_patterns[p].len) == 0)) {
|
||||
preamble_index = i;
|
||||
preamble_type = preamble_patterns[p].name;
|
||||
break;
|
||||
@@ -330,51 +294,64 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
}
|
||||
|
||||
if (preamble_index < 0) {
|
||||
PrintAndLogEx(INFO, " Preamble not found in manchester_demod_reversed");
|
||||
fail = "no preamble found";
|
||||
goto end;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " Preamble found (type %s) in manchester_demod_reversed at index %d",
|
||||
preamble_type, preamble_index);
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, " Preamble found (type %s) in manchester_demod_reversed at index %d", preamble_type, preamble_index);
|
||||
}
|
||||
|
||||
/* data_bits: 128 bits starting at preamble */
|
||||
// data_bits: 128 bits starting at preamble
|
||||
if (preamble_index + LF_COTAG_DATA_LEN > manchester_count) {
|
||||
PrintAndLogEx(INFO, " Not enough bits after preamble for full 128-bit data block");
|
||||
fail = "preamble found but the capture ends before a full 128 bit block";
|
||||
rv = PM3_EPARTIAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
const uint8_t *data_bits = &manchester_demod_reversed[preamble_index];
|
||||
|
||||
/* Print raw 128 bits */
|
||||
{
|
||||
// Print raw 128 bits
|
||||
if (verbose) {
|
||||
char str[LF_COTAG_DATA_LEN + 1];
|
||||
for (int i = 0; i < LF_COTAG_DATA_LEN; i++)
|
||||
for (int i = 0; i < LF_COTAG_DATA_LEN; i++) {
|
||||
str[i] = '0' + data_bits[i];
|
||||
}
|
||||
str[LF_COTAG_DATA_LEN] = '\0';
|
||||
PrintAndLogEx(SUCCESS, " data bits: %s", str);
|
||||
}
|
||||
/* Print bits grouped by 4, space-separated */
|
||||
{
|
||||
|
||||
// Print bits grouped by 4, space-separated
|
||||
if (verbose) {
|
||||
char str[LF_COTAG_DATA_LEN + LF_COTAG_DATA_LEN / 4];
|
||||
|
||||
int p = 0;
|
||||
for (int i = 0; i < LF_COTAG_DATA_LEN; i += 4) {
|
||||
if (i > 0) str[p++] = ' ';
|
||||
for (int j = 0; j < 4; j++)
|
||||
|
||||
if (i > 0) {
|
||||
str[p++] = ' ';
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
str[p++] = '0' + data_bits[i + j];
|
||||
}
|
||||
}
|
||||
|
||||
str[p] = '\0';
|
||||
PrintAndLogEx(SUCCESS, " data bits: %s", str);
|
||||
}
|
||||
/* Print bits as hex nibbles */
|
||||
{
|
||||
|
||||
// Print bits as hex nibbles
|
||||
if (verbose) {
|
||||
char str[LF_COTAG_DATA_LEN / 4 * 5 + 1];
|
||||
int p = 0;
|
||||
for (int i = 0; i < LF_COTAG_DATA_LEN; i += 4) {
|
||||
int nibble = (data_bits[i] << 3)
|
||||
| (data_bits[i + 1] << 2)
|
||||
| (data_bits[i + 2] << 1)
|
||||
| data_bits[i + 3];
|
||||
|
||||
int nibble = (data_bits[i] << 3)
|
||||
| (data_bits[i + 1] << 2)
|
||||
| (data_bits[i + 2] << 1)
|
||||
| data_bits[i + 3];
|
||||
|
||||
str[p++] = ' ';
|
||||
str[p++] = ' ';
|
||||
str[p++] = ' ';
|
||||
@@ -385,17 +362,19 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
PrintAndLogEx(SUCCESS, " data hex: %s", str);
|
||||
}
|
||||
|
||||
/* Card number: last 24 bits of data_bits as an integer */
|
||||
// Card number: last 24 bits of data_bits as an integer
|
||||
uint32_t c_num = 0;
|
||||
for (int i = LF_COTAG_DATA_LEN - 24; i < LF_COTAG_DATA_LEN; i++)
|
||||
for (int i = LF_COTAG_DATA_LEN - 24; i < LF_COTAG_DATA_LEN; i++) {
|
||||
c_num = (c_num << 1) | data_bits[i];
|
||||
PrintAndLogEx(SUCCESS, " card number: 0x%X == %u", c_num, c_num);
|
||||
}
|
||||
|
||||
/* Count how many subsequent 128-bit blocks equal data_bits */
|
||||
// Count how many subsequent 128-bit blocks equal data_bits
|
||||
int repeat_count = 0;
|
||||
bool fully_repeats = true;
|
||||
int pos = preamble_index + LF_COTAG_DATA_LEN;
|
||||
|
||||
while (pos + LF_COTAG_DATA_LEN <= manchester_count) {
|
||||
|
||||
if (memcmp(&manchester_demod_reversed[pos], data_bits, LF_COTAG_DATA_LEN) == 0) {
|
||||
repeat_count++;
|
||||
} else {
|
||||
@@ -405,14 +384,28 @@ static int demod_cotag(int32_t *samples, int num_samples, int clock, int clock_s
|
||||
pos += LF_COTAG_DATA_LEN;
|
||||
}
|
||||
|
||||
if (fully_repeats && repeat_count > 0)
|
||||
PrintAndLogEx(INFO, " Sequence fully repeats until the end %d time(s)", repeat_count);
|
||||
else
|
||||
PrintAndLogEx(INFO, " Sequence does NOT match at index %d (repeat count = %d)", pos, repeat_count);
|
||||
printf("\n");
|
||||
if (verbose) {
|
||||
if (fully_repeats && repeat_count > 0) {
|
||||
PrintAndLogEx(INFO, " Sequence fully repeats until the end %d time(s)", repeat_count);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, " Sequence does NOT match at index %d (repeat count = %d)", pos, repeat_count);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "COTAG - Card number " _GREEN_("%u") " ( 0x%06X )", c_num, c_num);
|
||||
|
||||
rv = PM3_SUCCESS;
|
||||
end:
|
||||
// One line when there is no card number to show, so a failed demod says
|
||||
// how far it got rather than either going silent or dumping every stage.
|
||||
if (rv != PM3_SUCCESS && fail != NULL) {
|
||||
PrintAndLogEx(FAILED, "COTAG demod failed - %s ( %d Manchester bits at rf/%d )"
|
||||
, fail
|
||||
, manchester_count
|
||||
, clock
|
||||
);
|
||||
}
|
||||
|
||||
free(manchester_demod_reversed);
|
||||
free(manchester_demod);
|
||||
free(high_low_demod_01);
|
||||
@@ -431,7 +424,8 @@ int demodCOTAG(bool verbose, int clock, int threshold) {
|
||||
static int CmdCOTAGDemod(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf cotag demod",
|
||||
"Demodulate COTAG samples from g_GraphBuffer. Try to find COTAG preamble, if found decode / descramble data.",
|
||||
"Demodulate COTAG samples from g_GraphBuffer.\n"
|
||||
"Try to find COTAG preamble, if found decode / descramble data.",
|
||||
"lf cotag demod"
|
||||
);
|
||||
|
||||
@@ -490,8 +484,9 @@ static int CmdCOTAGReader(const char *Cmd) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (g_session.pm3_present == false)
|
||||
if (g_session.pm3_present == false) {
|
||||
return PM3_ENOTTY;
|
||||
}
|
||||
|
||||
uint8_t effective_divisor = (divisor > -1) ? (uint8_t)divisor : LF_COTAG_DIVISOR;
|
||||
|
||||
@@ -542,97 +537,13 @@ static int CmdCOTAGReader(const char *Cmd) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0 // TODO: Remove this implementation?
|
||||
// When reading a COTAG.
|
||||
// 0 = HIGH/LOW signal - maxlength bigbuff
|
||||
// 1 = translation for HI/LO into bytes with manchester 0,1 - length 300
|
||||
// 2 = raw signal - maxlength bigbuff
|
||||
int CmdCOTAGReader_old(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf cotag reader",
|
||||
"read a COTAG tag, the current support for COTAG is limited. ",
|
||||
"lf cotag reader -2"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("1", NULL, "HIGH/LOW signal; maxlength bigbuff"),
|
||||
arg_lit0("2", NULL, "translation of HIGH/LOW into bytes with manchester 0,1"),
|
||||
arg_lit0("3", NULL, "raw signal; maxlength bigbuff"),
|
||||
arg_param_end
|
||||
};
|
||||
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
bool mode0 = arg_get_lit(ctx, 1);
|
||||
bool mode1 = arg_get_lit(ctx, 2);
|
||||
bool mode2 = arg_get_lit(ctx, 3);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if ((mode0 + mode1 + mode2) > 1) {
|
||||
PrintAndLogEx(ERR, "You can only use one option at a time");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
uint8_t mode = 0xFF;
|
||||
if (mode0)
|
||||
mode = 0;
|
||||
if (mode1)
|
||||
mode = 1;
|
||||
if (mode2)
|
||||
mode = 2;
|
||||
|
||||
struct p {
|
||||
uint8_t mode;
|
||||
} PACKED payload;
|
||||
payload.mode = mode;
|
||||
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_COTAG_READ, (uint8_t *)&payload, sizeof(payload));
|
||||
|
||||
uint8_t timeout = 3;
|
||||
int res = PM3_SUCCESS;
|
||||
while (WaitForResponseTimeout(CMD_LF_COTAG_READ, &resp, 1000) == false) {
|
||||
timeout--;
|
||||
if (timeout == 0) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
res = PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (timeout != 3)
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
switch (payload.mode) {
|
||||
case 0:
|
||||
case 2: {
|
||||
CmdPlot("");
|
||||
CmdGrid("-x 384");
|
||||
getSamples(0, false);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
memcpy(g_DemodBuffer, resp.data.asBytes, resp.length);
|
||||
g_DemodBufferLen = resp.length;
|
||||
return demodCOTAG(true);
|
||||
}
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"demod", CmdCOTAGDemod, AlwaysAvailable, "demodulate a COTAG tag"},
|
||||
{"reader", CmdCOTAGReader, IfPm3Lf, "attempt to read and extract tag data"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int CmdHelp(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
CmdsHelp(CommandTable);
|
||||
@@ -662,22 +573,25 @@ static int cmp_int32_asc(const void *a, const void *b) {
|
||||
* resolution for very low amplitude captures.
|
||||
*/
|
||||
static double trimmed_mean_abs(const int32_t *samples, int start, int count) {
|
||||
/* The values are sorted and the top 1/TRIM_DROP_DEN are discarded before averaging */
|
||||
/// The values are sorted and the top 1/TRIM_DROP_DEN are discarded before averaging
|
||||
const int TRIM_DROP_DEN = 4; // trimmed mean denominator
|
||||
int32_t buf[count];
|
||||
|
||||
for (int k = 0; k < count; k++)
|
||||
for (int k = 0; k < count; k++) {
|
||||
buf[k] = abs(samples[start + k]);
|
||||
}
|
||||
|
||||
qsort(buf, count, sizeof(int32_t), cmp_int32_asc);
|
||||
|
||||
int keep = count - count / TRIM_DROP_DEN;
|
||||
if (keep < 1)
|
||||
if (keep < 1) {
|
||||
keep = 1;
|
||||
}
|
||||
|
||||
int64_t sum = 0;
|
||||
for (int k = 0; k < keep; k++)
|
||||
for (int k = 0; k < keep; k++) {
|
||||
sum += buf[k];
|
||||
}
|
||||
|
||||
return (double)sum / (double)keep;
|
||||
}
|
||||
@@ -691,24 +605,26 @@ static double trimmed_mean_abs(const int32_t *samples, int start, int count) {
|
||||
* @param out_high_level the highest window trimmed mean seen
|
||||
* @param out_low_level the lowest window trimmed mean seen
|
||||
*/
|
||||
static void find_avg_high_low(const int32_t *samples, int num_samples,
|
||||
int clock,
|
||||
double *out_high_level, double *out_low_level) {
|
||||
static void find_avg_high_low(const int32_t *samples, int num_samples, int clock, double *out_high_level, double *out_low_level) {
|
||||
const int WINDOW = 256;
|
||||
double high_level = -DBL_MAX;
|
||||
double low_level = DBL_MAX;
|
||||
|
||||
int scan_end = 8 * clock;
|
||||
if (scan_end > num_samples)
|
||||
if (scan_end > num_samples) {
|
||||
scan_end = num_samples;
|
||||
}
|
||||
|
||||
for (int i = 0; i + WINDOW <= scan_end; i++) {
|
||||
double window_val = trimmed_mean_abs(samples, i, WINDOW);
|
||||
|
||||
if (window_val < low_level)
|
||||
if (window_val < low_level) {
|
||||
low_level = window_val;
|
||||
if (window_val > high_level)
|
||||
}
|
||||
|
||||
if (window_val > high_level) {
|
||||
high_level = window_val;
|
||||
}
|
||||
}
|
||||
|
||||
*out_high_level = high_level;
|
||||
@@ -726,12 +642,13 @@ static void find_avg_high_low(const int32_t *samples, int num_samples,
|
||||
*
|
||||
* @return Index of the detected edge, or 0 if none found.
|
||||
*/
|
||||
static int detect_edge(const int32_t *samples, int num_samples,
|
||||
int index_start, double threshold) {
|
||||
static int detect_edge(const int32_t *samples, int num_samples, int index_start, double threshold) {
|
||||
|
||||
const int GLITCH_WINDOW = 10;
|
||||
|
||||
if (num_samples <= 0 || index_start < 0 || index_start >= num_samples)
|
||||
if (num_samples <= 0 || index_start < 0 || index_start >= num_samples) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool prev_high = abs(samples[index_start]) >= threshold;
|
||||
|
||||
@@ -739,18 +656,18 @@ static int detect_edge(const int32_t *samples, int num_samples,
|
||||
bool curr_high = abs(samples[i]) >= threshold;
|
||||
|
||||
if (curr_high != prev_high) {
|
||||
/* Need enough samples on both sides for glitch check */
|
||||
// Need enough samples on both sides for glitch check
|
||||
if ((int)i < GLITCH_WINDOW || i + GLITCH_WINDOW > num_samples) {
|
||||
prev_high = curr_high;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Sum of GLITCH_WINDOW absolute values before the crossing */
|
||||
// Sum of GLITCH_WINDOW absolute values before the crossing
|
||||
int64_t before_sum = 0;
|
||||
for (int k = 0; k < GLITCH_WINDOW; k++)
|
||||
before_sum += abs(samples[i - GLITCH_WINDOW + k]);
|
||||
|
||||
/* Sum of GLITCH_WINDOW absolute values after the crossing */
|
||||
// Sum of GLITCH_WINDOW absolute values after the crossing
|
||||
int64_t after_sum = 0;
|
||||
for (int k = 0; k < GLITCH_WINDOW; k++)
|
||||
after_sum += abs(samples[i + k]);
|
||||
@@ -758,8 +675,9 @@ static int detect_edge(const int32_t *samples, int num_samples,
|
||||
bool before_high = (double)before_sum >= threshold * GLITCH_WINDOW;
|
||||
bool after_high = (double)after_sum >= threshold * GLITCH_WINDOW;
|
||||
|
||||
if (before_high != after_high)
|
||||
if (before_high != after_high) {
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
prev_high = curr_high;
|
||||
|
||||
@@ -310,7 +310,6 @@ static int brute_em4x70(const em4x70_cmd_input_brute_t *opts, em4x70_cmd_output_
|
||||
// Lowers the cognitive load AND makes it easier to understand.
|
||||
// opts structure stored value in BIG ENDIAN
|
||||
// Note that the FIRMWARE side will swap the byte order back to BIG ENDIAN.
|
||||
// (yes, this is a bit of a mess, but it is what it is for now...)
|
||||
uint16_t start_key_be = (opts->partial_key_start[0] << 8) | opts->partial_key_start[1];
|
||||
etd.start_key = start_key_be;
|
||||
|
||||
@@ -994,7 +993,7 @@ static int CmdEM4x70Recover(const char *Cmd) {
|
||||
alt_grn.grn[2]
|
||||
);
|
||||
}
|
||||
printf("\n");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
// which of those keys actually validates?
|
||||
if (recover_ctx.opts.verify) {
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
#define CMDLFEM4X70_H__
|
||||
|
||||
#include "common.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define TIMEOUT 2000
|
||||
|
||||
int CmdLFEM4X70(const char *Cmd);
|
||||
|
||||
// for `lf search`:
|
||||
bool detect_4x70_block(void);
|
||||
|
||||
#endif
|
||||
|
||||
+844
-279
File diff suppressed because it is too large
Load Diff
@@ -95,6 +95,10 @@ const static vocabulary_t vocabulary[] = {
|
||||
{ 1, "data manrawdecode" },
|
||||
{ 1, "data modulation" },
|
||||
{ 1, "data rawdemod" },
|
||||
{ 1, "data autodemod" },
|
||||
{ 1, "data fft" },
|
||||
{ 1, "data fitscore" },
|
||||
{ 1, "data spectrum" },
|
||||
{ 1, "data askedgedetect" },
|
||||
{ 1, "data autocorr" },
|
||||
{ 1, "data convertbitstream" },
|
||||
@@ -124,6 +128,7 @@ const static vocabulary_t vocabulary[] = {
|
||||
{ 0, "data hexsamples" },
|
||||
{ 0, "data samples" },
|
||||
{ 1, "data qrcode" },
|
||||
{ 0, "data gensignal" },
|
||||
{ 0, "data test_ss8" },
|
||||
{ 0, "data test_ss32" },
|
||||
{ 0, "data test_ss32s" },
|
||||
@@ -217,7 +222,6 @@ const static vocabulary_t vocabulary[] = {
|
||||
{ 0, "hf 15 writeafi" },
|
||||
{ 0, "hf 15 writedsfid" },
|
||||
{ 0, "hf 15 csetuid" },
|
||||
{ 0, "hf 15 cfinalize" },
|
||||
{ 1, "hf aliro help" },
|
||||
{ 1, "hf aliro list" },
|
||||
{ 0, "hf aliro info" },
|
||||
@@ -923,6 +927,10 @@ const static vocabulary_t vocabulary[] = {
|
||||
{ 1, "lf t55xx sniff" },
|
||||
{ 0, "lf t55xx special" },
|
||||
{ 0, "lf t55xx wipe" },
|
||||
{ 1, "lf trovan help" },
|
||||
{ 1, "lf trovan demod" },
|
||||
{ 0, "lf trovan reader" },
|
||||
{ 0, "lf trovan clone" },
|
||||
{ 1, "lf viking help" },
|
||||
{ 1, "lf viking demod" },
|
||||
{ 0, "lf viking reader" },
|
||||
|
||||
+169
-23
@@ -239,6 +239,28 @@
|
||||
],
|
||||
"usage": "data autocorr [-hg] [-w <dec>]"
|
||||
},
|
||||
"data autodemod": {
|
||||
"command": "data autodemod",
|
||||
"description": "Tries to work out the modulation, encoding and clock of the wave in the GraphBuffer then run the matching demodulator Adds no signal processing of its own, the analysis is `data spectrum` and `data fitscore` A fractional clock is resampled onto an integer grid first",
|
||||
"notes": [
|
||||
"data autodemod -> analyse and demodulate",
|
||||
"data autodemod --dry-run -> decide and print, demodulate nothing",
|
||||
"data autodemod --thres 6 -> insist on a 6 dB margin before trusting rank 1",
|
||||
"data autodemod --invert --amp -> pass invert and amplify through to the demod"
|
||||
],
|
||||
"offline": true,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--start <int> first sample of the GraphBuffer to use (def 0)",
|
||||
"--size <int> samples to analyse (def 16384)",
|
||||
"--thres <dB> margin below which rank 1 is called ambiguous (def 3.0)",
|
||||
"--dry-run analyse and decide, but do not demodulate",
|
||||
"-a, --amp amplify the signal before ASK demodulation",
|
||||
"-i, --invert invert the demodulated output",
|
||||
"-v, --verbose show the demodulator's own output"
|
||||
],
|
||||
"usage": "data autodemod [-haiv] [--start <int>] [--size <int>] [--thres <dB>] [--dry-run]"
|
||||
},
|
||||
"data biphaserawdecode": {
|
||||
"command": "data biphaserawdecode",
|
||||
"description": "Biphase decode binary stream in DemodBuffer Converts 10 or 01 -> 1 and 11 or 00 -> 0 - must have binary sequence in DemodBuffer (run `data rawdemod --ar` before) - invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester",
|
||||
@@ -407,6 +429,50 @@
|
||||
],
|
||||
"usage": "data envelope [-h]"
|
||||
},
|
||||
"data fft": {
|
||||
"command": "data fft",
|
||||
"description": "Fourier transform of the samples in the GraphBuffer. Reports the magnitude spectrum of the first N/2+1 bins, the input being real. The DC component is removed and the window is normalised to unit variance before the transform, so magnitudes are comparable between captures.",
|
||||
"notes": [
|
||||
"data fft -> transform the whole buffer",
|
||||
"data fft --size 4096 --win blackman -> 4096 point transform, blackman window",
|
||||
"data fft --start 1000 --size 8192 --db -> magnitudes in dB relative to the peak",
|
||||
"data fft --size 4096 --graph -> put the spectrum in the graph window"
|
||||
],
|
||||
"offline": true,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--start <int> first sample of the GraphBuffer to use (def 0)",
|
||||
"--size <int> transform length, rounded up to a power of two (def largest that fits)",
|
||||
"--win <hann|hamming|blackman|rect> window function (def hann)",
|
||||
"--db report magnitude in dB relative to the peak bin instead of linear",
|
||||
"--graph write the magnitude spectrum into the GraphBuffer and repaint",
|
||||
"--fs <int> sample rate in Hz, adds a frequency column in Hz",
|
||||
"--bins <int> how many bins to print (def 32, 0 for all)"
|
||||
],
|
||||
"usage": "data fft [-h] [--start <int>] [--size <int>] [--win <hann|hamming|blackman|rect>] [--db] [--graph] [--fs <int>] [--bins <int>]"
|
||||
},
|
||||
"data fitscore": {
|
||||
"command": "data fitscore",
|
||||
"description": "Rank matched filter hypotheses against the GraphBuffer. A hypothesis is a modulation, a symbol shape and a clock. Each one is scored by correlating the trace against a single symbol template and measuring how tightly the correlator output clusters at the decision instants. Phase is not searched: the correlation is done with an FFT, which yields every phase offset at once. Templates are shaped by an assumed antenna Q, because correlating a bandlimited signal against square edges biases the ranking toward short clocks.",
|
||||
"notes": [
|
||||
"data fitscore -> rank the whole bank",
|
||||
"data fitscore --mod ask --top 5 -> ASK hypotheses only",
|
||||
"data fitscore --clk 64 --all -> everything at clock 64",
|
||||
"data fitscore --verbose -> also put the rank 1 correlator output in the graph"
|
||||
],
|
||||
"offline": true,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--start <int> first sample of the GraphBuffer to use (def 0)",
|
||||
"--size <int> samples to analyse, rounded up to a power of two (def 16384)",
|
||||
"--mod <ask|fsk|psk|nrz> restrict to one modulation (def all)",
|
||||
"--clk <int> restrict to one clock (def all candidates)",
|
||||
"--top <int> rows to print (def 10)",
|
||||
"--all print every scored hypothesis",
|
||||
"-v, --verbose write the rank 1 correlator output into the GraphBuffer"
|
||||
],
|
||||
"usage": "data fitscore [-hv] [--start <int>] [--size <int>] [--mod <ask|fsk|psk|nrz>] [--clk <int>] [--top <int>] [--all]"
|
||||
},
|
||||
"data fsktonrz": {
|
||||
"command": "data fsktonrz",
|
||||
"description": "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk) Omitted values are autodetect instead",
|
||||
@@ -423,6 +489,34 @@
|
||||
],
|
||||
"usage": "data fsktonrz [-h] [-c <dec>] [--low <dec>] [--hi <dec>]"
|
||||
},
|
||||
"data gensignal": {
|
||||
"command": "data gensignal",
|
||||
"description": "Developer tool. Fill the GraphBuffer with a synthetic LF waveform. Used with `data fitscore` and `data autodemod`",
|
||||
"notes": [
|
||||
"data gensignal --mod ask --enc manchester --clk 64",
|
||||
"data gensignal --mod ask --enc manchester --clk 64.25 --noise 0.4 --len 20000"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--mod <ask|fsk|psk|nrz> modulation (def ask)",
|
||||
"--enc <raw|manchester|biphase> encoding (def raw)",
|
||||
"--clk <dbl> clock in samples/symbol, may be fractional (def 64)",
|
||||
"--len <int> samples to generate (def 16384)",
|
||||
"--noise <dbl> gaussian noise standard deviation (def 0)",
|
||||
"--drift <dbl> linear DC ramp across the capture (def 0)",
|
||||
"--env <dbl> amplitude envelope swing (def 0)",
|
||||
"--jitter <dbl> per symbol edge jitter, samples (def 0)",
|
||||
"--clip <dbl> hard clip level, 0 for none (def 0)",
|
||||
"--fc <int> PSK subcarrier period (def 4)",
|
||||
"--fchigh <int> FSK long field clock (def 10)",
|
||||
"--fclow <int> FSK short field clock (def 8)",
|
||||
"--q <int> antenna Q to shape the waveform with (def 8)",
|
||||
"--repeat <int> loop a message of this many bits, like a real tag (def 0, random)",
|
||||
"--seed <int> RNG seed, for reproducible runs (def 1)"
|
||||
],
|
||||
"usage": "data gensignal [-h] [--mod <ask|fsk|psk|nrz>] [--enc <raw|manchester|biphase>] [--clk <dbl>] [--len <int>] [--noise <dbl>] [--drift <dbl>] [--env <dbl>] [--jitter <dbl>] [--clip <dbl>] [--fc <int>] [--fchigh <int>] [--fclow <int>] [--q <int>] [--repeat <int>] [--seed <int>]"
|
||||
},
|
||||
"data getbitstream": {
|
||||
"command": "data getbitstream",
|
||||
"description": "Convert GraphBuffer's value accordingly - larger or equal to ONE becomes ONE - less than ONE becomes ZERO",
|
||||
@@ -452,7 +546,7 @@
|
||||
},
|
||||
"data help": {
|
||||
"command": "data help",
|
||||
"description": "help This help ----------- ------------------------- General------------------------- clear Clears various buffers used by the graph window hide Hide the graph window load Load contents of file into graph window num Converts dec/hex/bin plot Show the graph window print Print the data in the DemodBuffer save Save signal trace data setdebugmode Set Debugging Level on client side xor Xor a input string ----------- ------------------------- Modulation------------------------- biphaserawdecode Biphase decode bin stream in DemodBuffer detectclock Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer fsktonrz Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk) manrawdecode Manchester decode binary stream in DemodBuffer modulation Identify LF signal for clock and modulation rawdemod Demodulate the data in the GraphBuffer and output binary ----------- ------------------------- Graph------------------------- askedgedetect Adjust Graph for manual ASK demod autocorr Autocorrelation over window convertbitstream Convert GraphBuffer's 0/1 values to 127 / -127 cthreshold Average out all values between dirthreshold Max rising higher up-thres/ Min falling lower down-thres decimate Decimate samples envelope Generate square envelope of samples grid overlay grid on graph window getbitstream Convert GraphBuffer's >=1 values to 1 and <1 to 0 hpf Remove DC offset from trace iir Apply IIR buttersworth filter on plot data ltrim Trim samples from left of trace mtrim Trim out samples from the specified start to the specified stop norm Normalize max/min to +/-128 rtrim Trim samples from right of trace setgraphmarkers Set the markers in the graph window shiftgraphzero Shift 0 for Graphed wave + or - shift value timescale Set cursor display timescale undecimate Un-decimate samples zerocrossings Count time between zero-crossings ----------- ------------------------- Operations------------------------- asn1 ASN1 decoder atr ATR lookup bmap Convert hex value according a binary template crypto Encrypt and decrypt data diff Diff of input files qrcode Create a QR code --------------------------------------------------------------------------------------- data clear available offline: yes This function clears the BigBuf on device side and graph window ( graphbuffer )",
|
||||
"description": "help This help ----------- ------------------------------ General ------------------------------- clear Clears various buffers used by the graph window hide Hide the graph window load Load contents of file into graph window num Converts dec/hex/bin plot Show the graph window print Print the data in the DemodBuffer save Save signal trace data setdebugmode Set Debugging Level on client side xor Xor a input string ----------- ----------------------------- Modulation ----------------------------- biphaserawdecode Biphase decode bin stream in DemodBuffer detectclock Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer fsktonrz Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk) manrawdecode Manchester decode binary stream in DemodBuffer modulation Identify LF signal for clock and modulation rawdemod Demodulate the data in the GraphBuffer and output binary ----------- -------------------------- Frequency domain -------------------------- autodemod Detect modulation, encoding and clock, then demodulate fft Fourier transform of the GraphBuffer fitscore Rank matched filter hypotheses for modulation, encoding and clock spectrum Spectral peaks, symbol rate and modulation family hint ----------- ------------------------------- Graph -------------------------------- askedgedetect Adjust Graph for manual ASK demod autocorr Autocorrelation over window convertbitstream Convert GraphBuffer's 0/1 values to 127 / -127 cthreshold Average out all values between dirthreshold Max rising higher up-thres/ Min falling lower down-thres decimate Decimate samples envelope Generate square envelope of samples grid overlay grid on graph window getbitstream Convert GraphBuffer's >=1 values to 1 and <1 to 0 hpf Remove DC offset from trace iir Apply IIR buttersworth filter on plot data ltrim Trim samples from left of trace mtrim Trim out samples from the specified start to the specified stop norm Normalize max/min to +/-128 rtrim Trim samples from right of trace setgraphmarkers Set the markers in the graph window shiftgraphzero Shift 0 for Graphed wave + or - shift value timescale Set cursor display timescale undecimate Un-decimate samples zerocrossings Count time between zero-crossings ----------- ---------------------------- Operations ------------------------------ asn1 ASN1 decoder atr ATR lookup bmap Convert hex value according a binary template crypto Encrypt and decrypt data diff Diff of input files qrcode Create a QR code --------------------------------------------------------------------------------------- data clear available offline: yes This function clears the BigBuf on device side and graph window ( graphbuffer )",
|
||||
"notes": [
|
||||
"data clear"
|
||||
],
|
||||
@@ -774,6 +868,29 @@
|
||||
],
|
||||
"usage": "data shiftgraphzero [-h] -n <dec>"
|
||||
},
|
||||
"data spectrum": {
|
||||
"command": "data spectrum",
|
||||
"description": "Spectral analysis of the GraphBuffer. Reports the strongest spectral peaks with a sub bin estimate of the symbol clock, the squaring and delay-and-multiply spectra which expose rates the plain spectrum nulls out, and a modulation family hint derived from spectral shape alone. Run this on a trace that will not decode.",
|
||||
"notes": [
|
||||
"data spectrum -> peak table and family hint",
|
||||
"data spectrum --top 8 --sq -> more peaks, plus the squaring spectrum",
|
||||
"data spectrum --stft --size 2048 -> spectrogram over the whole capture",
|
||||
"data spectrum --stft --size 2048 --hop 256 -> finer time resolution"
|
||||
],
|
||||
"offline": true,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--start <int> first sample of the GraphBuffer to use (def 0)",
|
||||
"--size <int> transform length, rounded up to a power of two (def largest that fits)",
|
||||
"--win <hann|hamming|blackman|rect> window function (def hann)",
|
||||
"--top <int> number of peaks to report (def 5)",
|
||||
"--sq also show the squaring and delay-and-multiply spectra",
|
||||
"--stft sliding window spectrogram, ridge tracking and drift",
|
||||
"--hop <int> STFT hop in samples (def size/4)",
|
||||
"--fs <int> sample rate in Hz, adds a frequency column in Hz"
|
||||
],
|
||||
"usage": "data spectrum [-h] [--start <int>] [--size <int>] [--win <hann|hamming|blackman|rect>] [--top <int>] [--sq] [--stft] [--hop <int>] [--fs <int>]"
|
||||
},
|
||||
"data test_ss32": {
|
||||
"command": "data test_ss32",
|
||||
"description": "Tests the implementation of Buffer Save States (32-bit buffer)",
|
||||
@@ -1774,35 +1891,20 @@
|
||||
],
|
||||
"usage": "hf 14b wrbl [-h] [-b <dec>] -d <hex> [--512] [--4k] [--sb] [--force]"
|
||||
},
|
||||
"hf 15 cfinalize": {
|
||||
"command": "hf 15 cfinalize",
|
||||
"description": "Finalize a magic ISO15693 'V3' tag. This operation is irreversible. After finalize the configuration area is erased and the UID can no longer be changed. Set the UID with `hf 15 csetuid --v3` first, then lock it in with this command.",
|
||||
"notes": [
|
||||
"hf 15 cfinalize -y"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-y, --yes Confirm the irreversible finalize operation"
|
||||
],
|
||||
"usage": "hf 15 cfinalize [-hy]"
|
||||
},
|
||||
"hf 15 csetuid": {
|
||||
"command": "hf 15 csetuid",
|
||||
"description": "Set UID for magic Chinese card (only works with such cards) For magic 'V3' tags this writes the UID configuration only and is repeatable; run `hf 15 cfinalize` afterwards to lock the UID permanently.",
|
||||
"description": "Set UID for magic Chinese card (only works with such cards)",
|
||||
"notes": [
|
||||
"hf 15 csetuid -u E011223344556677 -> use gen1 command",
|
||||
"hf 15 csetuid -u E011223344556677 --v2 -> use gen2 command",
|
||||
"hf 15 csetuid -u E011223344556677 --v3 -> use gen3 (V3) magic tag"
|
||||
"hf 15 csetuid -u E011223344556677 --v2 -> use gen2 command"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-u, --uid <hex> UID, 8 hex bytes",
|
||||
"-2, --v2 Use gen2 magic command",
|
||||
"-3, --v3 Use gen3 (V3) magic tag (repeatable, needs cfinalize)"
|
||||
"-2, --v2 Use gen2 magic command"
|
||||
],
|
||||
"usage": "hf 15 csetuid [-h23] -u <hex>"
|
||||
"usage": "hf 15 csetuid [-h2] -u <hex>"
|
||||
},
|
||||
"hf 15 demod": {
|
||||
"command": "hf 15 demod",
|
||||
@@ -11997,7 +12099,7 @@
|
||||
},
|
||||
"lf help": {
|
||||
"command": "lf help",
|
||||
"description": "help This help ----------- -------------- Low Frequency -------------- awid { AWID RFIDs... } cotag { COTAG CHIPs... } destron { FDX-A Destron RFIDs... } em { EM CHIPs & RFIDs... } fdxb { FDX-B RFIDs... } gallagher { GALLAGHER RFIDs... } gproxii { Guardall Prox II RFIDs... } hid { HID Prox RFIDs... } hitag { Hitag CHIPs... } idteck { Idteck RFIDs... } indala { Indala RFIDs... } io { ioProx RFIDs... } jablotron { Jablotron RFIDs... } keri { KERI RFIDs... } motorola { Motorola Flexpass RFIDs... } nedap { Nedap RFIDs... } nexwatch { NexWatch RFIDs... } noralsy { Noralsy RFIDs... } pac { PAC/Stanley RFIDs... } paradox { Paradox RFIDs... } pcf7931 { PCF7931 CHIPs... } presco { Presco RFIDs... } pyramid { Farpointe/Pyramid RFIDs... } securakey { Securakey RFIDs... } ti { TI CHIPs... } t55xx { T55xx CHIPs... } viking { Viking RFIDs... } visa2000 { Visa2000 RFIDs... } ----------- --------------------- General --------------------- search Read and Search for valid known tag --------------------------------------------------------------------------------------- lf config available offline: no Get/Set config for LF sampling, bit/sample, decimation, frequency These changes are temporary, will be reset after a power cycle. - use `lf read` performs a read (active field) - use `lf sniff` performs a sniff (no active field)",
|
||||
"description": "help This help ----------- -------------- Low Frequency -------------- awid { AWID RFIDs... } cotag { COTAG CHIPs... } destron { FDX-A Destron RFIDs... } em { EM CHIPs & RFIDs... } fdxb { FDX-B RFIDs... } gallagher { GALLAGHER RFIDs... } gproxii { Guardall Prox II RFIDs... } hid { HID Prox RFIDs... } hitag { Hitag CHIPs... } idteck { Idteck RFIDs... } indala { Indala RFIDs... } io { ioProx RFIDs... } jablotron { Jablotron RFIDs... } keri { KERI RFIDs... } motorola { Motorola Flexpass RFIDs... } nedap { Nedap RFIDs... } nexwatch { NexWatch RFIDs... } noralsy { Noralsy RFIDs... } pac { PAC/Stanley RFIDs... } paradox { Paradox RFIDs... } pcf7931 { PCF7931 CHIPs... } presco { Presco RFIDs... } pyramid { Farpointe/Pyramid RFIDs... } securakey { Securakey RFIDs... } ti { TI CHIPs... } t55xx { T55xx CHIPs... } trovan { Trovan animal IDs... } viking { Viking RFIDs... } visa2000 { Visa2000 RFIDs... } ----------- --------------------- General --------------------- search Read and Search for valid known tag --------------------------------------------------------------------------------------- lf config available offline: no Get/Set config for LF sampling, bit/sample, decimation, frequency These changes are temporary, will be reset after a power cycle. - use `lf read` performs a read (active field) - use `lf sniff` performs a sniff (no active field)",
|
||||
"notes": [
|
||||
"lf config -> shows current config",
|
||||
"lf config -b 8 --125 -> samples at 125 kHz, 8 bps",
|
||||
@@ -14222,6 +14324,50 @@
|
||||
],
|
||||
"usage": "lf ti write [-h] -r <hex> [--crc <hex>]"
|
||||
},
|
||||
"lf trovan clone": {
|
||||
"command": "lf trovan clone",
|
||||
"description": "clone a Trovan animal ID to a T55x7, Q5/T5555 or EM4305/4469 tag The ID is the 10 hex digits printed on the tag, with or without dashes.",
|
||||
"notes": [
|
||||
"lf trovan clone --id 0007F9043A",
|
||||
"lf trovan clone --id 00-07F9-043A",
|
||||
"lf trovan clone --id 0007F9043A --q5"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--id <hex> Trovan animal ID, 10 hex digits",
|
||||
"--q5 specify writing to Q5/T5555 tag",
|
||||
"--em specify writing to EM4305/4469 tag"
|
||||
],
|
||||
"usage": "lf trovan clone [-h] --id <hex> [--q5] [--em]"
|
||||
},
|
||||
"lf trovan help": {
|
||||
"command": "lf trovan help",
|
||||
"description": "help This help demod demodulate a Trovan tag from the GraphBuffer --------------------------------------------------------------------------------------- lf trovan demod available offline: yes Demodulate a Trovan animal ID tag from the GraphBuffer",
|
||||
"notes": [
|
||||
"lf trovan demod"
|
||||
],
|
||||
"offline": true,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-v, --verbose verbose output"
|
||||
],
|
||||
"usage": "lf trovan demod [-hv]"
|
||||
},
|
||||
"lf trovan reader": {
|
||||
"command": "lf trovan reader",
|
||||
"description": "read a Trovan animal ID tag",
|
||||
"notes": [
|
||||
"lf trovan reader -@ -> continuous reader mode"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-@ optional - continuous reader mode",
|
||||
"-v, --verbose verbose output"
|
||||
],
|
||||
"usage": "lf trovan reader [-h@v]"
|
||||
},
|
||||
"lf tune": {
|
||||
"command": "lf tune",
|
||||
"description": "Continuously measure LF antenna tuning. Press button or <Enter> to interrupt.",
|
||||
@@ -15873,8 +16019,8 @@
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"commands_extracted": 889,
|
||||
"commands_extracted": 896,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2026-07-26T21:37:31+00:00"
|
||||
"extracted_on": "2026-07-28T11:00:12+00:00"
|
||||
}
|
||||
}
|
||||
|
||||
+17
-1
@@ -114,6 +114,10 @@ Check column "offline" for their availability.
|
||||
|`data manrawdecode `|Y |`Manchester decode binary stream in DemodBuffer`
|
||||
|`data modulation `|Y |`Identify LF signal for clock and modulation`
|
||||
|`data rawdemod `|Y |`Demodulate the data in the GraphBuffer and output binary`
|
||||
|`data autodemod `|Y |`Detect modulation, encoding and clock, then demodulate`
|
||||
|`data fft `|Y |`Fourier transform of the GraphBuffer`
|
||||
|`data fitscore `|Y |`Rank matched filter hypotheses for modulation, encoding and clock`
|
||||
|`data spectrum `|Y |`Spectral peaks, symbol rate and modulation family hint`
|
||||
|`data askedgedetect `|Y |`Adjust Graph for manual ASK demod`
|
||||
|`data autocorr `|Y |`Autocorrelation over window`
|
||||
|`data convertbitstream `|Y |`Convert GraphBuffer's 0/1 values to 127 / -127`
|
||||
@@ -143,6 +147,7 @@ Check column "offline" for their availability.
|
||||
|`data hexsamples `|N |`Dump big buffer as hex bytes`
|
||||
|`data samples `|N |`Get raw samples for graph window ( GraphBuffer )`
|
||||
|`data qrcode `|Y |`Create a QR code`
|
||||
|`data gensignal `|N |`Generate a synthetic LF waveform into the GraphBuffer`
|
||||
|`data test_ss8 `|N |`Test the implementation of Buffer Save States (8-bit buffer)`
|
||||
|`data test_ss32 `|N |`Test the implementation of Buffer Save States (32-bit buffer)`
|
||||
|`data test_ss32s `|N |`Test the implementation of Buffer Save States (32-bit signed buffer)`
|
||||
@@ -276,7 +281,6 @@ Check column "offline" for their availability.
|
||||
|`hf 15 writeafi `|N |`Writes the AFI on an ISO-15693 tag`
|
||||
|`hf 15 writedsfid `|N |`Writes the DSFID on an ISO-15693 tag`
|
||||
|`hf 15 csetuid `|N |`Set UID for magic card`
|
||||
|`hf 15 cfinalize `|N |`Finalize a magic V3 tag (irreversible)`
|
||||
|
||||
|
||||
### hf aliro
|
||||
@@ -1521,6 +1525,18 @@ Check column "offline" for their availability.
|
||||
|`lf t55xx wipe `|N |`Wipe a T55xx tag and set defaults (will destroy any data on tag)`
|
||||
|
||||
|
||||
### lf trovan
|
||||
|
||||
{ Trovan animal IDs... }
|
||||
|
||||
|command |offline |description
|
||||
|------- |------- |-----------
|
||||
|`lf trovan help `|Y |`This help`
|
||||
|`lf trovan demod `|Y |`demodulate a Trovan tag from the GraphBuffer`
|
||||
|`lf trovan reader `|N |`attempt to read and extract tag data`
|
||||
|`lf trovan clone `|N |`clone Trovan tag to T55x7 or Q5/T5555`
|
||||
|
||||
|
||||
### lf viking
|
||||
|
||||
{ Viking RFIDs... }
|
||||
|
||||
Reference in New Issue
Block a user