mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
ADD: added identification for Mifare TNP3xxx tags.
ADD: MD5-lua functionality ADD: AES 128 decrypt lua functionality ADD: test luc script for reading TNP3xxx tags CHG: testing some changes for "hf 14b sim" / "lf em4x 410xsim"
This commit is contained in:
parent
a25d5c1cde
commit
c15d2bdc9b
15 changed files with 971 additions and 65 deletions
|
@ -463,28 +463,15 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
|
|||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||
}
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
int8_t b;
|
||||
b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
// The samples are correlations against I and Q versions of the
|
||||
// tone that the tag AM-modulates, so every other sample is I,
|
||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
||||
// close to what we want.
|
||||
if(getNext) {
|
||||
int8_t r;
|
||||
if (getNext) {
|
||||
|
||||
if(b < 0) {
|
||||
r = -b;
|
||||
} else {
|
||||
r = b;
|
||||
}
|
||||
if(prev < 0) {
|
||||
r -= prev;
|
||||
} else {
|
||||
r += prev;
|
||||
}
|
||||
|
||||
dest[c++] = (uint8_t)r;
|
||||
dest[c++] = abs(b) + abs(prev);
|
||||
|
||||
if(c >= 20000) {
|
||||
break;
|
||||
|
@ -837,27 +824,27 @@ static void BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
|
|||
// Now the VICC>VCD responses when we are simulating a tag
|
||||
static void BuildInventoryResponse( uint8_t *uid)
|
||||
{
|
||||
uint8_t cmd[13];
|
||||
uint8_t cmd[12];
|
||||
|
||||
uint16_t crc;
|
||||
// one sub-carrier, inventory, 1 slot, fast rate
|
||||
// AFI is at bit 5 (1<<4) when doing an INVENTORY
|
||||
cmd[0] = 0x0d; // COM LEN? Data 8 + 4 //(1 << 2) | (1 << 5) | (1 << 1);
|
||||
cmd[1] = 0; // com_Adr
|
||||
cmd[2] = 0; // status 00 = success
|
||||
//(1 << 2) | (1 << 5) | (1 << 1);
|
||||
cmd[0] = 0; //
|
||||
cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
|
||||
// 64-bit UID
|
||||
cmd[3] = uid[7]; //0x32;
|
||||
cmd[4] = uid[6]; //0x4b;
|
||||
cmd[5] = uid[5]; //0x03;
|
||||
cmd[6] = uid[4]; //0x01;
|
||||
cmd[7] = uid[3]; //0x00;
|
||||
cmd[8] = uid[2]; //0x10;
|
||||
cmd[9] = uid[1]; //0x05;
|
||||
cmd[10] = uid[0]; //0xe0;
|
||||
cmd[2] = uid[7]; //0x32;
|
||||
cmd[3] = uid[6]; //0x4b;
|
||||
cmd[4] = uid[5]; //0x03;
|
||||
cmd[5] = uid[4]; //0x01;
|
||||
cmd[6] = uid[3]; //0x00;
|
||||
cmd[7] = uid[2]; //0x10;
|
||||
cmd[8] = uid[1]; //0x05;
|
||||
cmd[9] = uid[0]; //0xe0;
|
||||
//Now the CRC
|
||||
crc = Crc(cmd, 10);
|
||||
cmd[11] = crc & 0xff;
|
||||
cmd[12] = crc >> 8;
|
||||
cmd[10] = crc & 0xff;
|
||||
cmd[11] = crc >> 8;
|
||||
|
||||
CodeIso15693AsReader(cmd, sizeof(cmd));
|
||||
}
|
||||
|
@ -1124,9 +1111,6 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
|||
|
||||
memset(buf, 0x00, 100);
|
||||
|
||||
// Inventory response
|
||||
BuildInventoryResponse(uid);
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
@ -1149,6 +1133,9 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
|||
{
|
||||
// Build a suitable reponse to the reader INVENTORY cocmmand
|
||||
// not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below.
|
||||
|
||||
BuildInventoryResponse(uid);
|
||||
|
||||
TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait);
|
||||
}
|
||||
|
||||
|
@ -1156,6 +1143,10 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
|||
buf[0], buf[1], buf[2], buf[3],
|
||||
buf[4], buf[5], buf[6], buf[7], buf[8]);
|
||||
|
||||
Dbprintf("Simulationg uid: %x %x %x %x %x %x %x %x",
|
||||
uid[0], uid[1], uid[2], uid[3],
|
||||
uid[4], uid[5], uid[6], uid[7]);
|
||||
|
||||
LED_A_OFF();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
|
|
@ -456,21 +456,30 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
|
|||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
|
||||
|
||||
// Connect the A/D to the peak-detected low-frequency path.
|
||||
//SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
// Configure output and enable pin that is connected to the FPGA (for modulating)
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
|
||||
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // (PIO_PER) PIO Enable Register ,
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; // (PIO_OER) Output Enable Register
|
||||
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK; // (PIO_ODR) Output Disable Register
|
||||
|
||||
// Give it a bit of time for the resonant antenna to settle.
|
||||
SpinDelay(30);
|
||||
SpinDelay(150);
|
||||
|
||||
for(;;) {
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK); // wait for ssp_clk to go low
|
||||
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
|
||||
while(!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
|
||||
// PIO_PDSR = Pin Data Status Register
|
||||
// GPIO_SSC_CLK = SSC Transmit Clock
|
||||
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { // wait for ssp_clk to go high
|
||||
if(BUTTON_PRESS()) {
|
||||
DbpString("Stopped at 0");
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||
|
@ -479,12 +488,21 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
|
|||
WDT_HIT();
|
||||
}
|
||||
|
||||
if ( buff[i] )
|
||||
OPEN_COIL();
|
||||
else
|
||||
SHORT_COIL();
|
||||
// PIO_CODR = Clear Output Data Register
|
||||
// PIO_SODR = Set Output Data Register
|
||||
//#define LOW(x) AT91C_BASE_PIOA->PIO_CODR = (x)
|
||||
//#define HIGH(x) AT91C_BASE_PIOA->PIO_SODR = (x)
|
||||
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
||||
if ( buff[i] > 0 ){
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
//FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
|
||||
} else {
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
}
|
||||
|
||||
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { // wait for ssp_clk to go low
|
||||
if(BUTTON_PRESS()) {
|
||||
DbpString("Stopped at 1");
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||
|
@ -493,17 +511,22 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
|
|||
WDT_HIT();
|
||||
}
|
||||
|
||||
//SpinDelayUs(512);
|
||||
|
||||
++i;
|
||||
if(i == period) {
|
||||
i = 0;
|
||||
if (gap) {
|
||||
// turn of modulation
|
||||
SHORT_COIL();
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
// wait
|
||||
SpinDelay(gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
DbpString("Stopped");
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return;
|
||||
}
|
||||
|
||||
#define DEBUG_FRAME_CONTENTS 1
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "cmdmain.h"
|
||||
#include "cmddata.h"
|
||||
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
int CmdAmp(const char *Cmd)
|
||||
|
@ -670,7 +671,9 @@ int CmdManchesterDemod(const char *Cmd)
|
|||
// At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
|
||||
// Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
|
||||
// to stop output at the final bitidx2 value, not bitidx
|
||||
for (i = 0; i < bitidx; i += 2) {
|
||||
|
||||
//http://www.proxmark.org/forum/viewtopic.php?id=403
|
||||
for (i = 1; i < bitidx; i += 2) {
|
||||
if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
|
||||
BitStream[bit2idx++] = 1 ^ invert;
|
||||
} else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
|
||||
|
@ -713,7 +716,7 @@ int CmdManchesterDemod(const char *Cmd)
|
|||
BitStream[i+14],
|
||||
BitStream[i+15]);
|
||||
}
|
||||
return 0;
|
||||
return bit2idx;
|
||||
}
|
||||
|
||||
/* Modulate our data into manchester */
|
||||
|
@ -884,7 +887,7 @@ static command_t CommandTable[] =
|
|||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"amp", CmdAmp, 1, "Amplify peaks"},
|
||||
{"askdemod", Cmdaskdemod, 1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
|
||||
{"askdemod", Cmdaskdemod, 1, "<0|1> -- Attempt to demodulate simple ASK tags"},
|
||||
{"autocorr", CmdAutoCorr, 1, "<window length> -- Autocorrelation over window"},
|
||||
{"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
|
||||
{"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"},
|
||||
|
|
|
@ -202,6 +202,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
|
||||
switch (card->sak) {
|
||||
case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break;
|
||||
case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break;
|
||||
case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
|
||||
case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break;
|
||||
case 0x09: PrintAndLog("TYPE : NXP MIFARE Mini 0.3k"); break;
|
||||
|
|
|
@ -127,7 +127,7 @@ retest:
|
|||
PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);
|
||||
|
||||
/* Start back rows * 5 + 9 header bits, -1 to not start at same place */
|
||||
i -= 9 + (5 * rows) -2;
|
||||
i -= 9 + (5 * rows) -5;
|
||||
|
||||
rows = header = 0;
|
||||
}
|
||||
|
@ -220,11 +220,11 @@ int CmdEM410xSim(const char *Cmd)
|
|||
int clock = 64;
|
||||
|
||||
/* clear our graph */
|
||||
ClearGraph(1);
|
||||
ClearGraph(0);
|
||||
|
||||
/* write it out a few times */
|
||||
for (h = 0; h < 4; h++)
|
||||
{
|
||||
//for (h = 0; h < 4; h++)
|
||||
//{
|
||||
/* write 9 start bits */
|
||||
for (i = 0; i < 9; i++)
|
||||
AppendGraph(0, clock, 1);
|
||||
|
@ -262,10 +262,10 @@ int CmdEM410xSim(const char *Cmd)
|
|||
|
||||
/* stop bit */
|
||||
AppendGraph(0, clock, 0);
|
||||
}
|
||||
//}
|
||||
|
||||
/* modulate that biatch */
|
||||
CmdManchesterMod("64");
|
||||
//CmdManchesterMod("64");
|
||||
|
||||
/* booyah! */
|
||||
RepaintGraphWindow();
|
||||
|
@ -295,7 +295,7 @@ int CmdEM410xWatch(const char *Cmd)
|
|||
}
|
||||
|
||||
CmdLFRead(read_h ? "h" : "");
|
||||
CmdSamples("16000");
|
||||
CmdSamples("6000");
|
||||
|
||||
} while (
|
||||
!CmdEM410xRead("")
|
||||
|
@ -654,8 +654,10 @@ int CmdWriteWordPWD(const char *Cmd)
|
|||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
|
||||
{"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
|
||||
{"410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||
{"replay", MWRem4xReplay, 0, "Watches for tag and simulates manchester encoded em4x tag"},
|
||||
{"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
{"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||
{"410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
||||
|
@ -667,6 +669,265 @@ static command_t CommandTable[] =
|
|||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
//Confirms the parity of a bitstream as well as obtaining the data (TagID) from within the appropriate memory space.
|
||||
//Arguments:
|
||||
// Pointer to a string containing the desired bitsream
|
||||
// Pointer to a string that will receive the decoded tag ID
|
||||
// Length of the bitsream pointed at in the first argument, char* _strBitStream
|
||||
//Retuns:
|
||||
//1 Parity confirmed
|
||||
//0 Parity not confirmed
|
||||
int ConfirmEm410xTagParity( char* _strBitStream, char* pID, int LengthOfBitstream )
|
||||
{
|
||||
int i = 0;
|
||||
int rows = 0;
|
||||
int Parity[4] = {0x00};
|
||||
char ID[11] = {0x00};
|
||||
int k = 0;
|
||||
int BitStream[70] = {0x00};
|
||||
int counter = 0;
|
||||
//prepare variables
|
||||
for ( i = 0; i <= LengthOfBitstream; i++)
|
||||
{
|
||||
if (_strBitStream[i] == '1')
|
||||
{
|
||||
k =1;
|
||||
memcpy(&BitStream[i], &k,4);
|
||||
}
|
||||
else if (_strBitStream[i] == '0')
|
||||
{
|
||||
k = 0;
|
||||
memcpy(&BitStream[i], &k,4);
|
||||
}
|
||||
}
|
||||
while ( counter < 2 )
|
||||
{
|
||||
//set/reset variables and counters
|
||||
memset(ID,0x00,sizeof(ID));
|
||||
memset(Parity,0x00,sizeof(Parity));
|
||||
rows = 0;
|
||||
for ( i = 9; i <= LengthOfBitstream; i++)
|
||||
{
|
||||
if ( rows < 10 )
|
||||
{
|
||||
if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
|
||||
{
|
||||
sprintf(ID+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
|
||||
rows++;
|
||||
/* Keep parity info and move four bits ahead*/
|
||||
Parity[0] ^= BitStream[i];
|
||||
Parity[1] ^= BitStream[i+1];
|
||||
Parity[2] ^= BitStream[i+2];
|
||||
Parity[3] ^= BitStream[i+3];
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
if ( rows == 10 )
|
||||
{
|
||||
if ( BitStream[i] == Parity[0] && BitStream[i+1] == Parity[1] &&
|
||||
BitStream[i+2] == Parity[2] && BitStream[i+3] == Parity[3] &&
|
||||
BitStream[i+4] == 0)
|
||||
{
|
||||
memcpy(pID,ID,strlen(ID));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("[PARITY ->]Failed. Flipping Bits, and rechecking parity for bitstream:\n[PARITY ->]");
|
||||
for (k = 0; k < LengthOfBitstream; k++)
|
||||
{
|
||||
BitStream[k] ^= 1;
|
||||
printf("%i", BitStream[k]);
|
||||
}
|
||||
puts(" ");
|
||||
counter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//Reads and demodulates an em410x RFID tag. It further allows slight modification to the decoded bitstream
|
||||
//Once a suitable bitstream has been identified, and if needed, modified, it is replayed. Allowing emulation of the
|
||||
//"stolen" rfid tag.
|
||||
//No meaningful returns or arguments.
|
||||
int MWRem4xReplay(const char* Cmd)
|
||||
{
|
||||
// //header traces
|
||||
// static char ArrayTraceZero[] = { '0','0','0','0','0','0','0','0','0' };
|
||||
// static char ArrayTraceOne[] = { '1','1','1','1','1','1','1','1','1' };
|
||||
// //local string variables
|
||||
// char strClockRate[10] = {0x00};
|
||||
// char strAnswer[4] = {0x00};
|
||||
// char strTempBufferMini[2] = {0x00};
|
||||
// //our outbound bit-stream
|
||||
// char strSimulateBitStream[65] = {0x00};
|
||||
// //integers
|
||||
// int iClockRate = 0;
|
||||
// int needle = 0;
|
||||
// int j = 0;
|
||||
// int iFirstHeaderOffset = 0x00000000;
|
||||
// int numManchesterDemodBits=0;
|
||||
// //boolean values
|
||||
// bool bInverted = false;
|
||||
// //pointers to strings. memory will be allocated.
|
||||
// char* pstrInvertBitStream = 0x00000000;
|
||||
// char* pTempBuffer = 0x00000000;
|
||||
// char* pID = 0x00000000;
|
||||
// char* strBitStreamBuffer = 0x00000000;
|
||||
|
||||
|
||||
// puts("###################################");
|
||||
// puts("#### Em4x Replay ##");
|
||||
// puts("#### R.A.M. June 2013 ##");
|
||||
// puts("###################################");
|
||||
// //initialize
|
||||
// CmdLFRead("");
|
||||
// //Collect ourselves 10,000 samples
|
||||
// CmdSamples("10000");
|
||||
// puts("[->]preforming ASK demodulation\n");
|
||||
// //demodulate ask
|
||||
// Cmdaskdemod("0");
|
||||
// iClockRate = DetectClock(0);
|
||||
// sprintf(strClockRate, "%i\n",iClockRate);
|
||||
// printf("[->]Detected ClockRate: %s\n", strClockRate);
|
||||
|
||||
// //If detected clock rate is something completely unreasonable, dont go ahead
|
||||
// if ( iClockRate < 0xFFFE )
|
||||
// {
|
||||
// pTempBuffer = (char*)malloc(MAX_GRAPH_TRACE_LEN);
|
||||
// if (pTempBuffer == 0x00000000)
|
||||
// return 0;
|
||||
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
|
||||
// //Preform manchester de-modulation and display in a single line.
|
||||
// numManchesterDemodBits = CmdManchesterDemod( strClockRate );
|
||||
// //note: numManchesterDemodBits is set above in CmdManchesterDemod()
|
||||
// if ( numManchesterDemodBits == 0 )
|
||||
// return 0;
|
||||
// strBitStreamBuffer = malloc(numManchesterDemodBits+1);
|
||||
// if ( strBitStreamBuffer == 0x00000000 )
|
||||
// return 0;
|
||||
// memset(strBitStreamBuffer, 0x00, (numManchesterDemodBits+1));
|
||||
// //fill strBitStreamBuffer with demodulated, string formatted bits.
|
||||
// for ( j = 0; j <= numManchesterDemodBits; j++ )
|
||||
// {
|
||||
// sprintf(strTempBufferMini, "%i",BitStream[j]);
|
||||
// strcat(strBitStreamBuffer,strTempBufferMini);
|
||||
// }
|
||||
// printf("[->]Demodulated Bitstream: \n%s\n", strBitStreamBuffer);
|
||||
// //Reset counter and select most probable bit stream
|
||||
// j = 0;
|
||||
// while ( j < numManchesterDemodBits )
|
||||
// {
|
||||
// memset(strSimulateBitStream,0x00,64);
|
||||
// //search for header of nine (9) 0's : 000000000 or nine (9) 1's : 1111 1111 1
|
||||
// if ( ( strncmp(strBitStreamBuffer+j, ArrayTraceZero, sizeof(ArrayTraceZero)) == 0 ) ||
|
||||
// ( strncmp(strBitStreamBuffer+j, ArrayTraceOne, sizeof(ArrayTraceOne)) == 0 ) )
|
||||
// {
|
||||
// iFirstHeaderOffset = j;
|
||||
// memcpy(strSimulateBitStream, strBitStreamBuffer+j,64);
|
||||
// printf("[->]Offset of Header");
|
||||
// if ( strncmp(strBitStreamBuffer+iFirstHeaderOffset, "0", 1) == 0 )
|
||||
// printf("'%s'", ArrayTraceZero );
|
||||
// else
|
||||
// printf("'%s'", ArrayTraceOne );
|
||||
// printf(": %i\nHighlighted string : %s\n",iFirstHeaderOffset,strSimulateBitStream);
|
||||
// //allow us to escape loop or choose another frame
|
||||
// puts("[<-]Are we happy with this sample? [Y]es/[N]o");
|
||||
// gets(strAnswer);
|
||||
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
|
||||
// {
|
||||
// j = numManchesterDemodBits+1;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// j++;
|
||||
// }
|
||||
// }
|
||||
// else return 0;
|
||||
|
||||
// //Do we want the buffer inverted?
|
||||
// memset(strAnswer, 0x00, sizeof(strAnswer));
|
||||
// printf("[<-]Do you wish to invert the highlighted bitstream? [Y]es/[N]o\n");
|
||||
// gets(strAnswer);
|
||||
// if ( ( strncmp("y", strAnswer,1) == 0 ) || ( strncmp("Y", strAnswer, 1 ) == 0 ) )
|
||||
// {
|
||||
// //allocate heap memory
|
||||
// pstrInvertBitStream = (char*)malloc(numManchesterDemodBits);
|
||||
// if ( pstrInvertBitStream != 0x00000000 )
|
||||
// {
|
||||
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
|
||||
// bInverted = true;
|
||||
// //Invert Bitstream
|
||||
// for ( needle = 0; needle <= numManchesterDemodBits; needle++ )
|
||||
// {
|
||||
// if (strSimulateBitStream[needle] == '0')
|
||||
// strcat(pstrInvertBitStream,"1");
|
||||
// else if (strSimulateBitStream[needle] == '1')
|
||||
// strcat(pstrInvertBitStream,"0");
|
||||
// }
|
||||
// printf("[->]Inverted bitstream: %s\n", pstrInvertBitStream);
|
||||
// }
|
||||
// }
|
||||
// //Confirm parity of selected string
|
||||
// pID = (char*)malloc(11);
|
||||
// if (pID != 0x00000000)
|
||||
// {
|
||||
// memset(pID, 0x00, 11);
|
||||
// if (ConfirmEm410xTagParity(strSimulateBitStream,pID, 64) == 1)
|
||||
// {
|
||||
// printf("[->]Parity confirmed for selected bitstream!\n");
|
||||
// printf("[->]Tag ID was detected as: [hex]:%s\n",pID );
|
||||
// }
|
||||
// else
|
||||
// printf("[->]Parity check failed for the selected bitstream!\n");
|
||||
// }
|
||||
|
||||
// //Spoof
|
||||
// memset(strAnswer, 0x00, sizeof(strAnswer));
|
||||
// printf("[<-]Do you wish to continue with the EM4x simulation? [Y]es/[N]o\n");
|
||||
// gets(strAnswer);
|
||||
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
|
||||
// {
|
||||
// strcat(pTempBuffer, strClockRate);
|
||||
// strcat(pTempBuffer, " ");
|
||||
// if (bInverted == true)
|
||||
// strcat(pTempBuffer,pstrInvertBitStream);
|
||||
// if (bInverted == false)
|
||||
// strcat(pTempBuffer,strSimulateBitStream);
|
||||
// //inform the user
|
||||
// puts("[->]Starting simulation now: \n");
|
||||
// //Simulate tag with prepared buffer.
|
||||
// CmdLFSimManchester(pTempBuffer);
|
||||
// }
|
||||
// else if ( ( strcmp("n", strAnswer) == 0 ) || ( strcmp("N", strAnswer ) == 0 ) )
|
||||
// printf("[->]Exiting procedure now...\n");
|
||||
// else
|
||||
// printf("[->]Erroneous selection\nExiting procedure now....\n");
|
||||
|
||||
// //Clean up -- Exit function
|
||||
// //clear memory, then release pointer.
|
||||
// if ( pstrInvertBitStream != 0x00000000 )
|
||||
// {
|
||||
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
|
||||
// free(pstrInvertBitStream);
|
||||
// }
|
||||
// if ( pTempBuffer != 0x00000000 )
|
||||
// {
|
||||
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
|
||||
// free(pTempBuffer);
|
||||
// }
|
||||
// if ( pID != 0x00000000 )
|
||||
// {
|
||||
// memset(pID,0x00,11);
|
||||
// free(pID);
|
||||
// }
|
||||
// if ( strBitStreamBuffer != 0x00000000 )
|
||||
// {
|
||||
// memset(strBitStreamBuffer,0x00,numManchesterDemodBits);
|
||||
// free(strBitStreamBuffer);
|
||||
// }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFEM4X(const char *Cmd)
|
||||
{
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
|
|
|
@ -22,5 +22,6 @@ int CmdReadWord(const char *Cmd);
|
|||
int CmdReadWordPWD(const char *Cmd);
|
||||
int CmdWriteWord(const char *Cmd);
|
||||
int CmdWriteWordPWD(const char *Cmd);
|
||||
int MWRem4xReplay(const char* Cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -89,6 +89,9 @@ int DetectClock(int peak)
|
|||
case 1: clock--; break;
|
||||
case 2: clock -= 2; break;
|
||||
}
|
||||
if ( clock < 32)
|
||||
clock = 32;
|
||||
|
||||
printf("- adjusted it to %d \n", clock);
|
||||
return clock;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ local skel_1 = [[
|
|||
return "UNKNOWN"
|
||||
}
|
||||
|
||||
add("04,,,Mifare TNP3xxx Activision 1K,0f01,01");
|
||||
add("04,,,Mifare Mini,0004,09");
|
||||
add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08");
|
||||
add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10");
|
||||
|
|
384
client/lualibs/md5.lua
Normal file
384
client/lualibs/md5.lua
Normal file
|
@ -0,0 +1,384 @@
|
|||
local md5 = {
|
||||
_VERSION = "md5.lua 0.5.0",
|
||||
_DESCRIPTION = "MD5 computation in Lua (5.1)",
|
||||
_URL = "https://github.com/kikito/md5.lua",
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
-- bit lib implementions
|
||||
|
||||
local floor, abs, max = math.floor, math.abs, math.max
|
||||
local char, byte, format, rep, sub =
|
||||
string.char, string.byte, string.format, string.rep, string.sub
|
||||
|
||||
local function check_int(n)
|
||||
-- checking not float
|
||||
if(n - floor(n) > 0) then
|
||||
error("trying to use bitwise operation on non-integer!")
|
||||
end
|
||||
end
|
||||
|
||||
local function tbl2number(tbl)
|
||||
local n = #tbl
|
||||
|
||||
local rslt = 0
|
||||
local power = 1
|
||||
for i = 1, n do
|
||||
rslt = rslt + tbl[i]*power
|
||||
power = power*2
|
||||
end
|
||||
|
||||
return rslt
|
||||
end
|
||||
|
||||
local function expand(tbl_m, tbl_n)
|
||||
local big = {}
|
||||
local small = {}
|
||||
if(#tbl_m > #tbl_n) then
|
||||
big = tbl_m
|
||||
small = tbl_n
|
||||
else
|
||||
big = tbl_n
|
||||
small = tbl_m
|
||||
end
|
||||
-- expand small
|
||||
for i = #small + 1, #big do
|
||||
small[i] = 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local to_bits -- needs to be declared before bit_not
|
||||
|
||||
local function bit_not(n)
|
||||
local tbl = to_bits(n)
|
||||
local size = max(#tbl, 32)
|
||||
for i = 1, size do
|
||||
if(tbl[i] == 1) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
-- defined as local above
|
||||
to_bits = function (n)
|
||||
check_int(n)
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
return to_bits(bit_not(abs(n)) + 1)
|
||||
end
|
||||
-- to bits table
|
||||
local tbl = {}
|
||||
local cnt = 1
|
||||
while (n > 0) do
|
||||
local last = math.fmod(n,2)
|
||||
if(last == 1) then
|
||||
tbl[cnt] = 1
|
||||
else
|
||||
tbl[cnt] = 0
|
||||
end
|
||||
n = (n-last)/2
|
||||
cnt = cnt + 1
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
local function bit_or(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = max(#tbl_m, #tbl_n)
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
local function bit_and(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = max(#tbl_m, #tbl_n)
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
local function bit_xor(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = max(#tbl_m, #tbl_n)
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i] ~= tbl_n[i]) then
|
||||
tbl[i] = 1
|
||||
else
|
||||
tbl[i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
local function bit_rshift(n, bits)
|
||||
check_int(n)
|
||||
|
||||
local high_bit = 0
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(abs(n)) + 1
|
||||
high_bit = 2147483648 -- 0x80000000
|
||||
end
|
||||
|
||||
for i=1, bits do
|
||||
n = n/2
|
||||
n = bit_or(floor(n), high_bit)
|
||||
end
|
||||
return floor(n)
|
||||
end
|
||||
|
||||
local function bit_lshift(n, bits)
|
||||
check_int(n)
|
||||
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(abs(n)) + 1
|
||||
end
|
||||
|
||||
for i=1, bits do
|
||||
n = n*2
|
||||
end
|
||||
return bit_and(n, 4294967295) -- 0xFFFFFFFF
|
||||
end
|
||||
|
||||
-- convert little-endian 32-bit int to a 4-char string
|
||||
local function lei2str(i)
|
||||
local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
|
||||
return f(0)..f(8)..f(16)..f(24)
|
||||
end
|
||||
|
||||
-- convert raw string to big-endian int
|
||||
local function str2bei(s)
|
||||
local v=0
|
||||
for i=1, #s do
|
||||
v = v * 256 + byte(s, i)
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- convert raw string to little-endian int
|
||||
local function str2lei(s)
|
||||
local v=0
|
||||
for i = #s,1,-1 do
|
||||
v = v*256 + byte(s, i)
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- cut up a string in little-endian ints of given size
|
||||
local function cut_le_str(s,...)
|
||||
local o, r = 1, {}
|
||||
local args = {...}
|
||||
for i=1, #args do
|
||||
table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
|
||||
o = o + args[i]
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
local swap = function (w) return str2bei(lei2str(w)) end
|
||||
|
||||
local function hex2binaryaux(hexval)
|
||||
return char(tonumber(hexval, 16))
|
||||
end
|
||||
|
||||
local function hex2binary(hex)
|
||||
local result, _ = hex:gsub('..', hex2binaryaux)
|
||||
return result
|
||||
end
|
||||
|
||||
-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
|
||||
-- 10/02/2001 jcw@equi4.com
|
||||
|
||||
local FF = 0xffffffff
|
||||
local CONSTS = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
|
||||
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
|
||||
}
|
||||
|
||||
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
|
||||
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
|
||||
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
|
||||
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
|
||||
local z=function (f,a,b,c,d,x,s,ac)
|
||||
a=bit_and(a+f(b,c,d)+x+ac,FF)
|
||||
-- be *very* careful that left shift does not cause rounding!
|
||||
return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
|
||||
end
|
||||
|
||||
local function transform(A,B,C,D,X)
|
||||
local a,b,c,d=A,B,C,D
|
||||
local t=CONSTS
|
||||
|
||||
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
|
||||
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
|
||||
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
|
||||
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
|
||||
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
|
||||
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
|
||||
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
|
||||
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
|
||||
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
|
||||
d=z(f,d,a,b,c,X[ 9],12,t[10])
|
||||
c=z(f,c,d,a,b,X[10],17,t[11])
|
||||
b=z(f,b,c,d,a,X[11],22,t[12])
|
||||
a=z(f,a,b,c,d,X[12], 7,t[13])
|
||||
d=z(f,d,a,b,c,X[13],12,t[14])
|
||||
c=z(f,c,d,a,b,X[14],17,t[15])
|
||||
b=z(f,b,c,d,a,X[15],22,t[16])
|
||||
|
||||
a=z(g,a,b,c,d,X[ 1], 5,t[17])
|
||||
d=z(g,d,a,b,c,X[ 6], 9,t[18])
|
||||
c=z(g,c,d,a,b,X[11],14,t[19])
|
||||
b=z(g,b,c,d,a,X[ 0],20,t[20])
|
||||
a=z(g,a,b,c,d,X[ 5], 5,t[21])
|
||||
d=z(g,d,a,b,c,X[10], 9,t[22])
|
||||
c=z(g,c,d,a,b,X[15],14,t[23])
|
||||
b=z(g,b,c,d,a,X[ 4],20,t[24])
|
||||
a=z(g,a,b,c,d,X[ 9], 5,t[25])
|
||||
d=z(g,d,a,b,c,X[14], 9,t[26])
|
||||
c=z(g,c,d,a,b,X[ 3],14,t[27])
|
||||
b=z(g,b,c,d,a,X[ 8],20,t[28])
|
||||
a=z(g,a,b,c,d,X[13], 5,t[29])
|
||||
d=z(g,d,a,b,c,X[ 2], 9,t[30])
|
||||
c=z(g,c,d,a,b,X[ 7],14,t[31])
|
||||
b=z(g,b,c,d,a,X[12],20,t[32])
|
||||
|
||||
a=z(h,a,b,c,d,X[ 5], 4,t[33])
|
||||
d=z(h,d,a,b,c,X[ 8],11,t[34])
|
||||
c=z(h,c,d,a,b,X[11],16,t[35])
|
||||
b=z(h,b,c,d,a,X[14],23,t[36])
|
||||
a=z(h,a,b,c,d,X[ 1], 4,t[37])
|
||||
d=z(h,d,a,b,c,X[ 4],11,t[38])
|
||||
c=z(h,c,d,a,b,X[ 7],16,t[39])
|
||||
b=z(h,b,c,d,a,X[10],23,t[40])
|
||||
a=z(h,a,b,c,d,X[13], 4,t[41])
|
||||
d=z(h,d,a,b,c,X[ 0],11,t[42])
|
||||
c=z(h,c,d,a,b,X[ 3],16,t[43])
|
||||
b=z(h,b,c,d,a,X[ 6],23,t[44])
|
||||
a=z(h,a,b,c,d,X[ 9], 4,t[45])
|
||||
d=z(h,d,a,b,c,X[12],11,t[46])
|
||||
c=z(h,c,d,a,b,X[15],16,t[47])
|
||||
b=z(h,b,c,d,a,X[ 2],23,t[48])
|
||||
|
||||
a=z(i,a,b,c,d,X[ 0], 6,t[49])
|
||||
d=z(i,d,a,b,c,X[ 7],10,t[50])
|
||||
c=z(i,c,d,a,b,X[14],15,t[51])
|
||||
b=z(i,b,c,d,a,X[ 5],21,t[52])
|
||||
a=z(i,a,b,c,d,X[12], 6,t[53])
|
||||
d=z(i,d,a,b,c,X[ 3],10,t[54])
|
||||
c=z(i,c,d,a,b,X[10],15,t[55])
|
||||
b=z(i,b,c,d,a,X[ 1],21,t[56])
|
||||
a=z(i,a,b,c,d,X[ 8], 6,t[57])
|
||||
d=z(i,d,a,b,c,X[15],10,t[58])
|
||||
c=z(i,c,d,a,b,X[ 6],15,t[59])
|
||||
b=z(i,b,c,d,a,X[13],21,t[60])
|
||||
a=z(i,a,b,c,d,X[ 4], 6,t[61])
|
||||
d=z(i,d,a,b,c,X[11],10,t[62])
|
||||
c=z(i,c,d,a,b,X[ 2],15,t[63])
|
||||
b=z(i,b,c,d,a,X[ 9],21,t[64])
|
||||
|
||||
return A+a,B+b,C+c,D+d
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
function md5.sumhexa(s)
|
||||
local msgLen = #s
|
||||
local padLen = 56 - msgLen % 64
|
||||
|
||||
if msgLen % 64 > 56 then padLen = padLen + 64 end
|
||||
|
||||
if padLen == 0 then padLen = 64 end
|
||||
|
||||
s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
|
||||
|
||||
assert(#s % 64 == 0)
|
||||
|
||||
local t = CONSTS
|
||||
local a,b,c,d = t[65],t[66],t[67],t[68]
|
||||
|
||||
for i=1,#s,64 do
|
||||
local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
|
||||
assert(#X == 16)
|
||||
X[0] = table.remove(X,1) -- zero based!
|
||||
a,b,c,d = transform(a,b,c,d,X)
|
||||
end
|
||||
|
||||
return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
|
||||
end
|
||||
|
||||
function md5.sum(s)
|
||||
return hex2binary(md5.sumhexa(s))
|
||||
end
|
||||
|
||||
return md5
|
|
@ -141,7 +141,13 @@ local _keys = {
|
|||
'200000000000',
|
||||
'a00000000000',
|
||||
'b00000000000',
|
||||
}
|
||||
|
||||
--[[
|
||||
Should be for Mifare TNP3xxx tags A KEY.
|
||||
--]]
|
||||
'4b0b20107ccb',
|
||||
|
||||
}
|
||||
|
||||
---
|
||||
-- The keys above have just been pasted in, for completeness sake. They contain duplicates.
|
||||
|
|
|
@ -25,6 +25,7 @@ local ISO14A_COMMAND = {
|
|||
|
||||
local ISO14443a_TYPES = {}
|
||||
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C"
|
||||
ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
|
||||
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
|
||||
ISO14443a_TYPES[0x08] = "NXP MIFARE CLASSIC 1k | Plus 2k"
|
||||
ISO14443a_TYPES[0x09] = "NXP MIFARE Mini 0.3k"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "util.h"
|
||||
#include "nonce2key/nonce2key.h"
|
||||
#include "../common/iso15693tools.h"
|
||||
#include <openssl/aes.h>
|
||||
/**
|
||||
* The following params expected:
|
||||
* UsbCommand c
|
||||
|
@ -224,6 +225,44 @@ static int l_iso15693_crc(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Simple AES 128 cbc hook up to OpenSSL.
|
||||
params: key, input
|
||||
*/
|
||||
static int l_aes(lua_State *L)
|
||||
{
|
||||
//Check number of arguments
|
||||
int i;
|
||||
size_t size;
|
||||
const char *p_key = luaL_checklstring(L, 1, &size);
|
||||
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
|
||||
|
||||
const char *p_encTxt = luaL_checklstring(L, 2, &size);
|
||||
|
||||
unsigned char indata[AES_BLOCK_SIZE] = {0x00};
|
||||
unsigned char outdata[AES_BLOCK_SIZE] = {0x00};
|
||||
unsigned char aes_key[AES_BLOCK_SIZE] = {0x00};
|
||||
unsigned char iv[AES_BLOCK_SIZE] = {0x00};
|
||||
|
||||
// convert key to bytearray
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
|
||||
}
|
||||
|
||||
// convert input to bytearray
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
|
||||
}
|
||||
|
||||
AES_KEY key;
|
||||
AES_set_decrypt_key(aes_key, 128, &key);
|
||||
AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT);
|
||||
|
||||
//Push decrypted array as a string
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;// return 1 to signal one return value
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
|
||||
* able to do "require('foobar')" if foobar.lua is within lualibs folder.
|
||||
|
@ -261,6 +300,7 @@ int set_pm3_libraries(lua_State *L)
|
|||
{"clearCommandBuffer", l_clearCommandBuffer},
|
||||
{"console", l_CmdConsole},
|
||||
{"iso15693_crc", l_iso15693_crc},
|
||||
{"aes", l_aes},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -133,6 +133,8 @@ function nested(key,sak)
|
|||
typ = 0
|
||||
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
|
||||
typ = 2
|
||||
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
|
||||
typ = 1
|
||||
else
|
||||
print("I don't know how many sectors there are on this type of card, defaulting to 16")
|
||||
end
|
||||
|
|
189
client/scripts/tnp3.lua
Normal file
189
client/scripts/tnp3.lua
Normal file
|
@ -0,0 +1,189 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local bin = require('bin')
|
||||
local lib14a = require('read14a')
|
||||
local utils = require('utils')
|
||||
local md5 = require('md5')
|
||||
|
||||
example =[[
|
||||
1. script run tnp3
|
||||
2. script run tnp3 -k aabbccddeeff
|
||||
]]
|
||||
author = "Iceman"
|
||||
usage = "script run tnp3 -k <key>"
|
||||
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.
|
||||
Arguments:
|
||||
-h - this help
|
||||
-k <key> - Sector 0 Key A.
|
||||
]]
|
||||
|
||||
local hashconstant = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
||||
|
||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||
local DEBUG = true -- the debug flag
|
||||
local numBlocks = 64
|
||||
local numSectors = 16
|
||||
---
|
||||
-- A debug printout-function
|
||||
function dbg(args)
|
||||
if not DEBUG then
|
||||
return
|
||||
end
|
||||
|
||||
if type(args) == "table" then
|
||||
local i = 1
|
||||
while result[i] do
|
||||
dbg(result[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print("###", args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- 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
|
||||
--
|
||||
-- Exit message
|
||||
function ExitMsg(msg)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print(msg)
|
||||
print()
|
||||
end
|
||||
|
||||
local function show(data)
|
||||
if DEBUG then
|
||||
local formatString = ("H%d"):format(string.len(data))
|
||||
local _,hexdata = bin.unpack(formatString, data)
|
||||
dbg("Hexdata" , hexdata)
|
||||
end
|
||||
end
|
||||
|
||||
function waitCmd()
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||
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 main(args)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print()
|
||||
|
||||
local keyA
|
||||
local cmd
|
||||
local err
|
||||
local cmdReadBlockString = 'hf mf rdbl %d A %s'
|
||||
|
||||
-- Arguments for the script
|
||||
for o, a in getopt.getopt(args, 'hk:') do
|
||||
if o == "h" then return help() end
|
||||
if o == "k" then keyA = a end
|
||||
end
|
||||
|
||||
-- validate input args.
|
||||
keyA = keyA or '4b0b20107ccb'
|
||||
if #(keyA) ~= 12 then
|
||||
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
|
||||
end
|
||||
|
||||
result, err = lib14a.read1443a(false)
|
||||
if not result then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
print((" Found tag : %s"):format(result.name))
|
||||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
|
||||
print("This is not a TNP3xxx tag. aborting.")
|
||||
return
|
||||
end
|
||||
|
||||
-- Show info
|
||||
print(('Using keyA : %s'):format(keyA))
|
||||
print( string.rep('--',20) )
|
||||
|
||||
local cmdNestedString = 'hf mf nested 1 0 A %s d'
|
||||
local cmdDumpString = 'hf mf dump'
|
||||
--core.console(cmdNestedString.format(keyA) )
|
||||
--core.console(cmdDumpString)
|
||||
|
||||
print('Reading data need to dump data')
|
||||
|
||||
-- Read block 0
|
||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
|
||||
err = core.SendCommand(cmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local block0, err = waitCmd()
|
||||
if err then return oops(err) end
|
||||
|
||||
-- Read block 1
|
||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1,arg2 = 0,arg3 = 0, data = keyA}
|
||||
local err = core.SendCommand(cmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local block1, err = waitCmd()
|
||||
if err then return oops(err) end
|
||||
|
||||
|
||||
-- Read block 9
|
||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 9,arg2 = 0,arg3 = 0, data = '56f6313550f9'}
|
||||
local err = core.SendCommand(cmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local block9, err = waitCmd()
|
||||
if err then return oops(err) end
|
||||
|
||||
-- main loop
|
||||
print('BLOCK MD5 DECRYPTED ASCII' )
|
||||
|
||||
for block=0,numBlocks-1,1 do
|
||||
|
||||
if math.fmod(block,4) then
|
||||
|
||||
end
|
||||
|
||||
local base = ('%s%s%02d%s'):format(block0, block1, block, hashconstant)
|
||||
local md5hash = md5.sumhexa(base)
|
||||
local aestest = core.aes(md5hash, block9 )
|
||||
|
||||
local _,hex = bin.unpack(("H%d"):format(16),aestest)
|
||||
|
||||
|
||||
local hexascii = string.gsub(hex, '(%x%x)',
|
||||
function(value)
|
||||
return string.char(tonumber(value, 16))
|
||||
end
|
||||
)
|
||||
|
||||
print( block .. ' :: ' .. md5hash .. ' :: ' .. hex .. ' :: ' .. hexascii )
|
||||
|
||||
-- if core.ukbhit() then
|
||||
-- print("aborted by user")
|
||||
-- break
|
||||
-- end
|
||||
end
|
||||
end
|
||||
|
||||
main(args)
|
|
@ -428,7 +428,7 @@ typedef struct _AT91S_PIO {
|
|||
#define PIO_PDR (AT91_CAST(AT91_REG *) 0x00000004) // (PIO_PDR) PIO Disable Register
|
||||
#define PIO_PSR (AT91_CAST(AT91_REG *) 0x00000008) // (PIO_PSR) PIO Status Register
|
||||
#define PIO_OER (AT91_CAST(AT91_REG *) 0x00000010) // (PIO_OER) Output Enable Register
|
||||
#define PIO_ODR (AT91_CAST(AT91_REG *) 0x00000014) // (PIO_ODR) Output Disable Registerr
|
||||
#define PIO_ODR (AT91_CAST(AT91_REG *) 0x00000014) // (PIO_ODR) Output Disable Register
|
||||
#define PIO_OSR (AT91_CAST(AT91_REG *) 0x00000018) // (PIO_OSR) Output Status Register
|
||||
#define PIO_IFER (AT91_CAST(AT91_REG *) 0x00000020) // (PIO_IFER) Input Filter Enable Register
|
||||
#define PIO_IFDR (AT91_CAST(AT91_REG *) 0x00000024) // (PIO_IFDR) Input Filter Disable Register
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue