small improvements, added new command hf mf sniff (there will be cool sniffer). But now... here is optimized hf 14a snoop. As I see it works the same as th old version.

This commit is contained in:
Merlokbr@gmail.com 2012-07-06 16:19:05 +00:00
parent ac14bee321
commit b62a5a8444
12 changed files with 255 additions and 60 deletions

View file

@ -16,7 +16,7 @@ APP_CFLAGS = -O2 -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DW
#SRC_LCD = fonts.c LCD.c
SRC_LF = lfops.c hitag2.c
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
SRC_ISO14443b = iso14443.c
SRC_CRAPTO1 = crapto1.c crypto1.c

View file

@ -761,6 +761,11 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_MIFARE_EML_CGETBLOCK:
MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break;
// mifare sniffer
case CMD_MIFARE_SNIFFER:
SniffMifare();
break;
#endif
#ifdef WITH_ICLASS

View file

@ -135,6 +135,7 @@ uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
void iso14a_set_trigger(int enable);
void iso14a_clear_tracelen(void);
void iso14a_set_tracing(int enable);
void RAMFUNC SniffMifare(void);
// mifarecmd.h
void ReaderMifare(uint32_t parameter);

View file

@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
// Merlok - June 2011
// Merlok - June 2011, 2012
// Gerhard de Koning Gans - May 2008
// Hagen Fritsch - June 2010
//
@ -129,32 +129,7 @@ int LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity,
// The software UART that receives commands from the reader, and its state
// variables.
//-----------------------------------------------------------------------------
static struct {
enum {
STATE_UNSYNCD,
STATE_START_OF_COMMUNICATION,
STATE_MILLER_X,
STATE_MILLER_Y,
STATE_MILLER_Z,
STATE_ERROR_WAIT
} state;
uint16_t shiftReg;
int bitCnt;
int byteCnt;
int byteCntMax;
int posCnt;
int syncBit;
int parityBits;
int samples;
int highCnt;
int bitBuffer;
enum {
DROP_NONE,
DROP_FIRST_HALF,
DROP_SECOND_HALF
} drop;
uint8_t *output;
} Uart;
static tUart Uart;
static RAMFUNC int MillerDecoding(int bit)
{
@ -393,32 +368,7 @@ static RAMFUNC int MillerDecoding(int bit)
//=============================================================================
// ISO 14443 Type A - Manchester
//=============================================================================
static struct {
enum {
DEMOD_UNSYNCD,
DEMOD_START_OF_COMMUNICATION,
DEMOD_MANCHESTER_D,
DEMOD_MANCHESTER_E,
DEMOD_MANCHESTER_F,
DEMOD_ERROR_WAIT
} state;
int bitCount;
int posCount;
int syncBit;
int parityBits;
uint16_t shiftReg;
int buffer;
int buff;
int samples;
int len;
enum {
SUB_NONE,
SUB_FIRST_HALF,
SUB_SECOND_HALF
} sub;
uint8_t *output;
} Demod;
static tDemod Demod;
static RAMFUNC int ManchesterDecoding(int v)
{
@ -2402,9 +2352,7 @@ lbWORK: if (len == 0) break;
cardSTATE = MFEMUL_WORK;
break;
}
}
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -2416,3 +2364,132 @@ lbWORK: if (len == 0) break;
if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, traceLen);
}
//-----------------------------------------------------------------------------
// MIFARE sniffer.
//
//-----------------------------------------------------------------------------
void RAMFUNC SniffMifare(void) {
LEDsoff();
// init trace buffer
traceLen = 0;
memset(trace, 0x44, TRACE_SIZE);
// 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.
int triggered = FALSE; // FALSE to wait first for card
// The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough!
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
// The response (tag -> reader) that we're receiving.
uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
// As we receive stuff, we copy it from receivedCmd or receivedResponse
// into trace, along with its length and other annotations.
//uint8_t *trace = (uint8_t *)BigBuf;
// The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
int lastRxCounter;
int8_t *upTo;
int smpl;
int maxBehindBy = 0;
// Set up the demodulator for tag -> reader responses.
Demod.output = receivedResponse;
Demod.len = 0;
Demod.state = DEMOD_UNSYNCD;
// Set up the demodulator for the reader -> tag commands
memset(&Uart, 0, sizeof(Uart));
Uart.output = receivedCmd;
Uart.byteCntMax = 32; // was 100 (greg)//////////////////
Uart.state = STATE_UNSYNCD;
// Setup for the DMA.
FpgaSetupSsc();
upTo = dmaBuf;
lastRxCounter = DMA_BUFFER_SIZE;
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
// And put the FPGA in the appropriate mode
// Signal field is off with the appropriate LED
LED_D_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Count of samples received so far, so that we can include timing
// information in the trace buffer.
rsamples = 0;
// And now we loop, receiving samples.
while(true) {
LED_A_ON();
WDT_HIT();
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
(DMA_BUFFER_SIZE-1);
if(behindBy > maxBehindBy) {
maxBehindBy = behindBy;
if(behindBy > 400) {
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
goto done;
}
}
if(behindBy < 1) continue;
LED_A_OFF();
smpl = upTo[0];
upTo++;
lastRxCounter -= 1;
if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
upTo -= DMA_BUFFER_SIZE;
lastRxCounter += DMA_BUFFER_SIZE;
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
}
rsamples += 4;
if(MillerDecoding((smpl & 0xF0) >> 4)) {
LED_C_ON();
if(triggered) {
if (!LogTrace(receivedCmd, Uart.byteCnt, -1 * Uart.samples, Uart.parityBits, TRUE)) break;
}
/* And ready to receive another command. */
Uart.state = STATE_UNSYNCD;
/* And also reset the demod code, which might have been */
/* false-triggered by the commands from the reader. */
Demod.state = DEMOD_UNSYNCD;
LED_B_OFF();
}
if(ManchesterDecoding(smpl & 0x0F)) {
LED_B_ON();
if (!LogTrace(receivedResponse, Demod.len, -1 * Demod.samples, Demod.parityBits, FALSE)) break;
triggered = TRUE;
// And ready to receive another response.
memset(&Demod, 0, sizeof(Demod));
Demod.output = receivedResponse;
Demod.state = DEMOD_UNSYNCD;
LED_C_OFF();
}
if(BUTTON_PRESS()) {
DbpString("button cancelled");
goto done;
}
} // main cycle
DbpString("COMMAND FINISHED");
done:
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
Dbprintf("maxBehindBy=%x, Uart.state=%x, Uart.byteCnt=%x", maxBehindBy, Uart.state, Uart.byteCnt);
Dbprintf("Uart.byteCntMax=%x, traceLen=%x, Uart.output[0]=%x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
LEDsoff();
}

