From: marshmellow42 Date: Thu, 16 Jul 2015 02:25:11 +0000 (-0400) Subject: Merge remote-tracking branch 'upstream/master' X-Git-Tag: v2.3.0~33^2~1 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/d5810937bdf7fd5aab2629c58740eecac1ac3b7c?hp=b362de62621f17b297f08bd53082b3aea45219e6 Merge remote-tracking branch 'upstream/master' Conflicts: armsrc/iso14443b.c --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 75b9ad9b..42b6bcbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,19 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... -## [Unreleased][unreleased] +## [unreleased][unreleased] + +### Changed +- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers) + +## [2.2.0][2015-07-12] ### Changed - Added `hf 14b raw -s` option to auto select a 14b std tag before raw command - Changed `hf 14b write` to `hf 14b sriwrite` as it only applied to sri tags (marshmellow) - Added `hf 14b info` to `hf search` (marshmellow) +- Added compression of fpga config and data, *BOOTROM REFLASH REQUIRED* (piwi) +- Implemented better detection of mifare-tags that are not vulnerable to classic attacks (`hf mf mifare`, `hf mf nested`) (piwi) ### Added - Add `hf 14b info` to find and print info about std 14b tags and sri tags (using 14b raw commands in the client) (marshmellow) diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index b44a1263..0e2f1744 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -24,15 +24,15 @@ extern uint8_t *BigBuf_get_addr(void); extern uint8_t *BigBuf_get_EM_addr(void); extern uint16_t BigBuf_max_traceLen(void); -void BigBuf_Clear(void); +extern void BigBuf_Clear(void); extern uint8_t *BigBuf_malloc(uint16_t); extern void BigBuf_free(void); extern void BigBuf_free_keep_EM(void); -uint16_t BigBuf_get_traceLen(void); -void clear_trace(); -void set_tracing(bool enable); -bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); -int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); -uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); +extern uint16_t BigBuf_get_traceLen(void); +extern void clear_trace(); +extern void set_tracing(bool enable); +extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); +extern int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); +extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); #endif /* __BIGBUF_H */ diff --git a/armsrc/Makefile b/armsrc/Makefile index 1214c949..141cf0ec 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -9,17 +9,17 @@ APP_INCLUDES = apps.h #remove one of the following defines and comment out the relevant line -#in the next section to remove that particular feature from compilation +#in the next section to remove that particular feature from compilation APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE \ -fno-strict-aliasing -ffunction-sections -fdata-sections -#-DWITH_LCD +#-DWITH_LCD #SRC_LCD = fonts.c LCD.c SRC_LF = lfops.c hitag2.c lfsampling.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443b = iso14443b.c -SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c +SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c #the FPGA bitstream files. Note: order matters! @@ -65,7 +65,7 @@ ARMSRC = fpgaloader.c \ # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC include ../common/Makefile.common -OBJS = $(OBJDIR)/fullimage.s19 +OBJS = $(OBJDIR)/fullimage.s19 FPGA_COMPRESSOR = ../client/fpga_compress all: $(OBJS) @@ -80,13 +80,13 @@ $(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(FPGA_COMPRESSOR): make -C ../client $(notdir $(FPGA_COMPRESSOR)) - + $(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) $(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf $(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@ - + $(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@ @@ -94,14 +94,14 @@ $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf $(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@ $(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR) - $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ - + $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ + $(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ $(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ - + tarbin: $(OBJS) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) diff --git a/armsrc/apps.h b/armsrc/apps.h index bb094b33..42efd118 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -121,7 +121,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) //void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain); void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); +void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); diff --git a/armsrc/epa.c b/armsrc/epa.c index 6bd8692e..50c7d878 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -12,10 +12,11 @@ //----------------------------------------------------------------------------- #include "iso14443a.h" +#include "iso14443b.h" #include "epa.h" #include "cmd.h" -// Protocol and Parameter Selection Request +// Protocol and Parameter Selection Request for ISO 14443 type A cards // use regular (1x) speed in both directions // CRC is already included static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6}; @@ -100,6 +101,28 @@ static struct { // lengths of the replay APDUs static uint8_t apdu_lengths_replay[5]; +// type of card (ISO 14443 A or B) +static char iso_type = 0; + +//----------------------------------------------------------------------------- +// Wrapper for sending APDUs to type A and B cards +//----------------------------------------------------------------------------- +int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) +{ + switch(iso_type) + { + case 'a': + return iso14_apdu(apdu, (uint16_t) length, response); + break; + case 'b': + return iso14443b_apdu(apdu, length, response); + break; + default: + return 0; + break; + } +} + //----------------------------------------------------------------------------- // Closes the communication channel and turns off the field //----------------------------------------------------------------------------- @@ -107,6 +130,7 @@ void EPA_Finish() { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); + iso_type = 0; } //----------------------------------------------------------------------------- @@ -204,26 +228,26 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) int rapdu_length = 0; // select the file EF.CardAccess - rapdu_length = iso14_apdu((uint8_t *)apdu_select_binary_cardaccess, + rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess, sizeof(apdu_select_binary_cardaccess), response_apdu); - if (rapdu_length != 6 + if (rapdu_length < 6 || response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 3] != 0x00) { - Dbprintf("epa - no select cardaccess"); + DbpString("Failed to select EF.CardAccess!"); return -1; } // read the file - rapdu_length = iso14_apdu((uint8_t *)apdu_read_binary, + rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary, sizeof(apdu_read_binary), response_apdu); if (rapdu_length <= 6 || response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 3] != 0x00) { - Dbprintf("epa - no read cardaccess"); + Dbprintf("Failed to read EF.CardAccess!"); return -1; } @@ -338,7 +362,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) // send it uint8_t response_apdu[262]; - int send_return = iso14_apdu(apdu, + int send_return = EPA_APDU(apdu, sizeof(apdu), response_apdu); // check if the command succeeded @@ -409,7 +433,7 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) apdu[4] = apdu_length - 5; // send it uint8_t response_apdu[6]; - int send_return = iso14_apdu(apdu, + int send_return = EPA_APDU(apdu, apdu_length, response_apdu); // check if the command succeeded @@ -460,16 +484,13 @@ void EPA_PACE_Replay(UsbCommand *c) return; } - // increase the timeout (at least some cards really do need this!)///////////// - // iso14a_set_timeout(0x0003FFFF); - // response APDU uint8_t response_apdu[300] = {0}; // now replay the data and measure the timings for (int i = 0; i < sizeof(apdu_lengths_replay); i++) { StartCountUS(); - func_return = iso14_apdu(apdus_replay[i].data, + func_return = EPA_APDU(apdus_replay[i].data, apdu_lengths_replay[i], response_apdu); timings[i] = GetCountUS(); @@ -501,18 +522,33 @@ int EPA_Setup() uint8_t pps_response_par[1]; iso14a_card_select_t card_select_info; + // first, look for type A cards // power up the field iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); // select the card return_code = iso14443a_select_card(uid, &card_select_info, NULL); - if (return_code != 1) { - return 1; + if (return_code == 1) { + // send the PPS request + ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); + return_code = ReaderReceive(pps_response, pps_response_par); + if (return_code != 3 || pps_response[0] != 0xD0) { + return return_code == 0 ? 2 : return_code; + } + Dbprintf("ISO 14443 Type A"); + iso_type = 'a'; + return 0; } - // send the PPS request - ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); - return_code = ReaderReceive(pps_response, pps_response_par); - if (return_code != 3 || pps_response[0] != 0xD0) { - return return_code == 0 ? 2 : return_code; + + // if we're here, there is no type A card, so we look for type B + // power up the field + iso14443b_setup(); + // select the card + return_code = iso14443b_select_card(); + if (return_code == 1) { + Dbprintf("ISO 14443 Type B"); + iso_type = 'b'; + return 0; } - return 0; + Dbprintf("No card found."); + return 1; } diff --git a/armsrc/epa.h b/armsrc/epa.h index 0c580205..d2ebed57 100644 --- a/armsrc/epa.h +++ b/armsrc/epa.h @@ -19,7 +19,7 @@ typedef struct { uint8_t parameter_id; } pace_version_info_t; -// note: EPA_PACE_Collect_Nonce is declared in apps.h +// note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h // general functions void EPA_Finish(); diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index bfbd7bf5..82e5dd6a 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -19,6 +19,9 @@ #define RECEIVE_SAMPLES_TIMEOUT 2000 #define ISO14443B_DMA_BUFFER_SIZE 256 +// PCB Block number for APDUs +static uint8_t pcb_blocknum = 0; + //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using // a UART kind of thing that's implemented in software. When we get a @@ -311,7 +314,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) } } } - + return FALSE; } @@ -924,6 +927,98 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) } } +/* Sends an APDU to the tag + * TODO: check CRC and preamble + */ +int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response) +{ + uint8_t message_frame[message_length + 4]; + // PCB + message_frame[0] = 0x0A | pcb_blocknum; + pcb_blocknum ^= 1; + // CID + message_frame[1] = 0; + // INF + memcpy(message_frame + 2, message, message_length); + // EDC (CRC) + ComputeCrc14443(CRC_14443_B, message_frame, message_length + 2, &message_frame[message_length + 2], &message_frame[message_length + 3]); + // send + CodeAndTransmit14443bAsReader(message_frame, message_length + 4); + // get response + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, TRUE); + if(Demod.len < 3) + { + return 0; + } + // TODO: Check CRC + // copy response contents + if(response != NULL) + { + memcpy(response, Demod.output, Demod.len); + } + return Demod.len; +} + +/* Perform the ISO 14443 B Card Selection procedure + * Currently does NOT do any collision handling. + * It expects 0-1 cards in the device's range. + * TODO: Support multiple cards (perform anticollision) + * TODO: Verify CRC checksums + */ +int iso14443b_select_card() +{ + // WUPB command (including CRC) + // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state + static const uint8_t wupb[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; + // ATTRIB command (with space for CRC) + uint8_t attrib[] = { 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; + + // first, wake up the tag + CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + // ATQB too short? + if (Demod.len < 14) + { + return 2; + } + + // select the tag + // copy the PUPI to ATTRIB + memcpy(attrib + 1, Demod.output + 1, 4); + /* copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into + ATTRIB (Param 3) */ + attrib[7] = Demod.output[10] & 0x0F; + ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10); + CodeAndTransmit14443bAsReader(attrib, sizeof(attrib)); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + // Answer to ATTRIB too short? + if(Demod.len < 3) + { + return 2; + } + // reset PCB block number + pcb_blocknum = 0; + return 1; +} + +// Set up ISO 14443 Type B communication (similar to iso14443a_setup) +void iso14443b_setup() { + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + // Signal field is on with the appropriate LED + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + + // Start the timer + StartCountSspClk(); + + DemodReset(); + UartReset(); +} //----------------------------------------------------------------------------- // Read a SRI512 ISO 14443B tag. diff --git a/armsrc/iso14443b.h b/armsrc/iso14443b.h new file mode 100644 index 00000000..f90c54f3 --- /dev/null +++ b/armsrc/iso14443b.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Merlok - June 2011 +// Gerhard de Koning Gans - May 2008 +// Hagen Fritsch - June 2010 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Routines to support ISO 14443 type A. +//----------------------------------------------------------------------------- + +#ifndef __ISO14443B_H +#define __ISO14443B_H +#include "common.h" + +int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); +void iso14443b_setup(); +int iso14443b_select_card(); + +#endif /* __ISO14443B_H */ diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index c2d85abb..fd6fde63 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -642,8 +642,8 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // free eventually allocated BigBuf memory BigBuf_free(); - clear_trace(); - set_tracing(false); + if (calibrate) clear_trace(); + set_tracing(true); // statistics on nonce distance int16_t isOK = 0; @@ -820,18 +820,18 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - set_tracing(TRUE); } //----------------------------------------------------------------------------- // MIFARE check keys. key count up to 85. // //----------------------------------------------------------------------------- -void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { // params - uint8_t blockNo = arg0; - uint8_t keyType = arg1; + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + bool clearTrace = arg1; uint8_t keyCount = arg2; uint64_t ui64Key = 0; @@ -853,7 +853,7 @@ void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); + if (clearTrace) clear_trace(); set_tracing(TRUE); for (i = 0; i < keyCount; i++) { diff --git a/client/cmdhf.c b/client/cmdhf.c index 4c5db589..f8daff7e 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -378,7 +378,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); } uint8_t parityBits = parityBytes[j>>3]; - if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); } else { diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 5ef5273a..16612cba 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -18,7 +18,6 @@ int CmdHF14AMifare(const char *Cmd) uint32_t nt = 0, nr = 0; uint64_t par_list = 0, ks_list = 0, r_key = 0; int16_t isOK = 0; - uint8_t keyBlock[8] = {0}; UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}}; @@ -74,22 +73,13 @@ start: if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key)) { isOK = 2; PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt); - } else { - printf("------------------------------------------------------------------\n"); - PrintAndLog("Key found:%012"llx" \n", r_key); - - num_to_bytes(r_key, 6, keyBlock); - isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key); - } - - if (!isOK) - PrintAndLog("Found valid key:%012"llx, r_key); - else - { - if (isOK != 2) PrintAndLog("Found invalid key. "); PrintAndLog("Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce..."); c.arg[0] = false; goto start; + } else { + isOK = 0; + printf("------------------------------------------------------------------\n"); + PrintAndLog("Found valid key:%012"llx" \n", r_key); } PrintAndLog(""); @@ -689,7 +679,7 @@ int CmdHF14AMfNested(const char *Cmd) for (j = 0; j < 2; j++) { if (e_sector[i].foundKey[j]) continue; - res = mfCheckKeys(FirstBlockOfSector(i), j, 6, keyBlock, &key64); + res = mfCheckKeys(FirstBlockOfSector(i), j, true, 6, keyBlock, &key64); if (!res) { e_sector[i].Key[j] = key64; @@ -973,7 +963,7 @@ int CmdHF14AMfChk(const char *Cmd) uint32_t max_keys = keycnt>USB_CMD_DATA_SIZE/6?USB_CMD_DATA_SIZE/6:keycnt; for (uint32_t c = 0; c < keycnt; c+=max_keys) { uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c; - res = mfCheckKeys(b, t, size, &keyBlock[6*c], &key64); + res = mfCheckKeys(b, t, true, size, &keyBlock[6*c], &key64); if (res != 1) { if (!res) { PrintAndLog("Found valid key:[%012"llx"]",key64); diff --git a/client/mifarehost.c b/client/mifarehost.c index 95453ebf..eb145123 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -181,7 +181,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); num_to_bytes(key64, 6, keyBlock); key64 = 0; - if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, 1, keyBlock, &key64)) { + if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, 1, keyBlock, &key64)) { num_to_bytes(key64, 6, resultKey); break; } @@ -193,11 +193,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo return 0; } -int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){ +int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){ *key = 0; - UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}}; + UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}}; memcpy(c.d.asBytes, keyBlock, 6 * keycnt); SendCommand(&c); diff --git a/client/mifarehost.h b/client/mifarehost.h index a11f11d5..f6ffab3f 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -50,7 +50,7 @@ typedef struct { extern char logHexFileName[FILE_PATH_SIZE]; int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate); -int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); +int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index 111f58cd..70d874fe 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -133,7 +133,7 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_ key64 = *(last_keylist + i); num_to_bytes(key64, 6, keyBlock); key64 = 0; - if (!mfCheckKeys(0, 0, 1, keyBlock, &key64)) { + if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) { *key = key64; free(last_keylist); last_keylist = NULL; diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index eb98ffbf..9cc865f0 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -88,10 +88,33 @@ function mfcrack_inner() while not core.ukbhit() do local result = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) if result then - -- Unpacking the three arg-parameters - local count,cmd,isOK = bin.unpack('LL',result) - if isOK ~= 1 then return nil, "Error occurred" end + --[[ + I don't understand, they cmd and args are defined as uint32_t, however, + looking at the returned data, they all look like 64-bit things: + + print("result", bin.unpack("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH", result)) + + FF 00 00 00 00 00 00 00 <-- 64 bits of data + FE FF FF FF 00 00 00 00 <-- 64 bits of data + 00 00 00 00 00 00 00 00 <-- 64 bits of data + 00 00 00 00 00 00 00 00 <-- 64 bits of data + 04 7F 12 E2 00 <-- this is where 'data' starts + + So below I use LI to pick out the "FEFF FFFF", don't know why it works.. + --]] + -- Unpacking the arg-parameters + local count,cmd,isOK = bin.unpack('LI',result) + --print("response", isOK)--FF FF FF FF + if isOK == 0xFFFFFFFF then + return nil, "Button pressed. Aborted." + elseif isOK == 0xFFFFFFFE then + return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." + elseif isOK == 0xFFFFFFFD then + return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." + elseif isOK ~= 1 then + return nil, "Error occurred" + end -- The data-part is left