Merge branch 'master' of github.com:Proxmark/proxmark3

This commit is contained in:
Martin Holst Swende 2015-04-23 09:51:04 +02:00
commit a3abb02897
30 changed files with 1848 additions and 2065 deletions

View file

@ -4,11 +4,13 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [Unreleased][unreleased]
### Changed
- Improved LF manchester and biphase demodulation and ask clock detection especially for reads with heavy clipping. (marshmellow)
- Iclass read, `hf iclass read` now also reads tag config and prints configuration. (holiman)
- *bootrom* needs to be flashed, due to new address boundaries between os and fpga, after a size optimization (piwi)
### Fixed
- Fixed issue #19, problems with LF T55xx commands (marshmellow)
- Fixed EM4x50 read/demod of the tags broadcasted memory blocks. 'lf em4x em4x50read' (not page read) (marshmellow)
- Fixed issue #19, problems with LF T55xx commands (iceman1001, marshmellow)
### Added
- Added changelog

View file

@ -861,7 +861,7 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
size = BigBuf_max_traceLen();
//askdemod and manchester decode
if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format
errCnt = askmandemod(dest, &size, &clk, &invert, maxErr);
errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1);
WDT_HIT();
if (errCnt<0) continue;

File diff suppressed because it is too large Load diff

View file

@ -15,10 +15,7 @@ command_t * CmdDataCommands();
int CmdData(const char *Cmd);
void printDemodBuff(void);
void printBitStream(uint8_t BitStream[], uint32_t bitLen);
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
int CmdAmp(const char *Cmd);
int Cmdaskdemod(const char *Cmd);
int CmdAskEM410xDemod(const char *Cmd);
int CmdG_Prox_II_Demod(const char *Cmd);
int Cmdaskrawdemod(const char *Cmd);
@ -27,12 +24,10 @@ int AutoCorrelate(int window, bool SaveGrph, bool verbose);
int CmdAutoCorr(const char *Cmd);
int CmdBiphaseDecodeRaw(const char *Cmd);
int CmdBitsamples(const char *Cmd);
int CmdBitstream(const char *Cmd);
int CmdBuffClear(const char *Cmd);
int CmdDec(const char *Cmd);
int CmdDetectClockRate(const char *Cmd);
int CmdFSKdemodAWID(const char *Cmd);
int CmdFSKdemod(const char *Cmd);
int CmdFSKdemodHID(const char *Cmd);
int CmdFSKdemodIO(const char *Cmd);
int CmdFSKdemodParadox(const char *Cmd);
@ -40,6 +35,7 @@ int CmdFSKdemodPyramid(const char *Cmd);
int CmdFSKrawdemod(const char *Cmd);
int CmdPSK1rawDemod(const char *Cmd);
int CmdPSK2rawDemod(const char *Cmd);
int CmdPSKNexWatch(const char *Cmd);
int CmdGrid(const char *Cmd);
int CmdGetBitStream(const char *Cmd);
int CmdHexsamples(const char *Cmd);
@ -49,24 +45,22 @@ int CmdLoad(const char *Cmd);
int CmdLtrim(const char *Cmd);
int CmdRtrim(const char *Cmd);
int Cmdmandecoderaw(const char *Cmd);
int CmdManchesterDemod(const char *Cmd);
int CmdManchesterMod(const char *Cmd);
int CmdNorm(const char *Cmd);
int CmdNRZrawDemod(const char *Cmd);
int CmdPlot(const char *Cmd);
int CmdPrintDemodBuff(const char *Cmd);
int CmdRawDemod(const char *Cmd);
int CmdSamples(const char *Cmd);
int CmdTuneSamples(const char *Cmd);
int CmdSave(const char *Cmd);
int CmdScale(const char *Cmd);
int CmdThreshold(const char *Cmd);
int CmdDirectionalThreshold(const char *Cmd);
int CmdZerocrossings(const char *Cmd);
int CmdIndalaDecode(const char *Cmd);
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo);
int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo );
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose);
int ASKbiphaseDemod(const char *Cmd, bool verbose);
int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch);
int ASKrawDemod(const char *Cmd, bool verbose);
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType);
int FSKrawDemod(const char *Cmd, bool verbose);
int PSKDemod(const char *Cmd, bool verbose);
int NRZrawDemod(const char *Cmd, bool verbose);
@ -77,7 +71,7 @@ int getSamples(const char *Cmd, bool silent);
#define MAX_DEMOD_BUF_LEN (1024*128)
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
extern int DemodBufferLen;
extern uint8_t g_debugMode;
#define BIGBUF_SIZE 40000
#endif

View file

@ -1499,16 +1499,16 @@ int CmdHF14AMfCSetUID(const char *Cmd)
int CmdHF14AMfCSetBlk(const char *Cmd)
{
uint8_t uid[8] = {0x00};
uint8_t memBlock[16] = {0x00};
uint8_t blockNo = 0;
bool wipeCard = FALSE;
int res;
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)>");
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)> [w]");
PrintAndLog("sample: hf mf csetblk 1 01020304050607080910111213141516");
PrintAndLog("Set block data for magic Chinese card (only works with!!!)");
PrintAndLog("If you want wipe card then add 'w' into command line. \n");
PrintAndLog("Set block data for magic Chinese card (only works with such cards)");
PrintAndLog("If you also want wipe the card then add 'w' at the end of the command line");
return 0;
}
@ -1519,14 +1519,15 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
return 1;
}
char ctmp = param_getchar(Cmd, 2);
wipeCard = (ctmp == 'w' || ctmp == 'W');
PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16));
res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER);
res = mfCSetBlock(blockNo, memBlock, NULL, wipeCard, CSETBLOCK_SINGLE_OPER);
if (res) {
PrintAndLog("Can't write block. error=%d", res);
return 1;
}
PrintAndLog("Can't write block. error=%d", res);
return 1;
}
return 0;
}
@ -1637,7 +1638,7 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf cgetblk <block number>");
PrintAndLog("sample: hf mf cgetblk 1");
PrintAndLog("Get block data from magic Chinese card (only works with!!!)\n");
PrintAndLog("Get block data from magic Chinese card (only works with such cards)\n");
return 0;
}
@ -1664,7 +1665,7 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf cgetsc <sector number>");
PrintAndLog("sample: hf mf cgetsc 0");
PrintAndLog("Get sector data from magic Chinese card (only works with!!!)\n");
PrintAndLog("Get sector data from magic Chinese card (only works with such cards)\n");
return 0;
}

View file

@ -522,7 +522,8 @@ static void ChkBitstream(const char *str)
}
}
}
//appears to attempt to simulate manchester
//Attempt to simulate any wave in buffer (one bit per output sample)
// converts GraphBuffer to bitstream (based on zero crossings) if needed.
int CmdLFSim(const char *Cmd)
{
int i,j;
@ -530,11 +531,11 @@ int CmdLFSim(const char *Cmd)
sscanf(Cmd, "%i", &gap);
/* convert to bitstream if necessary */
// convert to bitstream if necessary
ChkBitstream(Cmd);
//can send 512 bits at a time (1 byte sent per bit...)
//can send only 512 bits at a time (1 byte sent per bit...)
printf("Sending [%d bytes]", GraphTraceLen);
for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
@ -606,8 +607,8 @@ int usage_lf_simpsk(void)
// - allow pull data from DemodBuffer
int CmdLFfskSim(const char *Cmd)
{
//might be able to autodetect FC and clock from Graphbuffer if using demod buffer
//will need FChigh, FClow, Clock, and bitstream
//might be able to autodetect FCs and clock from Graphbuffer if using demod buffer
// otherwise will need FChigh, FClow, Clock, and bitstream
uint8_t fcHigh=0, fcLow=0, clk=0;
uint8_t invert=0;
bool errors = FALSE;
@ -682,6 +683,8 @@ int CmdLFfskSim(const char *Cmd)
} else {
setDemodBuf(data, dataLen, 0);
}
//default if not found
if (clk == 0) clk = 50;
if (fcHigh == 0) fcHigh = 10;
if (fcLow == 0) fcLow = 8;
@ -706,9 +709,8 @@ int CmdLFfskSim(const char *Cmd)
int CmdLFaskSim(const char *Cmd)
{
//autodetect clock from Graphbuffer if using demod buffer
//will need clock, invert, manchester/raw as m or r, separator as s, and bitstream
// needs clock, invert, manchester/raw as m or r, separator as s, and bitstream
uint8_t encoding = 1, separator = 0;
//char cmdp = Cmd[0], par3='m', par4=0;
uint8_t clk=0, invert=0;
bool errors = FALSE;
char hexData[32] = {0x00};
@ -913,30 +915,6 @@ int CmdLFSimBidir(const char *Cmd)
return 0;
}
/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
/*
int CmdLFSimManchester(const char *Cmd)
{
static int clock, gap;
static char data[1024], gapstring[8];
sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
ClearGraph(0);
for (int i = 0; i < strlen(data) ; ++i)
AppendGraph(0, clock, data[i]- '0');
CmdManchesterMod("");
RepaintGraphWindow();
sprintf(&gapstring[0], "%i", gap);
CmdLFSim(gapstring);
return 0;
}
*/
int CmdVchDemod(const char *Cmd)
{
// Is this the entire sync pattern, or does this also include some
@ -1033,8 +1011,8 @@ int CmdLFfind(const char *Cmd)
}
if (!offline && (cmdp != '1')){
ans=CmdLFRead("");
ans=CmdSamples("20000");
CmdLFRead("s");
getSamples("30000",false);
} else if (GraphTraceLen < 1000) {
PrintAndLog("Data in Graphbuffer was too small.");
return 0;
@ -1094,26 +1072,36 @@ int CmdLFfind(const char *Cmd)
return 1;
}
ans=EM4x50Read("", false);
if (ans>0) {
PrintAndLog("\nValid EM4x50 ID Found!");
return 1;
}
ans=CmdPSKNexWatch("");
if (ans>0) {
PrintAndLog("\nValid NexWatch ID Found!");
return 1;
}
PrintAndLog("\nNo Known Tags Found!\n");
if (testRaw=='u' || testRaw=='U'){
//test unknown tag formats (raw mode)
PrintAndLog("\nChecking for Unknown tags:\n");
ans=AutoCorrelate(4000, FALSE, FALSE);
if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
ans=GetFskClock("",FALSE,FALSE); //CmdDetectClockRate("F"); //
ans=GetFskClock("",FALSE,FALSE);
if (ans != 0){ //fsk
ans=FSKrawDemod("",FALSE);
ans=FSKrawDemod("",TRUE);
if (ans>0) {
PrintAndLog("\nUnknown FSK Modulated Tag Found!");
printDemodBuff();
return 1;
}
}
ans=ASKmanDemod("",FALSE,FALSE);
ans=ASKDemod("0 0 0",TRUE,FALSE,1);
if (ans>0) {
PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
printDemodBuff();
return 1;
}
ans=CmdPSK1rawDemod("");
@ -1121,7 +1109,6 @@ int CmdLFfind(const char *Cmd)
PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'");
PrintAndLog("\nCould also be PSK3 - [currently not supported]");
PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
printDemodBuff();
return 1;
}
PrintAndLog("\nNo Data Found!\n");
@ -1147,7 +1134,6 @@ static command_t CommandTable[] =
{"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
{"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
//{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},

View file

@ -23,7 +23,6 @@ int CmdLFaskSim(const char *Cmd);
int CmdLFfskSim(const char *Cmd);
int CmdLFpskSim(const char *Cmd);
int CmdLFSimBidir(const char *Cmd);
//int CmdLFSimManchester(const char *Cmd);
int CmdLFSnoop(const char *Cmd);
int CmdVchDemod(const char *Cmd);
int CmdLFfind(const char *Cmd);

View file

@ -19,6 +19,7 @@
#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlfem4x.h"
#include "lfdemod.h"
char *global_em410xId;
static int CmdHelp(const char *Cmd);
@ -26,11 +27,11 @@ static int CmdHelp(const char *Cmd);
int CmdEMdemodASK(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
int findone = (cmdp == '1') ? 1 : 0;
UsbCommand c={CMD_EM410X_DEMOD};
c.arg[0]=findone;
SendCommand(&c);
return 0;
int findone = (cmdp == '1') ? 1 : 0;
UsbCommand c={CMD_EM410X_DEMOD};
c.arg[0]=findone;
SendCommand(&c);
return 0;
}
/* Read the ID of an EM410x tag.
@ -43,21 +44,21 @@ int CmdEMdemodASK(const char *Cmd)
*/
int CmdEM410xRead(const char *Cmd)
{
uint32_t hi=0;
uint64_t lo=0;
uint32_t hi=0;
uint64_t lo=0;
if(!AskEm410xDemod("", &hi, &lo)) return 0;
PrintAndLog("EM410x pattern found: ");
printEM410x(hi, lo);
if (hi){
PrintAndLog ("EM410x XL pattern found");
return 0;
}
char id[12] = {0x00};
sprintf(id, "%010llx",lo);
global_em410xId = id;
return 1;
if(!AskEm410xDemod("", &hi, &lo, false)) return 0;
PrintAndLog("EM410x pattern found: ");
printEM410x(hi, lo);
if (hi){
PrintAndLog ("EM410x XL pattern found");
return 0;
}
char id[12] = {0x00};
sprintf(id, "%010llx",lo);
global_em410xId = id;
return 1;
}
// emulate an EM410X tag
@ -83,52 +84,52 @@ int CmdEM410xSim(const char *Cmd)
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]);
PrintAndLog("Press pm3-button to about simulation");
/* clock is 64 in EM410x tags */
int clock = 64;
/* clock is 64 in EM410x tags */
int clock = 64;
/* clear our graph */
ClearGraph(0);
/* clear our graph */
ClearGraph(0);
/* write 9 start bits */
for (i = 0; i < 9; i++)
AppendGraph(0, clock, 1);
/* write 9 start bits */
for (i = 0; i < 9; i++)
AppendGraph(0, clock, 1);
/* for each hex char */
parity[0] = parity[1] = parity[2] = parity[3] = 0;
for (i = 0; i < 10; i++)
{
/* read each hex char */
sscanf(&Cmd[i], "%1x", &n);
for (j = 3; j >= 0; j--, n/= 2)
binary[j] = n % 2;
/* for each hex char */
parity[0] = parity[1] = parity[2] = parity[3] = 0;
for (i = 0; i < 10; i++)
{
/* read each hex char */
sscanf(&Cmd[i], "%1x", &n);
for (j = 3; j >= 0; j--, n/= 2)
binary[j] = n % 2;
/* append each bit */
AppendGraph(0, clock, binary[0]);
AppendGraph(0, clock, binary[1]);
AppendGraph(0, clock, binary[2]);
AppendGraph(0, clock, binary[3]);
/* append each bit */
AppendGraph(0, clock, binary[0]);
AppendGraph(0, clock, binary[1]);
AppendGraph(0, clock, binary[2]);
AppendGraph(0, clock, binary[3]);
/* append parity bit */
AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
/* append parity bit */
AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
/* keep track of column parity */
parity[0] ^= binary[0];
parity[1] ^= binary[1];
parity[2] ^= binary[2];
parity[3] ^= binary[3];
}
/* keep track of column parity */
parity[0] ^= binary[0];
parity[1] ^= binary[1];
parity[2] ^= binary[2];
parity[3] ^= binary[3];
}
/* parity columns */
AppendGraph(0, clock, parity[0]);
AppendGraph(0, clock, parity[1]);
AppendGraph(0, clock, parity[2]);
AppendGraph(0, clock, parity[3]);
/* parity columns */
AppendGraph(0, clock, parity[0]);
AppendGraph(0, clock, parity[1]);
AppendGraph(0, clock, parity[2]);
AppendGraph(0, clock, parity[3]);
/* stop bit */
AppendGraph(1, clock, 0);
/* stop bit */
AppendGraph(1, clock, 0);
CmdLFSim("0"); //240 start_gap.
return 0;
CmdLFSim("0"); //240 start_gap.
return 0;
}
/* Function is equivalent of lf read + data samples + em410xread
@ -139,7 +140,6 @@ int CmdEM410xSim(const char *Cmd)
* rate gets lower, then grow the number of samples
* Changed by martin, 4000 x 4 = 16000,
* see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235
*/
int CmdEM410xWatch(const char *Cmd)
{
@ -150,12 +150,13 @@ int CmdEM410xWatch(const char *Cmd)
}
CmdLFRead("s");
getSamples("8192",true); //capture enough to get 2 full messages
getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9)
} while (!CmdEM410xRead(""));
return 0;
}
//currently only supports manchester modulations
int CmdEM410xWatchnSpoof(const char *Cmd)
{
CmdEM410xWatch(Cmd);
@ -164,154 +165,10 @@ int CmdEM410xWatchnSpoof(const char *Cmd)
return 0;
}
/* Read the transmitted data of an EM4x50 tag
* Format:
*
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* CCCCCCCC <- column parity bits
* 0 <- stop bit
* LW <- Listen Window
*
* This pattern repeats for every block of data being transmitted.
* Transmission starts with two Listen Windows (LW - a modulated
* pattern of 320 cycles each (32/32/128/64/64)).
*
* Note that this data may or may not be the UID. It is whatever data
* is stored in the blocks defined in the control word First and Last
* Word Read values. UID is stored in block 32.
*/
int CmdEM4x50Read(const char *Cmd)
{
int i, j, startblock, skip, block, start, end, low, high;
bool complete= false;
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
char tmp[6];
high= low= 0;
memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
/* first get high and low values */
for (i = 0; i < GraphTraceLen; i++)
{
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
/* populate a buffer with pulse lengths */
i= 0;
j= 0;
while (i < GraphTraceLen)
{
// measure from low to low
while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
++i;
start= i;
while ((GraphBuffer[i] < high) && (i<GraphTraceLen))
++i;
while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
++i;
if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
break;
}
tmpbuff[j++]= i - start;
}
/* look for data start - should be 2 pairs of LW (pulses of 192,128) */
start= -1;
skip= 0;
for (i= 0; i < j - 4 ; ++i)
{
skip += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
{
start= i + 3;
break;
}
}
startblock= i + 3;
/* skip over the remainder of the LW */
skip += tmpbuff[i+1]+tmpbuff[i+2];
while (skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low)
++skip;
skip += 8;
/* now do it again to find the end */
end= start;
for (i += 3; i < j - 4 ; ++i)
{
end += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
{
complete= true;
break;
}
}
if (start >= 0)
PrintAndLog("Found data at sample: %i",skip);
else
{
PrintAndLog("No data found!");
PrintAndLog("Try again with more samples.");
return 0;
}
if (!complete)
{
PrintAndLog("*** Warning!");
PrintAndLog("Partial data - no end found!");
PrintAndLog("Try again with more samples.");
}
/* get rid of leading crap */
sprintf(tmp,"%i",skip);
CmdLtrim(tmp);
/* now work through remaining buffer printing out data blocks */
block= 0;
i= startblock;
while (block < 6)
{
PrintAndLog("Block %i:", block);
// mandemod routine needs to be split so we can call it for data
// just print for now for debugging
CmdManchesterDemod("i 64");
skip= 0;
/* look for LW before start of next block */
for ( ; i < j - 4 ; ++i)
{
skip += tmpbuff[i];
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
break;
}
while (GraphBuffer[skip] > low)
++skip;
skip += 8;
sprintf(tmp,"%i",skip);
CmdLtrim(tmp);
start += skip;
block++;
}
return 0;
}
int CmdEM410xWrite(const char *Cmd)
{
uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value
int card = 0xFF; // invalid card value
uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value
int card = 0xFF; // invalid card value
unsigned int clock = 0; // invalid clock value
sscanf(Cmd, "%" PRIx64 " %d %d", &id, &card, &clock);
@ -370,133 +227,404 @@ int CmdEM410xWrite(const char *Cmd)
return 0;
}
UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}};
SendCommand(&c);
UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}};
SendCommand(&c);
return 0;
return 0;
}
bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
if (rows*cols>size) return false;
uint8_t colP=0;
//assume last col is a parity and do not test
for (uint8_t colNum = 0; colNum < cols-1; colNum++) {
for (uint8_t rowNum = 0; rowNum < rows; rowNum++) {
colP ^= BitStream[(rowNum*cols)+colNum];
}
if (colP != pType) return false;
}
return true;
}
bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
{
if (rows*cols>size) return false;
uint8_t rowP=0;
//assume last row is a parity row and do not test
for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) {
for (uint8_t colNum = 0; colNum < cols; colNum++) {
rowP ^= BitStream[(rowNum*cols)+colNum];
}
if (rowP != pType) return false;
}
return true;
}
uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest)
{
if (size<45) return 0;
uint32_t code = bytebits_to_byte(BitStream,8);
code = code<<8 | bytebits_to_byte(BitStream+9,8);
code = code<<8 | bytebits_to_byte(BitStream+18,8);
code = code<<8 | bytebits_to_byte(BitStream+27,8);
if (verbose || g_debugMode){
for (uint8_t i = 0; i<5; i++){
if (i == 4) PrintAndLog(""); //parity byte spacer
PrintAndLog("%d%d%d%d%d%d%d%d %d -> 0x%02x",
BitStream[i*9],
BitStream[i*9+1],
BitStream[i*9+2],
BitStream[i*9+3],
BitStream[i*9+4],
BitStream[i*9+5],
BitStream[i*9+6],
BitStream[i*9+7],
BitStream[i*9+8],
bytebits_to_byte(BitStream+i*9,8)
);
}
if (pTest)
PrintAndLog("Parity Passed");
else
PrintAndLog("Parity Failed");
}
return code;
}
/* Read the transmitted data of an EM4x50 tag
* Format:
*
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
* CCCCCCCC <- column parity bits
* 0 <- stop bit
* LW <- Listen Window
*
* This pattern repeats for every block of data being transmitted.
* Transmission starts with two Listen Windows (LW - a modulated
* pattern of 320 cycles each (32/32/128/64/64)).
*
* Note that this data may or may not be the UID. It is whatever data
* is stored in the blocks defined in the control word First and Last
* Word Read values. UID is stored in block 32.
*/
//completed by Marshmellow
int EM4x50Read(const char *Cmd, bool verbose)
{
uint8_t fndClk[] = {8,16,32,40,50,64,128};
int clk = 0;
int invert = 0;
int tol = 0;
int i, j, startblock, skip, block, start, end, low, high, minClk;
bool complete = false;
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
uint32_t Code[6];
char tmp[6];
char tmp2[20];
int phaseoff;
high = low = 0;
memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
// get user entry if any
sscanf(Cmd, "%i %i", &clk, &invert);
// save GraphBuffer - to restore it later
save_restoreGB(1);
// first get high and low values
for (i = 0; i < GraphTraceLen; i++) {
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
i = 0;
j = 0;
minClk = 255;
// get to first full low to prime loop and skip incomplete first pulse
while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
++i;
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
++i;
skip = i;
// populate tmpbuff buffer with pulse lengths
while (i < GraphTraceLen) {
// measure from low to low
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
++i;
start= i;
while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
++i;
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
++i;
if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
break;
}
tmpbuff[j++]= i - start;
if (i-start < minClk && i < GraphTraceLen) {
minClk = i - start;
}
}
// set clock
if (!clk) {
for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
tol = fndClk[clkCnt]/8;
if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) {
clk=fndClk[clkCnt];
break;
}
}
if (!clk) return 0;
} else tol = clk/8;
// look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2)
start = -1;
for (i= 0; i < j - 4 ; ++i) {
skip += tmpbuff[i];
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
{
start= i + 4;
break;
}
}
startblock = i + 4;
// skip over the remainder of LW
skip += tmpbuff[i+1] + tmpbuff[i+2] + clk;
if (tmpbuff[i+3]>clk)
phaseoff = tmpbuff[i+3]-clk;
else
phaseoff = 0;
// now do it again to find the end
end = skip;
for (i += 3; i < j - 4 ; ++i) {
end += tmpbuff[i];
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
{
complete= true;
break;
}
}
end = i;
// report back
if (verbose || g_debugMode) {
if (start >= 0) {
PrintAndLog("\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)");
} else {
PrintAndLog("No data found!, clock tried:%d",clk);
PrintAndLog("Try again with more samples.");
PrintAndLog(" or after a 'data askedge' command to clean up the read");
return 0;
}
} else if (start < 0) return 0;
start = skip;
snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47);
// get rid of leading crap
snprintf(tmp, sizeof(tmp), "%i", skip);
CmdLtrim(tmp);
bool pTest;
bool AllPTest = true;
// now work through remaining buffer printing out data blocks
block = 0;
i = startblock;
while (block < 6) {
if (verbose || g_debugMode) PrintAndLog("\nBlock %i:", block);
skip = phaseoff;
// look for LW before start of next block
for ( ; i < j - 4 ; ++i) {
skip += tmpbuff[i];
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
if (tmpbuff[i+1] >= clk-tol)
break;
}
if (i >= j-4) break; //next LW not found
skip += clk;
if (tmpbuff[i+1]>clk)
phaseoff = tmpbuff[i+1]-clk;
else
phaseoff = 0;
i += 2;
if (ASKDemod(tmp2, false, false, 1) < 1) {
save_restoreGB(0);
return 0;
}
//set DemodBufferLen to just one block
DemodBufferLen = skip/clk;
//test parities
pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen,5,9,0);
pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0);
AllPTest &= pTest;
//get output
Code[block] = OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest);
if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d", skip, skip/clk);
//skip to start of next block
snprintf(tmp,sizeof(tmp),"%i",skip);
CmdLtrim(tmp);
block++;
if (i >= end) break; //in case chip doesn't output 6 blocks
}
//print full code:
if (verbose || g_debugMode || AllPTest){
if (!complete) {
PrintAndLog("*** Warning!");
PrintAndLog("Partial data - no end found!");
PrintAndLog("Try again with more samples.");
}
PrintAndLog("Found data at sample: %i - using clock: %i", start, clk);
end = block;
for (block=0; block < end; block++){
PrintAndLog("Block %d: %08x",block,Code[block]);
}
if (AllPTest) {
PrintAndLog("Parities Passed");
} else {
PrintAndLog("Parities Failed");
PrintAndLog("Try cleaning the read samples with 'data askedge'");
}
}
//restore GraphBuffer
save_restoreGB(0);
return (int)AllPTest;
}
int CmdEM4x50Read(const char *Cmd)
{
return EM4x50Read(Cmd, true);
}
int CmdReadWord(const char *Cmd)
{
int Word = -1; //default to invalid word
UsbCommand c;
sscanf(Cmd, "%d", &Word);
UsbCommand c;
sscanf(Cmd, "%d", &Word);
if ( (Word > 15) | (Word < 0) ) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Reading word %d", Word);
c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = 0;
c.arg[1] = Word;
c.arg[2] = 0;
SendCommand(&c);
return 0;
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Reading word %d", Word);
c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = 0;
c.arg[1] = Word;
c.arg[2] = 0;
SendCommand(&c);
return 0;
}
int CmdReadWordPWD(const char *Cmd)
{
int Word = -1; //default to invalid word
int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c;
sscanf(Cmd, "%d %x", &Word, &Password);
int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c;
sscanf(Cmd, "%d %x", &Word, &Password);
if ( (Word > 15) | (Word < 0) ) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Reading word %d with password %08X", Word, Password);
c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = 0;
c.arg[1] = Word;
c.arg[2] = Password;
SendCommand(&c);
return 0;
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Reading word %d with password %08X", Word, Password);
c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = 0;
c.arg[1] = Word;
c.arg[2] = Password;
SendCommand(&c);
return 0;
}
int CmdWriteWord(const char *Cmd)
{
int Word = 16; //default to invalid block
int Data = 0xFFFFFFFF; //default to blank data
UsbCommand c;
sscanf(Cmd, "%x %d", &Data, &Word);
if (Word > 15) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Writing word %d with data %08X", Word, Data);
c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = Data;
c.arg[1] = Word;
c.arg[2] = 0;
SendCommand(&c);
return 0;
int Word = 16; //default to invalid block
int Data = 0xFFFFFFFF; //default to blank data
UsbCommand c;
sscanf(Cmd, "%x %d", &Data, &Word);
if (Word > 15) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Writing word %d with data %08X", Word, Data);
c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = Data;
c.arg[1] = Word;
c.arg[2] = 0;
SendCommand(&c);
return 0;
}
int CmdWriteWordPWD(const char *Cmd)
{
int Word = 16; //default to invalid word
int Data = 0xFFFFFFFF; //default to blank data
int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c;
sscanf(Cmd, "%x %d %x", &Data, &Word, &Password);
if (Word > 15) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password);
c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = Data;
c.arg[1] = Word;
c.arg[2] = Password;
SendCommand(&c);
return 0;
int Word = 16; //default to invalid word
int Data = 0xFFFFFFFF; //default to blank data
int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c;
sscanf(Cmd, "%x %d %x", &Data, &Word, &Password);
if (Word > 15) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password);
c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = Data;
c.arg[1] = Word;
c.arg[2] = Password;
SendCommand(&c);
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
{NULL, NULL, 0, NULL}
{"help", CmdHelp, 1, "This help"},
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
{"em410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
{NULL, NULL, 0, NULL}
};
int CmdLFEM4X(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);
return 0;
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
CmdsHelp(CommandTable);
return 0;
}

View file

@ -11,7 +11,6 @@
#ifndef CMDLFEM4X_H__
#define CMDLFEM4X_H__
int CmdLFEM4X(const char *Cmd);
int CmdEMdemodASK(const char *Cmd);
int CmdEM410xRead(const char *Cmd);
int CmdEM410xSim(const char *Cmd);
@ -19,9 +18,11 @@ int CmdEM410xWatch(const char *Cmd);
int CmdEM410xWatchnSpoof(const char *Cmd);
int CmdEM410xWrite(const char *Cmd);
int CmdEM4x50Read(const char *Cmd);
int CmdLFEM4X(const char *Cmd);
int CmdReadWord(const char *Cmd);
int CmdReadWordPWD(const char *Cmd);
int CmdWriteWord(const char *Cmd);
int CmdWriteWordPWD(const char *Cmd);
int EM4x50Read(const char *Cmd, bool verbose);
#endif

View file

