void FpgaSetupSsc(void);
void SetupSpi(int mode);
void FpgaSetupSscDma(uint8_t *buf, int len);
+void inline FpgaDisableSscDma(void){
+ AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+}
+void inline FpgaEnableSscDma(void){
+ AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
+}
void SetAdcMuxFor(uint32_t whichGpio);
// Definitions for the FPGA commands.
if (++sniffCounter > 65) {
if (MfSniffSend(2000)) {
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
+ FpgaEnableSscDma();
}
sniffCounter = 0;
}
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!!! %d", dataLen); // temporary
+ Dbprintf("RxEmpty ERROR!!! data length:%d", dataLen); // temporary
}
// secondary buffer sets as primary, secondary buffer was stopped
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
DbpString("COMMAND FINISHED");
done:
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+ FpgaDisableSscDma();
MfSniffEnd();
- Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.byteCnt=%x", maxDataLen, Uart.state, Uart.byteCnt);
- Dbprintf("Uart.byteCntMax=%x, traceLen=%x", Uart.byteCntMax, traceLen);
+ Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.byteCnt=%x Uart.byteCntMax=%x", maxDataLen, Uart.state, Uart.byteCnt, Uart.byteCntMax);
LEDsoff();
}
\ No newline at end of file
\r
int RAMFUNC MfSniffLogic(const uint8_t * data, int len, int bitCnt, int reader) {\r
\r
- if ((len == 1) && (bitCnt = 9)) { \r
+ if ((len == 1) && (bitCnt = 9) && (data[0] > 0x0F)) { \r
sniffState = SNF_INIT;\r
}\r
\r
\r
if (!traceLen) return 0;\r
\r
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
+ FpgaDisableSscDma();\r
\r
while (pckLen > 0) {\r
pckSize = min(32, pckLen);\r
}\r
\r
int CmdHF14AMfSniff(const char *Cmd){\r
+ // params\r
+ bool wantLogToFile = 0;\r
+ bool wantDecrypt = 0;\r
+ bool wantSaveToEml = 0;\r
+ bool wantSaveToEmlFile = 0;\r
+\r
+ //var \r
int res = 0;\r
int len = 0;\r
int blockLen = 0;\r
memset(buf, 0x00, 3000);\r
\r
if (param_getchar(Cmd, 0) == 'h') {\r
- PrintAndLog("Usage: hf mf sniff ");\r
- PrintAndLog(" sample: hf mf sniff ");\r
+ PrintAndLog("It continuously get data from the field and saves it to: log, emulator, emulator file.");\r
+ PrintAndLog("You can specify:");\r
+ PrintAndLog(" l - save encrypted sequence to logfile `uid.log`");\r
+ PrintAndLog(" d - decrypt sequence and put it to log file `uid.log`");\r
+ PrintAndLog(" n/a e - decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory");\r
+ PrintAndLog(" n/a r - decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`");\r
+ PrintAndLog("Usage: hf mf sniff [l][d][e][r]");\r
+ PrintAndLog(" sample: hf mf sniff l d e");\r
return 0;\r
} \r
\r
+ for (int i = 0; i < 4; i++) {\r
+ char ctmp = param_getchar(Cmd, i);\r
+ if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true;\r
+ if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true;\r
+ if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true;\r
+ if (ctmp == 'f' || ctmp == 'F') wantSaveToEmlFile = true;\r
+ }\r
+ \r
printf("-------------------------------------------------------------------------\n");\r
printf("Executing command. \n");\r
printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n");\r
memcpy(uid, bufPtr + 2, 7);\r
memcpy(atqa, bufPtr + 2 + 7, 2);\r
sak = bufPtr[11];\r
+ \r
PrintAndLog("tag select uid:%s atqa:%02x %02x sak:0x%02x", sprint_hex(uid, 7), atqa[0], atqa[1], sak);\r
+ if (wantLogToFile) {\r
+ FillFileNameByUID(logHexFileName, uid, ".log");\r
+ AddLogCurrentDT(logHexFileName);\r
+ } \r
+ if (wantDecrypt) mfTraceInit(uid, atqa, sak);\r
} else {\r
PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len));\r
+ if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);\r
+ if (wantDecrypt) mfTraceDecode(bufPtr, len);\r
}\r
bufPtr += len;\r
num++;\r
// at your option, any later version. See the LICENSE.txt file for the text of\r
// the license.\r
//-----------------------------------------------------------------------------\r
-// High frequency ISO14443A commands\r
+// mifare commands\r
//-----------------------------------------------------------------------------\r
\r
#include <stdio.h>\r
#include <string.h>\r
#include "mifarehost.h"\r
\r
+// MIFARE\r
\r
int compar_int(const void * a, const void * b) {\r
return (*(uint64_t*)b - *(uint64_t*)a);\r
return 0;\r
}\r
\r
+// EMULATOR\r
+\r
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {\r
UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};\r
\r
return 0;\r
}\r
\r
+// "MAGIC" CARD\r
+\r
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe) {\r
uint8_t block0[16];\r
memset(block0, 0, 16);\r
}\r
return 0;\r
}\r
+\r
+// SNIFFER\r
+\r
+// variables\r
+char logHexFileName[200] = {0x00};\r
+static uint8_t traceCard[4096];\r
+static int traceState = TRACE_IDLE;\r
+static uint8_t traceCurBlock = 0;\r
+static uint8_t traceCurKey = 0;\r
+\r
+struct Crypto1State *traceCrypto1 = NULL;\r
+\r
+struct Crypto1State *revstate;\r
+uint64_t lfsr;\r
+uint32_t ks2;\r
+uint32_t ks3;\r
+\r
+uint32_t uid; // serial number\r
+uint32_t nt; // tag challenge\r
+uint32_t nr_enc; // encrypted reader challenge\r
+uint32_t ar_enc; // encrypted reader response\r
+uint32_t at_enc; // encrypted tag response\r
+\r
+int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak) {\r
+\r
+ if (traceCrypto1) crypto1_destroy(traceCrypto1);\r
+ traceCrypto1 = NULL;\r
+\r
+ memset(traceCard, 0x00, 4096);\r
+ memcpy(traceCard, tuid + 3, 4);\r
+ traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3];\r
+ traceCard[5] = sak;\r
+ memcpy(&traceCard[6], atqa, 2);\r
+ traceCurBlock = 0;\r
+ uid = bytes_to_num(tuid + 3, 4);\r
+ \r
+ traceState = TRACE_IDLE;\r
+\r
+ return 0;\r
+}\r
+\r
+void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted){\r
+ uint8_t bt = 0;\r
+ int i;\r
+ \r
+ if (len != 1) {\r
+ for (i = 0; i < len; i++)\r
+ data[i] = crypto1_byte(pcs, 0x00, isEncrypted) ^ data[i];\r
+ } else {\r
+ bt = 0;\r
+ for (i = 0; i < 4; i++)\r
+ bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], i)) << i;\r
+ \r
+ data[0] = bt;\r
+ }\r
+ return;\r
+}\r
+\r
+\r
+int mfTraceDecode(uint8_t *data_src, int len) {\r
+ uint8_t data[64];\r
+\r
+ if (traceState == TRACE_ERROR) return 1;\r
+ if (len > 64) {\r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+ \r
+ memcpy(data, data_src, len);\r
+ if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) {\r
+ mf_crypto1_decrypt(traceCrypto1, data, len, 0);\r
+ PrintAndLog("dec> %s", sprint_hex(data, len));\r
+ AddLogHex(logHexFileName, "dec> ", data, len); \r
+ }\r
+ \r
+ switch (traceState) {\r
+ case TRACE_IDLE: \r
+ // TODO: check packet crc16!\r
+ \r
+ // AUTHENTICATION\r
+ if ((len ==4) && ((data[0] == 0x60) || (data[0] == 0x61))) {\r
+ traceState = TRACE_AUTH1;\r
+ traceCurBlock = data[1];\r
+ traceCurKey = data[0] == 60 ? 1:0;\r
+ return 0;\r
+ }\r
+\r
+ // READ\r
+ if ((len ==4) && ((data[0] == 0x30))) {\r
+ traceState = TRACE_READ_DATA;\r
+ traceCurBlock = data[1];\r
+ return 0;\r
+ }\r
+\r
+ // WRITE\r
+ if ((len ==4) && ((data[0] == 0xA0))) {\r
+ traceState = TRACE_WRITE_OK;\r
+ traceCurBlock = data[1];\r
+ return 0;\r
+ }\r
+\r
+ // HALT\r
+ if ((len ==4) && ((data[0] == 0x50) && (data[1] == 0x00))) {\r
+ traceState = TRACE_ERROR; // do not decrypt the next commands\r
+ return 0;\r
+ }\r
+ \r
+ return 0;\r
+ break;\r
+ \r
+ case TRACE_READ_DATA: \r
+ if (len == 18) {\r
+ traceState = TRACE_IDLE;\r
+\r
+ memcpy(traceCard + traceCurBlock * 16, data, 16);\r
+ return 0;\r
+ } else {\r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+ break;\r
+\r
+ case TRACE_WRITE_OK: \r
+ if ((len == 1) && (data[0] = 0x0a)) {\r
+ traceState = TRACE_WRITE_DATA;\r
+\r
+ return 0;\r
+ } else {\r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+ break;\r
+\r
+ case TRACE_WRITE_DATA: \r
+ if (len == 18) {\r
+ traceState = TRACE_IDLE;\r
+\r
+ memcpy(traceCard + traceCurBlock * 16, data, 16);\r
+ return 0;\r
+ } else {\r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+ break;\r
+\r
+ case TRACE_AUTH1: \r
+ if (len == 4) {\r
+ traceState = TRACE_AUTH2;\r
+\r
+ nt = bytes_to_num(data, 4);\r
+ return 0;\r
+ } else {\r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+ break;\r
+\r
+ case TRACE_AUTH2: \r
+ if (len == 8) {\r
+ traceState = TRACE_AUTH_OK;\r
+\r
+ nr_enc = bytes_to_num(data, 4);\r
+ ar_enc = bytes_to_num(data + 4, 4);\r
+ return 0;\r
+ } else {\r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+ break;\r
+\r
+ case TRACE_AUTH_OK: \r
+ if (len ==4) {\r
+ traceState = TRACE_IDLE;\r
+\r
+ at_enc = bytes_to_num(data, 4);\r
+ \r
+ // decode key here)\r
+ if (!traceCrypto1) {\r
+ ks2 = ar_enc ^ prng_successor(nt, 64);\r
+ ks3 = at_enc ^ prng_successor(nt, 96);\r
+ revstate = lfsr_recovery64(ks2, ks3);\r
+ lfsr_rollback_word(revstate, 0, 0);\r
+ lfsr_rollback_word(revstate, 0, 0);\r
+ lfsr_rollback_word(revstate, nr_enc, 1);\r
+ lfsr_rollback_word(revstate, uid ^ nt, 0);\r
+ }else{\r
+ ks2 = ar_enc ^ prng_successor(nt, 64);\r
+ ks3 = at_enc ^ prng_successor(nt, 96);\r
+ revstate = lfsr_recovery64(ks2, ks3);\r
+ lfsr_rollback_word(revstate, 0, 0);\r
+ lfsr_rollback_word(revstate, 0, 0);\r
+ lfsr_rollback_word(revstate, nr_enc, 1);\r
+ lfsr_rollback_word(revstate, uid ^ nt, 0);\r
+ }\r
+ crypto1_get_lfsr(revstate, &lfsr);\r
+ printf("key> %x%x\n", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF));\r
+ AddLogUint64(logHexFileName, "key> ", lfsr); \r
+ \r
+ if (traceCurKey) {\r
+ num_to_bytes(lfsr, 6, traceCard + traceCurBlock * 16 + 10);\r
+ } else {\r
+ num_to_bytes(lfsr, 6, traceCard + traceCurBlock * 16);\r
+ }\r
+\r
+ if (traceCrypto1) {\r
+ crypto1_destroy(traceCrypto1);\r
+ }\r
+ \r
+ // set cryptosystem state\r
+ traceCrypto1 = lfsr_recovery64(ks2, ks3);\r
+ \r
+// nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt;\r
+\r
+ /* traceCrypto1 = crypto1_create(lfsr); // key in lfsr\r
+ crypto1_word(traceCrypto1, nt ^ uid, 0);\r
+ crypto1_word(traceCrypto1, ar, 1);\r
+ crypto1_word(traceCrypto1, 0, 0);\r
+ crypto1_word(traceCrypto1, 0, 0);*/\r
+ \r
+ return 0;\r
+ } else {\r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+ break;\r
+\r
+ default: \r
+ traceState = TRACE_ERROR;\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
#define CSETBLOCK_RESET_FIELD 0x10\r
#define CSETBLOCK_SINGLE_OPER 0x1F\r
\r
+// mifare tracer flags\r
+#define TRACE_IDLE 0x00\r
+#define TRACE_AUTH1 0x01\r
+#define TRACE_AUTH2 0x02\r
+#define TRACE_AUTH_OK 0x03\r
+#define TRACE_READ_DATA 0x04\r
+#define TRACE_WRITE_OK 0x05\r
+#define TRACE_WRITE_DATA 0x06\r
+\r
+#define TRACE_ERROR 0xFF\r
+\r
typedef struct fnVector { uint8_t blockNo, keyType; uint32_t uid, nt, ks1; } fnVector;\r
\r
typedef struct {\r
int count;\r
} countKeys;\r
\r
+extern char logHexFileName[200];\r
+\r
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys);\r
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);\r
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);\r
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe);\r
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params);\r
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);\r
+int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak);\r
+int mfTraceDecode(uint8_t *data_src, int len);\r
// utilities
//-----------------------------------------------------------------------------
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
#include "util.h"
#ifndef WIN32
}
#endif
+// log files functions
+void AddLogLine(char *fileName, char *extData, char *c) {
+ FILE *fLog = NULL;
+
+ fLog = fopen(fileName, "a");
+ if (!fLog) {
+ printf("Could not append log file %s", fileName);
+ return;
+ }
+
+ fprintf(fLog, "%s", extData);
+ fprintf(fLog, "%s\n", c);
+ fclose(fLog);
+}
+
+void AddLogHex(char *fileName, char *extData, const uint8_t * data, const size_t len){
+ AddLogLine(fileName, extData, sprint_hex(data, len));
+}
+
+void AddLogUint64(char *fileName, char *extData, const uint64_t data) {
+ char buf[100] = {0};
+ sprintf(buf, "%x%x", (unsigned int)((data & 0xFFFFFFFF00000000) >> 32), (unsigned int)(data & 0xFFFFFFFF));
+ AddLogLine(fileName, extData, buf);
+}
+
+void AddLogCurrentDT(char *fileName) {
+ char buff[20];
+ struct tm *curTime;
+
+ time_t now = time(0);
+ curTime = gmtime(&now);
+
+ strftime (buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", curTime);
+ AddLogLine(fileName, "\nanticollision: ", buff);
+}
+
+void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext) {
+ char * fnameptr = fileName;
+ memset(fileName, 0x00, 200);
+
+ for (int j = 0; j < 7; j++, fnameptr += 2)
+ sprintf(fnameptr, "%02x", uid[j]);
+ sprintf(fnameptr, "%s", ext);
+
+ printf("fname:%s", fileName);
+}
+
+// printing and converting functions
void print_hex(const uint8_t * data, const size_t len)
{
#include <stdio.h>
#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
int ukbhit(void);
+void AddLogLine(char *fileName, char *extData, char *c);
+void AddLogHex(char *fileName, char *extData, const uint8_t * data, const size_t len);
+void AddLogUint64(char *fileName, char *extData, const uint64_t data);
+void AddLogCurrentDT(char *fileName);
+void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext);
+
void print_hex(const uint8_t * data, const size_t len);
char * sprint_hex(const uint8_t * data, const size_t len);
uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
int param_getstr(const char *line, int paramnum, char * str);
+