diff --git a/CHANGELOG.md b/CHANGELOG.md index 20f1c1f8f..329eda594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 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] + - Added HF sniff standalone mode with optional storing of ULC/NTAG/ULEV1 authentication attempts (@bogiton) - Fix 'Lining up plot and control window' (@anticat) - Fix 'annoying focus behaviour' on OSX (@Anticat) - Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (@AntiCat) diff --git a/armsrc/Makefile b/armsrc/Makefile index 8f0cd025e..d1895e7fa 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -42,6 +42,7 @@ APP_CFLAGS = -DWITH_CRC \ # -DWITH_HF_YOUNG # -DWITH_HF_MATTYRUN # -DWITH_HF_COLIN +# -DWITH_HF_BOG SRC_LCD = fonts.c LCD.c @@ -106,6 +107,10 @@ endif ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS))) SRC_STANDALONE = vtsend.c hf_colin.c endif +# WITH_HF_BOG +ifneq (,$(findstring WITH_HF_BOG,$(APP_CFLAGS))) + SRC_STANDALONE = hf_bog.c +endif #the FPGA bitstream files. Note: order matters! FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c new file mode 100644 index 000000000..761e67b1a --- /dev/null +++ b/armsrc/Standalone/hf_bog.c @@ -0,0 +1,289 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +// main code for standalone HF Sniff (and ULC/NTAG/ULEV1 pwd storing) +//----------------------------------------------------------------------------- + +/* +This can actually be used in two separate ways. +It can either be used to just HF 14a sniff on the go and/or grab the +authentication attempts for ULC/NTAG/ULEV1 into the flash mem (RDV4). + +The retrieved sniffing session can be acquired by connecting the device +to a client that supports the reconnect capability and issue 'hf 14a list'. + +In order to view the grabbed authentication attempts in the flash mem, +you can simply 'mem read l 256' from the client to view the stored quadlets. +*/ + +#include "hf_bog.h" + +#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) +#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) + +// Maximum number of auth attempts per standalone session +#define MAX_PWDS_PER_SESSION 64 + +uint8_t FindOffsetInFlash() { + uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; + uint8_t memcnt = 0; + + while (memcnt < 4096) + { + Flash_ReadData(memcnt, mem, 4); + if (memcmp(mem, eom, 4) == 0) { + return memcnt; + } + memcnt += 4; + } + + return 0; // wrap-around +} + +void EraseMemory() +{ + if (!FlashInit()){ + return; + } + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + Flash_Erase4k(0,0); + + if (MF_DBGLEVEL > 1) Dbprintf("[!] Erased flash!"); + FlashStop(); + SpinDelay(100); +} + +void RAMFUNC SniffAndStore(uint8_t param) { + + /* This is actually copied from SniffIso14443a */ + + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + + // Allocate memory from BigBuf for some buffers + // free all previous allocations first + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + // Array to store the authpwds + uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); + + // The command (reader -> tag) that we're receiving. + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); + + // The response (tag -> reader) that we're receiving. + uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); + + // The DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + uint8_t *data = dmaBuf; + + uint8_t previous_data = 0; + int dataLen = 0; + bool TagIsActive = false; + bool ReaderIsActive = false; + + // Set up the demodulator for tag -> reader responses. + DemodInit(receivedResp, receivedRespPar); + + // Set up the demodulator for the reader -> tag commands + UartInit(receivedCmd, receivedCmdPar); + + // Setup and start DMA. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } + + tUart* uart = GetUart(); + tDemod* demod = GetDemod(); + + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + // triggered == false -- to wait first for card + bool triggered = !(param & 0x03); + + uint32_t rsamples = 0; + + // Current captured passwords counter + uint8_t auth_attempts = 0; + + SpinDelay(50); + + // loop and listen + while (!BUTTON_PRESS()) { + WDT_HIT(); + LED_A_ON(); + + int register readBufDataP = data - dmaBuf; + int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; + if (readBufDataP <= dmaBufDataP) + dataLen = dmaBufDataP - readBufDataP; + else + dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; + + // test for length of buffer + if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly + Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); + break; + } + if (dataLen < 1) continue; + + // primary buffer was stopped( <-- we lost data! + if (!AT91C_BASE_PDC_SSC->PDC_RCR) { + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; + //Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary + } + // secondary buffer sets as primary, secondary buffer was stopped + if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + } + + LED_A_OFF(); + + // Need two samples to feed Miller and Manchester-Decoder + if (rsamples & 0x01) { + + if (!TagIsActive) { // no need to try decoding reader data if the tag is sending + uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); + if (MillerDecoding(readerdata, (rsamples-1)*4)) { + LED_C_ON(); + + // check - if there is a short 7bit request from reader + if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true; + + if (triggered) { + if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) { + if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]); + + // temporarily save the captured pwd in our array + memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4); + auth_attempts++; + } + + if (!LogTrace(receivedCmd, + uart->len, + uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + uart->parity, + true)) break; + } + /* ready to receive another command. */ + UartReset(); + /* reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); + LED_B_OFF(); + } + ReaderIsActive = (uart->state != STATE_UNSYNCD); + } + + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + if (!ReaderIsActive) { + uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); + if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { + LED_B_ON(); + + if (!LogTrace(receivedResp, + demod->len, + demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + demod->parity, + false)) break; + + if ((!triggered) && (param & 0x01)) triggered = true; + + // ready to receive another response. + DemodReset(); + // reset the Miller decoder including its (now outdated) input buffer + UartReset(); + //UartInit(receivedCmd, receivedCmdPar); + LED_C_OFF(); + } + TagIsActive = (demod->state != DEMOD_UNSYNCD); + } + } + + previous_data = *data; + rsamples++; + data++; + if (data == dmaBuf + DMA_BUFFER_SIZE) { + data = dmaBuf; + } + } // end main loop + + FpgaDisableSscDma(); + set_tracing(false); + + Dbprintf("Stopped sniffing"); + + SpinDelay(200); + + // Write stuff to flash + if (auth_attempts > 0) { + if (MF_DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts); + + // Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34) + FlashmemSetSpiBaudrate(48000000); + + // Find the offset in flash mem to continue writing the auth attempts + uint8_t memoffset = FindOffsetInFlash(); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset); + + // Get previous data from flash mem + uint8_t *previousdata = BigBuf_malloc(memoffset); + uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); + + // create new bigbuf to hold all data + size_t total_size = memoffset + 4 * auth_attempts; + uint8_t *total_data = BigBuf_malloc(total_size); + + // Add the previousdata array into total_data array + memcpy(total_data, previousdata, memoffset); + + // Copy bytes of capturedPwds immediately following bytes of previousdata + memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts); + + // Erase first page of flash mem + EraseMemory(); + + //for (int i=0; i 1) Dbprintf("[-] total_data[%d] = 0x%02x", i, total_data[i]); + + // Write total data to flash mem + uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); + + SpinDelay(100); + + // Reset the SPI Baudrate to the default value (24MHz) + FlashmemSetSpiBaudrate(24000000); + } +} + +void RunMod() +{ + Dbprintf("Sniffing started"); + + SpinDelay(200); + + // param: + // bit 0 - trigger from first card answer + // bit 1 - trigger from first reader 7-bit request + SniffAndStore(0); + + LEDsoff(); + + SpinDelay(300); +} diff --git a/armsrc/Standalone/hf_bog.h b/armsrc/Standalone/hf_bog.h new file mode 100644 index 000000000..8b7d4c695 --- /dev/null +++ b/armsrc/Standalone/hf_bog.h @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +// StandAlone Mod +//----------------------------------------------------------------------------- + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef __HF_BOG_H +#define __HF_BOG_H + +#include "proxmark3.h" +#include "mifareutil.h" +#include "iso14443a.h" +#include "protocols.h" +#include "util.h" +#include "standalone.h" // standalone definitions +#include // for bool +#include +#include +#include "apps.h" +#include "printf.h" + +#include "parity.h" +#include "random.h" + +#endif /* __HF_BOG_H */ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index a84a33d48..2a3ae823a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -453,7 +453,10 @@ void printStandAloneModes(void) { #if defined(WITH_HF_COLIN) DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); #endif - +#if defined(WITH_HF_BOG) + DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)"); +#endif + //DbpString("Running "); //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); @@ -1530,7 +1533,7 @@ void __attribute__((noreturn)) AppMain(void) { RunMod(); #endif -#if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) ) +#if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) || defined(WITH_HF_BOG) ) RunMod(); #endif