View file

@ -23,6 +23,60 @@
typedef struct nestedVector { uint32_t nt, ks1; } nestedVector;
typedef struct {
enum {
DEMOD_UNSYNCD,
DEMOD_START_OF_COMMUNICATION,
DEMOD_MANCHESTER_D,
DEMOD_MANCHESTER_E,
DEMOD_MANCHESTER_F,
DEMOD_ERROR_WAIT
} state;
int bitCount;
int posCount;
int syncBit;
int parityBits;
uint16_t shiftReg;
int buffer;
int buff;
int samples;
int len;
enum {
SUB_NONE,
SUB_FIRST_HALF,
SUB_SECOND_HALF
} sub;
uint8_t *output;
} tDemod;
typedef struct {
enum {
STATE_UNSYNCD,
STATE_START_OF_COMMUNICATION,
STATE_MILLER_X,
STATE_MILLER_Y,
STATE_MILLER_Z,
STATE_ERROR_WAIT
} state;
uint16_t shiftReg;
int bitCnt;
int byteCnt;
int byteCntMax;
int posCnt;
int syncBit;
int parityBits;
int samples;
int highCnt;
int bitBuffer;
enum {
DROP_NONE,
DROP_FIRST_HALF,
DROP_SECOND_HALF
} drop;
uint8_t *output;
} tUart;
extern byte_t oddparity (const byte_t bt);
extern uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
extern void AppendCrc14443a(uint8_t* data, int len);

View file

@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
// Merlok - June 2011
// Merlok - June 2011, 2012
// Gerhard de Koning Gans - May 2008
// Hagen Fritsch - June 2010
//

15
armsrc/mifaresniff.c Normal file
View file

@ -0,0 +1,15 @@
//-----------------------------------------------------------------------------
// Merlok - 2012
//
// 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 mifare classic sniffer.
//-----------------------------------------------------------------------------
#include "mifaresniff.h"
#include "apps.h"

26
armsrc/mifaresniff.h Normal file
View file

@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// Merlok - June 2012
//
// 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 mifare classic sniffer.
//-----------------------------------------------------------------------------
#ifndef __MIFARESNIFF_H
#define __MIFARESNIFF_H
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "common.h"
#endif

View file

@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
// Merlok, May 2011
// Merlok, May 2011, 2012
// Many authors, whom made it possible
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,

View file

@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2011 Merlok
// Copyright (C) 2011,2012 Merlok
//
// 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
@ -1542,6 +1542,20 @@ int CmdHF14AMfCSave(const char *Cmd) {
}
}
int CmdHF14AMfSniff(const char *Cmd){
if (param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf sniff ");
PrintAndLog(" sample: hf mf sniff ");
return 0;
}
UsbCommand c = {CMD_MIFARE_SNIFFER, {0, 0, 0}};
SendCommand(&c);
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
@ -1554,6 +1568,7 @@ static command_t CommandTable[] =
{"chk", CmdHF14AMfChk, 0, "Test block keys"},
{"mifare", CmdHF14AMifare, 0, "Read parity error messages. param - <used card nonce>"},
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},

View file

@ -1,4 +1,4 @@
// Merlok, 2011
// Merlok, 2011, 2012
// people from mifare@nethemba.com, 2010
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,

View file

@ -127,6 +127,8 @@ typedef struct {
#define CMD_MIFARE_WRITEBL 0x0622
#define CMD_MIFARE_CHKKEYS 0x0623
#define CMD_MIFARE_SNIFFER 0x0630
#define CMD_UNKNOWN 0xFFFF
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: