From 6923d3f14ff7c6439d708470f4da2edcc3eca854 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sat, 5 Mar 2016 23:45:28 -0500 Subject: [PATCH] Add @iceman1001 s presco and pyramid functions + plus comment some includes. fix indala error checking bugs cmddata.h previously relied on several headers being included prior to cmddata.h, now self contained. --- client/Makefile | 2 + client/cmddata.c | 49 +++++----- client/cmddata.h | 6 ++ client/cmdlf.c | 37 +++---- client/cmdlfpresco.c | 223 ++++++++++++++++++++++++++++++++++++++++++ client/cmdlfpresco.h | 30 ++++++ client/cmdlfpyramid.c | 185 +++++++++++++++++++++++++++++++++++ client/cmdlfpyramid.h | 30 ++++++ client/util.h | 5 +- common/lfdemod.c | 13 +++ common/lfdemod.h | 6 +- 11 files changed, 538 insertions(+), 48 deletions(-) create mode 100644 client/cmdlfpresco.c create mode 100644 client/cmdlfpresco.h create mode 100644 client/cmdlfpyramid.c create mode 100644 client/cmdlfpyramid.h diff --git a/client/Makefile b/client/Makefile index 0972f441..7f9c4c84 100644 --- a/client/Makefile +++ b/client/Makefile @@ -99,6 +99,8 @@ CMDSRCS = nonce2key/crapto1.c\ cmdlft55xx.c \ cmdlfpcf7931.c\ cmdlfviking.c\ + cmdlfpresco.c\ + cmdlfpyramid.c\ pm3_binlib.c\ scripting.c\ cmdscript.c\ diff --git a/client/cmddata.c b/client/cmddata.c index 801649ee..9854ccfa 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -8,23 +8,22 @@ // Data and Graph commands //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include "proxmark3.h" -#include "data.h" -#include "ui.h" -#include "graph.h" -#include "cmdparser.h" +#include // also included in util.h +#include // also included in util.h +#include // for CmdNorm INT_MIN && INT_MAX +#include "data.h" // also included in util.h +#include "cmddata.h" #include "util.h" #include "cmdmain.h" -#include "cmddata.h" -#include "lfdemod.h" -#include "usb_cmd.h" -#include "crc.h" -#include "crc16.h" -#include "loclass/cipherutils.h" +#include "proxmark3.h" +#include "ui.h" // for show graph controls +#include "graph.h" // for graph data +#include "cmdparser.h"// already included in cmdmain.h +#include "usb_cmd.h" // already included in cmdmain.h and proxmark3.h +#include "lfdemod.h" // for demod code +#include "crc.h" // for pyramid checksum maxim +#include "crc16.h" // for FDXB demod checksum +#include "loclass/cipherutils.h" // for decimating samples in getsamples uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; uint8_t g_debugMode=0; @@ -1265,7 +1264,7 @@ int CmdFSKdemodAWID(const char *Cmd) //get binary from fsk wave int idx = AWIDdemodFSK(BitStream, &size); if (idx<=0){ - if (g_debugMode==1){ + if (g_debugMode){ if (idx == -1) PrintAndLog("DEBUG: Error - not enough samples"); else if (idx == -2) @@ -1303,7 +1302,7 @@ int CmdFSKdemodAWID(const char *Cmd) size = removeParity(BitStream, idx+8, 4, 1, 88); if (size != 66){ - if (g_debugMode==1) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format"); + if (g_debugMode) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format"); return 0; } // ok valid card found! @@ -1363,7 +1362,7 @@ int CmdFSKdemodPyramid(const char *Cmd) //get binary from fsk wave int idx = PyramiddemodFSK(BitStream, &size); if (idx < 0){ - if (g_debugMode==1){ + if (g_debugMode){ if (idx == -5) PrintAndLog("DEBUG: Error - not enough samples"); else if (idx == -1) @@ -1419,7 +1418,7 @@ int CmdFSKdemodPyramid(const char *Cmd) size = removeParity(BitStream, idx+8, 8, 1, 120); if (size != 105){ - if (g_debugMode==1) + if (g_debugMode) PrintAndLog("DEBUG: Error at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %x",size, idx, rawHi3); return 0; } @@ -1642,21 +1641,21 @@ int CmdIndalaDecode(const char *Cmd) } if (!ans){ - if (g_debugMode==1) + if (g_debugMode) PrintAndLog("Error1: %d",ans); return 0; } uint8_t invert=0; size_t size = DemodBufferLen; - size_t startIdx = indala26decode(DemodBuffer, &size, &invert); - if (startIdx < 1 || size > 224) { - if (g_debugMode==1) + int startIdx = indala26decode(DemodBuffer, &size, &invert); + if (startIdx < 0 || size > 224) { + if (g_debugMode) PrintAndLog("Error2: %d",ans); return -1; } - setDemodBuf(DemodBuffer, size, startIdx); + setDemodBuf(DemodBuffer, size, (size_t)startIdx); if (invert) - if (g_debugMode==1) + if (g_debugMode) PrintAndLog("Had to invert bits"); PrintAndLog("BitLen: %d",DemodBufferLen); diff --git a/client/cmddata.h b/client/cmddata.h index 20bdbd2b..9b9f2da9 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -11,6 +11,12 @@ #ifndef CMDDATA_H__ #define CMDDATA_H__ +#include //size_t +#include //uint_32+ +#include //bool + +#include "cmdparser.h" // for command_t + command_t * CmdDataCommands(); int CmdData(const char *Cmd); diff --git a/client/cmdlf.c b/client/cmdlf.c index 9d23d97c..22bceda4 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -13,24 +13,25 @@ #include #include #include "proxmark3.h" -#include "data.h" -#include "graph.h" -#include "ui.h" -#include "cmdparser.h" -#include "cmdmain.h" -#include "cmddata.h" -#include "util.h" #include "cmdlf.h" -#include "cmdlfhid.h" -#include "cmdlfawid.h" -#include "cmdlfti.h" -#include "cmdlfem4x.h" -#include "cmdlfhitag.h" -#include "cmdlft55xx.h" -#include "cmdlfpcf7931.h" -#include "cmdlfio.h" -#include "cmdlfviking.h" -#include "lfdemod.h" +#include "util.h" // for parsing cli command utils +#include "ui.h" // for show graph controls +#include "graph.h" // for graph data +#include "cmdparser.h" // for getting cli commands included in cmdmain.h +#include "cmdmain.h" // for sending cmds to device +#include "data.h" // for GetFromBigBuf +#include "cmddata.h" // for `lf search` +#include "cmdlfawid.h" // for awid menu +#include "cmdlfem4x.h" // for em4x menu +#include "cmdlfhid.h" // for hid menu +#include "cmdlfhitag.h" // for hitag menu +#include "cmdlfio.h" // for ioprox menu +#include "cmdlft55xx.h" // for t55xx menu +#include "cmdlfti.h" // for ti menu +#include "cmdlfpresco.h" // for presco menu +#include "cmdlfpcf7931.h"// for pcf7931 menu +#include "cmdlfpyramid.h"// for pyramid menu +#include "cmdlfviking.h" // for viking menu static int CmdHelp(const char *Cmd); @@ -1220,7 +1221,9 @@ static command_t CommandTable[] = {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, {"io", CmdLFIO, 1, "{ ioProx tags... }"}, + {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"}, {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"}, + {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"}, {"ti", CmdLFTI, 1, "{ TI RFIDs... }"}, {"viking", CmdLFViking, 1, "{ Viking tags... }"}, diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c new file mode 100644 index 00000000..20b42bc1 --- /dev/null +++ b/client/cmdlfpresco.c @@ -0,0 +1,223 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency Presco tag commands +//----------------------------------------------------------------------------- +#include +#include +#include "cmdlfpresco.h" +static int CmdHelp(const char *Cmd); + +int usage_lf_presco_clone(void){ + PrintAndLog("clone a Presco tag to a T55x7 tag."); + PrintAndLog("Usage: lf presco clone "); + PrintAndLog("Options :"); + PrintAndLog(" : 9 digit presco card number"); + //PrintAndLog(" : specify write to Q5 (t5555 instead of t55x7)"); + PrintAndLog(""); + PrintAndLog("Sample : lf presco clone 123456789"); + return 0; +} + +int usage_lf_presco_sim(void) { + PrintAndLog("Enables simulation of presco card with specified card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated."); + PrintAndLog(""); + PrintAndLog("Usage: lf presco sim "); + PrintAndLog("Options :"); + PrintAndLog(" : 9 digit presco card number"); + PrintAndLog(""); + PrintAndLog("Sample : lf presco sim 123456789"); + return 0; +} + +// calc checksum +int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode) { + + uint8_t val = 0; + for (int index =0; index < strlen(id); ++index) { + + // Get value from number string. + if ( id[index] == '*' ) val = 10; + if ( id[index] == '#') val = 11; + if ( id[index] >= 0x30 && id[index] <= 0x39 ) + val = id[index] - 0x30; + + *sitecode += val; + + // last digit is only added, not multipled. + if ( index < strlen(id)-1 ) + *sitecode *= 12; + } + *usercode = *sitecode % 65536; + *sitecode /= 16777216; + return 0; +} + +int GetPrescoBits(uint32_t sitecode, uint32_t usercode, uint8_t *prescoBits) { + uint8_t pre[66]; + memset(pre, 0, sizeof(pre)); + prescoBits[7]=1; + num_to_bytebits(26, 8, pre); + + uint8_t wiegand[24]; + num_to_bytebits(sitecode, 8, wiegand); + num_to_bytebits(usercode, 16, wiegand+8); + + wiegand_add_parity(pre+8, wiegand, 24); + size_t bitLen = addParity(pre, prescoBits+8, 66, 4, 1); + + if (bitLen != 88) return 0; + return 1; +} +//see ASKDemod for what args are accepted +int CmdPrescoDemod(const char *Cmd) { + if (!ASKDemod(Cmd, false, false, 1)) { + if (g_debugMode) PrintAndLog("ASKDemod failed"); + return 0; + } + size_t size = DemodBufferLen; + //call lfdemod.c demod for Viking + int ans = PrescoDemod(DemodBuffer, &size); + if (ans < 0) { + if (g_debugMode) PrintAndLog("Error Presco_Demod %d", ans); + return 0; + } + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32); + uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32); + PrintAndLog("Presco Tag Found: Card ID %08X", cardid); + PrintAndLog("Raw: %08X%08X", raw1,raw2); + setDemodBuf(DemodBuffer+ans, 64, 0); + + // uint32_t sitecode = 0, usercode = 0; + // GetWiegandFromPresco(id, &sitecode, &usercode); + // PrintAndLog8("SiteCode %d | UserCode %d", sitecode, usercode); + + return 1; +} + +//see ASKDemod for what args are accepted +int CmdPrescoRead(const char *Cmd) { + // Presco Number: 123456789 --> Sitecode 30 | usercode 8665 + + // read lf silently + CmdLFRead("s"); + // get samples silently + getSamples("30000",false); + // demod and output Presco ID + return CmdPrescoDemod(Cmd); +} + +int CmdPrescoClone(const char *Cmd) { + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_presco_clone(); + + uint32_t sitecode=0, usercode=0; + uint8_t bits[96]; + uint8_t *bs = bits; + memset(bs,0,sizeof(bits)); + uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4<> 32),(uint32_t) (rawID & 0xFFFFFFFF)); + + // UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; + // num_to_bytebits(rawID, size, c.d.asBytes); + // clearCommandBuffer(); + // SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"read", CmdPrescoRead, 0, "Attempt to read and Extract tag data"}, + {"clone", CmdPrescoClone, 0, "<8 digit ID number> clone presco tag"}, +// {"sim", CmdPrescoSim, 0, "<8 digit ID number> simulate presco tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFPresco(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h new file mode 100644 index 00000000..f9cfbd95 --- /dev/null +++ b/client/cmdlfpresco.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency T55xx commands +//----------------------------------------------------------------------------- +#ifndef CMDLFPRESCO_H__ +#define CMDLFPRESCO_H__ +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest +int CmdLFPresco(const char *Cmd); +int CmdPrescoClone(const char *Cmd); +//int CmdPrescoSim(const char *Cmd); + +int usage_lf_presco_clone(void); +int usage_lf_presco_sim(void); + +int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode); +#endif + diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c new file mode 100644 index 00000000..990dccbb --- /dev/null +++ b/client/cmdlfpyramid.c @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency Farpoint / Pyramid tag commands +//----------------------------------------------------------------------------- +#include +#include +#include "cmdlfpyramid.h" +static int CmdHelp(const char *Cmd); + +int usage_lf_pyramid_clone(void){ + PrintAndLog("clone a Farpointe/Pyramid tag to a T55x7 tag."); + PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. "); + PrintAndLog("Currently work only on 26bit"); + PrintAndLog(""); + PrintAndLog("Usage: lf pyramid clone "); + PrintAndLog("Options :"); + PrintAndLog(" : 8-bit value facility code"); + PrintAndLog(" : 16-bit value card number"); + PrintAndLog(""); + PrintAndLog("Sample : lf pyramid clone 123 11223"); + return 0; +} + +int usage_lf_pyramid_sim(void) { + PrintAndLog("Enables simulation of Farpointe/Pyramid card with specified card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated."); + PrintAndLog("Currently work only on 26bit"); + PrintAndLog(""); + PrintAndLog("Usage: lf pyramid sim "); + PrintAndLog("Options :"); + PrintAndLog(" : 8-bit value facility code"); + PrintAndLog(" : 16-bit value card number"); + PrintAndLog(""); + PrintAndLog("Sample : lf pyramid sim 123 11223"); + return 0; +} + +// Works for 26bits. +int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) { + + uint8_t pre[128]; + memset(pre, 0x00, sizeof(pre)); + + // format start bit + pre[79] = 1; + + // Get 26 wiegand from FacilityCode, CardNumber + uint8_t wiegand[24]; + memset(wiegand, 0x00, sizeof(wiegand)); + num_to_bytebits(fc, 8, wiegand); + num_to_bytebits(cn, 16, wiegand+8); + + // add wiegand parity bits (dest, source, len) + wiegand_add_parity(pre+80, wiegand, 24); + + // add paritybits (bitsource, dest, sourcelen, paritylen, parityType (odd, even,) + addParity(pre+8, pyramidBits+8, 102, 8, 1); + + // add checksum + uint8_t csBuff[13]; + for (uint8_t i = 0; i < 13; i++) + csBuff[i] = bytebits_to_byte(pyramidBits + 16 + (i*8), 8); + + uint32_t crc = CRC8Maxim(csBuff, 13); + num_to_bytebits(crc, 8, pyramidBits+120); + return 1; +} + +int CmdPyramidRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("30000",false); + return CmdFSKdemodPyramid(""); +} + +int CmdPyramidClone(const char *Cmd) { + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_clone(); + + uint32_t facilitycode=0, cardnumber=0, fc = 0, cn = 0; + uint32_t blocks[5]; + uint8_t i; + uint8_t bs[128]; + memset(bs, 0x00, sizeof(bs)); + + if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_clone(); + + facilitycode = (fc & 0x000000FF); + cardnumber = (cn & 0x0000FFFF); + + if ( !GetPyramidBits(facilitycode, cardnumber, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return 1; + } + +// if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q') +// blocks[0] = T5555_MODULATION_FSK2 | 50< clone pyramid tag"}, + {"sim", CmdPyramidSim, 0, " simulate pyramid tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFPyramid(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h new file mode 100644 index 00000000..d00b7d06 --- /dev/null +++ b/client/cmdlfpyramid.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency T55xx commands +//----------------------------------------------------------------------------- +#ifndef CMDLFPYRAMID_H__ +#define CMDLFPYRAMID_H__ +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest +#include "crc.h" + +int CmdLFPyramid(const char *Cmd); +int CmdPyramidClone(const char *Cmd); +int CmdPyramidSim(const char *Cmd); + +int usage_lf_pyramid_clone(void); +int usage_lf_pyramid_sim(void); +#endif + diff --git a/client/util.h b/client/util.h index 5674adcf..dc5dcfa0 100644 --- a/client/util.h +++ b/client/util.h @@ -9,13 +9,12 @@ //----------------------------------------------------------------------------- #include -#include -#include +#include included in data.h #include #include #include #include -#include "data.h" +#include "data.h" //for FILE_PATH_SIZE #ifndef ROTR # define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n)))) diff --git a/common/lfdemod.c b/common/lfdemod.c index 665bad89..d6c024fa 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -684,6 +684,19 @@ int VikingDemod_AM(uint8_t *dest, size_t *size) { return (int) startIdx; } +// find presco preamble 0x10D in already demoded data +int PrescoDemod(uint8_t *dest, size_t *size) { + //make sure buffer has data + if (*size < 64*2) return -2; + + size_t startIdx = 0; + uint8_t preamble[] = {1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx); + if (errChk == 0) return -4; //preamble not found + //return start position + return (int) startIdx; +} + // Ask/Biphase Demod then try to locate an ISO 11784/85 ID // BitStream must contain previously askrawdemod and biphasedemoded data int FDXBdemodBI(uint8_t *dest, size_t *size) diff --git a/common/lfdemod.h b/common/lfdemod.h index d4a1fda0..56c758ae 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -13,8 +13,8 @@ #ifndef LFDEMOD_H__ #define LFDEMOD_H__ -#include -#include "common.h" //for bool +#include // for uint_32+ +#include // for bool //generic size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType); @@ -54,5 +54,5 @@ int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); int PyramiddemodFSK(uint8_t *dest, size_t *size); int VikingDemod_AM(uint8_t *dest, size_t *size); - +int PrescoDemod(uint8_t *dest, size_t *size); #endif -- 2.39.2