@ -17,7 +17,7 @@
#include "cmdlfhid.h"
static int CmdHelp(const char *Cmd);
/*
int CmdHIDDemod(const char *Cmd)
{
if (GraphTraceLen < 4800) {
@ -36,7 +36,7 @@ int CmdHIDDemod(const char *Cmd)
RepaintGraphWindow();
return 0;
}
*/
int CmdHIDDemodFSK(const char *Cmd)
{
int findone=0;
@ -106,7 +106,7 @@ int CmdHIDClone(const char *Cmd)
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"},
//{"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"},
{"fskdemod", CmdHIDDemodFSK, 0, "['1'] Realtime HID FSK demodulator (option '1' for one tag only)"},
{"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
{"clone", CmdHIDClone, 0, "<ID> ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"},

View file

@ -12,9 +12,9 @@
#define CMDLFHID_H__
int CmdLFHID(const char *Cmd);
int CmdHIDDemod(const char *Cmd);
//int CmdHIDDemod(const char *Cmd);
int CmdHIDDemodFSK(const char *Cmd);
int CmdHIDSim(const char *Cmd);
int CmdHIDClone(const char *Cmd);
#endif

View file

@ -24,7 +24,7 @@ int CmdIODemodFSK(const char *Cmd)
SendCommand(&c);
return 0;
}
/*
int CmdIOProxDemod(const char *Cmd){
if (GraphTraceLen < 4800) {
PrintAndLog("too short; need at least 4800 samples");
@ -37,7 +37,7 @@ int CmdIOProxDemod(const char *Cmd){
RepaintGraphWindow();
return 0;
}
*/
int CmdIOClone(const char *Cmd)
{
unsigned int hi = 0, lo = 0;
@ -67,7 +67,7 @@ int CmdIOClone(const char *Cmd)
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
//{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
{"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
{"clone", CmdIOClone, 0, "Clone ioProx Tag"},
{NULL, NULL, 0, NULL}
@ -83,4 +83,4 @@ int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}
}

View file

@ -10,6 +10,7 @@
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <time.h>
#include "proxmark3.h"
#include "ui.h"
#include "graph.h"
@ -147,31 +148,37 @@ int CmdT55xxSetConfig(const char *Cmd) {
param_getstr(Cmd, cmdp+1, modulation);
cmdp += 2;
if ( strcmp(modulation, "FSK" ) == 0)
if ( strcmp(modulation, "FSK" ) == 0) {
config.modulation = DEMOD_FSK;
else if ( strcmp(modulation, "FSK1" ) == 0)
} else if ( strcmp(modulation, "FSK1" ) == 0) {
config.modulation = DEMOD_FSK1;
else if ( strcmp(modulation, "FSK1a" ) == 0)
config.inverted=1;
} else if ( strcmp(modulation, "FSK1a" ) == 0) {
config.modulation = DEMOD_FSK1a;
else if ( strcmp(modulation, "FSK2" ) == 0)
config.inverted=0;
} else if ( strcmp(modulation, "FSK2" ) == 0) {
config.modulation = DEMOD_FSK2;
else if ( strcmp(modulation, "FSK2a" ) == 0)
config.inverted=0;
} else if ( strcmp(modulation, "FSK2a" ) == 0) {
config.modulation = DEMOD_FSK2a;
else if ( strcmp(modulation, "ASK" ) == 0)
config.inverted=1;
} else if ( strcmp(modulation, "ASK" ) == 0) {
config.modulation = DEMOD_ASK;
else if ( strcmp(modulation, "NRZ" ) == 0)
} else if ( strcmp(modulation, "NRZ" ) == 0) {
config.modulation = DEMOD_NRZ;
else if ( strcmp(modulation, "PSK1" ) == 0)
} else if ( strcmp(modulation, "PSK1" ) == 0) {
config.modulation = DEMOD_PSK1;
else if ( strcmp(modulation, "PSK2" ) == 0)
} else if ( strcmp(modulation, "PSK2" ) == 0) {
config.modulation = DEMOD_PSK2;
else if ( strcmp(modulation, "PSK3" ) == 0)
} else if ( strcmp(modulation, "PSK3" ) == 0) {
config.modulation = DEMOD_PSK3;
else if ( strcmp(modulation, "BIa" ) == 0)
} else if ( strcmp(modulation, "BIa" ) == 0) {
config.modulation = DEMOD_BIa;
else if ( strcmp(modulation, "BI" ) == 0)
config.inverted=1;
} else if ( strcmp(modulation, "BI" ) == 0) {
config.modulation = DEMOD_BI;
else {
config.inverted=0;
} else {
PrintAndLog("Unknown modulation '%s'", modulation);
errors = TRUE;
}
@ -255,77 +262,51 @@ int CmdT55xxReadBlock(const char *Cmd) {
bool DecodeT55xxBlock(){
char buf[8] = {0x00};
char buf[30] = {0x00};
char *cmdStr = buf;
int ans = 0;
uint8_t bitRate[8] = {8,16,32,40,50,64,100,128};
DemodBufferLen = 0x00;
//trim 1/2 a clock from beginning
snprintf(cmdStr, sizeof(buf),"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
switch( config.modulation ){
case DEMOD_FSK:
//CmdLtrim("26");
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d %d", bitRate[config.bitrate], config.inverted );
snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted );
ans = FSKrawDemod(cmdStr, FALSE);
break;
case DEMOD_FSK1:
//CmdLtrim("26");
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 1 8 5", bitRate[config.bitrate] );
ans = FSKrawDemod(cmdStr, FALSE);
break;
case DEMOD_FSK1a:
//CmdLtrim("26");
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 0 8 5", bitRate[config.bitrate] );
snprintf(cmdStr, sizeof(buf),"%d %d 8 5", bitRate[config.bitrate], config.inverted );
ans = FSKrawDemod(cmdStr, FALSE);
break;
case DEMOD_FSK2:
//CmdLtrim("26");
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 0 10 8", bitRate[config.bitrate] );
ans = FSKrawDemod(cmdStr, FALSE);
break;
case DEMOD_FSK2a:
//CmdLtrim("26");
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
CmdLtrim(cmdStr);
sprintf(cmdStr,"%d 1 10 8", bitRate[config.bitrate] );
snprintf(cmdStr, sizeof(buf),"%d %d 10 8", bitRate[config.bitrate], config.inverted );
ans = FSKrawDemod(cmdStr, FALSE);
break;
case DEMOD_ASK:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
ans = ASKmanDemod(cmdStr, FALSE, FALSE);
snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted );
ans = ASKDemod(cmdStr, FALSE, FALSE, 1);
break;
case DEMOD_PSK1:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted );
ans = PSKDemod(cmdStr, FALSE);
break;
case DEMOD_PSK2:
sprintf(cmdStr,"%d 1", bitRate[config.bitrate] );
ans = PSKDemod(cmdStr, FALSE);
psk1TOpsk2(DemodBuffer, DemodBufferLen);
break;
case DEMOD_PSK3:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
case DEMOD_PSK2: //inverted won't affect this
case DEMOD_PSK3: //not fully implemented
snprintf(cmdStr, sizeof(buf),"%d 0 1", bitRate[config.bitrate] );
ans = PSKDemod(cmdStr, FALSE);
psk1TOpsk2(DemodBuffer, DemodBufferLen);
break;
case DEMOD_NRZ:
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted );
ans = NRZrawDemod(cmdStr, FALSE);
break;
case DEMOD_BI:
sprintf(cmdStr,"0 %d 0 1", bitRate[config.bitrate] );
ans = ASKbiphaseDemod(cmdStr, FALSE);
break;
case DEMOD_BIa:
sprintf(cmdStr,"0 %d 1 1", bitRate[config.bitrate] );
snprintf(cmdStr, sizeof(buf),"0 %d %d 0", bitRate[config.bitrate], config.inverted );
ans = ASKbiphaseDemod(cmdStr, FALSE);
break;
default:
@ -354,114 +335,141 @@ bool tryDetectModulation(){
char cmdStr[8] = {0};
uint8_t hits = 0;
t55xx_conf_block_t tests[15];
int bitRate=0;
uint8_t fc1 = 0, fc2 = 0, clk=0;
save_restoreGB(1);
if (GetFskClock("", FALSE, FALSE)){
uint8_t fc1 = 0, fc2 = 0, clk=0;
fskClocks(&fc1, &fc2, &clk, FALSE);
sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr);
if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset)){
if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)){
tests[hits].modulation = DEMOD_FSK;
if (fc1==8 && fc2 == 5)
tests[hits].modulation = DEMOD_FSK1a;
else if (fc1==10 && fc2 == 8)
tests[hits].modulation = DEMOD_FSK2;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset)) {
if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_FSK;
if (fc1==8 && fc2 == 5)
if (fc1 == 8 && fc2 == 5)
tests[hits].modulation = DEMOD_FSK1;
else if (fc1==10 && fc2 == 8)
else if (fc1 == 10 && fc2 == 8)
tests[hits].modulation = DEMOD_FSK2a;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
} else {
if ( ASKmanDemod("0 0 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_ASK;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( ASKmanDemod("0 1 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_ASK;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
// PSK2 - needs a call to psk1TOpsk2.
if ( PSKDemod("0 0 1", FALSE)) {
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (test(DEMOD_PSK2, &tests[hits].offset)){
tests[hits].modulation = DEMOD_PSK2;
clk = GetAskClock("", FALSE, FALSE);
if (clk>0) {
sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr);
if ( ASKDemod("0 0 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_ASK;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
} // inverse waves does not affect this demod
// PSK3 - needs a call to psk1TOpsk2.
if ( PSKDemod("0 0 1", FALSE)) {
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (test(DEMOD_PSK3, &tests[hits].offset)){
tests[hits].modulation = DEMOD_PSK3;
if ( ASKDemod("0 1 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_ASK;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( ASKbiphaseDemod("0 0 0 0", FALSE) && test(DEMOD_BI, &tests[hits].offset, &bitRate) ) {
tests[hits].modulation = DEMOD_BI;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
} // inverse waves does not affect this demod
if ( ASKbiphaseDemod("0 0 0 1", FALSE) && test(DEMOD_BI, &tests[hits].offset) ) {
tests[hits].modulation = DEMOD_BI;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
if ( ASKbiphaseDemod("0 0 1 0", FALSE) && test(DEMOD_BIa, &tests[hits].offset, &bitRate) ) {
tests[hits].modulation = DEMOD_BIa;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
}
if ( ASKbiphaseDemod("0 0 1 1", FALSE) && test(DEMOD_BIa, &tests[hits].offset) ) {
tests[hits].modulation = DEMOD_BIa;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
//undo trim from ask
save_restoreGB(0);
clk = GetNrzClock("", FALSE, FALSE);
if (clk>0) {
sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr);
if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_NRZ;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
}
//undo trim from nrz
save_restoreGB(0);
clk = GetPskClock("", FALSE, FALSE);
if (clk>0) {
PrintAndLog("clk %d",clk);
sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr);
if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) {
tests[hits].modulation = DEMOD_PSK1;
tests[hits].bitrate = bitRate;
tests[hits].inverted = TRUE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
// PSK2 - needs a call to psk1TOpsk2.
if ( PSKDemod("0 0 1", FALSE)) {
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (test(DEMOD_PSK2, &tests[hits].offset, &bitRate)){
tests[hits].modulation = DEMOD_PSK2;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
} // inverse waves does not affect this demod
// PSK3 - needs a call to psk1TOpsk2.
if ( PSKDemod("0 0 1", FALSE)) {
psk1TOpsk2(DemodBuffer, DemodBufferLen);
if (test(DEMOD_PSK3, &tests[hits].offset, &bitRate)){
tests[hits].modulation = DEMOD_PSK3;
tests[hits].bitrate = bitRate;
tests[hits].inverted = FALSE;
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
++hits;
}
} // inverse waves does not affect this demod
}
}
if ( hits == 1) {
config.modulation = tests[0].modulation;
config.bitrate = tests[0].bitrate;
config.inverted = tests[0].inverted;
config.offset = tests[0].offset;
config.block0 = tests[0].block0;
@ -516,81 +524,32 @@ bool testBitRate(uint8_t readRate, uint8_t mod){
uint8_t detRate = 0;
switch( mod ){
case DEMOD_FSK:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK1:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK1a:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK2:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_FSK2a:
detRate = GetFskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
if (expected[readRate] == detRate)
return TRUE;
}
break;
case DEMOD_ASK:
case DEMOD_BI:
case DEMOD_BIa:
detRate = GetAskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
if (expected[readRate] == detRate)
return TRUE;
}
break;
case DEMOD_PSK1:
detRate = GetPskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_PSK2:
detRate = GetPskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
case DEMOD_PSK3:
detRate = GetPskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
if (expected[readRate] == detRate)
return TRUE;
}
break;
case DEMOD_NRZ:
detRate = GetNrzClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
if (expected[readRate] == detRate)
return TRUE;
}
break;
case DEMOD_BI:
detRate = GetAskClock("",FALSE, FALSE);
if (expected[readRate] == detRate) {
config.bitrate = readRate;
return TRUE;
}
break;
default:
return FALSE;
@ -598,26 +557,27 @@ bool testBitRate(uint8_t readRate, uint8_t mod){
return FALSE;
}
bool test(uint8_t mode, uint8_t *offset){
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate){
if ( !DemodBufferLen) return FALSE;
if ( DemodBufferLen < 64 ) return FALSE;
uint8_t si = 0;
for (uint8_t idx = 0; idx < 64; idx++){
si = idx;
if ( PackBits(si, 32, DemodBuffer) == 0x00 ) continue;
uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key
uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key
uint8_t resv = PackBits(si, 4, DemodBuffer); 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;
uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //new
uint8_t bitRate = PackBits(si, 3, DemodBuffer); si += 3; //new could check bit rate
uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //extended mode part of rate
int bitRate = PackBits(si, 3, DemodBuffer); si += 3; //bit rate
if (bitRate > 7) continue;
uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode
uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; //new
//uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //new could check psk cr
uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24 , 30, 31 could be tested for 0 if not extended mode
uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1;
//uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr
uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode
uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2;
//if extended mode
@ -628,15 +588,15 @@ bool test(uint8_t mode, uint8_t *offset){
}
//test modulation
if (!testModulation(mode, modread)) continue;
*offset = idx;
if (!testBitRate(bitRate, mode)) continue;
*fndBitRate = bitRate;
*offset = idx;
return TRUE;
}
return FALSE;
}
void printT55xxBlock(const char *demodStr){
void printT55xxBlock(const char *blockNum){
uint8_t i = config.offset;
uint8_t endpos = 32 + i;
@ -654,7 +614,7 @@ void printT55xxBlock(const char *demodStr){
bits[i - config.offset]=DemodBuffer[i];
blockData = PackBits(0, 32, bits);
PrintAndLog("0x%08X %s [%s]", blockData, sprint_bin(bits,32), demodStr);
PrintAndLog("[%s] 0x%08X %s", blockNum, blockData, sprint_bin(bits,32));
}
int special(const char *Cmd) {
@ -746,16 +706,28 @@ int CmdT55xxReadTrace(const char *Cmd)
uint32_t bl0 = PackBits(si, 32, DemodBuffer);
uint32_t bl1 = PackBits(si+32, 32, DemodBuffer);
uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8;
uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8;
uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5;
uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3;
uint32_t year = PackBits(si, 4, DemodBuffer); si += 4;
uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2;
uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14;
uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5;
uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8;
uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8;
uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5;
uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3;
uint32_t year = PackBits(si, 4, DemodBuffer); si += 4;
uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2;
uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14;
uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5;
uint32_t dw = PackBits(si, 15, DemodBuffer);
time_t t = time(NULL);
struct tm tm = *localtime(&t);
if ( year > tm.tm_year-110)
year += 2000;
else
year += 2010;
if ( acl != 0xE0 ) {
PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");
return 1;
}
PrintAndLog("");
PrintAndLog("-- T55xx Trace Information ----------------------------------");
PrintAndLog("-------------------------------------------------------------");
@ -764,7 +736,7 @@ int CmdT55xxReadTrace(const char *Cmd)
PrintAndLog(" CID : 0x%02X (%d) - %s", cid, cid, GetModelStrFromCID(cid));
PrintAndLog(" ICR IC Revision : %d",icr );
PrintAndLog(" Manufactured");
PrintAndLog(" Year/Quarter : 20?%d/%d",year, quarter);
PrintAndLog(" Year/Quarter : %d/%d",year, quarter);
PrintAndLog(" Lot ID : %d", lotid );
PrintAndLog(" Wafer number : %d", wafer);
PrintAndLog(" Die Number : %d", dw);
@ -774,8 +746,6 @@ int CmdT55xxReadTrace(const char *Cmd)
PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat+32,32) );
PrintAndLog("-------------------------------------------------------------");
if ( acl != 0xE0 )
PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");
/*
TRACE - BLOCK O
Bits Definition HEX
@ -809,10 +779,10 @@ int CmdT55xxInfo(const char *Cmd){
if (strlen(Cmd)==0)
AquireData( CONFIGURATION_BLOCK );
if (!DecodeT55xxBlock()) return 1;
if ( !DemodBufferLen) return 1;
if ( DemodBufferLen < 32) return 1;
uint8_t si = config.offset;
uint32_t bl0 = PackBits(si, 32, DemodBuffer);
@ -922,7 +892,8 @@ int AquireData( uint8_t block ){
}
char * GetBitRateStr(uint32_t id){
static char buf[40];
static char buf[25];
char *retStr = buf;
switch (id){
case 0:
@ -957,7 +928,6 @@ char * GetBitRateStr(uint32_t id){
return buf;
}
char * GetSaferStr(uint32_t id){
static char buf[40];
char *retStr = buf;
@ -974,7 +944,7 @@ char * GetSaferStr(uint32_t id){
}
char * GetModulationStr( uint32_t id){
static char buf[40];
static char buf[60];
char *retStr = buf;
switch (id){
@ -1003,7 +973,7 @@ char * GetModulationStr( uint32_t id){
snprintf(retStr,sizeof(buf),"%d - FSK 2a RF/10 RF/8",id);
break;
case 8:
snprintf(retStr,sizeof(buf),"%d - Manschester",id);
snprintf(retStr,sizeof(buf),"%d - Manchester",id);
break;
case 16:
snprintf(retStr,sizeof(buf),"%d - Biphase",id);
@ -1026,8 +996,8 @@ char * GetModelStrFromCID(uint32_t cid){
static char buf[10];
char *retStr = buf;
if (cid == 1) sprintf(retStr,"ATA5577M1");
if (cid == 2) sprintf(retStr,"ATA5577M2");
if (cid == 1) snprintf(retStr, sizeof(buf),"ATA5577M1");
if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2");
return buf;
}

View file

@ -53,13 +53,13 @@ char * GetSaferStr(uint32_t id);
char * GetModulationStr( uint32_t id);
char * GetModelStrFromCID(uint32_t cid);
char * GetSelectedModulationStr( uint8_t id);
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bitstream);
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream);
void printT55xxBlock(const char *demodStr);
void printConfiguration( t55xx_conf_block_t b);
bool DecodeT55xxBlock();
bool tryDetectModulation();
bool test(uint8_t mode, uint8_t *offset);
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate);
int special(const char *Cmd);
int AquireData( uint8_t block );

View file

@ -17,7 +17,6 @@
int GraphBuffer[MAX_GRAPH_TRACE_LEN];
int GraphTraceLen;
/* write a manchester bit to the graph */
void AppendGraph(int redraw, int clock, int bit)
{
@ -46,6 +45,24 @@ int ClearGraph(int redraw)
return gtl;
}
// option '1' to save GraphBuffer any other to restore
void save_restoreGB(uint8_t saveOpt)
{
static int SavedGB[MAX_GRAPH_TRACE_LEN];
static int SavedGBlen;
static bool GB_Saved = false;
if (saveOpt==1) { //save
memcpy(SavedGB, GraphBuffer, sizeof(GraphBuffer));
SavedGBlen = GraphTraceLen;
GB_Saved=true;
} else if (GB_Saved){ //restore
memcpy(GraphBuffer, SavedGB, sizeof(GraphBuffer));
GraphTraceLen = SavedGBlen;
RepaintGraphWindow();
}
return;
}
// DETECT CLOCK NOW IN LFDEMOD.C
@ -126,10 +143,10 @@ int GetAskClock(const char str[], bool printAns, bool verbose)
PrintAndLog("Failed to copy from graphbuffer");
return -1;
}
DetectASKClock(grph, size, &clock, 20);
int start = DetectASKClock(grph, size, &clock, 20);
// Only print this message if we're not looping something
if (printAns){
PrintAndLog("Auto-detected clock rate: %d", clock);
PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start);
}
return clock;
}

View file

@ -23,6 +23,7 @@ uint8_t GetNrzClock(const char str[], bool printAns, bool verbose);
uint8_t GetFskClock(const char str[], bool printAns, bool verbose);
uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose);
void setGraphBuf(uint8_t *buff, size_t size);
void save_restoreGB(uint8_t saveOpt);
bool HasGraphData();
void DetectHighLowInGraph(int *high, int *low, bool addFuzz);

View file

@ -138,6 +138,8 @@ local _commands = {
CMD_MIFAREUC_AUTH1 = 0x0724,
CMD_MIFAREUC_AUTH2 = 0x0725,
CMD_MIFAREUC_READCARD = 0x0726,
CMD_MIFAREUC_SETPWD = 0x0727,
CMD_MIFAREU_SETUID = 0x0728,
--// mifare desfire
CMD_MIFARE_DESFIRE_READBL = 0x0728,
@ -153,10 +155,10 @@ local _commands = {
local _reverse_lookup,k,v = {}
for k, v in pairs(_commands) do
_reverse_lookup[v] = k
end
_commands.tostring = function(command)
for k, v in pairs(_commands) do
_reverse_lookup[v] = k
end
_commands.tostring = function(command)
if(type(command) == 'number') then
return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
end
@ -217,7 +219,6 @@ function Command:getBytes()
local data = self.data
local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data);
end
return _commands

View file

@ -1,196 +1,333 @@
local _names = {
--[[
--[[ decimal, hexadecimal, ccc, elements, group, name
--]]
["0000"]="WHIRLWIND",
["0100"]="SONIC BOOM",
["0200"]="WARNADO",
["0300"]="LIGHTNINGROD",
["0400"]="BASH",
["0500"]="TERRAFIN",
["0600"]="DINORANG" ,
["0700"]="LIGHTCORE PRISM BREAK",
["0800"]="SUNBURN",
["0900"]="LIGHTCORE ERUPTOR",
["0A00"]="IGNITOR",
["0B00"]="FLAMESLINGER",
["0C00"]="ZAP",
["0D00"]="WHAM SHELL",
["0E00"]="GILL GRUNT",
["0F00"]="SLAMBAM",
["1000"]="SPYRO",
["1100"]="VOODOOD",
["1200"]="DOUBLE TROUBLE",
["1300"]="TRIGGER HAPPY",
["1400"]="DROBOT",
["1500"]="DRILLSERGEANT",
["1600"]="BOOMER",
["1700"]="WRECKING BALL",
["1800"]="CAMO",
["1900"]="ZOOK",
["1A00"]="STEALTH ELF",
["1B00"]="STUMP SMASH",
["1D00"]="HEX",
["1C00"]="DARK SPYRO",
["1E00"]="CHOPCHOP",
["1F00"]="GHOST ROASTER",
["2000"]="CYNDER",
--[[
GIANTS
--]]
["6400"]="GIANT JET-VAC",
["6500"]="GIANT SWARM",
["6600"]="GIANT CRUSHER",
["6700"]="GIANT FLASHWING",
["6800"]="GIANT HOTHEAD",
["6900"]="GIANT HOTDOG",
["6A00"]="GIANT CHILL",
["6B00"]="GIANT THUMPBACK",
["6C00"]="GIANT POPFIZZ",
["6D00"]="GIANT NINJINI",
["6E00"]="GIANT BOUNCER",
["6F00"]="GIANT SPROCKET",
["7000"]="GIANT TREE REX",
["7100"]="LIGHTCORE SHROOMBOOM",
["7200"]="GIANT EYEBROAWL",
["7300"]="GIANT FRIGHTRIDER",
{"0", "0000", "0030", "air", "regular", "Whirlwind"},
--{"0", "0000", "0030", "air", "regular", "Elite Whirlwind"},
--{"0", "0000", "0030", "air", "regular", "Polar Whirlwind"},
{"1", "0100", "0030", "air", "regular", "Sonic Boom"},
{"2", "0200", "0030", "air", "regular", "Warnado"},
{"3", "0300", "0030", "air", "regular", "Lightning Rod"},
{"4", "0400", "0030", "earth", "regular", "Bash"},
--{"4", "0400", "0030", "earth", "regular", "Birthday Bash"},
{"5", "0500", "0030", "earth", "regular", "Terrafin"},
--{"5", "0500", "0030", "earth", "regular", "Elite Terrafin"},
{"6", "0600", "0030", "earth", "regular", "Dino Rang"},
{"7", "0700", "0030", "earth", "regular", "Prism Break"}, --lightcore
{"8", "0800", "0030", "fire", "regular", "Sunburn"},
{"9", "0900", "0030", "fire", "regular", "Eruptor"}, --lightcore
--{"9", "0900", "0030", "fire", "regular", "Elite Eruptor"},
--{"9", "0900", "0030", "fire", "regular", "Volcanic Eruptor"},
{"10", "0a00", "0030", "fire", "regular", "Ignitor"},
{"11", "0b00", "0030", "fire", "regular", "Flameslinger"},
--{"11", "0b00", "0030", "fire", "regular", "Cupid Flameslinger"},
{"12", "0c00", "0030", "water", "regular", "Zap"},
{"13", "0d00", "0030", "water", "regular", "Wham Shell"},
{"14", "0e00", "0030", "water", "regular", "Gill Grunt"},
--{"14", "0e00", "0030", "water", "regular", "Elite Gill Grunt"},
{"15", "0f00", "0030", "water", "regular", "Slam Bam"},
--{"15", "0f00", "0030", "water", "regular", "Surfer Slam Bam"},
{"16", "1000", "0030", "magic", "regular", "Spyro"},
{"17", "1100", "0030", "magic", "regular", "Voodood"},
{"18", "1200", "0030", "magic", "regular", "Double Trouble"},
--{"18", "1200", "0030", "magic", "regular", "Royal Double Trouble"},
{"19", "1300", "0030", "tech", "regular", "Trigger Happy"},
--{"19", "1300", "0030", "tech", "regular", "Elite Trigger Happy"},
--{"19", "1300", "0030", "tech", "regular", "Springtime Trigger Happy"},
{"20", "1400", "0030", "tech", "regular", "Drobot"},
{"21", "1500", "0030", "tech", "regular", "Drill Sergeant"},
{"22", "1600", "0030", "tech", "regular", "Boomer"},
--{"22", "1600", "0030", "tech", "regular", "Lucky Boomer"},
{"23", "1700", "0030", "magic", "regular", "Wrecking Ball"},
--{"23", "1700", "0030", "magic", "regular", "Buddy Wrecking Ball"},
{"24", "1800", "0030", "life", "regular", "Camo"},
{"25", "1900", "0030", "life", "regular", "Zook"},
{"26", "1a00", "0030", "life", "regular", "Stealth Elf"},
--{"26", "1a00", "0030", "life", "regular", "Elite Stealth Elf"},
--{"26", "1a00", "0030", "life", "regular", "Dark Stealth Elf"},
{"27", "1b00", "0030", "life", "regular", "Stump Smash"},
{"27", "1b00", "0118", "life", "regular", "Stump Smash"},
--{"27", "1b00", "0030", "life", "regular", "Autumn Stump Smash"},
{"28", "1c00", "0030", "magic", "regular", "Dark Spyro"},
--{"28", "1c00", "0030", "magic", "regular", "Elite Spyro"},
{"29", "1d00", "0030", "undead", "regular", "Hex"},
--{"29", "1d00", "0030", "undead", "regular", "Hallows' Eve Hex"},
{"30", "1e00", "0030", "undead", "regular", "Chop Chop"},
--{"30", "1e00", "0030", "undead", "regular", "Elite Chop Chop"},
--{"30", "1e00", "0030", "undead", "regular", "Grill Master Chop Chop"},
{"31", "1f00", "0030", "undead", "regular", "Ghost Roaster"},
{"32", "2000", "0030", "undead", "regular", "Cynder"},
--{"32", "2000", "0030", "undead", "regular", "Skeletal Cynder"},
--[[
ITEM
--]]
["C800"]="ANVIL",
["C900"]="SECRET STASH",
["CA00"]="REGENERATION",
["CD00"]="SHIELD",
["CB00"]="CROSSED SWORDS",
["CC00"]="HOURGLASS",
["CE00"]="SPEED BOOTS",
["CF00"]="SPARX",
["D000"]="CANNON",
["D100"]="SCORPIONSTRIKER",
{"100", "6400", "0030", "air", "giant", "Jet Vac"},
{"101", "6500", "0030", "air", "giant", "Swarm"},
{"102", "6600", "0030", "earth", "giant", "Crusher"},
{"103", "6700", "0030", "earth", "giant", "Flashwing"},
--{"103", "6700", "0030", "earth", "giant", "Jade Flashwing"},
{"104", "6800", "0030", "fire", "giant", "Hot Head"},
{"105", "6900", "0030", "fire", "giant", "Hot Dog"},
--{"105", "6900", "0030", "fire", "giant", "Molten Hot Dog"},
{"106", "6a00", "0030", "water", "giant", "Chill"},
{"107", "6b00", "0030", "water", "giant", "Thumpback"},
--{"107", "6b00", "0030", "water", "giant", "Admiral Thumpback"},
{"108", "6c00", "0030", "magic", "giant", "Pop Fizz"},
--{"108", "6c00", "0030", "magic", "giant", "Hoppity Pop Fizz"},
{"108", "6c00", "023c", "magic", "giant", "Love Potion Pop Fizz"},
--{"108", "6c00", "0030", "magic", "giant", "Punch Pop Fizz"},
{"109", "6d00", "0030", "magic", "giant", "Nin Jini"},
{"110", "6e00", "0030", "tech", "giant", "Bouncer"},
{"111", "6f00", "0030", "tech", "giant", "Sprocket"},
{"112", "7000", "0030", "life", "giant", "Tree Rex"},
--{"112", "7000", "0030", "life", "giant", "Gnarly Tree Rex"},
{"113", "7100", "0030", "life", "giant", "Shroomboom"}, --lightcore
{"114", "7200", "0030", "undead", "giant", "Eye Broawl"},
{"115", "7300", "0030", "undead", "giant", "Fright Rider"},
--[[
ITEM TRAPS
--]]
["D200"]="MAGIC TRAP",
["D300"]="WATER TRAP",
["D400"]="AIR TRAP",
["D500"]="UNDEAD TRAP",
["D600"]="TECH TRAP",
["D700"]="FIRE TRAP",
["D800"]="EARTH TRAP",
["D900"]="LIFE TRAP",
["DA00"]="DARK TRAP",
["DB00"]="LIGHT TRAP",
["DC00"]="KAOS TRAP",
{"200", "c800", "0030", "", "item", "Anvil Rain"},
{"201", "c900", "0030", "", "item", "Platinum Treasure Chest"},
{"202", "ca00", "0030", "", "item", "Healing Elixer"},
{"203", "cb00", "0030", "", "item", "Ghost Pirate Swords"},
{"204", "cc00", "0030", "", "item", "Time Twist Hourglass"},
{"205", "cd00", "0030", "", "item", "Sky Iron Shield"},
{"206", "ce00", "0030", "", "item", "Winged Boots"},
{"207", "cf00", "0030", "", "item", "Sparx"},
{"208", "d000", "0030", "", "item", "Cannon"},
{"209", "d100", "0030", "", "item", "Scorpion Striker"},
--[[
ITEM
--]]
["E600"]="HAND OF FATE",
["E700"]="PIGGYBANK",
["E800"]="ROCKET RAM",
["E900"]="TIKI SPEAKY",
{"210", "d200", "0230", "magic", "trap", "Biter's Bane"},
{"210", "d200", "0830", "magic", "trap", "Sorcerous Skull"},
-- legendary Sorcerous Skull?
{"210", "d200", "0b30", "magic", "trap", "Axe Of Illusion"},
{"210", "d200", "0e30", "magic", "trap", "Arcane Hourglass"},
{"210", "d200", "1230", "magic", "trap", "Spell Slapper"},
{"210", "d200", "1430", "magic", "trap", "Rune Rocket"},
{"211", "d300", "0130", "water", "trap", "Tidal Tiki"},
{"211", "d300", "0230", "water", "trap", "Wet Walter"},
{"211", "d300", "0630", "water", "trap", "Flood Flask"},
-- legendary flood flask?
{"211", "d300", "0730", "water", "trap", "Soaking Staff"},
{"211", "d300", "0b30", "water", "trap", "Aqua Axe"},
{"211", "d300", "1630", "water", "trap", "Frost Helm"},
{"212", "d400", "0330", "air", "trap", "Breezy Bird"},
{"212", "d400", "0630", "air", "trap", "Drafty Decanter"},
{"212", "d400", "0d30", "air", "trap", "Tempest Timer"},
{"212", "d400", "1030", "air", "trap", "Cloudy Cobra"},
{"212", "d400", "1130", "air", "trap", "Storm Warning"},
{"212", "d400", "1830", "air", "trap", "Cycone Saber"},
{"213", "d500", "0430", "undead", "trap", "Spirit Sphere"},
{"213", "d500", "0830", "undead", "trap", "Spectral Skull"},
{"213", "d500", "0b30", "undead", "trap", "Haunted Hatchet"},
{"213", "d500", "0c30", "undead", "trap", "Grim Gripper"},
{"213", "d500", "1030", "undead", "trap", "Spooky Snake"},
{"213", "d500", "1730", "undead", "trap", "Dream Piercer"},
{"214", "d600", "0030", "tech", "trap", "tech Totem"},
{"214", "d600", "0730", "tech", "trap", "Automatic Angel"},
{"214", "d600", "0930", "tech", "trap", "Factory Flower"},
{"214", "d600", "0c30", "tech", "trap", "Grabbing Gadget"},
{"214", "d600", "1630", "tech", "trap", "Makers Mana"},
{"214", "d600", "1a30", "tech", "trap", "Topsy techy"},
{"215", "d700", "0530", "fire", "trap", "Eternal Flame"},
{"215", "d700", "0930", "fire", "trap", "fire Flower"},
{"215", "d700", "1130", "fire", "trap", "Scorching Stopper"},
{"215", "d700", "1230", "fire", "trap", "Searing Spinner"},
{"215", "d700", "1730", "fire", "trap", "Spark Spear"},
{"215", "d700", "1b30", "fire", "trap", "Blazing Belch"},
{"216", "d800", "0030", "earth", "trap", "Banded Boulder"},
{"216", "d800", "0330", "earth", "trap", "Rock Hawk"},
{"216", "d800", "0a30", "earth", "trap", "Slag Hammer"},
{"216", "d800", "0e30", "earth", "trap", "Dust Of Time"},
{"216", "d800", "1330", "earth", "trap", "Spinning Sandstorm"},
{"216", "d800", "1a30", "earth", "trap", "Rubble Trouble"},
{"217", "d900", "0330", "life", "trap", "Oak Eagle"},
{"217", "d900", "0530", "life", "trap", "Emerald Energy"},
{"217", "d900", "0a30", "life", "trap", "Weed Whacker"},
{"217", "d900", "1030", "life", "trap", "Seed Serpent"},
{"217", "d900", "1830", "life", "trap", "Jade Blade"},
{"217", "d900", "1b30", "life", "trap", "Shrub Shrieker"},
{"218", "da00", "0030", "dark", "trap", "dark Dagger"},
{"218", "da00", "1430", "dark", "trap", "Shadow Spider"},
{"218", "da00", "1a30", "dark", "trap", "Ghastly Grimace"},
{"219", "db00", "0030", "light", "trap", "Shining Ship"},
{"219", "db00", "0f30", "light", "trap", "Heavenly Hawk"},
{"219", "db00", "1b30", "light", "trap", "Beam Scream"},
{"220", "dc00", "3030", "kaos", "trap", "Kaos trap!"},
--{"220", "dc00", "3130", "kaos", "trap", "Ultimate Kaos trap!"}, ?
--[[
EXPANSION
--]]
["012C"]="DRAGONS PEAK",
["012D"]="EMPIRE OF ICE",
["012E"]="PIRATE SEAS",
["012F"]="DARKLIGHT CRYPT",
["0130"]="VOLCANIC VAULT",
["0131"]="MIRROR OF MYSTERY",
["0132"]="NIGHTMARE EXPRESS",
["0133"]="SUNSCRAPER SPIRE",
["0134"]="MIDNIGHT MUSEUM",
{"230", "e600", "0030", "none", "item", "Hand Of Fate"},
{"231", "e700", "0030", "none", "item", "Piggy Bank"},
{"232", "e800", "0030", "none", "item", "Rocket Ram"},
{"233", "e900", "0030", "none", "item", "Tiki Speaky"},
{"300", "2c01", "0030", "none", "location", "Dragons Peak"},
{"301", "2d01", "0030", "none", "location", "Empire Of Ice"},
{"302", "2e01", "0030", "none", "location", "Pirate Seas"},
{"303", "2f01", "0030", "none", "location", "darklight Crypt"},
{"304", "3001", "0030", "none", "location", "Volcanic Vault"},
{"305", "3101", "0030", "none", "location", "Mirror Of Mystery"},
{"306", "3201", "0030", "none", "location", "Nightmare Express"},
{"307", "3301", "0030", "light", "location", "Sunscraper Spire"},
{"308", "3401", "0030", "dark", "location", "Midnight Museum"},
{"404", "9401", "0030", "earth", "legendary","Bash"},
{"416", "a001", "0030", "magic", "legendary", "Spyro"},
--{"", "", "0030", "magic", "legendary", "Deja Vu"},
{"419", "a301", "0030", "tech", "legendary", "Trigger Happy"},
--{"", "", "0030", "tech", "legendary", "bouncer"},
--{"", "", "0030", "tech", "legendary", "jawbreaker"},
{"430", "ae01", "0030", "undead", "legendary", "Chop Chop"},
--{"", "", "0030", "undead", "legendary", "grim creeper"},
--{"", "", "0030", "undead", "legendary", "night shift"},
--[[
LEGENDARY
--]]
["0194"]="LEGENDARY BASH",
["01A0"]="LEGENDARY SPYRO",
["01A3"]="LEGENDARY TRIGGER HAPPY",
["01AE"]="LEGENDARY CHOPCHOP",
--{"", "", "0030", "air", "legendary", "blades"},
--{"", "", "0030", "air", "legendary", "jet vac"},
--{"", "", "0030", "air", "legendary", "Free Ranger"},
--{"", "", "0030", "life", "legendary", "stealth elf"},
--{"", "", "0030", "life", "legendary", "Bushwhack"},
--{"", "", "0030", "fire", "legendary", "ignitor"},
--{"", "", "0030", "water", "legendary", "slam bam"},
--{"", "", "0030", "water", "legendary", "chill"},
--{"", "", "0030", "", "legendary", "zoo lou"},
--[[
TRAPTEAM
--]]
["01C2"]="TRAPTEAM GUSTO",
["01C3"]="TRAPTEAM THUNDERBOLT",
["01C4"]="TRAPTEAM FLING KONG",
["01C5"]="TRAPTEAM BLADES",
["01C6"]="TRAPTEAM WALLOP",
["01C7"]="TRAPTEAM HEAD RUSH",
["01C8"]="TRAPTEAM FIST BUMP",
["01C9"]="TRAPTEAM ROCKY ROLL",
["01CA"]="TRAPTEAM WILDFIRE",
["01CB"]="TRAPTEAM KA BOOM",
["01CC"]="TRAPTEAM TRAIL BLAZER",
["01CD"]="TRAPTEAM TORCH",
["01CE"]="TRAPTEAM SNAP SHOT",
["01CF"]="TRAPTEAM LOB STAR",
["01D0"]="TRAPTEAM FLIP WRECK",
["01D1"]="TRAPTEAM ECHO",
["01D2"]="TRAPTEAM BLASTERMIND",
["01D3"]="TRAPTEAM ENIGMA",
["01D4"]="TRAPTEAM DEJA VU",
["01D5"]="TRAPTEAM COBRA CADABRA",
["01D6"]="TRAPTEAM JAWBREAKER",
["01D7"]="TRAPTEAM GEARSHIFT",
["01D8"]="TRAPTEAM CHOPPER",
["01D9"]="TRAPTEAM TREAD HEAD",
["01DA"]="TRAPTEAM BUSHWHACK",
["01DB"]="TRAPTEAM TUFF LUCK",
["01DC"]="TRAPTEAM FOOD FIGHT",
["01DD"]="TRAPTEAM HIGH FIVE",
["01DE"]="TRAPTEAM NITRO KRYPT KING",
["01DF"]="TRAPTEAM SHORT CUT",
["01E0"]="TRAPTEAM BAT SPIN",
["01E1"]="TRAPTEAM FUNNY BONE",
["01E2"]="TRAPTEAM KNIGHT LIGHT",
["01E3"]="TRAPTEAM SPOTLIGHT",
["01E4"]="TRAPTEAM KNIGHT MARE",
["01E5"]="TRAPTEAM BLACKOUT",
{"450", "c201", "0030", "air", "trapmaster", "Gusto"},
--{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"},
{"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"},
--{"451", "c301", "0234", "air", "trapmaster", "Special Thunderbolt"},
{"452", "c401", "0030", "air", "regular", "Fling Kong"},
{"453", "c501", "0030", "air", "regular", "Blades"},
{"454", "c601", "0030", "earth", "trapmaster", "Wallop"},
--{"454", "c601", "0234", "earth", "trapmaster", "Special Wallop"},
{"455", "c701", "0030", "earth", "trapmaster", "Head Rush"},
{"455", "c701", "0234", "earth", "trapmaster", "Nitro Head Rush"},
{"456", "c801", "0030", "earth", "regular", "Fist Bump"},
{"457", "c901", "0030", "earth", "regular", "Rocky Roll"},
--{"457", "c901", "0030", "earth", "regular", "Rocky Egg Roll"},
{"458", "ca01", "0030", "fire", "trapmaster", "Wildfire"},
{"458", "ca01", "0234", "fire", "trapmaster", "Dark Wildfire"},
{"459", "cb01", "0030", "fire", "trapmaster", "Ka Boom"},
--{"459", "cb01", "0234", "fire", "trapmaster", "Special Ka Boom"},
{"460", "cc01", "0030", "fire", "regular", "Trail Blazer"},
{"461", "cd01", "0030", "fire", "regular", "Torch"},
{"462", "ce01", "0030", "water", "trapmaster", "Snap Shot"},
{"462", "ce01", "0234", "water", "trapmaster", "Dark Snap Shot"},
{"462", "6c00", "023c", "water", "trapmaster", "Instant Snap Shot"},
--, "water", "trapmaster", "Merry Snap Shot"},
{"463", "cf01", "0030", "water", "trapmaster", "Lob Star"},
{"463", "cf01", "0234", "water", "trapmaster", "Winterfest Lob Star"},
{"464", "d001", "0030", "water", "regular", "Flip Wreck"},
{"465", "d101", "0030", "water", "regular", "Echo"},
{"466", "d201", "0030", "magic", "trapmaster", "Blastermind"},
--{"466", "d201", "0234", "magic", "trapmaster", "Special Blastermind"},
{"467", "d301", "0030", "magic", "trapmaster", "Enigma"},
--{"467", "d301", "0234", "magic", "trapmaster", "Special Enigma"},
{"468", "d401", "0030", "magic", "regular", "Deja Vu"},
{"469", "d501", "0030", "magic", "regular", "Cobra Cadabra"},
--{"469", "d501", "0030", "magic", "regular", "Charming Cobra Cadabra"},
--{"469", "d501", "0030", "magic", "regular", "King Cobra Cadabra"},
{"470", "d601", "0030", "tech", "trapmaster", "Jawbreaker"},
--{"470", "d601", "0234", "tech", "trapmaster", "Special Jawbreaker"},
--{"470", "d601", "0234", "tech", "trapmaster", "Knockout Jawbreaker"},
{"471", "d701", "0030", "tech", "trapmaster", "Gearshift"},
--{"471", "d701", "0234", "tech", "trapmaster", "Special Gearshift"},
{"472", "d801", "0030", "tech", "regular", "Chopper"},
{"473", "d901", "0030", "tech", "regular", "Tread Head"},
{"474", "da01", "0030", "life", "trapmaster", "Bushwhack"},
--{"474", "da01", "0234", "life", "trapmaster", "Special Bushwhack"},
{"475", "db01", "0030", "life", "trapmaster", "Tuff Luck"},
--{"475", "db01", "0234", "life", "trapmaster", "Special Tuff Luck"},
{"476", "dc01", "0030", "life", "regular", "Food Fight"},
{"476", "dc01", "0612", "life", "regular", "LightCore Food Fight"},
--{"476", "dc01", "0030", "life", "regular", "Dark Food Fight"},
--{"476", "dc01", "0030", "life", "regular", "Frosted Food Fight"},
--{"476", "dc01", "0030", "life", "regular", "Instant Food Fight"},
{"477", "dd01", "0030", "life", "regular", "High Five"},
{"478", "de01", "0030", "undead", "trapmaster", "Krypt King"},
{"478", "de01", "0234", "undead", "trapmaster", "Nitro Krypt King"},
{"479", "df01", "0030", "undead", "trapmaster", "Short Cut"},
--{"479", "df01", "0234", "undead", "trapmaster", "Special Short Cut"},
{"480", "e001", "0030", "undead", "regular", "Bat Spin"},
{"481", "e101", "0030", "undead", "regular", "Funny Bone"},
{"481", "e101", "0612", "undead", "regular", "LightCore Funny Bone"},
--{"481", "e101", "0030", "undead", "regular", "Fortune Funny Bone"},
{"482", "e201", "0030", "light", "trapmaster", "Knight light"},
--{"482", "e201", "0234", "light", "trapmaster", "Special Knight light"},
{"483", "e301", "0030", "light", "regular", "Spotlight"},
--{"483", "e301", "0234", "light", "regular", "Special Spotlight"},
{"484", "e401", "0030", "dark", "trapmaster", "Knight Mare"},
--{"484", "e401", "0234", "dark", "trapmaster", "Special Knight Mare"},
{"485", "e501", "0030", "dark", "regular", "Blackout"},
--{"485", "e501", "0234", "dark", "regular", "Special Blackout"},
--[[
PET
--]]
["01F6"]="PET BOP",
["01F7"]="PET SPRY",
["01F8"]="PET HIJINX",
["01F9"]="PET TERRAFIN",
["01FA"]="PET BREEZE",
["01FB"]="PET WEERUPTOR",
["01FC"]="PET PET VAC",
["01FD"]="PET SMALL FRY",
["01FE"]="PET DROBIT",
["0202"]="PET GILL GRUNT",
["0207"]="PET TRIGGER SNAPPY",
["020E"]="PET WHISPER ELF",
["021C"]="PET BARKLEY",
["021D"]="PET THUMPLING",
["021E"]="PET MINI JINI",
["021F"]="PET EYE SMALL",
{"502", "f601", "0030", "earth", "mini", "Bop"},
{"503", "f701", "0030", "magic", "mini", "Spry"},
{"504", "f801", "0030", "undead", "mini", "Hijinx"},
{"505", "f901", "0030", "earth", "mini", "Terrabite"},
{"506", "fa01", "0030", "air", "mini", "Breeze"},
{"507", "fb01", "0030", "fire", "mini", "Weeruptor"},
--{"507", "fb01", "0030", "fire", "mini", "Eggsellent Weeruptor"},
{"508", "fc01", "0030", "air", "mini", "Pet Vac"},
--{"508", "fc01", "0030", "air", "mini", "Power Punch Pet Vac"},
{"509", "fd01", "0030", "fire", "mini", "Small Fry"},
{"510", "fe01", "0030", "tech", "mini", "Drobit"},
{"514", "0202", "0030", "water", "mini", "Gill Runt"},
{"519", "0702", "0030", "tech", "mini", "Trigger Snappy"},
{"526", "0e02", "0030", "life", "mini", "Whisper Elf"},
{"540", "1c02", "0030", "life", "mini", "Barkley"},
--{"540", "1c02", "0030", "life", "mini", "Gnarly Barkley"},
{"541", "1d02", "0030", "water", "mini", "Thumpling"},
{"542", "1e02", "0030", "magic", "mini", "mini Jini"},
{"543", "1f02", "0030", "undead", "mini", "Eye Small"},
--[[
SWAP FORCE
--]]
["0BB8"]="SWAPFORCE SCRATCH",
["0BB9"]="SWAPFORCE POPTHORN",
["0BBA"]="SWAPFORCE SLOBBER TOOTH",
["0BBB"]="SWAPFORCE SCORP",
["0BBC"]="SWAPFORCE HOG WILD FRYNO",
["0BBD"]="SWAPFORCE SMOLDER DASH",
["0BBE"]="SWAPFORCE BUMBLE BLAST",
["0BBF"]="SWAPFORCE ZOO LOU",
["0BC0"]="SWAPFORCE DUNE BUG",
["0BC1"]="SWAPFORCE STAR STRIKE",
["0BC2"]="SWAPFORCE COUNTDOWN",
["0BC3"]="SWAPFORCE WIND UP",
["0BC4"]="SWAPFORCE ROLLER BRAWL",
["0BC5"]="SWAPFORCE GRIM CREEPER",
["0BC6"]="SWAPFORCE RIP TIDE",
["0BC7"]="SWAPFORCE PUNK SHOCK",
{"3000", "b80b", "0030", "air", "SWAPFORCE", "Scratch"},
{"3001", "b90b", "0030", "air", "SWAPFORCE", "Pop Thorn"},
--{"3001", "b90b", "0030", "air", "SWAPFORCE", "Buttered Pop Thorn"},
{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Slobber Tooth"},
--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Dark Slobber Tooth"},
--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Sundae Slobber Tooth"},
{"3003", "bb0b", "0030", "earth", "SWAPFORCE", "Scorp"},
{"3004", "bc0b", "0030", "fire", "SWAPFORCE", "Fryno"},
{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Hog Wild Fryno"},
--{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Flip flop Fryno"},
{"3005", "bd0b", "0030", "fire", "SWAPFORCE", "Smolderdash"},
{"3006", "be0b", "0030", "life", "SWAPFORCE", "Bumble Blast"},
--{"3006", "be0b", "0030", "life", "SWAPFORCE", "Jolly Bumble Blast"},
{"3007", "bf0b", "0030", "life", "SWAPFORCE", "Zoo Lou"},
{"3008", "c00b", "0030", "magic", "SWAPFORCE", "Dune Bug"},
{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Star Strike"},
--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Enchanted Star Strike"},
--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Mystic Star Strike"},
{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Countdown"},
--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Kickoff Countdown"},
--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "New Year's Countdown"},
{"3011", "c30b", "0030", "tech", "SWAPFORCE", "Wind Up"},
{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Roller Brawl"},
--{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Snowler Roller Brawl"},
{"3013", "c50b", "0030", "undead", "SWAPFORCE", "Grim Creeper"},
{"3014", "c60b", "0030", "water", "SWAPFORCE", "Rip Tide"},
{"3015", "c70b", "0030", "water", "SWAPFORCE", "Punk Shock"},
}
local function find( main, sub)
main = main:lower()
sub = sub:lower()
for k, v in pairs(_names) do
if ( v[2]:lower() == main and v[3]:lower() == sub) then
return v
end
end
return nil
end
return {
Find = find,
}
return _names

View file

@ -205,7 +205,7 @@ local function main( args)
-- NDEF compliant?
if b3chars[1] ~= 0xE1 then
return oops("This tag is not NDEF-Complian")
return oops("This tag is not NDEF-Compliant")
end
local ndefVersion = b3chars[2]

View file

@ -95,6 +95,7 @@ end
function test()
local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
@ -107,7 +108,7 @@ function test()
dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)

View file

@ -89,6 +89,7 @@ end
function test()
local y
local block = "00"
for y = 1, 0x1D, 4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
@ -98,10 +99,10 @@ function test()
elseif _ == 1 then
local config = pcmd:format(config1, y, config2)
dbg(('lf t55xx wr 0 %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)

View file

@ -92,6 +92,7 @@ end
function test(modulation)
local y
local block = "00"
for y = 0x0, 0x1d, 0x4 do
for _ = 1, #procedurecmds do
local pcmd = procedurecmds[_]
@ -104,7 +105,7 @@ function test(modulation)
dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16)
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)

View file

@ -108,6 +108,7 @@ end
function test(modulation)
local bitrate
local clockrate
local block = "00"
for bitrate = 0x0, 0x1d, 0x4 do
for clockrate = 0,8,4 do
@ -125,8 +126,8 @@ function test(modulation)
dbg(('lf t55xx write 0 %s'):format(config))
config = tonumber(config,16)
local writecommand = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config ,arg2 = 0, arg3 = 0}
local err = core.SendCommand(writecommand:getBytes())
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
local err = core.SendCommand(writecmd:getBytes())
if err then return oops(err) end
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
else

View file

@ -0,0 +1,161 @@
local cmds = require('commands')
local getopt = require('getopt')
local lib14a = require('read14a')
local utils = require('utils')
local pre = require('precalc')
local toys = require('default_toys')
local lsh = bit32.lshift
local rsh = bit32.rshift
local bor = bit32.bor
local band = bit32.band
example =[[
script run tnp3clone
script run tnp3clone -h
script run tnp3clone -t aa00 -s 0030
]]
author = "Iceman"
usage = "script run tnp3clone -t <toytype> -s <subtype>"
desc =[[
This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card.
Arguments:
-h : this help
-t <data> : toytype id, 4hex symbols.
-s <data> : subtype id, 4hex symbols
For fun, try the following subtype id:
0612 - Lightcore
0118 - Series 1
0138 - Series 2
0234 - Special
023c - Special
]]
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
end
local function waitCmd()
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block."
end
end
return nil, "No response from device"
end
local function readblock( blocknum, keyA )
-- Read block 0
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
end
local function readmagicblock( blocknum )
-- Read block 0
local CSETBLOCK_SINGLE_OPERATION = 0x1F
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
err = core.SendCommand(cmd:getBytes())
if err then return nil, err end
local block0, err = waitCmd()
if err then return nil, err end
return block0
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local numBlocks = 64
local cset = 'hf mf csetbl '
local csetuid = 'hf mf csetuid '
local cget = 'hf mf cgetbl '
local empty = '00000000000000000000000000000000'
local AccAndKeyB = '7F078869000000000000'
-- Defaults to Gusto
local toytype = 'C201'
local subtype = '0030'
local DEBUG = true
-- Arguments for the script
for o, a in getopt.getopt(args, 'ht:s:') do
if o == "h" then return help() end
if o == "t" then toytype = a end
if o == "s" then subtype = a end
end
if #toytype ~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end
if #subtype ~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end
-- look up type, find & validate types
local item = toys.Find( toytype, subtype)
if item then
print( (' Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print('Didn\'t find item type. If you are sure about it, report it in')
end
--15,16
--13-14
-- find tag
result, err = lib14a.read1443a(false)
if not result then return oops(err) end
-- load keys
local akeys = pre.GetAll(result.uid)
local keyA = akeys:sub(1, 12 )
local b0 = readblock(0,keyA)
if not b0 then
print('failed reading block with factorydefault key. Trying chinese magic read.')
b0, err = readmagicblock(0)
if not b0 then
oops(err)
return oops('failed reading block with chinese magic command. quitting...')
end
end
-- wipe card.
local cmd = (csetuid..'%s 0004 08 w'):format(result.uid)
core.console(cmd)
local b1 = toytype..'00000000000000000000'..subtype
local calc = utils.Crc16(b0..b1)
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
core.console(cmd)
local pos, key
for blockNo = 2, numBlocks-1, 1 do
pos = (math.floor( blockNo / 4 ) * 12)+1
key = akeys:sub(pos, pos + 11 )
if blockNo%4 == 3 then
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
core.console(cmd)
end
end
core.clearCommandBuffer()
end
main(args)

View file

@ -5,19 +5,21 @@ local lib14a = require('read14a')
local utils = require('utils')
local md5 = require('md5')
local dumplib = require('html_dumplib')
local toyNames = require('default_toys')
local toys = require('default_toys')
example =[[
1. script run tnp3dump
2. script run tnp3dump -n
3. script run tnp3dump -k aabbccddeeff
4. script run tnp3dump -k aabbccddeeff -n
5. script run tnp3dump -o myfile
6. script run tnp3dump -n -o myfile
7. script run tnp3dump -k aabbccddeeff -n -o myfile
script run tnp3dump
script run tnp3dump -n
script run tnp3dump -p
script run tnp3dump -k aabbccddeeff
script run tnp3dump -k aabbccddeeff -n
script run tnp3dump -o myfile
script run tnp3dump -n -o myfile
script run tnp3dump -p -o myfile
script run tnp3dump -k aabbccddeeff -n -o myfile
]]
author = "Iceman"
usage = "script run tnp3dump -k <key> -n -o <filename>"
usage = "script run tnp3dump -k <key> -n -p -o <filename>"
desc =[[
This script will try to dump the contents of a Mifare TNP3xxx card.
It will need a valid KeyA in order to find the other keys and decode the card.
@ -25,11 +27,10 @@ Arguments:
-h : this help
-k <key> : Sector 0 Key A.
-n : Use the nested cmd to find all keys
-p : Use the precalc to find all keys
-o : filename for the saved dumps
]]
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = false -- the debug flag
local numBlocks = 64
@ -93,16 +94,6 @@ local function waitCmd()
return nil, "No response from device"
end
local function computeCrc16(s)
local hash = core.crc16(utils.ConvertHexToAscii(s))
return hash
end
local function reverseCrcBytes(crc)
crc2 = crc:sub(3,4)..crc:sub(1,2)
return tonumber(crc2,16)
end
local function main(args)
print( string.rep('--',20) )
@ -112,18 +103,20 @@ local function main(args)
local cmd
local err
local useNested = false
local usePreCalc = false
local cmdReadBlockString = 'hf mf rdbl %d A %s'
local input = "dumpkeys.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
-- Arguments for the script
for o, a in getopt.getopt(args, 'hk:no:') do
for o, a in getopt.getopt(args, 'hk:npo:') do
if o == "h" then return help() end
if o == "k" then keyA = a end
if o == "n" then useNested = true end
if o == "p" then usePreCalc = true end
if o == "o" then outputTemplate = a end
end
-- validate input args.
keyA = keyA or '4b0b20107ccb'
if #(keyA) ~= 12 then
@ -141,30 +134,31 @@ local function main(args)
core.clearCommandBuffer()
if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
return oops('This is not a TNP3xxx tag. aborting.')
end
-- Show tag info
print((' Found tag : %s'):format(result.name))
print(('Using keyA : %s'):format(keyA))
print((' Found tag %s'):format(result.name))
dbg(('Using keyA : %s'):format(keyA))
--Trying to find the other keys
if useNested then
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
end
core.clearCommandBuffer()
-- Loading keyfile
print('Loading dumpkeys.bin')
local hex, err = utils.ReadDumpFile(input)
if not hex then
return oops(err)
local akeys = ''
if usePreCalc then
local pre = require('precalc')
akeys = pre.GetAll(result.uid)
else
print('Loading dumpkeys.bin')
local hex, err = utils.ReadDumpFile(input)
if not hex then
return oops(err)
end
akeys = hex:sub(0,12*16)
end
local akeys = hex:sub(0,12*16)
-- Read block 0
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
@ -179,6 +173,8 @@ local function main(args)
local block1, err = waitCmd()
if err then return oops(err) end
local tmpHash = block0..block1..'%02x'..RANDOM
local key
local pos = 0
local blockNo
@ -188,7 +184,7 @@ local function main(args)
core.clearCommandBuffer()
-- main loop
io.write('Decrypting blocks > ')
io.write('Reading blocks > ')
for blockNo = 0, numBlocks-1, 1 do
if core.ukbhit() then
@ -204,25 +200,23 @@ local function main(args)
local blockdata, err = waitCmd()
if err then return oops(err) end
if blockNo%4 ~= 3 then
if blockNo < 8 then
-- Block 0-7 not encrypted
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
local base = ('%s%s%02x%s'):format(block0, block1, blockNo, HASHCONSTANT)
local baseStr = utils.ConvertHexToAscii(base)
local md5hash = md5.sumhexa(baseStr)
local aestest = core.aes(md5hash, blockdata)
local hex = utils.ConvertAsciiToBytes(aestest)
hex = utils.ConvertBytesToHex(hex)
-- blocks with zero not encrypted.
if string.find(blockdata, '^0+$') then
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
io.write( blockNo..',')
local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo))
local key = md5.sumhexa(baseStr)
local aestest = core.aes128_decrypt(key, blockdata)
local hex = utils.ConvertAsciiToBytes(aestest)
hex = utils.ConvertBytesToHex(hex)
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
end
end
else
@ -246,31 +240,38 @@ local function main(args)
emldata = emldata..slice..'\n'
for c in (str):gmatch('.') do
bindata[#bindata+1] = c
end
end
end
print( string.rep('--',20) )
local uid = block0:sub(1,8)
local itemtype = block1:sub(1,4)
local toytype = block1:sub(1,4)
local cardidLsw = block1:sub(9,16)
local cardidMsw = block1:sub(16,24)
local cardid = block1:sub(9,24)
local traptype = block1:sub(25,28)
local subtype = block1:sub(25,28)
-- Write dump to files
if not DEBUG then
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'_uid_'..uid..'.bin')
print(("Wrote a BIN dump to the file %s"):format(foo))
local bar = dumplib.SaveAsText(emldata, outputTemplate..'_uid_'..uid..'.eml')
print(("Wrote a EML dump to the file %s"):format(bar))
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin')
print(("Wrote a BIN dump to: %s"):format(foo))
local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml')
print(("Wrote a EML dump to: %s"):format(bar))
end
-- Show info
print( string.rep('--',20) )
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
print( (' Alter ego / traptype : 0x%s'):format(traptype) )
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) )
-- Show info
local item = toys.Find(toytype, subtype)
if item then
print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) )
else
print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype))
end
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) )
end
main(args)

View file

@ -4,7 +4,7 @@ local bin = require('bin')
local lib14a = require('read14a')
local utils = require('utils')
local md5 = require('md5')
local toyNames = require('default_toys')
local toys = require('default_toys')
example =[[
1. script run tnp3sim
@ -27,6 +27,17 @@ Arguments:
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = true -- the debug flag
local band = bit32.band
local bor = bit32.bor
local lshift = bit32.lshift
local rshift = bit32.rshift
local byte = string.byte
local char = string.char
local sub = string.sub
local format = string.format
---
-- A debug printout-function
function dbg(args)
@ -65,7 +76,6 @@ function ExitMsg(msg)
print()
end
local function writedumpfile(infile)
t = infile:read("*all")
len = string.len(t)
@ -187,7 +197,6 @@ local function ValidateCheckSums(blocks)
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
end
local function LoadEmulator(blocks)
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local cmd
@ -219,6 +228,102 @@ local function LoadEmulator(blocks)
io.write('\n')
end
local function Num2Card(m, l)
local k = {
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B,
0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00
}
local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
if msw > 0x17ea1 then
return "too big"
end
if msw == 0x17ea1 and lsw > 0x8931fee8 then
return "out of range"
end
local s = ""
local index
for i = 1,10 do
index, msw, lsw = DivideByK( msw, lsw)
if ( index <= 1 ) then
s = char(k[index]) .. s
else
s = char(k[index-1]) .. s
end
print (index-1, msw, lsw)
end
return s
end
--33LRT-LM9Q9
--7, 122, 3474858630
--20, 4, 1008436634
--7, 0, 627182959
--17, 0, 21626998
--16, 0, 745758
--23, 0, 25715
--21, 0, 886
--16, 0, 30
--1, 0, 1
--1, 0, 0
function DivideByK(msw, lsw)
local lowLSW
local highLSW
local remainder = 0
local RADIX = 29
--local num = 0 | band( rshift(msw,16), 0xffff)
local num = band( rshift(msw, 16), 0xffff)
--highLSW = 0 | lshift( (num / RADIX) , 16)
highLSW = lshift( (num / RADIX) , 16)
remainder = num % RADIX
num = bor( lshift(remainder,16), band(msw, 0xffff))
--highLSW |= num / RADIX
highLSW = highLSW or (num / RADIX)
remainder = num % RADIX
num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
--lowLSW = 0 | (num / RADIX) << 16
lowLSW = 0 or (lshift( (num / RADIX), 16))
remainder = num % RADIX
num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
lowLSW = bor(lowLSW, (num / RADIX))
remainder = num % RADIX
return remainder, highLSW, lowLSW
-- uint num = 0 | (msw >> 16) & 0xffff;
-- highLSW = 0 | (num / RADIX) << 16;
-- remainder = num % RADIX;
-- num = (remainder << 16) | (msw & 0xffff);
-- highLSW |= num / RADIX;
-- remainder = num % RADIX;
-- num = (remainder << 16) | ((lsw >> 16) & 0xffff);
-- lowLSW = 0 | (num / RADIX) << 16;
-- remainder = num % RADIX;
-- num = (remainder << 16) | (lsw & 0xffff);
-- lowLSW |= num / RADIX;
-- remainder = num % RADIX;
end
local function main(args)
print( string.rep('--',20) )
@ -277,16 +382,31 @@ local function main(args)
print( string.rep('--',20) )
print(' Gathering info')
local uid = blocks[0]:sub(1,8)
local itemtype = blocks[1]:sub(1,4)
local cardid = blocks[1]:sub(9,24)
local toytype = blocks[1]:sub(1,4)
local cardidLsw = blocks[1]:sub(9,16)
local cardidMsw = blocks[1]:sub(17,24)
local subtype = blocks[1]:sub(25,28)
-- Show info
print( string.rep('--',20) )
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
local item = toys.Find( toytype, subtype)
if item then
local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4])
print(' ITEM TYPE :'..itemStr )
else
print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) )
end
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( (' CARDID : 0x%s %s [%s]'):format(
cardidMsw,cardidLsw,
--Num2Card(cardidMsw, cardidLsw))
'')
)
print( string.rep('--',20) )
-- lets do something.
--
local experience = blocks[8]:sub(1,6)
@ -351,7 +471,7 @@ local function main(args)
err = LoadEmulator(blocks)
if err then return oops(err) end
core.clearCommandBuffer()
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..' x\" <--')
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
end
end
main(args)

