mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-22 00:06:13 +08:00
commit
8c140a8912
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Added support to demodulate Electra tags and column parity check for EM410x (@doegox)
|
||||
- Fix demod plot for various demodulations (@doegox)
|
||||
- Fix `lf t55xx detect/rdbl/dump` - to override if user set `lf config` and use default values during operation (@iceman1001)
|
||||
- Added `hf iclass encode --wiegand/--fc/--cn` - direct fmt/fc/cn support (@bettse)
|
||||
|
|
|
@ -96,8 +96,9 @@ static uint32_t IceEM410xdemod(void) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
|
||||
if (errCnt != 1) {
|
||||
int type = Em410xDecode(dest, &size, &idx, &hi, &lo);
|
||||
// Did we find a Short EM or a Long EM?
|
||||
if ((type & (0x1 | 0x2)) == 0) {
|
||||
BigBuf_free();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
|
|
@ -1476,31 +1476,52 @@ int lf_em410x_watch(int findone, uint32_t *high, uint64_t *low) {
|
|||
|
||||
WDT_HIT();
|
||||
|
||||
errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
|
||||
if (errCnt == 1) {
|
||||
if (size == 128) {
|
||||
Dbprintf("EM XL TAG ID: " _GREEN_("%06x%08x%08x") " - ( %05d_%03d_%08d )",
|
||||
hi,
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
int type = Em410xDecode(dest, &size, &idx, &hi, &lo);
|
||||
if (type & 0x1) {
|
||||
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d )",
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
}
|
||||
if (type & 0x2) {
|
||||
Dbprintf("EM XL TAG ID: " _GREEN_("%06x%08x%08x") " - ( %05d_%03d_%08d )",
|
||||
hi,
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
}
|
||||
if (type & 0x4) {
|
||||
uint64_t data = (lo << 20) >> 20;
|
||||
// Convert back to Short ID
|
||||
uint64_t id = ((uint64_t)hi << 16 ) | (lo >> 48);
|
||||
if ((data & 0xFFFFFFFF) == 0) {
|
||||
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d ) Electra "_GREEN_("%i"),
|
||||
(uint32_t)(id >> 32),
|
||||
(uint32_t)id,
|
||||
(uint32_t)(id & 0xFFFF),
|
||||
(uint32_t)((id >> 16LL) & 0xFF),
|
||||
(uint32_t)(id & 0xFFFFFF),
|
||||
(uint32_t)(data >> 32));
|
||||
} else {
|
||||
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d )",
|
||||
(uint32_t)(lo >> 32),
|
||||
(uint32_t)lo,
|
||||
(uint32_t)(lo & 0xFFFF),
|
||||
(uint32_t)((lo >> 16LL) & 0xFF),
|
||||
(uint32_t)(lo & 0xFFFFFF));
|
||||
}
|
||||
|
||||
if (findone) {
|
||||
*high = hi;
|
||||
*low = lo;
|
||||
break;
|
||||
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d ) on 128b frame with data "_GREEN_("%03x%08x"),
|
||||
(uint32_t)(id >> 32),
|
||||
(uint32_t)id,
|
||||
(uint32_t)(id & 0xFFFF),
|
||||
(uint32_t)((id >> 16LL) & 0xFF),
|
||||
(uint32_t)(id & 0xFFFFFF),
|
||||
(uint32_t)(data >> 32),
|
||||
(uint32_t)data);
|
||||
}
|
||||
}
|
||||
if ((type > 0) && findone) {
|
||||
*high = hi;
|
||||
*low = lo;
|
||||
break;
|
||||
}
|
||||
hi = lo = size = idx = 0;
|
||||
clk = invert = 0;
|
||||
}
|
||||
|
|
|
@ -592,10 +592,11 @@ static int Cmdmandecoderaw(const char *Cmd) {
|
|||
uint64_t id = 0;
|
||||
uint32_t hi = 0;
|
||||
size_t idx = 0;
|
||||
if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1) {
|
||||
int res = Em410xDecode(bits, &size, &idx, &hi, &id);
|
||||
if (res > 0) {
|
||||
//need to adjust to set bitstream back to manchester encoded data
|
||||
//setDemodBuff(bits, size, idx);
|
||||
printEM410x(hi, id, false);
|
||||
printEM410x(hi, id, false, res);
|
||||
}
|
||||
}
|
||||
setDemodBuff(bits, size, 0);
|
||||
|
|
|
@ -100,35 +100,55 @@ static void em410x_construct_emul_graph(uint8_t *uid, uint8_t clock, uint8_t gap
|
|||
}
|
||||
|
||||
//print 64 bit EM410x ID in multiple formats
|
||||
void printEM410x(uint32_t hi, uint64_t id, bool verbose) {
|
||||
void printEM410x(uint32_t hi, uint64_t id, bool verbose, int type) {
|
||||
|
||||
if (!id && !hi) return;
|
||||
|
||||
uint64_t n = 1;
|
||||
uint64_t id2lo = 0;
|
||||
uint8_t m, i;
|
||||
for (m = 5; m > 0; m--) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8)));
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose == false) {
|
||||
|
||||
if (hi) {
|
||||
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%06X%016" PRIX64), hi, id);
|
||||
} else {
|
||||
if (type & 0x1) { // Short ID
|
||||
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
|
||||
}
|
||||
if (type & 0x2) { // Long ID
|
||||
PrintAndLogEx(SUCCESS, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64), hi, id);
|
||||
}
|
||||
if (type & 0x4) { // Short Extended ID
|
||||
uint64_t data = (id << 20) >> 20;
|
||||
// Convert back to Short ID
|
||||
id = ((uint64_t)hi << 16 ) | (id >> 48);
|
||||
if ((data & 0xFFFFFFFF) == 0) {
|
||||
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64)" Electra "_GREEN_("%03" PRIu64), id, data >> 32);
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64)" on 128b frame with data "_GREEN_("%011" PRIX64), id, data);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (hi) {
|
||||
if (type & 0x2) { // Long ID
|
||||
//output 88 bit em id
|
||||
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%06X%016" PRIX64), hi, id);
|
||||
PrintAndLogEx(SUCCESS, "EM410x XL ( RF/%d )", g_DemodClock);
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64)" ( RF/%d )", hi, id, g_DemodClock);
|
||||
}
|
||||
if (type & 0x4) { // Short Extended ID
|
||||
PrintAndLogEx(SUCCESS, "EM 410x Short ID found on a 128b frame");
|
||||
uint64_t data = (id << 20) >> 20;
|
||||
PrintAndLogEx(SUCCESS, " Data after ID: "_GREEN_("%011" PRIX64), data);
|
||||
if ((data & 0xFFFFFFFF) == 0) {
|
||||
PrintAndLogEx(SUCCESS, " Possibly an Electra (RO), 0x"_GREEN_("%03" PRIX64)" = "_GREEN_("%03" PRIu64), data >> 32, data >> 32);
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, " Short ID details:");
|
||||
// Convert back to Short ID
|
||||
id = ((uint64_t)hi << 16 ) | (id >> 48);
|
||||
}
|
||||
if (type & (0x4 | 0x1)) { // Short Extended or Short ID
|
||||
//output 40 bit em id
|
||||
uint64_t n = 1;
|
||||
uint64_t id2lo = 0;
|
||||
uint8_t m, i;
|
||||
for (m = 5; m > 0; m--) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8)));
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
|
||||
PrintAndLogEx(SUCCESS, "EM410x ( RF/%d )", g_DemodClock);
|
||||
PrintAndLogEx(INFO, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
|
||||
|
@ -252,7 +272,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) {
|
|||
printDemodBuff(0, false, false, true);
|
||||
}
|
||||
|
||||
printEM410x(*hi, *lo, verbose);
|
||||
printEM410x(*hi, *lo, verbose, ans);
|
||||
g_em410xid = *lo;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
int CmdLFEM410X(const char *Cmd);
|
||||
|
||||
int demodEM410x(bool verbose);
|
||||
void printEM410x(uint32_t hi, uint64_t id, bool verbose);
|
||||
void printEM410x(uint32_t hi, uint64_t id, bool verbose, int type);
|
||||
|
||||
int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo);
|
||||
int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose);
|
||||
|
|
|
@ -253,6 +253,55 @@ size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType,
|
|||
return bitCnt;
|
||||
}
|
||||
|
||||
static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bool *validShort, bool *validShortExtended, bool *validLong) {
|
||||
uint32_t parityWd = 0;
|
||||
size_t bitCnt = 0;
|
||||
bool validColParity = false;
|
||||
bool validRowParity = true;
|
||||
bool validRowParitySkipColP = true;
|
||||
*validShort = false;
|
||||
*validShortExtended = false;
|
||||
*validLong = false;
|
||||
uint8_t bLen = isLong ? 110 : 55;
|
||||
uint16_t parityCol[4] = { 0, 0, 0, 0 };
|
||||
for (int word = 0; word < bLen; word += 5) {
|
||||
for (int bit = 0; bit < 5; bit++) {
|
||||
if (word + bit >= bLen) break;
|
||||
parityWd = (parityWd << 1) | bits[startIdx + word + bit];
|
||||
if ((word <= 50) && (bit < 4))
|
||||
parityCol[bit] = (parityCol[bit] << 1) | bits[startIdx + word + bit];
|
||||
bits[bitCnt++] = (bits[startIdx + word + bit]);
|
||||
}
|
||||
if (word + 5 > bLen) break;
|
||||
|
||||
bitCnt--; // overwrite parity with next data
|
||||
validRowParity &= parityTest(parityWd, 5, 0) != 0;
|
||||
if (word == 50) { // column parity nibble on short EM and on Electra
|
||||
validColParity = parityTest(parityCol[0], 11, 0) != 0;
|
||||
validColParity &= parityTest(parityCol[1], 11, 0) != 0;
|
||||
validColParity &= parityTest(parityCol[2], 11, 0) != 0;
|
||||
validColParity &= parityTest(parityCol[3], 11, 0) != 0;
|
||||
} else {
|
||||
validRowParitySkipColP &= parityTest(parityWd, 5, 0) != 0;
|
||||
}
|
||||
parityWd = 0;
|
||||
}
|
||||
if (!isLong && validRowParitySkipColP && validColParity) {
|
||||
*validShort = true;
|
||||
}
|
||||
if (isLong && validRowParity) {
|
||||
*validLong = true;
|
||||
}
|
||||
if (isLong && validRowParitySkipColP && validColParity) {
|
||||
*validShortExtended = true;
|
||||
}
|
||||
if (*validShort || *validShortExtended || *validLong) {
|
||||
return bitCnt;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// by marshmellow
|
||||
// takes a array of binary values, length of bits per parity (includes parity bit),
|
||||
// Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
|
||||
|
@ -2122,7 +2171,6 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u
|
|||
if (bits[1] > 1) return -1;
|
||||
if (*size < 64) return -2;
|
||||
|
||||
uint8_t fmtlen;
|
||||
*start_idx = 0;
|
||||
|
||||
// preamble 0111111111
|
||||
|
@ -2131,32 +2179,29 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u
|
|||
if (!preambleSearch(bits, preamble, sizeof(preamble), size, start_idx))
|
||||
return -4;
|
||||
|
||||
// (iceman) if the preamble doesn't find two occuriences, this identification fails.
|
||||
fmtlen = (*size == 128) ? 22 : 10;
|
||||
bool validShort = false;
|
||||
bool validShortExtended = false;
|
||||
bool validLong = false;
|
||||
*size = removeEm410xParity(bits, *start_idx + sizeof(preamble), *size == 128, &validShort, &validShortExtended, &validLong);
|
||||
|
||||
//skip last 4bit parity row for simplicity
|
||||
*size = removeParity(bits, *start_idx + sizeof(preamble), 5, 0, fmtlen * 5);
|
||||
|
||||
switch (*size) {
|
||||
case 40: {
|
||||
// std em410x format
|
||||
*hi = 0;
|
||||
*lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32));
|
||||
break;
|
||||
}
|
||||
case 88: {
|
||||
// long em format
|
||||
*hi = (bytebits_to_byte(bits, 24));
|
||||
*lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -6;
|
||||
if (validShort) {
|
||||
// std em410x format
|
||||
*hi = 0;
|
||||
*lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32));
|
||||
// 1 = Short
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
if (validShortExtended || validLong) {
|
||||
// store in long em format
|
||||
*hi = (bytebits_to_byte(bits, 24));
|
||||
*lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32));
|
||||
// 2 = Long
|
||||
// 4 = ShortExtended
|
||||
return ((int)validShortExtended << 2) + ((int)validLong << 1);
|
||||
}
|
||||
return -6;
|
||||
}
|
||||
|
||||
|
||||
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
|
||||
int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) {
|
||||
//make sure buffer has data
|
||||
|
|
Loading…
Reference in a new issue