Merge pull request #1 from RfidResearchGroup/master

merge origin
This commit is contained in:
danshuk 2020-01-01 11:57:51 +00:00 committed by GitHub
commit fc15eca36c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 122 additions and 15 deletions

View file

@ -3,6 +3,8 @@ 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 `c <card id>` option to `lf pac clone` to allow cloning PAC/Stanley tag from card ID (@danshuk)
- Added decoded PAC/Stanley card ID to `lf pac read` (@danshuk)
- Chg mifare classic keytable output refactored and uses colors (@iceman1001)
- Fix `hf mf nested` - now writes the correct blockno (@iceman1001)
- Chg `lf t55xx dump` - now supports saving to JSON (@iceman1001)

View file

@ -4,8 +4,8 @@
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Low frequency Stanley/PAC tag commands
// NRZ, RF/32, 128 bits long (unknown cs)
// Low frequency PAC/Stanley tag commands
// NRZ, RF/32, 128 bits long
//-----------------------------------------------------------------------------
#include "cmdlfpac.h"
@ -21,22 +21,111 @@
#include "lfdemod.h" // preamble test
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "parity.h"
static int CmdHelp(const char *Cmd);
static int usage_lf_pac_clone(void) {
PrintAndLogEx(NORMAL, "clone a Stanley/PAC tag to a T55x7 tag.");
PrintAndLogEx(NORMAL, "clone a PAC/Stanley tag to a T55x7 tag.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf pac clone [h] [b <raw hex>]");
PrintAndLogEx(NORMAL, "Usage: lf pac clone [h] [c <card id>] [b <raw hex>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
PrintAndLogEx(NORMAL, " c <card id> : 8 byte card ID");
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 16 bytes max");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pac clone c CD4F5552 ");
PrintAndLogEx(NORMAL, " lf pac clone b FF2049906D8511C593155B56D5B2649F ");
return PM3_SUCCESS;
}
// by danshuk
// PAC_8byte format: preamble (8 mark/idle bits), ascii STX (02), ascii '2' (32), ascii '0' (30), ascii bytes 0..7 (cardid), then xor checksum of cardid bytes
// all bytes following 8 bit preamble are one start bit (0), 7 data bits (lsb first), odd parity bit, and one stop bit (1)
static int demodbuf_to_pacid(uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_size) {
const size_t byteLength = 10; // start bit, 7 data bits, parity bit, stop bit
const size_t startIndex = 8 + (3 * byteLength) + 1; // skip 8 bits preamble, STX, '2', '0', and first start bit
const size_t dataLength = 9;
if (startIndex + byteLength * (dataLength - 1) > src_size) {
PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Source buffer too small");
return PM3_EOVFLOW;
}
if (dataLength > dst_size) {
PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Destination buffer too small");
return PM3_EOVFLOW;
}
uint8_t checksum = 0;
for (size_t idx = 0; idx < dataLength; idx++) {
uint8_t byte = (uint8_t)bytebits_to_byteLSBF(src + startIndex + (byteLength * idx), 8);
dst[idx] = byte & 0x7F; // discard the parity bit
if (oddparity8(dst[idx]) != (byte & 0x80) >> 7) {
PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Parity check failed");
return PM3_ESOFT;
}
if (idx < dataLength - 1) checksum ^= byte;
}
if (dst[dataLength - 1] != checksum) {
PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Bad checksum - expected: %02X, actual: %02X", dst[dataLength - 1], checksum);
return PM3_ESOFT;
}
dst[dataLength - 1] = 0; // overwrite checksum byte with null terminator
return PM3_SUCCESS;
}
/*
// convert a 16 byte array of raw demod data (FF204990XX...) to 8 bytes of PAC_8byte ID
// performs no parity or checksum validation
static void pacRawToCardId(uint8_t* outCardId, const uint8_t* rawBytes) {
for (int i = 4; i < 12; i++) {
uint8_t shift = 7 - (i + 3) % 4 * 2;
size_t index = i + (i - 1) / 4;
outCardId[i - 4] = reflect8((((rawBytes[index] << 8) | (rawBytes[index + 1])) >> shift) & 0xFE);
}
}
*/
// convert 8 bytes of PAC_8byte ID to 16 byte array of raw data (FF204990XX...)
static void pacCardIdToRaw(uint8_t* outRawBytes, const char* cardId) {
uint8_t idbytes[10];
// prepend PAC_8byte card type "20"
idbytes[0] = '2';
idbytes[1] = '0';
for (size_t i = 0; i < 8; i++)
idbytes[i + 2] = toupper(cardId[i]);
// initialise array with start and stop bits
for (size_t i = 0; i < 16; i++)
outRawBytes[i] = 0x40 >> (i + 3) % 5 * 2;
outRawBytes[0] = 0xFF; // mark + stop
outRawBytes[1] = 0x20; // start + reflect8(STX)
uint8_t checksum = 0;
for (size_t i = 2; i < 13; i++) {
uint8_t shift = 7 - (i + 3) % 4 * 2;
uint8_t index = i + (i - 1) / 4;
uint16_t pattern;
if (i < 12) {
pattern = reflect8(idbytes[i - 2]);
pattern |= oddparity8(pattern);
if (i > 3) checksum ^= idbytes[i - 2];
}
else
pattern = (reflect8(checksum) & 0xFE) | oddparity8(checksum);
pattern <<= shift;
outRawBytes[index] |= pattern >> 8 & 0xFF;
outRawBytes[index + 1] |= pattern & 0xFF;
}
}
//see NRZDemod for what args are accepted
static int CmdPacDemod(const char *Cmd) {
@ -68,13 +157,14 @@ static int CmdPacDemod(const char *Cmd) {
uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32);
uint32_t raw4 = bytebits_to_byte(DemodBuffer + 96, 32);
// preamble then appears to have marker bits of "10" CS?
// 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001
// unknown checksum 9 bits at the end
const size_t idLen = 9; // 8 bytes + null terminator
uint8_t cardid[idLen];
int retval = demodbuf_to_pacid(DemodBuffer, DemodBufferLen, cardid, sizeof(cardid));
if (retval == PM3_SUCCESS)
PrintAndLogEx(SUCCESS, "PAC/Stanley Tag Found -- Card ID: %s, Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
PrintAndLogEx(SUCCESS, "PAC/Stanley Tag Found -- Raw: %08X%08X%08X%08X", raw1, raw2, raw3, raw4);
PrintAndLogEx(INFO, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum");
return PM3_SUCCESS;
return retval;
}
static int CmdPacRead(const char *Cmd) {
@ -93,6 +183,21 @@ static int CmdPacClone(const char *Cmd) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_pac_clone();
case 'c': {
// skip first block, 4*4 = 16 bytes left
uint8_t rawhex[16] = {0};
char cardid[9];
int res = param_getstr(Cmd, cmdp + 1, cardid, sizeof(cardid));
if (res < 8)
errors = true;
pacCardIdToRaw(rawhex, cardid);
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t));
}
cmdp += 2;
break;
}
case 'b': {
// skip first block, 4*4 = 16 bytes left
uint8_t rawhex[16] = {0};
@ -115,10 +220,10 @@ static int CmdPacClone(const char *Cmd) {
if (errors || cmdp == 0) return usage_lf_pac_clone();
//Pac - compat mode, NRZ, data rate 40, 3 data blocks
blocks[0] = T55x7_MODULATION_DIRECT | T55x7_BITRATE_RF_40 | 4 << T55x7_MAXBLOCK_SHIFT;
//Pac - compat mode, NRZ, data rate 32, 3 data blocks
blocks[0] = T55x7_MODULATION_DIRECT | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT;
PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex");
PrintAndLogEx(INFO, "Preparing to clone PAC/Stanley tag to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks));
@ -133,7 +238,7 @@ static int CmdPacSim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdPacDemod, AlwaysAvailable, "Demodulate an PAC tag from the GraphBuffer"},
{"demod", CmdPacDemod, AlwaysAvailable, "Demodulate a PAC tag from the GraphBuffer"},
{"read", CmdPacRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdPacClone, IfPm3Lf, "clone PAC tag to T55x7"},
{"sim", CmdPacSim, IfPm3Lf, "simulate PAC tag"},