From 5f84531b82309c5cbb72ea5bdaaee3a1be734eb5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E2=98=83=20Stephen=20Shkardoon=20=E2=98=83?= Date: Sat, 5 Jan 2019 21:48:59 +1300 Subject: [PATCH 1/1] Paradox clone functionality implemented (#747) This involves a refactor to the arm HID code to allow for arbitrary preambles (such as HID Proximity and Paradox). The client also borrows from the HID code, but is not shared, so could use a significant refactor in the future. --- CHANGELOG.md | 2 ++ armsrc/appmain.c | 8 +++++-- armsrc/apps.h | 2 +- armsrc/lfops.c | 12 +++++------ client/cmdlfhid.c | 8 +++---- client/cmdlfhid.h | 2 ++ client/cmdlfparadox.c | 42 +++++++++++++++++++++++++++++++++++-- client/hidcardformatutils.c | 2 +- include/usb_cmd.h | 2 ++ 9 files changed, 64 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b856ec1..19db5195 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,8 +22,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `lf hitag reader 03` - read block (instead of pages) - Added `lf hitag reader 04` - read block (instead of pages) - Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (Merlok) +- Added `lf paradox clone` to clone a Paradox card - Added `emv` commmands working for both contactless and smart cards (Merlok) + ## [v3.1.0][2018-10-10] ### Changed diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 35c9e5bf..c5c17867 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -744,7 +744,7 @@ void SamyRun() /* need this delay to prevent catching some weird data */ SpinDelay(500); - CopyHIDtoT55x7(tops[selected] & 0x000FFFFF, high[selected], low[selected], (tops[selected] != 0 && ((high[selected]& 0xFFFFFFC0) != 0))); + CopyHIDtoT55x7(tops[selected] & 0x000FFFFF, high[selected], low[selected], (tops[selected] != 0 && ((high[selected]& 0xFFFFFFC0) != 0)), 0x1D); if (tops[selected] > 0) Dbprintf("Cloned %x %x%08x%08x", selected, tops[selected], high[selected], low[selected]); else @@ -1003,7 +1003,11 @@ void UsbPacketReceived(uint8_t *packet, int len) CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_HID_CLONE_TAG: - CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); + CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0], 0x1D); + break; + case CMD_PARADOX_CLONE_TAG: + // Paradox cards are the same as HID, with a different preamble, so we can reuse the same function + CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0], 0x0F); break; case CMD_IO_DEMOD_FSK: CmdIOdemodFSK(c->arg[0], 0, 0, 1); diff --git a/armsrc/apps.h b/armsrc/apps.h index 6af22b57..b9b1f3de 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -78,7 +78,7 @@ void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol); // Realt void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol); void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol); void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567 -void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567 +void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, uint8_t preamble); // Clone an HID-like card to T5557/T5567 void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5); void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo); void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7 diff --git a/armsrc/lfops.c b/armsrc/lfops.c index b56c3f51..1816bdca 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1417,8 +1417,8 @@ void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) { } } -// Copy HID id to card and setup block 0 config -void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { +// Copy a HID-like card (e.g. HID Proximity, Paradox) to a T55x7 compatible card +void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, uint8_t preamble) { uint32_t data[] = {0,0,0,0,0,0,0}; uint8_t last_block = 0; @@ -1430,15 +1430,15 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { } // Build the 6 data blocks for supplied 84bit ID last_block = 6; - // load preamble (1D) & long format identifier (9E manchester encoded) - data[1] = 0x1D96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF); + // load preamble & long format identifier (9E manchester encoded) + data[1] = (preamble << 24) | 0x96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF); // load raw id from hi2, hi, lo to data blocks (manchester encoded) data[2] = manchesterEncode2Bytes(hi2 & 0xFFFF); data[3] = manchesterEncode2Bytes(hi >> 16); data[4] = manchesterEncode2Bytes(hi & 0xFFFF); data[5] = manchesterEncode2Bytes(lo >> 16); data[6] = manchesterEncode2Bytes(lo & 0xFFFF); - } else { + } else { // Ensure no more than 44 bits supplied if (hi>0xFFF) { DbpString("Tags can only have 44 bits."); @@ -1447,7 +1447,7 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { // Build the 3 data blocks for supplied 44bit ID last_block = 3; // load preamble - data[1] = 0x1D000000 | (manchesterEncode2Bytes(hi) & 0xFFFFFF); + data[1] = (preamble << 24) | (manchesterEncode2Bytes(hi) & 0xFFFFFF); data[2] = manchesterEncode2Bytes(lo >> 16); data[3] = manchesterEncode2Bytes(lo & 0xFFFF); } diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 38e7073c..14340082 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -39,7 +39,7 @@ * * Returns the number of nibbles (4 bits) entered. */ -int hexstring_to_int96(/* out */ uint32_t* hi2,/* out */ uint32_t* hi, /* out */ uint32_t* lo, const char* str) { +int hid_hexstring_to_int96(/* out */ uint32_t* hi2,/* out */ uint32_t* hi, /* out */ uint32_t* lo, const char* str) { // TODO: Replace this with param_gethex when it supports arbitrary length // inputs. int n = 0, i = 0; @@ -201,7 +201,7 @@ int CmdHIDReadFSK(const char *Cmd) int CmdHIDSim(const char *Cmd) { uint32_t hi2 = 0, hi = 0, lo = 0; - hexstring_to_int96(&hi2, &hi, &lo, Cmd); + hid_hexstring_to_int96(&hi2, &hi, &lo, Cmd); if (hi2 != 0) { PrintAndLog("Emulating tag with ID %x%08x%08x", hi2, hi, lo); } else { @@ -218,7 +218,7 @@ int CmdHIDSim(const char *Cmd) int CmdHIDClone(const char *Cmd) { unsigned int top = 0, mid = 0, bot = 0; - hexstring_to_int96(&top, &mid, &bot, Cmd); + hid_hexstring_to_int96(&top, &mid, &bot, Cmd); hidproxmessage_t packed = initialize_proxmessage_object(top, mid, bot); Write(&packed); return 0; @@ -234,7 +234,7 @@ int CmdHIDDecode(const char *Cmd){ uint32_t top = 0, mid = 0, bot = 0; bool ignoreParity = false; - hexstring_to_int96(&top, &mid, &bot, Cmd); + hid_hexstring_to_int96(&top, &mid, &bot, Cmd); hidproxmessage_t packed = initialize_proxmessage_object(top, mid, bot); char opt = param_getchar(Cmd, 1); diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index ef907f67..353805db 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -22,4 +22,6 @@ int CmdHIDClone(const char *Cmd); int CmdHIDDecode(const char *Cmd); int CmdHIDEncode(const char *Cmd); int CmdHIDWrite(const char *Cmd); +// This is used by the Paradox code +int hid_hexstring_to_int96(/* out */ uint32_t* hi2,/* out */ uint32_t* hi, /* out */ uint32_t* lo, const char* str); #endif diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index e918c7fe..d6710219 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -19,7 +19,14 @@ #include "cmddata.h" #include "cmdlf.h" #include "lfdemod.h" +#include "comms.h" +// This card type is similar to HID, so we include the utils from there +#include "cmdlfhid.h" +#include "hidcardformats.h" +#include "hidcardformatutils.h" + static int CmdHelp(const char *Cmd); +void ParadoxWrite(hidproxmessage_t *packed); //by marshmellow //Paradox Prox demod - FSK RF/50 with preamble of 00001111 (then manchester encoded) @@ -55,14 +62,24 @@ int CmdFSKdemodParadox(const char *Cmd) if (g_debugMode) PrintAndLog("DEBUG: Error - no value found"); return 0; } + uint32_t fc = ((hi & 0x3)<<6) | (lo>>26); uint32_t cardnum = (lo>>10)&0xFFFF; uint32_t rawLo = bytebits_to_byte(BitStream+idx+64,32); uint32_t rawHi = bytebits_to_byte(BitStream+idx+32,32); uint32_t rawHi2 = bytebits_to_byte(BitStream+idx,32); - PrintAndLog("Paradox TAG ID: %x%08x - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x", - hi>>10, (hi & 0x3)<<26 | (lo>>10), fc, cardnum, (lo>>2) & 0xFF, rawHi2, rawHi, rawLo); + // Steal the HID parsing to output a "full" ID we can send to the HID cloning function + hidproxmessage_t packed = initialize_proxmessage_object(hi2, hi, lo); + + if (packed.top != 0) { + PrintAndLog("Paradox TAG ID: %x%08x (Full ID: %x%08x%08x) - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x", + hi>>10, (hi & 0x3)<<26 | (lo>>10), (uint32_t)packed.top, (uint32_t)packed.mid, (uint32_t)packed.bot, fc, cardnum, (lo>>2) & 0xFF, rawHi2, rawHi, rawLo); + } else { + PrintAndLog("Paradox TAG ID: %x%08x (Full ID: %x%08x) - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x", + hi>>10, (hi & 0x3)<<26 | (lo>>10), (uint32_t)packed.mid, (uint32_t)packed.bot, fc, cardnum, (lo>>2) & 0xFF, rawHi2, rawHi, rawLo); + + } setDemodBuf(BitStream,BitLen,idx); setClockGrid(50, waveIdx + (idx*50)); if (g_debugMode){ @@ -80,10 +97,31 @@ int CmdParadoxRead(const char *Cmd) { return CmdFSKdemodParadox(Cmd); } +int CmdParadoxClone(const char *Cmd) +{ + unsigned int top = 0, mid = 0, bot = 0; + hid_hexstring_to_int96(&top, &mid, &bot, Cmd); + hidproxmessage_t packed = initialize_proxmessage_object(top, mid, bot); + ParadoxWrite(&packed); + return 0; +} + +void ParadoxWrite(hidproxmessage_t *packed){ + UsbCommand c; + c.d.asBytes[0] = (packed->top != 0 && ((packed->mid & 0xFFFFFFC0) != 0)) + ? 1 : 0; // Writing long format? + c.cmd = CMD_PARADOX_CLONE_TAG; + c.arg[0] = (packed->top & 0x000FFFFF); + c.arg[1] = packed->mid; + c.arg[2] = packed->bot; + SendCommand(&c); +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"demod", CmdFSKdemodParadox, 1, "Demodulate a Paradox FSK tag from the GraphBuffer"}, {"read", CmdParadoxRead, 0, "Attempt to read and Extract tag data from the antenna"}, + {"clone", CmdParadoxClone, 0, " -- Clone Paradox to T55x7 (tag must be in antenna)"}, {NULL, NULL, 0, NULL} }; diff --git a/client/hidcardformatutils.c b/client/hidcardformatutils.c index 3abee223..e4fb6349 100644 --- a/client/hidcardformatutils.c +++ b/client/hidcardformatutils.c @@ -169,4 +169,4 @@ bool add_HID_header(/* inout */hidproxmessage_t* data){ data->bot |= 1 << data->Length; // leading 1: start bit } return true; -} \ No newline at end of file +} diff --git a/include/usb_cmd.h b/include/usb_cmd.h index fa66634f..306c52bf 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -111,6 +111,8 @@ typedef struct{ #define CMD_VIKING_CLONE_TAG 0x0223 #define CMD_T55XX_WAKEUP 0x0224 #define CMD_COTAG 0x0225 +// misc extra +#define CMD_PARADOX_CLONE_TAG 0x0226 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ -- 2.39.5