View file

@ -121,19 +121,24 @@ char * sprint_hex(const uint8_t * data, const size_t len) {
return buf;
}
char * sprint_bin(const uint8_t * data, const size_t len) {
char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) {
int maxLen = ( len > 1024) ? 1024 : len;
static char buf[1024];
char * tmp = buf;
size_t i;
char *tmp = buf;
for (i=0; i < maxLen; ++i, ++tmp)
sprintf(tmp, "%u", data[i]);
for (size_t i=0; i < maxLen; ++i){
sprintf(tmp++, "%u", data[i]);
if (breaks > 0 && !((i+1) % breaks))
sprintf(tmp++, "%s","\n");
}
return buf;
}
char *sprint_bin(const uint8_t *data, const size_t len) {
return sprint_bin_break(data, len, 0);
}
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
{
while (len--) {

View file

@ -39,6 +39,7 @@ void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext, int byteCount);
void print_hex(const uint8_t * data, const size_t len);
char * sprint_hex(const uint8_t * data, const size_t len);
char * sprint_bin(const uint8_t * data, const size_t len);
char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks);
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);

View file

@ -81,10 +81,8 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_
// otherwise could be a void with no arguments
//set defaults
uint32_t i = 0;
if (BitStream[1]>1){ //allow only 1s and 0s
// PrintAndLog("no data found");
return 0;
}
if (BitStream[1]>1) return 0; //allow only 1s and 0s
// 111111111 bit pattern represent start of frame
// include 0 in front to help get start pos
uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1};
@ -115,216 +113,11 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_
}
//by marshmellow
//takes 3 arguments - clock, invert, maxErr as integers
//attempts to demodulate ask while decoding manchester
//prints binary found and saves in graphbuffer for further commands
int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr)
{
size_t i;
int start = DetectASKClock(BinStream, *size, clk, 20); //clock default
if (*clk==0 || start < 0) return -3;
if (*invert != 1) *invert=0;
uint8_t initLoopMax = 255;
if (initLoopMax > *size) initLoopMax = *size;
// Detect high and lows
// 25% fuzz in case highs and lows aren't clipped [marshmellow]
int high, low;
if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) return -2; //just noise
// PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low);
int lastBit = 0; //set first clock check
uint16_t bitnum = 0; //output counter
uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
if (*clk <= 32) tol=1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
size_t iii = 0;
//if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance
if (!maxErr) initLoopMax = *clk * 2;
uint16_t errCnt = 0, MaxBits = 512;
uint16_t bestStart = start;
uint16_t bestErrCnt = 0;
// PrintAndLog("DEBUG - lastbit - %d",lastBit);
// if best start position not already found by detect clock then
if (start <= 0 || start > initLoopMax){
bestErrCnt = maxErr+1;
// loop to find first wave that works
for (iii=0; iii < initLoopMax; ++iii){
// if no peak skip
if (BinStream[iii] < high && BinStream[iii] > low) continue;
lastBit = iii - *clk;
// loop through to see if this start location works
for (i = iii; i < *size; ++i) {
if ((i-lastBit) > (*clk-tol) && (BinStream[i] >= high || BinStream[i] <= low)) {
lastBit += *clk;
} else if ((i-lastBit) > (*clk+tol)) {
errCnt++;
lastBit += *clk;
}
if ((i-iii) > (MaxBits * *clk) || errCnt > maxErr) break; //got plenty of bits or too many errors
}
//we got more than 64 good bits and not all errors
if ((((i-iii)/ *clk) > (64)) && (errCnt<=maxErr)) {
//possible good read
if (!errCnt || errCnt < bestErrCnt){
bestStart = iii; //set this as new best run
bestErrCnt = errCnt;
if (!errCnt) break; //great read - finish
}
}
errCnt = 0;
}
}
if (bestErrCnt > maxErr){
*invert = bestStart;
*clk = iii;
return -1;
}
//best run is good enough set to best run and set overwrite BinStream
lastBit = bestStart - *clk;
errCnt = 0;
for (i = bestStart; i < *size; ++i) {
if ((BinStream[i] >= high) && ((i-lastBit) > (*clk-tol))){
//high found and we are expecting a bar
lastBit += *clk;
BinStream[bitnum++] = *invert;
} else if ((BinStream[i] <= low) && ((i-lastBit) > (*clk-tol))){
//low found and we are expecting a bar
lastBit += *clk;
BinStream[bitnum++] = *invert ^ 1;
} else if ((i-lastBit)>(*clk+tol)){
//should have hit a high or low based on clock!!
//PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit);
if (bitnum > 0) {
BinStream[bitnum++] = 77;
errCnt++;
}
lastBit += *clk;//skip over error
}
if (bitnum >= MaxBits) break;
}
*size = bitnum;
return bestErrCnt;
}
//by marshmellow
//encode binary data into binary manchester
int ManchesterEncode(uint8_t *BitStream, size_t size)
{
size_t modIdx=20000, i=0;
if (size>modIdx) return -1;
for (size_t idx=0; idx < size; idx++){
BitStream[idx+modIdx++] = BitStream[idx];
BitStream[idx+modIdx++] = BitStream[idx]^1;
}
for (; i<(size*2); i++){
BitStream[i] = BitStream[i+20000];
}
return i;
}
//by marshmellow
//take 10 and 01 and manchester decode
//run through 2 times and take least errCnt
int manrawdecode(uint8_t * BitStream, size_t *size)
{
uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
size_t i, ii;
uint16_t bestErr = 1000, bestRun = 0;
if (size == 0) return -1;
for (ii=0;ii<2;++ii){
for (i=ii; i<*size-2; i+=2)
if (BitStream[i]==BitStream[i+1])
errCnt++;
if (bestErr>errCnt){
bestErr=errCnt;
bestRun=ii;
}
errCnt=0;
}
if (bestErr<20){
for (i=bestRun; i < *size-2; i+=2){
if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
BitStream[bitnum++]=0;
} else if((BitStream[i] == 0) && BitStream[i+1] == 1){
BitStream[bitnum++]=1;
} else {
BitStream[bitnum++]=77;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
}
return bestErr;
}
//by marshmellow
//take 01 or 10 = 1 and 11 or 00 = 0
//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert)
{
uint16_t bitnum = 0;
uint16_t errCnt = 0;
size_t i = offset;
uint16_t MaxBits=512;
//if not enough samples - error
if (*size < 51) return -1;
//check for phase change faults - skip one sample if faulty
uint8_t offsetA = 1, offsetB = 1;
for (; i<48; i+=2){
if (BitStream[i+1]==BitStream[i+2]) offsetA=0;
if (BitStream[i+2]==BitStream[i+3]) offsetB=0;
}
if (!offsetA && offsetB) offset++;
for (i=offset; i<*size-3; i+=2){
//check for phase error
if (BitStream[i+1]==BitStream[i+2]) {
BitStream[bitnum++]=77;
errCnt++;
}
if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){
BitStream[bitnum++]=1^invert;
} else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){
BitStream[bitnum++]=invert;
} else {
BitStream[bitnum++]=77;
errCnt++;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
return errCnt;
}
//by marshmellow
void askAmp(uint8_t *BitStream, size_t size)
{
int shift = 127;
int shiftedVal=0;
for(size_t i = 1; i<size; i++){
if (BitStream[i]-BitStream[i-1]>=30) //large jump up
shift=127;
else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down
shift=-127;
shiftedVal=BitStream[i]+shift;
if (shiftedVal>255)
shiftedVal=255;
else if (shiftedVal<0)
shiftedVal=0;
BitStream[i-1] = shiftedVal;
}
return;
}
// demodulates strong heavily clipped samples
//demodulates strong heavily clipped samples
int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low)
{
size_t bitCnt=0, smplCnt=0, errCnt=0;
uint8_t waveHigh = 0;
//PrintAndLog("clk: %d", clk);
for (size_t i=0; i < *size; i++){
if (BinStream[i] >= high && waveHigh){
smplCnt++;
@ -335,7 +128,7 @@ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int
if (smplCnt > clk-(clk/4)-1) { //full clock
if (smplCnt > clk + (clk/4)+1) { //too many samples
errCnt++;
BinStream[bitCnt++]=77;
BinStream[bitCnt++]=7;
} else if (waveHigh) {
BinStream[bitCnt++] = invert;
BinStream[bitCnt++] = invert;
@ -371,111 +164,79 @@ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int
}
//by marshmellow
//takes 3 arguments - clock, invert and maxErr as integers
//attempts to demodulate ask only
int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp)
void askAmp(uint8_t *BitStream, size_t size)
{
for(size_t i = 1; i<size; i++){
if (BitStream[i]-BitStream[i-1]>=30) //large jump up
BitStream[i]=127;
else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down
BitStream[i]=-127;
}
return;
}
//by marshmellow
//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester
int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType)
{
if (*size==0) return -1;
int start = DetectASKClock(BinStream, *size, clk, 20); //clock default
if (*clk==0 || start < 0) return -1;
int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default
if (*clk==0 || start < 0) return -3;
if (*invert != 1) *invert = 0;
if (amp==1) askAmp(BinStream, *size);
uint8_t initLoopMax = 255;
if (initLoopMax > *size) initLoopMax=*size;
if (initLoopMax > *size) initLoopMax = *size;
// Detect high and lows
//25% clip in case highs and lows aren't clipped [marshmellow]
int high, low;
if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1)
return -1; //just noise
return -2; //just noise
size_t errCnt = 0;
// if clean clipped waves detected run alternate demod
if (DetectCleanAskWave(BinStream, *size, high, low))
return cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
if (DetectCleanAskWave(BinStream, *size, high, low)) {
errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
if (askType) //askman
return manrawdecode(BinStream, size, 0);
else //askraw
return errCnt;
}
int lastBit = 0; //set first clock check - can go negative
size_t i, iii = 0;
size_t errCnt = 0, bitnum = 0; //output counter
int lastBit; //set first clock check - can go negative
size_t i, bitnum = 0; //output counter
uint8_t midBit = 0;
size_t bestStart = start, bestErrCnt = 0; //(*size/1000);
uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
size_t MaxBits = 1024;
lastBit = start - *clk;
//if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance
if (!maxErr) initLoopMax = *clk * 2;
//if best start not already found by detectclock
if (start <= 0 || start > initLoopMax){
bestErrCnt = maxErr+1;
//PrintAndLog("DEBUG - lastbit - %d",lastBit);
//loop to find first wave that works
for (iii=0; iii < initLoopMax; ++iii){
if ((BinStream[iii] >= high) || (BinStream[iii] <= low)){
lastBit = iii - *clk;
//loop through to see if this start location works
for (i = iii; i < *size; ++i) {
if (i-lastBit > *clk && (BinStream[i] >= high || BinStream[i] <= low)){
lastBit += *clk;
midBit = 0;
} else if (i-lastBit > (*clk/2) && midBit == 0) {
midBit = 1;
} else if ((i-lastBit) > *clk) {
//should have hit a high or low based on clock!!
//PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit);
errCnt++;
lastBit += *clk;//skip over until hit too many errors
if (errCnt > maxErr)
break;
}
if ((i-iii)>(MaxBits * *clk)) break; //got enough bits
}
//we got more than 64 good bits and not all errors
if ((((i-iii)/ *clk) > 64) && (errCnt<=maxErr)) {
//possible good read
if (errCnt==0){
bestStart=iii;
bestErrCnt=errCnt;
break; //great read - finish
}
if (errCnt<bestErrCnt){ //set this as new best run
bestErrCnt=errCnt;
bestStart = iii;
}
}
errCnt=0;
}
}
}
if (bestErrCnt > maxErr){
*invert = bestStart;
*clk = iii;
return -1;
}
//best run is good enough - set to best run and overwrite BinStream
lastBit = bestStart - *clk - 1;
errCnt = 0;
for (i = bestStart; i < *size; ++i) {
if (i - lastBit > *clk){
for (i = start; i < *size; ++i) {
if (i-lastBit >= *clk-tol){
if (BinStream[i] >= high) {
BinStream[bitnum++] = *invert;
} else if (BinStream[i] <= low) {
BinStream[bitnum++] = *invert ^ 1;
} else {
} else if (i-lastBit >= *clk+tol) {
if (bitnum > 0) {
BinStream[bitnum++]=77;
BinStream[bitnum++]=7;
errCnt++;
}
} else { //in tolerance - looking for peak
continue;
}
midBit = 0;
lastBit += *clk;
} else if (i-lastBit > (*clk/2) && midBit == 0){
} else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){
if (BinStream[i] >= high) {
BinStream[bitnum++] = *invert;
} else if (BinStream[i] <= low) {
BinStream[bitnum++] = *invert ^ 1;
} else {
} else if (i-lastBit >= *clk/2+tol) {
BinStream[bitnum] = BinStream[bitnum-1];
bitnum++;
} else { //in tolerance - looking for peak
continue;
}
midBit = 1;
}
@ -485,6 +246,98 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max
return errCnt;
}
//by marshmellow
//take 10 and 01 and manchester decode
//run through 2 times and take least errCnt
int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert)
{
uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
size_t i, ii;
uint16_t bestErr = 1000, bestRun = 0;
if (*size < 16) return -1;
//find correct start position [alignment]
for (ii=0;ii<2;++ii){
for (i=ii; i<*size-3; i+=2)
if (BitStream[i]==BitStream[i+1])
errCnt++;
if (bestErr>errCnt){
bestErr=errCnt;
bestRun=ii;
}
errCnt=0;
}
//decode
for (i=bestRun; i < *size-3; i+=2){
if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
BitStream[bitnum++]=invert;
} else if((BitStream[i] == 0) && BitStream[i+1] == 1){
BitStream[bitnum++]=invert^1;
} else {
BitStream[bitnum++]=7;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
return bestErr;
}
//by marshmellow
//encode binary data into binary manchester
int ManchesterEncode(uint8_t *BitStream, size_t size)
{
size_t modIdx=20000, i=0;
if (size>modIdx) return -1;
for (size_t idx=0; idx < size; idx++){
BitStream[idx+modIdx++] = BitStream[idx];
BitStream[idx+modIdx++] = BitStream[idx]^1;
}
for (; i<(size*2); i++){
BitStream[i] = BitStream[i+20000];
}
return i;
}
//by marshmellow
//take 01 or 10 = 1 and 11 or 00 = 0
//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert)
{
uint16_t bitnum = 0;
uint16_t errCnt = 0;
size_t i = offset;
uint16_t MaxBits=512;
//if not enough samples - error
if (*size < 51) return -1;
//check for phase change faults - skip one sample if faulty
uint8_t offsetA = 1, offsetB = 1;
for (; i<48; i+=2){
if (BitStream[i+1]==BitStream[i+2]) offsetA=0;
if (BitStream[i+2]==BitStream[i+3]) offsetB=0;
}
if (!offsetA && offsetB) offset++;
for (i=offset; i<*size-3; i+=2){
//check for phase error
if (BitStream[i+1]==BitStream[i+2]) {
BitStream[bitnum++]=7;
errCnt++;
}
if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){
BitStream[bitnum++]=1^invert;
} else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){
BitStream[bitnum++]=invert;
} else {
BitStream[bitnum++]=7;
errCnt++;
}
if(bitnum>MaxBits) break;
}
*size=bitnum;
return errCnt;
}
// by marshmellow
// demod gProxIIDemod
// error returns as -x
// success returns start position in BitStream
@ -780,12 +633,13 @@ int PyramiddemodFSK(uint8_t *dest, size_t *size)
return (int)startIdx;
}
uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low)
// by marshmellow
// to detect a wave that has heavily clipped (clean) samples
uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low)
{
uint16_t allPeaks=1;
uint16_t cntPeaks=0;
size_t loopEnd = 572;
size_t loopEnd = 512+60;
if (loopEnd > size) loopEnd = size;
for (size_t i=60; i<loopEnd; i++){
if (dest[i]>low && dest[i]<high)
@ -801,53 +655,39 @@ uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low)
// by marshmellow
// to help detect clocks on heavily clipped samples
// based on counts between zero crossings
int DetectStrongAskClock(uint8_t dest[], size_t size)
// based on count of low to low
int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low)
{
int clk[]={0,8,16,32,40,50,64,100,128};
size_t idx = 40;
uint8_t high=0;
size_t cnt = 0;
size_t highCnt = 0;
size_t highCnt2 = 0;
for (;idx < size; idx++){
if (dest[idx]>128) {
if (!high){
high=1;
if (cnt > highCnt){
if (highCnt != 0) highCnt2 = highCnt;
highCnt = cnt;
} else if (cnt > highCnt2) {
highCnt2 = cnt;
}
cnt=1;
} else {
cnt++;
}
} else if (dest[idx] <= 128){
if (high) {
high=0;
if (cnt > highCnt) {
if (highCnt != 0) highCnt2 = highCnt;
highCnt = cnt;
} else if (cnt > highCnt2) {
highCnt2 = cnt;
}
cnt=1;
} else {
cnt++;
}
}
uint8_t fndClk[] = {8,16,32,40,50,64,128};
size_t startwave;
size_t i = 0;
size_t minClk = 255;
// get to first full low to prime loop and skip incomplete first pulse
while ((dest[i] < high) && (i < size))
++i;
while ((dest[i] > low) && (i < size))
++i;
// loop through all samples
while (i < size) {
// measure from low to low
while ((dest[i] > low) && (i < size))
++i;
startwave= i;
while ((dest[i] < high) && (i < size))
++i;
while ((dest[i] > low) && (i < size))
++i;
//get minimum measured distance
if (i-startwave < minClk && i < size)
minClk = i - startwave;
}
uint8_t tol;
for (idx=8; idx>0; idx--){
tol = clk[idx]/8;
if (clk[idx] >= highCnt - tol && clk[idx] <= highCnt + tol)
return clk[idx];
if (clk[idx] >= highCnt2 - tol && clk[idx] <= highCnt2 + tol)
return clk[idx];
// set clock
for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
if (minClk >= fndClk[clkCnt]-(fndClk[clkCnt]/8) && minClk <= fndClk[clkCnt]+1)
return fndClk[clkCnt];
}
return -1;
return 0;
}
// by marshmellow
@ -856,45 +696,61 @@ int DetectStrongAskClock(uint8_t dest[], size_t size)
// return start index of best starting position for that clock and return clock (by reference)
int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
{
size_t i=0;
uint8_t clk[]={8,16,32,40,50,64,100,128,255};
size_t i=1;
uint8_t clk[] = {255,8,16,32,40,50,64,100,128,255};
uint8_t clkEnd = 9;
uint8_t loopCnt = 255; //don't need to loop through entire array...
if (size <= loopCnt) return -1; //not enough samples
//if we already have a valid clock quit
for (;i<8;++i)
if (clk[i] == *clock) return 0;
//if we already have a valid clock
uint8_t clockFnd=0;
for (;i<clkEnd;++i)
if (clk[i] == *clock) clockFnd = i;
//clock found but continue to find best startpos
//get high and low peak
int peak, low;
if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1;
//test for large clean peaks
if (DetectCleanAskWave(dest, size, peak, low)==1){
int ans = DetectStrongAskClock(dest, size);
for (i=7; i>0; i--){
if (clk[i] == ans) {
*clock = ans;
return 0;
if (!clockFnd){
if (DetectCleanAskWave(dest, size, peak, low)==1){
int ans = DetectStrongAskClock(dest, size, peak, low);
for (i=clkEnd-1; i>0; i--){
if (clk[i] == ans) {
*clock = ans;
//clockFnd = i;
return 0; // for strong waves i don't use the 'best start position' yet...
//break; //clock found but continue to find best startpos [not yet]
}
}
}
}
uint8_t ii;
uint8_t clkCnt, tol = 0;
uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000};
uint8_t bestStart[]={0,0,0,0,0,0,0,0,0};
size_t errCnt = 0;
size_t arrLoc, loopEnd;
if (clockFnd>0) {
clkCnt = clockFnd;
clkEnd = clockFnd+1;
}
else clkCnt=1;
//test each valid clock from smallest to greatest to see which lines up
for(clkCnt=0; clkCnt < 8; clkCnt++){
if (clk[clkCnt] == 32){
for(; clkCnt < clkEnd; clkCnt++){
if (clk[clkCnt] <= 32){
tol=1;
}else{
tol=0;
}
if (!maxErr) loopCnt=clk[clkCnt]*2;
//if no errors allowed - keep start within the first clock
if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt]<128) loopCnt=clk[clkCnt]*2;
bestErr[clkCnt]=1000;
//try lining up the peaks by moving starting point (try first 256)
//try lining up the peaks by moving starting point (try first few clocks)
for (ii=0; ii < loopCnt; ii++){
if (dest[ii] < peak && dest[ii] > low) continue;
@ -910,11 +766,11 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
errCnt++;
}
}
//if we found no errors then we can stop here
//if we found no errors then we can stop here and a low clock (common clocks)
// this is correct one - return this clock
//PrintAndLog("DEBUG: clk %d, err %d, ii %d, i %d",clk[clkCnt],errCnt,ii,i);
if(errCnt==0 && clkCnt<6) {
*clock = clk[clkCnt];
if(errCnt==0 && clkCnt<7) {
if (!clockFnd) *clock = clk[clkCnt];
return ii;
}
//if we found errors see if it is lowest so far and save it as best run
@ -924,9 +780,9 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
}
}
}
uint8_t iii=0;
uint8_t iii;
uint8_t best=0;
for (iii=0; iii<8; ++iii){
for (iii=1; iii<clkEnd; ++iii){
if (bestErr[iii] < bestErr[best]){
if (bestErr[iii] == 0) bestErr[iii]=1;
// current best bit to error ratio vs new bit to error ratio
@ -935,8 +791,8 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr)
}
}
}
if (bestErr[best] > maxErr) return -1;
*clock = clk[best];
//if (bestErr[best] > maxErr) return -1;
if (!clockFnd) *clock = clk[best];
return bestStart[best];
}
@ -1115,7 +971,7 @@ void psk1TOpsk2(uint8_t *BitStream, size_t size)
size_t i=1;
uint8_t lastBit=BitStream[0];
for (; i<size; i++){
if (BitStream[i]==77){
if (BitStream[i]==7){
//ignore errors
} else if (lastBit!=BitStream[i]){
lastBit=BitStream[i];
@ -1308,7 +1164,7 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr)
if (ignoreCnt == 0){
bitHigh = 0;
if (errBitHigh == 1){
dest[bitnum++] = 77;
dest[bitnum++] = 7;
errCnt++;
}
errBitHigh=0;
@ -1583,7 +1439,7 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
//noise after a phase shift - ignore
} else { //phase shift before supposed to based on clock
errCnt++;
dest[numBits++] = 77;
dest[numBits++] = 7;
}
} else if (i+1 > lastClkBit + *clock + tol + fc){
lastClkBit += *clock; //no phase shift but clock bit

View file

@ -15,34 +15,37 @@
#define LFDEMOD_H__
#include <stdint.h>
int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr);
uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low);
int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr);
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
int ManchesterEncode(uint8_t *BitStream, size_t size);
int manrawdecode(uint8_t *BitStream, size_t *size);
int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp);
//generic
int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType);
int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj);
int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr);
uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow);
int DetectNRZClock(uint8_t dest[], size_t size, int clock);
int DetectPSKClock(uint8_t dest[], size_t size, int clock);
int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
int ManchesterEncode(uint8_t *BitStream, size_t size);
int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert);
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr);
uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
void psk2TOpsk1(uint8_t *BitStream, size_t size);
void psk1TOpsk2(uint8_t *BitStream, size_t size);
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
//tag specific
int AWIDdemodFSK(uint8_t *dest, size_t *size);
int gProxII_Demod(uint8_t BitStream[], size_t *size);
int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
int IOdemodFSK(uint8_t *dest, size_t size);
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr);
void psk1TOpsk2(uint8_t *BitStream, size_t size);
void psk2TOpsk1(uint8_t *BitStream, size_t size);
int DetectNRZClock(uint8_t dest[], size_t size, int clock);
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
int PyramiddemodFSK(uint8_t *dest, size_t *size);
int AWIDdemodFSK(uint8_t *dest, size_t *size);
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj);
uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow);
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
int DetectPSKClock(uint8_t dest[], size_t size, int clock);
#endif