@mwalker33 psk tests, maybe one day its good enough to merge in

This commit is contained in:
iceman1001 2024-04-22 09:42:46 +02:00
commit d3f8323a3f

View file

@ -66,6 +66,265 @@ static t55xx_conf_block_t config = {
};
static t55xx_memory_item_t cardmem[T55x7_BLOCK_COUNT] = {{0}};
/*
#define DC(x) ((x) + 128)
static bool t55xx_is_valid_block0(uint32_t block, uint8_t rfclk, uint8_t pskcf) {
if (block == 0x00) {
return false;
}
// Master key = 6 or 9
if ((((block >> 28)& 0xF) != 0x0) &&
(((block >> 28)& 0xF) != 0x6) &&
(((block >> 28)& 0xF) != 0x9)) {
return false;
}
// X Mode
if ( ((block >> 17) & 1) && ((((block >> 28) & 0xf) == 0x6) || (((block >> 28) & 0xf) == 0x9)) ) {
// X mode fixed 0 bits
if ((block & 0x0F000000) != 0x00) {
return false;
}
} else {
// / Basic Mode fixed 0 bits
if ((block & 0x0FE00106) != 0x00) {
return false;
}
}
// Modulation
if ( (((block >> 12) & 0x1F) != 0x00) && // Direct
(((block >> 12) & 0x1F) != 0x01) && // PSK1
(((block >> 12) & 0x1F) != 0x02) && // PSK2
(((block >> 12) & 0x1F) != 0x03) && // PSK3
(((block >> 12) & 0x1F) != 0x04) && // FSK1
(((block >> 12) & 0x1F) != 0x05) && // FSK2
(((block >> 12) & 0x1F) != 0x06) && // FSK1a
(((block >> 12) & 0x1F) != 0x07) && // FSK2a
(((block >> 12) & 0x1F) != 0x08) && // Manchester
(((block >> 12) & 0x1F) != 0x10) && // Bi-phase
(((block >> 12) & 0x1F) != 0x18) ) { // Reserved
return false;
}
PrintAndLogEx(DEBUG, "suggested block... %08x", block);
// check pskcf
if ((pskcf <= 3) && (((block >> 10) & 0x3) != pskcf)) {
PrintAndLogEx(DEBUG, "fail 6 - %u %u", pskcf, (block >> 10) & 0x3);
return false;
}
uint8_t testSpeed;
// check rfclk
if ((((block >> 17) & 1) == 1) && ((((block >> 28) & 0xf) == 0x6) || (((block >> 28) & 0xf) == 0x9)) ){ // X mode speedBits
testSpeed = (((block >> 18) & 0x3F) * 2) + 2;
} else {
uint8_t basicSpeeds[] = {8,16,32,40,50,64,100,128};
testSpeed = basicSpeeds[(block >> 18) & 0x7];
}
if (testSpeed != rfclk) {
PrintAndLogEx(DEBUG, "fail 7 - %u %u ", testSpeed , rfclk);
return false;
}
return true;
}
static void t55xx_psk1_demod (int *data, uint8_t rfclk, uint8_t pskcf, uint32_t *block) {
if ((rfclk < 8) || (rfclk > 128)) {
return;
}
switch (pskcf) {
case 0: {
pskcf = 2;
break;
}
case 1: {
pskcf = 4;
break;
}
case 2: {
pskcf = 8;
break;
}
default: {
break;
}
}
int startOffset = 1; // where to start reading data samples
int sampleCount = 0; // Counter for 1 bit of samples
int samples0, samples1; // Number of High even and odd bits in a sample.
int startBitOffset = 1; // which bit to start at e.g. for rf/32 1 33 65 ...
int bitCount = 0;
uint32_t myblock = 0;
int offset;
uint8_t drift = 0;
uint8_t tuneOffset = 0;
drift = (rfclk % pskcf); // 50 2 = 1 50 4 = 2
// locate first "0" - high transisiton for correct start offset
while (DC(data[startOffset]) <= (DC(data[startOffset - 1]) + 5)) {
// sampleToggle ^= 1;
startOffset++;
}
// Start sample may be 1 off due to sample alignment with chip modulation
// so seach for the first lower value, and adjust as needed
if (pskcf == 2) {
tuneOffset = startOffset + 1;
while (DC(data[tuneOffset]) >= (DC(data[tuneOffset - 1]) + 5)) {
tuneOffset++;
}
if ((tuneOffset - startOffset - 1) % 2) {
startOffset++;
}
}
uint8_t pskcfidx = 0;
// Get the offset to the first sample of the data block
offset = (rfclk * startBitOffset) + startOffset;
pskcfidx = (drift / 2);
pskcfidx = pskcfidx % pskcf;
// while data my be in the settle period of sampling
// First 18 - 24 bits not usable for reference only
while (offset < 20) {
offset += (32 * rfclk);
}
// Read 1 block of data
for (bitCount = 0; bitCount < 32; bitCount++) {
samples0 = 0;
samples1 = 0;
// Get 1 bit of data
for (sampleCount = 0; sampleCount < rfclk; sampleCount++){
// Count number of even and odd high bits at center to edge
switch (pskcf) {
case 2: {
// if current sample is high
if (DC(data[offset]) > DC(data[offset + 1])) {
if (pskcfidx == 0) {
samples0++;
} else {
samples1++;
}
}
break;
}
case 4: {
// only check pskcf 2nd bit x 1 x x
if (pskcfidx == 1) {
// if current sample is high
if (DC(data[offset]) > DC(data[offset + 2])) {
samples0++;
} else {
samples1++;
}
}
break;
}
case 8: {
if (pskcfidx == 3) { // x x x 1 x x x x // 00041840 : FFFBE7BF
// if current sample is high
if (DC(data[offset]) > DC(data[offset + 4])) {
samples0++;
} else {
samples1++;
}
}
break;
}
default: {
break;
}
}
// If at bit boundary (after first bit) then adjust phase check for drift
if ((sampleCount > 0) && (sampleCount % rfclk) == 0) {
pskcfidx -= drift;
}
offset++;
pskcfidx++;
pskcfidx = pskcfidx % pskcf;
}
myblock <<= 1;
if (samples1 > samples0) {
myblock++;
}
}
*block = myblock;
}
static void t55xx_psk2_demod (int *data, uint8_t rfclk, uint8_t pskcf, uint32_t *block) {
// decode PSK
t55xx_psk1_demod (data, rfclk, pskcf, block);
uint32_t new_block = 0;
uint8_t prev_phase = 1;
// Convert to PSK2
for (int8_t bit = 31; bit >= 0; bit--) {
new_block <<= 1;
if (((*block >> bit) & 1) != prev_phase) {
new_block++;
}
prev_phase = ((*block >> bit) & 1);
}
*block = new_block;
}
static void t55xx_search_config_psk(int *d, int pskV) {
for (uint8_t pskcf = 0; pskcf < 3; pskcf++) {
for (uint8_t speedBits = 0; speedBits < 64; speedBits++) {
uint8_t rfclk = rfclk = (2 * speedBits) + 2;
uint32_t block = 0;
if (pskV == 1) {
t55xx_psk1_demod (d, rfclk, pskcf, &block);
}
if (pskV == 2) {
t55xx_psk2_demod (d, rfclk, pskcf, &block);
}
if (t55xx_is_valid_block0(block, rfclk, pskcf)) {
PrintAndLogEx(SUCCESS, "Valid config block [%08X] - rfclk [%d] - pskcf [%d]", block, rfclk, pskcf);
}
}
}
}
*/
t55xx_conf_block_t Get_t55xx_Config(void) {
return config;
@ -1200,6 +1459,9 @@ bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32
}
} // inverse waves does not affect this demod
//undo trim samples
// t55xx_search_config_psk(g_GraphBuffer, 1);
// t55xx_search_config_psk(g_GraphBuffer, 2);
save_restoreGB(GRAPH_RESTORE);
}
}
@ -1450,10 +1712,17 @@ static bool testBitRate(uint8_t readRate, uint8_t clk) {
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) {
if (g_DemodBufferLen < 64) return false;
if (g_DemodBufferLen < 64) {
return false;
}
for (uint8_t idx = 28; idx < 64; idx++) {
uint8_t si = idx;
if (PackBits(si, 28, g_DemodBuffer) == 0x00) continue;
if (PackBits(si, 28, g_DemodBuffer) == 0x00) {
continue;
}
uint8_t safer = PackBits(si, 4, g_DemodBuffer);
si += 4; //master key
@ -1461,7 +1730,10 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5)
si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode
// 2nibble must be zeroed.
// moved test to here, since this gets most faults first.
if (resv > 0x00) continue;
if (resv > 0x00) {
continue;
}
int bitRate = PackBits(si, 6, g_DemodBuffer);
si += 6; //bit rate (includes extended mode part of rate)
@ -1476,20 +1748,33 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5)
//if extended mode
bool extMode = ((safer == 0x6 || safer == 0x9) && extend) ? true : false;
if (!extMode) {
if (bitRate > 7) continue;
if (!testBitRate(bitRate, clk)) continue;
} else { //extended mode bitrate = same function to calc bitrate as em4x05
if (EM4x05_GET_BITRATE(bitRate) != clk) continue;
if (extMode == false) {
if (bitRate > 7) {
continue;
}
if (testBitRate(bitRate, clk) == false) {
continue;
}
} else { //extended mode bitrate = same function to calc bitrate as em4x05
if (EM4x05_GET_BITRATE(bitRate) != clk) {
continue;
}
}
//test modulation
if (!testModulation(mode, modread)) continue;
if (testModulation(mode, modread) == false) {
continue;
}
*fndBitRate = bitRate;
*offset = idx;
*Q5 = false;
return true;
}
if (testQ5(mode, offset, fndBitRate, clk)) {
*Q5 = true;
return true;
@ -4407,7 +4692,7 @@ static command_t CommandTable[] = {
{"write", CmdT55xxWriteBlock, IfPm3Lf, "Write T55xx block data"},
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("recovery") " ---------------------"},
{"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "Simple bruteforce attack to find password"},
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"},
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords"},
{"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"},
{"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "Try to recover from bad password write from a cloner"},
{"sniff", CmdT55xxSniff, AlwaysAvailable, "Attempt to recover T55xx commands from sample buffer"},
@ -4426,3 +4711,22 @@ int CmdLFT55XX(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}
/*
one of
// Leading 0
lf t55 write -b 3 --pg1 -d 90000800
// 1 of 4
lf t55 write -b 3 --pg1 -d 90000C00
T55xx clone card lock: block 3 page 1 0x00000020 00000000 00000000 00000000 00100000
(this bit in any combo seems to lock the card)
You can have other data in the block write, but if that single bit is set "1" the entire card locks in its current state; no know way to unlock
*/