From: iceman1001 Date: Mon, 3 Nov 2014 12:49:19 +0000 (+0100) Subject: ADD: added identification for Mifare TNP3xxx tags. X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/c15d2bdc9b25da89931c767902639fa7e8c9b764 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" --- diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 42cb0ab8..11a49902 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -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(b < 0) { - r = -b; - } else { - r = b; - } - if(prev < 0) { - r -= prev; - } else { - r += prev; - } + if (getNext) { - 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(); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c80caf77..dc5efe68 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -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); + + 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(!BUTTON_PRESS()) { + WDT_HIT(); - for(;;) { - - while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { + // 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(); - - while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { + // 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) + + 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 @@ -492,18 +510,23 @@ 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 diff --git a/client/cmddata.c b/client/cmddata.c index b01b45ba..1df3486d 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -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, " -- Autocorrelation over window"}, {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, {"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"}, diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index bd19cee4..0f2b5222 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -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; diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 67013b2e..07f909ac 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -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, " -- 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, " <'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); diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index a209e8f9..587dbf7f 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -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 diff --git a/client/graph.c b/client/graph.c index 4e8cb89c..7b45f3f2 100644 --- a/client/graph.c +++ b/client/graph.c @@ -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; } diff --git a/client/lualibs/htmlskel.lua b/client/lualibs/htmlskel.lua index a52abdef..b468eb2d 100644 --- a/client/lualibs/htmlskel.lua +++ b/client/lualibs/htmlskel.lua @@ -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"); diff --git a/client/lualibs/md5.lua b/client/lualibs/md5.lua new file mode 100644 index 00000000..2390f957 --- /dev/null +++ b/client/lualibs/md5.lua @@ -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 diff --git a/client/lualibs/mf_default_keys.lua b/client/lualibs/mf_default_keys.lua index 4859ff0c..b9b414d8 100644 --- a/client/lualibs/mf_default_keys.lua +++ b/client/lualibs/mf_default_keys.lua @@ -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. diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua index 24021a1d..10e7c2d4 100644 --- a/client/lualibs/read14a.lua +++ b/client/lualibs/read14a.lua @@ -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" diff --git a/client/scripting.c b/client/scripting.c index 963bb64c..fd065a04 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -18,6 +18,7 @@ #include "util.h" #include "nonce2key/nonce2key.h" #include "../common/iso15693tools.h" +#include /** * 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. @@ -259,8 +298,9 @@ int set_pm3_libraries(lua_State *L) {"foobar", l_foobar}, {"ukbhit", l_ukbhit}, {"clearCommandBuffer", l_clearCommandBuffer}, - {"console", l_CmdConsole}, - {"iso15693_crc", l_iso15693_crc}, + {"console", l_CmdConsole}, + {"iso15693_crc", l_iso15693_crc}, + {"aes", l_aes}, {NULL, NULL} }; diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index 8d0d358f..eb98ffbf 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -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 diff --git a/client/scripts/tnp3.lua b/client/scripts/tnp3.lua new file mode 100644 index 00000000..3eb5af1c --- /dev/null +++ b/client/scripts/tnp3.lua @@ -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 " +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 - 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) \ No newline at end of file diff --git a/include/at91sam7s512.h b/include/at91sam7s512.h index 5be13622..2cdcbce3 100644 --- a/include/at91sam7s512.h +++ b/include/at91sam7s512.h @@ -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