Merge pull request #1 from Proxmark/master

Sync
This commit is contained in:
bigboyq 2016-08-27 23:50:00 +08:00 committed by GitHub
commit d1cda053ca
151 changed files with 113355 additions and 3396 deletions

2
.gitignore vendored
View file

@ -1,6 +1,7 @@
# .gitignore
# don't push these files to the repository
.history
*.log
*.eml
*.o
@ -20,6 +21,7 @@ flasher
version.c
lua
luac
fpga_compress
fpga/*
!fpga/tests

View file

@ -5,16 +5,65 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
### Added
- Added lf pyramid commands (iceman)
- Added lf presco commands - some bits not fully understood... (iceman)
- Added experimental HitagS support (Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg)
see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s
English video available
- Added a LF ASK Sequence Terminator detection option to the standard ask demod - and applied it to `lf search u`, `lf t55xx detect`, and `data rawdemod am s` (marshmellow)
- `lf t55xx bruteforce <start password> <end password> [i <*.dic>]` - Simple bruteforce attack to find password - (iceman and others)
- `lf viking clone`- clone viking tag to t55x7 or Q5 from 4byte hex ID input
- `lf viking sim` - sim full viking tag from 4byte hex ID input
- `lf viking read` - read viking tag and output ID
- `lf t55xx wipe` - sets t55xx back to factory defaults
- Added viking demod to `lf search` (marshmellow)
- `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow)
- `lf t55xx resetread` added reset then read command - should allow determining start of stream transmissions (marshmellow)
- `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow)
- `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow)
- `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
- `hf iclass writeblk` to select, authenticate, and write 1 block to an iclass card (or picopass) (marshmellow + others)
- `hf iclass clone` to take a saved dump file and clone selected blocks to a new tag (marshmellow + others)
- `hf iclass calcnewkey` - to calculate the div_key change to change a key - (experimental) (marshmellow + others)
- `hf iclass encryptblk` - to encrypt a data block hex to prep for writing that block (marshmellow)
- ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young)
- AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young)
- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman)
- Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman)
- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman)
- Added 'hf snoop'. This command take digitalized signal from FPGA and put in BigBuffer. (pwpiwi + enio)
- Added Topaz (NFC type 1) protocol support ('hf topaz reader', 'hf list topaz', 'hf 14a raw -T', 'hf topaz snoop'). (piwi)
- Added option c to 'hf list' (mark CRC bytes) (piwi)
- Added option `l` or `h` to `hw tune` to save time and unnecessary fpga writes if you are only interested in lf or hf.
### Changed
- Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
- Fixed bug in lf viking clone/sim (iceman)
- Fixed broken `data askedgedetect` (marshmellow)
- Adjusted hf mf sim command (marshmellow)
added auto run mfkey32 to extract all keys
also added f parameter to allow attacking with UIDs from a file (implies x and i parameters)
also added e parameter to allow adding the extracted keys to emulator memory for the next simulation
added 10 byte uid option
- Added `[l] <length>` option to data printdemodbuffer (marshmellow)
- Adjusted lf awid clone to optionally clone to Q5 tags (marshmellow)
- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7 (marshmellow)
- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal) (marshmellow)
- Adjusted lf pskindalademod to reduce false positive reads. (marshmellow)
- Small adjustments to psk, nrz, and ask clock detect routines - more reliable. (marshmellow)
- Adjusted lf em410x em410xsim to accept a clock argument (marshmellow)
- Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow)
- Adjusted lf t55xx write input variables (marshmellow)
- Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman)
- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. (marshmellow)
- Adjusted timings for t55xx commands. more reliable now. (marshmellow & iceman)
- `lf cmdread` adjusted input methods and added help text (marshmellow & iceman)
- changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow)
- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet) (marshmellow)
- Revised workflow for StandAloneMode14a (Craig Young)
- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)
- Added `r` option to iclass functions - allows key to be provided in raw block 3/4 format
## [2.2.0][2015-07-12]

View file

@ -86,19 +86,22 @@ Tested on OSX 10.10 Yosemite
1 - Install Xcode and Xcode Command Line Tools
2 - Install Homebrew and dependencies
brew install readline
brew instal libusb
brew install readline libusb p7zip libusb-compat wget qt5 pkgconfig
3 - Download DevKitARM for OSX
http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
3 - Install DevKitARM for OSX
Option 1:
http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
Option 2:
brew tap nitsky/stm32
brew install arm-none-eabi-gcc
4 - Edit proxmark3/client/Makefile adding path to readline
4 - Edit proxmark3/client/Makefile adding path to readline and qt5
LDLIBS = -L/usr/local/Cellar/readline/6.3.8/lib/ -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
CFLAGS = -std=c99 -I/usr/local/Cellar/readline/6.3.8/include/ -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
LDLIBS = -L/usr/local/opt/readline/lib -L/usr/local/opt/qt5/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
CFLAGS = -std=c99 -I/usr/local/opt/qt5/include -I/usr/local/opt/readline/include -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
Replace path /usr/local/Cellar/readline/6.3.8 with your actuall readline path. See homebrew manuals.
If your old brew intallation use /usr/local/Cellar/ path replace /usr/local/opt/readline/lib with your actuall readline and qt5 path. See homebrew manuals.
5 - Set Environment

View file

@ -22,7 +22,7 @@ help:
@echo + all - Make bootrom, armsrc and the OS-specific host directory
@echo + client - Make only the OS-specific host directory
@echo + flash-bootrom - Make bootrom and flash it
@echo + flash-os - Make armsrc and flash os (includes fpga)
@echo + flash-os - Make armsrc and flash os \(includes fpga\)
@echo + flash-all - Make bootrom and armsrc and flash bootrom and os image
@echo + clean - Clean in bootrom, armsrc and the OS-specific host directory

View file

@ -50,11 +50,21 @@ uint8_t *BigBuf_get_EM_addr(void)
// clear ALL of BigBuf
void BigBuf_Clear(void)
{
BigBuf_Clear_ext(true);
}
// clear ALL of BigBuf
void BigBuf_Clear_ext(bool verbose)
{
memset(BigBuf,0,BIGBUF_SIZE);
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
if (verbose)
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
}
void BigBuf_Clear_keep_EM(void)
{
memset(BigBuf,0,BigBuf_hi);
}
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
// at the beginning of BigBuf is always for traces/samples
@ -178,8 +188,12 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
traceLen += iLen;
// parity bytes
if (parity != NULL && iLen != 0) {
memcpy(trace + traceLen, parity, num_paritybytes);
if (num_paritybytes != 0) {
if (parity != NULL) {
memcpy(trace + traceLen, parity, num_paritybytes);
} else {
memset(trace + traceLen, 0x00, num_paritybytes);
}
}
traceLen += num_paritybytes;
@ -228,6 +242,8 @@ int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwP
return TRUE;
}
// Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
uint8_t* mem = BigBuf_get_EM_addr();

View file

@ -12,6 +12,8 @@
#ifndef __BIGBUF_H
#define __BIGBUF_H
#include <stdbool.h> // for bool
#include "common.h" // for ramfunc
#define BIGBUF_SIZE 40000
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
@ -25,6 +27,8 @@ extern uint8_t *BigBuf_get_addr(void);
extern uint8_t *BigBuf_get_EM_addr(void);
extern uint16_t BigBuf_max_traceLen(void);
extern void BigBuf_Clear(void);
extern void BigBuf_Clear_ext(bool verbose);
extern void BigBuf_Clear_keep_EM(void);
extern uint8_t *BigBuf_malloc(uint16_t);
extern void BigBuf_free(void);
extern void BigBuf_free_keep_EM(void);

View file

@ -10,12 +10,12 @@ 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
APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE \
APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -DWITH_HFSNOOP \
-fno-strict-aliasing -ffunction-sections -fdata-sections
#-DWITH_LCD
#SRC_LCD = fonts.c LCD.c
SRC_LF = lfops.c hitag2.c lfsampling.c
SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
SRC_ISO14443b = iso14443b.c
@ -52,7 +52,6 @@ THUMBSRC = start.c \
# These are to be compiled in ARM mode
ARMSRC = fpgaloader.c \
legicrf.c \
lfdemod.c \
$(SRC_ISO14443a) \
$(SRC_ISO14443b) \
$(SRC_CRAPTO1) \
@ -60,7 +59,8 @@ ARMSRC = fpgaloader.c \
legic_prng.c \
iclass.c \
BigBuf.c \
optimized_cipher.c
optimized_cipher.c \
hfsnoop.c
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common/Makefile.common

View file

@ -23,9 +23,11 @@
#include "legicrf.h"
#include <hitag2.h>
#include <hitagS.h>
#include "lfsampling.h"
#include "BigBuf.h"
#include "mifareutil.h"
#include "pcf7931.h"
#ifdef WITH_LCD
#include "LCD.h"
#endif
@ -35,8 +37,6 @@
#include "iso14443a.h"
#endif
#define abs(x) ( ((x)<0) ? -(x) : (x) )
//=============================================================================
// A buffer where we can queue things up to be sent through the FPGA, for
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
@ -180,13 +180,9 @@ int AvgAdc(int ch) // was static - merlok
return (a + 15) >> 5;
}
void MeasureAntennaTuning(void)
void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv, uint8_t LF_Results[])
{
uint8_t LF_Results[256];
int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0
int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
LED_B_ON();
int i, adcval = 0, peak = 0;
/*
* Sweeps the useful LF range of the proxmark from
@ -196,38 +192,67 @@ void MeasureAntennaTuning(void)
* the resonating frequency of your LF antenna
* ( hopefully around 95 if it is tuned to 125kHz!)
*/
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
for (i=255; i>=19; i--) {
WDT_HIT();
WDT_HIT();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
SpinDelay(20);
adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
if (i==95) vLf125 = adcval; // voltage at 125Khz
if (i==89) vLf134 = adcval; // voltage at 134Khz
if (i==95) *vLf125 = adcval; // voltage at 125Khz
if (i==89) *vLf134 = adcval; // voltage at 134Khz
LF_Results[i] = adcval>>8; // scale int to fit in byte for graphing purposes
if(LF_Results[i] > peak) {
peakv = adcval;
*peakv = adcval;
peak = LF_Results[i];
peakf = i;
*peakf = i;
//ptr = i;
}
}
for (i=18; i >= 0; i--) LF_Results[i] = 0;
LED_A_ON();
return;
}
void MeasureAntennaTuningHfOnly(int *vHf)
{
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
LED_A_ON();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
SpinDelay(20);
vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
*vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
LED_A_OFF();
return;
}
void MeasureAntennaTuning(int mode)
{
uint8_t LF_Results[256] = {0};
int peakv = 0, peakf = 0;
int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
LED_B_ON();
if (((mode & FLAG_TUNE_ALL) == FLAG_TUNE_ALL) && (FpgaGetCurrent() == FPGA_BITSTREAM_HF)) {
// Reverse "standard" order if HF already loaded, to avoid unnecessary swap.
MeasureAntennaTuningHfOnly(&vHf);
MeasureAntennaTuningLfOnly(&vLf125, &vLf134, &peakf, &peakv, LF_Results);
} else {
if (mode & FLAG_TUNE_LF) {
MeasureAntennaTuningLfOnly(&vLf125, &vLf134, &peakf, &peakv, LF_Results);
}
if (mode & FLAG_TUNE_HF) {
MeasureAntennaTuningHfOnly(&vHf);
}
}
cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_A_OFF();
LED_B_OFF();
return;
}
@ -661,7 +686,7 @@ void SamyRun()
SpinDelay(500);
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
Dbprintf("Recorded %x %x %x", selected, high[selected], low[selected]);
Dbprintf("Recorded %x %x%08x", selected, high[selected], low[selected]);
LEDsoff();
LED(selected + 1, 0);
@ -682,7 +707,7 @@ void SamyRun()
LED(LED_ORANGE, 0);
// record
Dbprintf("Cloning %x %x %x", selected, high[selected], low[selected]);
Dbprintf("Cloning %x %x%08x", selected, high[selected], low[selected]);
// wait for button to be released
while(BUTTON_PRESS())
@ -691,8 +716,8 @@ void SamyRun()
/* need this delay to prevent catching some weird data */
SpinDelay(500);
CopyHIDtoT55x7(high[selected], low[selected], 0, 0);
Dbprintf("Cloned %x %x %x", selected, high[selected], low[selected]);
CopyHIDtoT55x7(0, high[selected], low[selected], 0);
Dbprintf("Cloned %x %x%08x", selected, high[selected], low[selected]);
LEDsoff();
LED(selected + 1, 0);
@ -725,7 +750,7 @@ void SamyRun()
// wait for button to be released
while(BUTTON_PRESS())
WDT_HIT();
Dbprintf("%x %x %x", selected, high[selected], low[selected]);
Dbprintf("%x %x%08x", selected, high[selected], low[selected]);
CmdHIDsimTAG(high[selected], low[selected], 0);
DbpString("Done playing");
if (BUTTON_HELD(1000) > 0)
@ -840,7 +865,7 @@ void ListenReaderField(int limit)
if (limit != HF_ONLY) {
if(mode == 1) {
if (abs(lf_av - lf_baseline) > REPORT_CHANGE)
if (ABS(lf_av - lf_baseline) > REPORT_CHANGE)
LED_D_ON();
else
LED_D_OFF();
@ -848,7 +873,7 @@ void ListenReaderField(int limit)
lf_av_new = AvgAdc(ADC_CHAN_LF);
// see if there's a significant change
if(abs(lf_av - lf_av_new) > REPORT_CHANGE) {
if(ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
lf_av = lf_av_new;
if (lf_av > lf_max)
@ -858,7 +883,7 @@ void ListenReaderField(int limit)
if (limit != LF_ONLY) {
if (mode == 1){
if (abs(hf_av - hf_baseline) > REPORT_CHANGE)
if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)
LED_B_ON();
else
LED_B_OFF();
@ -866,7 +891,7 @@ void ListenReaderField(int limit)
hf_av_new = AvgAdc(ADC_CHAN_HF);
// see if there's a significant change
if(abs(hf_av - hf_av_new) > REPORT_CHANGE) {
if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
hf_av = hf_av_new;
if (hf_av > hf_max)
@ -945,7 +970,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
CmdIOdemodFSK(c->arg[0], 0, 0, 1);
break;
case CMD_IO_CLONE_TAG:
CopyIOtoT55x7(c->arg[0], c->arg[1], c->d.asBytes[0]);
CopyIOtoT55x7(c->arg[0], c->arg[1]);
break;
case CMD_EM410X_DEMOD:
CmdEM410xdemod(c->arg[0], 0, 0, 1);
@ -974,21 +999,22 @@ void UsbPacketReceived(uint8_t *packet, int len)
CopyIndala224toT55x7(c->d.asDwords[0], c->d.asDwords[1], c->d.asDwords[2], c->d.asDwords[3], c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6]);
break;
case CMD_T55XX_READ_BLOCK:
T55xxReadBlock(c->arg[1], c->arg[2],c->d.asBytes[0]);
T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]);
break;
case CMD_T55XX_WRITE_BLOCK:
T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
cmd_send(CMD_ACK,0,0,0,0,0);
break;
case CMD_T55XX_READ_TRACE:
T55xxReadTrace();
case CMD_T55XX_WAKEUP:
T55xxWakeUp(c->arg[0]);
break;
case CMD_T55XX_RESET_READ:
T55xxResetRead();
break;
case CMD_PCF7931_READ:
ReadPCF7931();
cmd_send(CMD_ACK,0,0,0,0,0);
break;
case CMD_PCF7931_WRITE:
WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]);
WritePCF7931(c->d.asBytes[0],c->d.asBytes[1],c->d.asBytes[2],c->d.asBytes[3],c->d.asBytes[4],c->d.asBytes[5],c->d.asBytes[6], c->d.asBytes[9], c->d.asBytes[7]-128,c->d.asBytes[8]-128, c->arg[0], c->arg[1], c->arg[2]);
break;
case CMD_EM4X_READ_WORD:
EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]);
@ -998,7 +1024,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
break;
case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
break;
break;
case CMD_VIKING_CLONE_TAG:
CopyVikingtoT55xx(c->arg[0], c->arg[1], c->arg[2]);
break;
#endif
#ifdef WITH_HITAG
@ -1011,6 +1040,18 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function
ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
break;
case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content
SimulateHitagSTag((bool)c->arg[0],(byte_t*)c->d.asBytes);
break;
case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file
check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes);
break;
case CMD_READ_HITAG_S://Reader for only Hitag S tags, args = key or challenge
ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
break;
case CMD_WR_HITAG_S://writer for Hitag tags args=data to write,page and key or challenge
WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]);
break;
#endif
#ifdef WITH_ISO15693
@ -1178,11 +1219,34 @@ void UsbPacketReceived(uint8_t *packet, int len)
ReaderIClass(c->arg[0]);
break;
case CMD_READER_ICLASS_REPLAY:
ReaderIClass_Replay(c->arg[0], c->d.asBytes);
ReaderIClass_Replay(c->arg[0], c->d.asBytes);
break;
case CMD_ICLASS_EML_MEMSET:
case CMD_ICLASS_EML_MEMSET:
emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
break;
case CMD_ICLASS_WRITEBLOCK:
iClass_WriteBlock(c->arg[0], c->d.asBytes);
break;
case CMD_ICLASS_READCHECK: // auth step 1
iClass_ReadCheck(c->arg[0], c->arg[1]);
break;
case CMD_ICLASS_READBLOCK:
iClass_ReadBlk(c->arg[0]);
break;
case CMD_ICLASS_AUTHENTICATION: //check
iClass_Authentication(c->d.asBytes);
break;
case CMD_ICLASS_DUMP:
iClass_Dump(c->arg[0], c->arg[1]);
break;
case CMD_ICLASS_CLONE:
iClass_Clone(c->arg[0], c->arg[1], c->d.asBytes);
break;
#endif
#ifdef WITH_HFSNOOP
case CMD_HF_SNIFFER:
HfSnoop(c->arg[0], c->arg[1]);
break;
#endif
case CMD_BUFF_CLEAR:
@ -1190,7 +1254,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
break;
case CMD_MEASURE_ANTENNA_TUNING:
MeasureAntennaTuning();
MeasureAntennaTuning(c->arg[0]);
break;
case CMD_MEASURE_ANTENNA_TUNING_HF:
@ -1320,7 +1384,7 @@ void __attribute__((noreturn)) AppMain(void)
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;
// PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |
AT91C_PMC_PRES_CLK_4;
AT91C_PMC_PRES_CLK_4; // 4 for 24Mhz pck0, 2 for 48 MHZ pck0
AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;
// Reset SPI

View file

@ -16,6 +16,7 @@
#include <stddef.h>
#include "common.h"
#include "hitag2.h"
#include "hitagS.h"
#include "mifare.h"
#include "../common/crc32.h"
#include "BigBuf.h"
@ -58,13 +59,14 @@ extern uint8_t bits_per_sample ;
extern bool averaging;
void AcquireRawAdcSamples125k(int divisor);
void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command);
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command);
void ReadTItag(void);
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
void AcquireTiType(void);
void AcquireRawBitsTI(void);
void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
@ -73,24 +75,18 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol); // Realtime demodulation mode for AWID26
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol);
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an ioProx card to T5557/T5567
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5);
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
void CopyIndala64toT55x7(int hi, int lo); // Clone Indala 64-bit tag by UID to T55x7
void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int uid6, int uid7); // Clone Indala 224-bit tag by UID to T55x7
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
void T55xxResetRead(void);
void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode);
void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode );
void T55xxReadTrace(void);
int DemodPCF7931(uint8_t **outBlocks);
int IsBlock0PCF7931(uint8_t *Block);
int IsBlock1PCF7931(uint8_t *Block);
void ReadPCF7931();
void SendCmdPCF7931(uint32_t * tab);
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd);
void T55xxWakeUp(uint32_t Pwd);
void TurnReadLFOn();
//void T55xxReadTrace(void);
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
@ -156,9 +152,6 @@ void OnSuccess();
void OnError(uint8_t reason);
/// iso15693.h
void RecordRawAdcSamplesIso15693(void);
void AcquireRawAdcSamplesIso15693(void);
@ -174,16 +167,31 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
void ReaderIClass(uint8_t arg0);
void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
void IClass_iso14443A_GetPublic(uint8_t arg0);
void iClass_Authentication(uint8_t *MAC);
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data);
void iClass_ReadBlk(uint8_t blockNo);
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata);
void iClass_Dump(uint8_t blockno, uint8_t numblks);
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
// hitag2.h
void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
void ReaderHitag(hitag_function htf, hitag_data* htd);
//hitagS.h
void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data);
void ReadHitagS(hitag_function htf, hitag_data* htd);
void WritePageHitagS(hitag_function htf, hitag_data* htd,int page);
void check_challenges(bool file_given, byte_t* data);
// cmd.h
bool cmd_receive(UsbCommand* cmd);
bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
/// util.h
void HfSnoop(int , int);
#endif

View file

@ -274,7 +274,7 @@ uint32_t des_f(uint32_t r, uint8_t* kr){
uint64_t data;
uint8_t *sbp; /* sboxpointer */
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
for(i=0; i<7; ++i)
for(i=0; i<6; ++i)
((uint8_t*)&data)[i] ^= kr[i];
/* Sbox substitution */

View file

@ -566,3 +566,7 @@ void Fpga_print_status(void)
else if(downloaded_bitstream == FPGA_BITSTREAM_LF) Dbprintf(" mode.............LF");
else Dbprintf(" mode.............%d", downloaded_bitstream);
}
int FpgaGetCurrent() {
return downloaded_bitstream;
}

View file

@ -18,6 +18,7 @@ void FpgaSetupSsc(void);
void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, int len);
void Fpga_print_status();
int FpgaGetCurrent();
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
void SetAdcMuxFor(uint32_t whichGpio);
@ -43,6 +44,7 @@ void SetAdcMuxFor(uint32_t whichGpio);
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5)
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5)
// BOTH
#define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_ADC

79
armsrc/hfsnoop.c Normal file
View file

@ -0,0 +1,79 @@
#include "proxmark3.h"
#include "apps.h"
#include "BigBuf.h"
#include "util.h"
static void RAMFUNC optimizedSnoop(void);
static void RAMFUNC optimizedSnoop(void)
{
int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
uint16_t *dest = (uint16_t *)BigBuf_get_addr();
uint16_t *destend = dest + n;
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); // Setting Frame mode, 16 bits per word
// Reading data loop
while(dest <= destend)
{
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)
{
*dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
dest = dest + 1;
}
}
//Resetting Frame mode (First set in fpgaloader.c)
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
}
void HfSnoop(int samplesToSkip, int triggersToSkip)
{
Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.", samplesToSkip, triggersToSkip);
bool trigger_cnt;
LED_D_ON();
// Select correct configs
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Set up the synchronous serial port
FpgaSetupSsc();
// connect Demodulated Signal to ADC:
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
SpinDelay(100);
BigBuf_free();
BigBuf_Clear();
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); // Setting Frame Mode For better performance on high speed data transfer.
trigger_cnt = 0;
uint16_t r = 0;
while(!BUTTON_PRESS()) {
WDT_HIT();
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
r = (uint16_t)AT91C_BASE_SSC->SSC_RHR;
r = MAX(r & 0xff, r >> 8);
if (r >= 240)
{
if (++trigger_cnt > triggersToSkip) {
break;
}
}
}
}
if(!BUTTON_PRESS()) {
int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0
while(waitcount != 0) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
waitcount--;
}
}
optimizedSnoop();
Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r);
}
DbpString("HF Snoop end");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
}

View file

@ -411,7 +411,7 @@ static void hitag_reader_send_bit(int bit) {
// Binary puls length modulation (BPLM) is used to encode the data stream
// This means that a transmission of a one takes longer than that of a zero
// Enable modulation, which means, drop the the field
// Enable modulation, which means, drop the field
HIGH(GPIO_SSC_DOUT);
// Wait for 4-10 times the carrier period
@ -442,7 +442,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
}
// Send EOF
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
// Enable modulation, which means, drop the the field
// Enable modulation, which means, drop the field
HIGH(GPIO_SSC_DOUT);
// Wait for 4-10 times the carrier period
while(AT91C_BASE_TC0->TC_CV < T0*6);
@ -1148,7 +1148,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
case RHT2F_CRYPTO: {
DbpString("Authenticating using key:");
memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code.
Dbhexdump(6,key,false);
blocknr = 0;
bQuiet = false;

2146
armsrc/hitagS.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1447,7 +1447,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
}
WDT_HIT();
}
if (samples) *samples = (c + *wait) << 3;
if (samples && wait) *samples = (c + *wait) << 3;
}
@ -1601,16 +1601,16 @@ void setupIclassReader()
}
size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
{
while(retries-- > 0)
{
ReaderTransmitIClass(command, cmdsize);
if(expected_size == ReaderReceiveIClass(resp)){
return 0;
return true;
}
}
return 1;//Error
return false;//Error
}
/**
@ -1620,14 +1620,17 @@ size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t*
* 1 = Got CSN
* 2 = Got CSN and CC
*/
uint8_t handshakeIclassTag(uint8_t *card_data)
uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key)
{
static uint8_t act_all[] = { 0x0a };
static uint8_t identify[] = { 0x0c };
//static uint8_t identify[] = { 0x0c };
static uint8_t identify[] = { 0x0c, 0x00, 0x73, 0x33 };
static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t readcheck_cc[]= { 0x88, 0x02,};
static uint8_t readcheck_cc[]= { 0x88, 0x02 };
if (use_credit_key)
readcheck_cc[0] = 0x18;
else
readcheck_cc[0] = 0x88;
uint8_t resp[ICLASS_BUFFER_SIZE];
@ -1668,6 +1671,9 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
return read_status;
}
uint8_t handshakeIclassTag(uint8_t *card_data){
return handshakeIclassTag_ext(card_data, false);
}
// Reader iClass Anticollission
@ -1687,6 +1693,9 @@ void ReaderIClass(uint8_t arg0) {
uint8_t result_status = 0;
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
bool use_credit_key = false;
if (arg0 & FLAG_ICLASS_READER_CEDITKEY)
use_credit_key = true;
set_tracing(TRUE);
setupIclassReader();
@ -1701,7 +1710,7 @@ void ReaderIClass(uint8_t arg0) {
}
WDT_HIT();
read_status = handshakeIclassTag(card_data);
read_status = handshakeIclassTag_ext(card_data, use_credit_key);
if(read_status == 0) continue;
if(read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
@ -1715,11 +1724,10 @@ void ReaderIClass(uint8_t arg0) {
if(arg0 & FLAG_ICLASS_READER_CONF)
{
if(sendCmdGetResponseWithRetries(readConf, sizeof(readConf),card_data+8, 10, 10))
{
Dbprintf("Failed to dump config block");
}else
{
result_status |= FLAG_ICLASS_READER_CONF;
} else {
Dbprintf("Failed to dump config block");
}
}
@ -1727,10 +1735,9 @@ void ReaderIClass(uint8_t arg0) {
if(arg0 & FLAG_ICLASS_READER_AA){
if(sendCmdGetResponseWithRetries(readAA, sizeof(readAA),card_data+(8*4), 10, 10))
{
// Dbprintf("Failed to dump AA block");
}else
{
result_status |= FLAG_ICLASS_READER_AA;
} else {
//Dbprintf("Failed to dump AA block");
}
}
@ -1762,8 +1769,8 @@ void ReaderIClass(uint8_t arg0) {
}
LED_B_OFF();
}
cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF();
cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF();
}
void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
@ -1814,7 +1821,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
//for now replay captured auth (as cc not updated)
memcpy(check+5,MAC,4);
if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
if(!sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
{
Dbprintf("Error: Authentication Fail!");
continue;
@ -1826,7 +1833,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
read[2] = crc >> 8;
read[3] = crc & 0xff;
if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
if(!sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
{
Dbprintf("Dump config (block 1) failed");
continue;
@ -1853,7 +1860,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
read[2] = crc >> 8;
read[3] = crc & 0xff;
if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
if(sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
{
Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
block, resp[0], resp[1], resp[2],
@ -1904,130 +1911,129 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
LED_A_OFF();
}
//2. Create Read method (cut-down from above) based off responses from 1.
// Since we have the MAC could continue to use replay function.
//3. Create Write method
/*
void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) {
uint8_t act_all[] = { 0x0a };
uint8_t identify[] = { 0x0c };
uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t readcheck_cc[]= { 0x88, 0x02 };
uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint16_t crc = 0;
uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) {
uint8_t readcheck[] = { keyType, blockNo };
uint8_t resp[] = {0,0,0,0,0,0,0,0};
size_t isOK = 0;
isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6);
cmd_send(CMD_ACK,isOK,0,0,0,0);
}
// Reset trace buffer
memset(trace, 0x44, RECV_CMD_OFFSET);
traceLen = 0;
void iClass_Authentication(uint8_t *MAC) {
uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t resp[ICLASS_BUFFER_SIZE];
memcpy(check+5,MAC,4);
bool isOK;
isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6);
cmd_send(CMD_ACK,isOK,0,0,0,0);
}
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) {
uint8_t readcmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; //0x88, 0x00 // can i use 0C?
char bl = blockNo;
uint16_t rdCrc = iclass_crc16(&bl, 1);
readcmd[2] = rdCrc >> 8;
readcmd[3] = rdCrc & 0xff;
uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0};
bool isOK = false;
// Setup SSC
FpgaSetupSsc();
// Start from off (no field generated)
// Signal field is off with the appropriate LED
LED_D_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200);
//readcmd[1] = blockNo;
isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, 10, 10);
memcpy(readdata, resp, sizeof(resp));
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
return isOK;
}
// Now give it time to spin up.
// Signal field is on with the appropriate LED
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
SpinDelay(200);
void iClass_ReadBlk(uint8_t blockno) {
uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
bool isOK = false;
isOK = iClass_ReadBlock(blockno, readblockdata);
cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
}
LED_A_ON();
void iClass_Dump(uint8_t blockno, uint8_t numblks) {
uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
bool isOK = false;
uint8_t blkCnt = 0;
for(int i=0;i<1;i++) {
if(traceLen > TRACE_SIZE) {
DbpString("Trace full");
break;
}
if (BUTTON_PRESS()) break;
// Send act_all
ReaderTransmitIClass(act_all, 1);
// Card present?
if(ReaderReceiveIClass(resp)) {
ReaderTransmitIClass(identify, 1);
if(ReaderReceiveIClass(resp) == 10) {
// Select card
memcpy(&select[1],resp,8);
ReaderTransmitIClass(select, sizeof(select));
if(ReaderReceiveIClass(resp) == 10) {
Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
resp[0], resp[1], resp[2],
resp[3], resp[4], resp[5],
resp[6], resp[7]);
}
// Card selected
Dbprintf("Readcheck on Sector 2");
ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
if(ReaderReceiveIClass(resp) == 8) {
Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x",
resp[0], resp[1], resp[2],
resp[3], resp[4], resp[5],
resp[6], resp[7]);
}else return;
Dbprintf("Authenticate");
//for now replay captured auth (as cc not updated)
memcpy(check+5,MAC,4);
Dbprintf(" AA: %02x %02x %02x %02x",
check[5], check[6], check[7],check[8]);
ReaderTransmitIClass(check, sizeof(check));
if(ReaderReceiveIClass(resp) == 4) {
Dbprintf(" AR: %02x %02x %02x %02x",
resp[0], resp[1], resp[2],resp[3]);
}else {
Dbprintf("Error: Authentication Fail!");
return;
}
Dbprintf("Write Block");
//read configuration for max block number
read_success=false;
read[1]=1;
uint8_t *blockno=&read[1];
crc = iclass_crc16((char *)blockno,1);
read[2] = crc >> 8;
read[3] = crc & 0xff;
while(!read_success){
ReaderTransmitIClass(read, sizeof(read));
if(ReaderReceiveIClass(resp) == 10) {
read_success=true;
mem=resp[5];
memory.k16= (mem & 0x80);
memory.book= (mem & 0x20);
memory.k2= (mem & 0x8);
memory.lockauth= (mem & 0x2);
memory.keyaccess= (mem & 0x1);
}
}
if (memory.k16){
cardsize=255;
}else cardsize=32;
//check card_size
memcpy(write+1,blockNo,1);
memcpy(write+2,data,8);
memcpy(write+10,mac,4);
while(!send_success){
ReaderTransmitIClass(write, sizeof(write));
if(ReaderReceiveIClass(resp) == 10) {
write_success=true;
}
}//
}
WDT_HIT();
BigBuf_free();
uint8_t *dataout = BigBuf_malloc(255*8);
if (dataout == NULL){
Dbprintf("out of memory");
OnError(1);
return;
}
LED_A_OFF();
}*/
memset(dataout,0xFF,255*8);
for (;blkCnt < numblks; blkCnt++) {
isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata);
if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0xBB || readblockdata[2] == 0xBB)) { //try again
isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata);
if (!isOK) {
Dbprintf("Block %02X failed to read", blkCnt+blockno);
break;
}
}
memcpy(dataout+(blkCnt*8),readblockdata,8);
}
//return pointer to dump memory in arg3
cmd_send(CMD_ACK,isOK,blkCnt,BigBuf_max_traceLen(),0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
BigBuf_free();
}
bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//uint8_t readblockdata[10];
//write[1] = blockNo;
memcpy(write+2, data, 12); // data + mac
uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0};
bool isOK;
isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10);
if (isOK) {
//Dbprintf("WriteResp: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",resp[0],resp[1],resp[2],resp[3],resp[4],resp[5],resp[6],resp[7],resp[8],resp[9]);
if (memcmp(write+2,resp,8)) {
//error try again
isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10);
}
}
return isOK;
}
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) {
bool isOK = iClass_WriteBlock_ext(blockNo, data);
if (isOK){
Dbprintf("Write block [%02x] successful",blockNo);
} else {
Dbprintf("Write block [%02x] failed",blockNo);
}
cmd_send(CMD_ACK,isOK,0,0,0,0);
}
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
int i;
int written = 0;
int total_block = (endblock - startblock) + 1;
for (i = 0; i < total_block;i++){
// block number
if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){
Dbprintf("Write block [%02x] successful",i + startblock);
written++;
} else {
if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){
Dbprintf("Write block [%02x] successful",i + startblock);
written++;
} else {
Dbprintf("Write block [%02x] failed",i + startblock);
}
}
}
if (written == total_block)
Dbprintf("Clone complete");
else
Dbprintf("Clone incomplete");
cmd_send(CMD_ACK,1,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}

File diff suppressed because it is too large Load diff

View file

@ -56,15 +56,14 @@ typedef struct {
// DROP_FIRST_HALF,
} state;
uint16_t shiftReg;
uint16_t bitCount;
int16_t bitCount;
uint16_t len;
uint16_t byteCntMax;
uint16_t posCnt;
uint16_t syncBit;
uint8_t parityBits;
uint8_t parityLen;
uint16_t highCnt;
uint16_t twoBits;
uint32_t fourBits;
uint32_t startTime, endTime;
uint8_t *output;
uint8_t *parity;

View file

@ -547,15 +547,20 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
}
*/
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
#define CHECK_FOR_SUBCARRIER() { \
v = MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2); \
}
/*
if(ci < 0) { \
if(cq < 0) { /* ci < 0, cq < 0 */ \
if(cq < 0) { \ // ci < 0, cq < 0
if (cq < ci) { \
v = -cq - (ci >> 1); \
} else { \
v = -ci - (cq >> 1); \
} \
} else { /* ci < 0, cq >= 0 */ \
} else { \ // ci < 0, cq >= 0
if (cq < -ci) { \
v = -ci + (cq >> 1); \
} else { \
@ -563,13 +568,13 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
} \
} \
} else { \
if(cq < 0) { /* ci >= 0, cq < 0 */ \
if(cq < 0) { \ // ci >= 0, cq < 0
if (-cq < ci) { \
v = ci - (cq >> 1); \
} else { \
v = -cq + (ci >> 1); \
} \
} else { /* ci >= 0, cq >= 0 */ \
} else { \ // ci >= 0, cq >= 0
if (cq < ci) { \
v = ci + (cq >> 1); \
} else { \
@ -578,6 +583,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
} \
} \
}
*/
switch(Demod.state) {
case DEMOD_UNSYNCD:

View file

@ -319,18 +319,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
// 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;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
@ -468,18 +457,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
// 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;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
@ -648,18 +626,7 @@ void AcquireRawAdcSamplesIso15693(void)
// 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;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
@ -713,18 +680,7 @@ void RecordRawAdcSamplesIso15693(void)
// 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;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
#include "apps.h"
#include "util.h"
#include "string.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "lfsampling.h"
sample_config config = { 1, 8, 1, 95, 0 } ;
@ -103,7 +103,6 @@ void LFSetupFPGAForADC(int divisor, bool lf_field)
FpgaSetupSsc();
}
/**
* Does the sample acquisition. If threshold is specified, the actual sampling
* is not commenced until the threshold has been reached.
@ -125,7 +124,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
uint8_t *dest = BigBuf_get_addr();
int bufsize = BigBuf_max_traceLen();
memset(dest, 0, bufsize);
//memset(dest, 0, bufsize); //creates issues with cmdread (marshmellow)
if(bits_per_sample < 1) bits_per_sample = 1;
if(bits_per_sample > 8) bits_per_sample = 8;
@ -154,9 +153,6 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
if ((trigger_threshold > 0) && (sample < (trigger_threshold+128)) && (sample > (128-trigger_threshold))) //
continue;
//if (trigger_threshold > 0 && sample < trigger_threshold) //
//continue;
trigger_threshold = 0;
sample_total_numbers++;
@ -252,3 +248,70 @@ uint32_t SnoopLF()
{
return ReadLF(false, true);
}
/**
* acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds
* the data is collected in BigBuf.
**/
void doT55x7Acquisition(size_t sample_size) {
#define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
#define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
#define T55xx_READ_TOL 5
uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > sample_size )
bufsize = sample_size;
uint16_t i = 0;
bool startFound = false;
bool highFound = false;
bool lowFound = false;
uint8_t curSample = 0;
uint8_t lastSample = 0;
uint16_t skipCnt = 0;
while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt<1000 && i<bufsize ) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF();
// skip until the first high sample above threshold
if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) {
//if (curSample > lastSample)
// lastSample = curSample;
highFound = true;
} else if (!highFound) {
skipCnt++;
continue;
}
// skip until the first Low sample below threshold
if (!startFound && curSample < T55xx_READ_LOWER_THRESHOLD) {
//if (curSample > lastSample)
lastSample = curSample;
lowFound = true;
} else if (!lowFound) {
skipCnt++;
continue;
}
// skip until first high samples begin to change
if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD+T55xx_READ_TOL){
// if just found start - recover last sample
if (!startFound) {
dest[i++] = lastSample;
startFound = true;
}
// collect samples
dest[i++] = curSample;
}
}
}
}

View file

@ -1,6 +1,12 @@
#ifndef LFSAMPLING_H
#define LFSAMPLING_H
/**
* acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds
* the data is collected in BigBuf.
**/
void doT55x7Acquisition(size_t sample_size);
/**
* Initializes the FPGA for reader-mode (field on), and acquires the samples.
* @return number of bits sampled
@ -41,7 +47,6 @@ uint32_t DoAcquisition_config( bool silent);
**/
void LFSetupFPGAForADC(int divisor, bool lf_field);
/**
* Called from the USB-handler to set the sampling configuration
* The sampling config is used for std reading and snooping.

View file

@ -42,14 +42,15 @@ extern int MF_DBGLEVEL;
#define MFEMUL_IDLE 1
#define MFEMUL_SELECT1 2
#define MFEMUL_SELECT2 3
#define MFEMUL_AUTH1 4
#define MFEMUL_AUTH2 5
#define MFEMUL_WORK 6
#define MFEMUL_WRITEBL2 7
#define MFEMUL_INTREG_INC 8
#define MFEMUL_INTREG_DEC 9
#define MFEMUL_INTREG_REST 10
#define MFEMUL_HALTED 11
#define MFEMUL_SELECT3 4
#define MFEMUL_AUTH1 5
#define MFEMUL_AUTH2 6
#define MFEMUL_WORK 7
#define MFEMUL_WRITEBL2 8
#define MFEMUL_INTREG_INC 9
#define MFEMUL_INTREG_DEC 10
#define MFEMUL_INTREG_REST 11
#define MFEMUL_HALTED 12
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();

525
armsrc/pcf7931.c Normal file
View file

@ -0,0 +1,525 @@
#include "proxmark3.h"
#include "apps.h"
#include "lfsampling.h"
#include "pcf7931.h"
#include "string.h"
#define T0_PCF 8 //period for the pcf7931 in us
#define ALLOC 16
int DemodPCF7931(uint8_t **outBlocks) {
uint8_t bits[256] = {0x00};
uint8_t blocks[8][16];
uint8_t *dest = BigBuf_get_addr();
int GraphTraceLen = BigBuf_max_traceLen();
if ( GraphTraceLen > 18000 )
GraphTraceLen = 18000;
int i, j, lastval, bitidx, half_switch;
int clock = 64;
int tolerance = clock / 8;
int pmc, block_done;
int lc, warnings = 0;
int num_blocks = 0;
int lmin=128, lmax=128;
uint8_t dir;
//clear read buffer
BigBuf_Clear_keep_EM();
LFSetupFPGAForADC(95, true);
DoAcquisition_default(0, true);
lmin = 64;
lmax = 192;
i = 2;
/* Find first local max/min */
if(dest[1] > dest[0]) {
while(i < GraphTraceLen) {
if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
break;
i++;
}
dir = 0;
}
else {
while(i < GraphTraceLen) {
if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
break;
i++;
}
dir = 1;
}
lastval = i++;
half_switch = 0;
pmc = 0;
block_done = 0;
for (bitidx = 0; i < GraphTraceLen; i++)
{
if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin))
{
lc = i - lastval;
lastval = i;
// Switch depending on lc length:
// Tolerance is 1/8 of clock rate (arbitrary)
if (ABS(lc-clock/4) < tolerance) {
// 16T0
if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
i += (128+127+16+32+33+16)-1;
lastval = i;
pmc = 0;
block_done = 1;
}
else {
pmc = i;
}
} else if (ABS(lc-clock/2) < tolerance) {
// 32TO
if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
i += (128+127+16+32+33)-1;
lastval = i;
pmc = 0;
block_done = 1;
}
else if(half_switch == 1) {
bits[bitidx++] = 0;
half_switch = 0;
}
else
half_switch++;
} else if (ABS(lc-clock) < tolerance) {
// 64TO
bits[bitidx++] = 1;
} else {
// Error
warnings++;
if (warnings > 10)
{
Dbprintf("Error: too many detection errors, aborting.");
return 0;
}
}
if(block_done == 1) {
if(bitidx == 128) {
for(j=0; j<16; j++) {
blocks[num_blocks][j] = 128*bits[j*8+7]+
64*bits[j*8+6]+
32*bits[j*8+5]+
16*bits[j*8+4]+
8*bits[j*8+3]+
4*bits[j*8+2]+
2*bits[j*8+1]+
bits[j*8];
}
num_blocks++;
}
bitidx = 0;
block_done = 0;
half_switch = 0;
}
if(i < GraphTraceLen)
dir =(dest[i-1] > dest[i]) ? 0 : 1;
}
if(bitidx==255)
bitidx=0;
warnings = 0;
if(num_blocks == 4) break;
}
memcpy(outBlocks, blocks, 16*num_blocks);
return num_blocks;
}
int IsBlock0PCF7931(uint8_t *Block) {
// Assume RFU means 0 :)
if((memcmp(Block, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) == 0) && memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) // PAC enabled
return 1;
if((memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block[7] == 0) // PAC disabled, can it *really* happen ?
return 1;
return 0;
}
int IsBlock1PCF7931(uint8_t *Block) {
// Assume RFU means 0 :)
if(Block[10] == 0 && Block[11] == 0 && Block[12] == 0 && Block[13] == 0)
if((Block[14] & 0x7f) <= 9 && Block[15] <= 9)
return 1;
return 0;
}
void ReadPCF7931() {
uint8_t Blocks[8][17];
uint8_t tmpBlocks[4][16];
int i, j, ind, ind2, n;
int num_blocks = 0;
int max_blocks = 8;
int ident = 0;
int error = 0;
int tries = 0;
memset(Blocks, 0, 8*17*sizeof(uint8_t));
do {
memset(tmpBlocks, 0, 4*16*sizeof(uint8_t));
n = DemodPCF7931((uint8_t**)tmpBlocks);
if(!n)
error++;
if(error==10 && num_blocks == 0) {
Dbprintf("Error, no tag or bad tag");
return;
}
else if (tries==20 || error==10) {
Dbprintf("Error reading the tag");
Dbprintf("Here is the partial content");
goto end;
}
for(i=0; i<n; i++)
Dbprintf("(dbg) %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
tmpBlocks[i][0], tmpBlocks[i][1], tmpBlocks[i][2], tmpBlocks[i][3], tmpBlocks[i][4], tmpBlocks[i][5], tmpBlocks[i][6], tmpBlocks[i][7],
tmpBlocks[i][8], tmpBlocks[i][9], tmpBlocks[i][10], tmpBlocks[i][11], tmpBlocks[i][12], tmpBlocks[i][13], tmpBlocks[i][14], tmpBlocks[i][15]);
if(!ident) {
for(i=0; i<n; i++) {
if(IsBlock0PCF7931(tmpBlocks[i])) {
// Found block 0 ?
if(i < n-1 && IsBlock1PCF7931(tmpBlocks[i+1])) {
// Found block 1!
// \o/
ident = 1;
memcpy(Blocks[0], tmpBlocks[i], 16);
Blocks[0][ALLOC] = 1;
memcpy(Blocks[1], tmpBlocks[i+1], 16);
Blocks[1][ALLOC] = 1;
max_blocks = MAX((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
// Debug print
Dbprintf("(dbg) Max blocks: %d", max_blocks);
num_blocks = 2;
// Handle following blocks
for(j=i+2, ind2=2; j!=i; j++, ind2++, num_blocks++) {
if(j==n) j=0;
if(j==i) break;
memcpy(Blocks[ind2], tmpBlocks[j], 16);
Blocks[ind2][ALLOC] = 1;
}
break;
}
}
}
}
else {
for(i=0; i<n; i++) { // Look for identical block in known blocks
if(memcmp(tmpBlocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { // Block is not full of 00
for(j=0; j<max_blocks; j++) {
if(Blocks[j][ALLOC] == 1 && !memcmp(tmpBlocks[i], Blocks[j], 16)) {
// Found an identical block
for(ind=i-1,ind2=j-1; ind >= 0; ind--,ind2--) {
if(ind2 < 0)
ind2 = max_blocks;
if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found
// Dbprintf("Tmp %d -> Block %d", ind, ind2);
memcpy(Blocks[ind2], tmpBlocks[ind], 16);
Blocks[ind2][ALLOC] = 1;
num_blocks++;
if(num_blocks == max_blocks) goto end;
}
}
for(ind=i+1,ind2=j+1; ind < n; ind++,ind2++) {
if(ind2 > max_blocks)
ind2 = 0;
if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found
// Dbprintf("Tmp %d -> Block %d", ind, ind2);
memcpy(Blocks[ind2], tmpBlocks[ind], 16);
Blocks[ind2][ALLOC] = 1;
num_blocks++;
if(num_blocks == max_blocks) goto end;
}
}
}
}
}
}
}
tries++;
if (BUTTON_PRESS()) return;
} while (num_blocks != max_blocks);
end:
Dbprintf("-----------------------------------------");
Dbprintf("Memory content:");
Dbprintf("-----------------------------------------");
for(i=0; i<max_blocks; i++) {
if(Blocks[i][ALLOC]==1)
Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
Blocks[i][0], Blocks[i][1], Blocks[i][2], Blocks[i][3], Blocks[i][4], Blocks[i][5], Blocks[i][6], Blocks[i][7],
Blocks[i][8], Blocks[i][9], Blocks[i][10], Blocks[i][11], Blocks[i][12], Blocks[i][13], Blocks[i][14], Blocks[i][15]);
else
Dbprintf("<missing block %d>", i);
}
Dbprintf("-----------------------------------------");
cmd_send(CMD_ACK,0,0,0,0,0);
}
/* Write on a byte of a PCF7931 tag
* @param address : address of the block to write
@param byte : address of the byte to write
@param data : data to write
*/
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data)
{
uint32_t tab[1024]={0}; // data times frame
uint32_t u = 0;
uint8_t parity = 0;
bool comp = 0;
//BUILD OF THE DATA FRAME
//alimentation of the tag (time for initializing)
AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
//PMC
Dbprintf("Initialization delay : %d us", init_delay);
AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
//password indication bit
AddBitPCF7931(1, tab, l, p);
//password (on 56 bits)
Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7);
AddBytePCF7931(pass1, tab, l, p);
AddBytePCF7931(pass2, tab, l, p);
AddBytePCF7931(pass3, tab, l, p);
AddBytePCF7931(pass4, tab, l, p);
AddBytePCF7931(pass5, tab, l, p);
AddBytePCF7931(pass6, tab, l, p);
AddBytePCF7931(pass7, tab, l, p);
//programming mode (0 or 1)
AddBitPCF7931(0, tab, l, p);
//block adress on 6 bits
Dbprintf("Block address : %02x", address);
for (u=0; u<6; u++)
{
if (address&(1<<u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
} else{ // bit 0
AddBitPCF7931(0, tab, l, p);
}
}
//byte address on 4 bits
Dbprintf("Byte address : %02x", byte);
for (u=0; u<4; u++)
{
if (byte&(1<<u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
} else{ // bit 0
AddBitPCF7931(0, tab, l, p);
}
}
//data on 8 bits
Dbprintf("Data : %02x", data);
for (u=0; u<8; u++)
{
if (data&(1<<u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
} else{ //bit 0
AddBitPCF7931(0, tab, l, p);
}
}
//parity bit
if((parity%2)==0){
AddBitPCF7931(0, tab, l, p); //even parity
}else{
AddBitPCF7931(1, tab, l, p);//odd parity
}
//time access memory
AddPatternPCF7931(5120+2680, 0, 0, tab);
//conversion of the scale time
for(u=0;u<500;u++){
tab[u]=(tab[u] * 3)/2;
}
//compennsation of the counter reload
while (!comp){
comp = 1;
for(u=0;tab[u]!=0;u++){
if(tab[u] > 0xFFFF){
tab[u] -= 0xFFFF;
comp = 0;
}
}
}
SendCmdPCF7931(tab);
}
/* Send a trame to a PCF7931 tags
* @param tab : array of the data frame
*/
void SendCmdPCF7931(uint32_t * tab){
uint16_t u=0;
uint16_t tempo=0;
Dbprintf("SENDING DATA FRAME...");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
LED_A_ON();
// steal this pin from the SSP and use it to control the modulation
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
//initialization of the timer
AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
AT91C_BASE_TCB->TCB_BCR = 1;
tempo = AT91C_BASE_TC0->TC_CV;
for(u=0;tab[u]!= 0;u+=3){
// modulate antenna
HIGH(GPIO_SSC_DOUT);
while(tempo != tab[u]){
tempo = AT91C_BASE_TC0->TC_CV;
}
// stop modulating antenna
LOW(GPIO_SSC_DOUT);
while(tempo != tab[u+1]){
tempo = AT91C_BASE_TC0->TC_CV;
}
// modulate antenna
HIGH(GPIO_SSC_DOUT);
while(tempo != tab[u+2]){
tempo = AT91C_BASE_TC0->TC_CV;
}
}
LED_A_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200);
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
DbpString("FINISH !");
DbpString("(Could be usefull to send the same trame many times)");
LED(0xFFFF, 1000);
}
/* Add a byte for building the data frame of PCF7931 tags
* @param b : byte to add
* @param tab : array of the data frame
* @param l : offset on low pulse width
* @param p : offset on low pulse positioning
*/
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
uint32_t u;
for (u=0; u<8; u++)
{
if (byte&(1<<u)) { //bit à 1
if(AddBitPCF7931(1, tab, l, p)==1)return 1;
} else { //bit à 0
if(AddBitPCF7931(0, tab, l, p)==1)return 1;
}
}
return 0;
}
/* Add a bits for building the data frame of PCF7931 tags
* @param b : bit to add
* @param tab : array of the data frame
* @param l : offset on low pulse width
* @param p : offset on low pulse positioning
*/
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
uint8_t u = 0;
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
if(b==1){ //add a bit 1
if(u==0) tab[u] = 34*T0_PCF+p;
else tab[u] = 34*T0_PCF+tab[u-1]+p;
tab[u+1] = 6*T0_PCF+tab[u]+l;
tab[u+2] = 88*T0_PCF+tab[u+1]-l-p;
return 0;
}else{ //add a bit 0
if(u==0) tab[u] = 98*T0_PCF+p;
else tab[u] = 98*T0_PCF+tab[u-1]+p;
tab[u+1] = 6*T0_PCF+tab[u]+l;
tab[u+2] = 24*T0_PCF+tab[u+1]-l-p;
return 0;
}
return 1;
}
/* Add a custom pattern in the data frame
* @param a : delay of the first high pulse
* @param b : delay of the low pulse
* @param c : delay of the last high pulse
* @param tab : array of the data frame
*/
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){
uint32_t u = 0;
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
if(u==0) tab[u] = a;
else tab[u] = a + tab[u-1];
tab[u+1] = b+tab[u];
tab[u+2] = c+tab[u+1];
return 0;
}

14
armsrc/pcf7931.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef __PCF7931_H
#define __PCF7931_H
int DemodPCF7931(uint8_t **outBlocks);
int IsBlock0PCF7931(uint8_t *Block);
int IsBlock1PCF7931(uint8_t *Block);
void ReadPCF7931();
void SendCmdPCF7931(uint32_t * tab);
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
#endif

View file

@ -57,14 +57,14 @@ CORESRCS = uart.c \
CMDSRCS = nonce2key/crapto1.c\
nonce2key/crypto1.c\
nonce2key/nonce2key.c\
loclass/cipher.c \
loclass/cipherutils.c \
loclass/des.c \
loclass/ikeys.c \
loclass/elite_crack.c\
loclass/fileutils.c\
nonce2key/crypto1.c\
nonce2key/nonce2key.c\
loclass/cipher.c \
loclass/cipherutils.c \
loclass/des.c \
loclass/ikeys.c \
loclass/elite_crack.c\
loclass/fileutils.c\
mifarehost.c\
crc.c \
crc16.c \
@ -85,6 +85,7 @@ CMDSRCS = nonce2key/crapto1.c\
cmdhficlass.c \
cmdhfmf.c \
cmdhfmfu.c \
cmdhftopaz.c \
cmdhw.c \
cmdlf.c \
cmdlfio.c \
@ -97,6 +98,9 @@ CMDSRCS = nonce2key/crapto1.c\
cmdmain.c \
cmdlft55xx.c \
cmdlfpcf7931.c\
cmdlfviking.c\
cmdlfpresco.c\
cmdlfpyramid.c\
pm3_binlib.c\
scripting.c\
cmdscript.c\

View file

@ -8,23 +8,22 @@
// Data and Graph commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "proxmark3.h"
#include "data.h"
#include "ui.h"
#include "graph.h"
#include "cmdparser.h"
#include <stdio.h> // also included in util.h
#include <string.h> // also included in util.h
#include <limits.h> // for CmdNorm INT_MIN && INT_MAX
#include "data.h" // also included in util.h
#include "cmddata.h"
#include "util.h"
#include "cmdmain.h"
#include "cmddata.h"
#include "lfdemod.h"
#include "usb_cmd.h"
#include "crc.h"
#include "crc16.h"
#include "loclass/cipherutils.h"
#include "proxmark3.h"
#include "ui.h" // for show graph controls
#include "graph.h" // for graph data
#include "cmdparser.h"// already included in cmdmain.h
#include "usb_cmd.h" // already included in cmdmain.h and proxmark3.h
#include "lfdemod.h" // for demod code
#include "crc.h" // for pyramid checksum maxim
#include "crc16.h" // for FDXB demod checksum
#include "loclass/cipherutils.h" // for decimating samples in getsamples
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
uint8_t g_debugMode=0;
@ -58,11 +57,12 @@ int CmdSetDebugMode(const char *Cmd)
}
int usage_data_printdemodbuf(){
PrintAndLog("Usage: data printdemodbuffer x o <offset>");
PrintAndLog("Usage: data printdemodbuffer x o <offset> l <length>");
PrintAndLog("Options: ");
PrintAndLog(" h This help");
PrintAndLog(" x output in hex (omit for binary output)");
PrintAndLog(" o <offset> enter offset in # of bits");
PrintAndLog(" l <length> enter length to print in # of bits or hex characters respectively");
return 0;
}
@ -87,7 +87,8 @@ int CmdPrintDemodBuff(const char *Cmd)
char hex[512]={0x00};
bool hexMode = false;
bool errors = false;
uint8_t offset = 0;
uint32_t offset = 0; //could be size_t but no param_get16...
uint32_t length = 512;
char cmdp = 0;
while(param_getchar(Cmd, cmdp) != 0x00)
{
@ -103,10 +104,16 @@ int CmdPrintDemodBuff(const char *Cmd)
break;
case 'o':
case 'O':
offset = param_get8(Cmd, cmdp+1);
offset = param_get32ex(Cmd, cmdp+1, 0, 10);
if (!offset) errors = true;
cmdp += 2;
break;
case 'l':
case 'L':
length = param_get32ex(Cmd, cmdp+1, 512, 10);
if (!length) errors = true;
cmdp += 2;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
@ -116,18 +123,17 @@ int CmdPrintDemodBuff(const char *Cmd)
}
//Validations
if(errors) return usage_data_printdemodbuf();
int numBits = (DemodBufferLen-offset) & 0x7FC; //make sure we don't exceed our string
length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length;
int numBits = (length) & 0x00FFC; //make sure we don't exceed our string
if (hexMode){
char *buf = (char *) (DemodBuffer + offset);
numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits;
numBits = binarraytohex(hex, buf, numBits);
if (numBits==0) return 0;
PrintAndLog("DemodBuffer: %s",hex);
} else {
//setDemodBuf(DemodBuffer, DemodBufferLen-offset, offset);
char *bin = sprint_bin_break(DemodBuffer+offset,numBits,16);
PrintAndLog("DemodBuffer:\n%s",bin);
PrintAndLog("DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset,numBits,16));
}
return 1;
}
@ -270,7 +276,8 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo )
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose)
{
if (!ASKDemod(Cmd, FALSE, FALSE, 1)) return 0;
bool st = TRUE;
if (!ASKDemod_ext(Cmd, FALSE, FALSE, 1, &st)) return 0;
return AskEm410xDecode(verbose, hi, lo);
}
@ -305,8 +312,7 @@ int CmdAskEM410xDemod(const char *Cmd)
//verbose will print results and demoding messages
//emSearch will auto search for EM410x format in bitstream
//askType switches decode: ask/raw = 0, ask/manchester = 1
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
{
int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
int invert=0;
int clk=0;
int maxErr=100;
@ -315,7 +321,7 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
char amp = param_getchar(Cmd, 0);
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &amp);
if (!maxLen) maxLen = 512*64;
if (!maxLen) maxLen = BIGBUF_SIZE;
if (invert != 0 && invert != 1) {
PrintAndLog("Invalid argument: %s", Cmd);
return 0;
@ -327,15 +333,22 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
if (amp == 'a' || amp == 'A') askAmp=1;
size_t BitLen = getFromGraphBuf(BitStream);
if (g_debugMode) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
if (BitLen<255) return 0;
if (maxLen<BitLen && maxLen != 0) BitLen = maxLen;
if (BitLen < 255) return 0;
if (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
int foundclk = 0;
bool st = false;
if (*stCheck) st = DetectST(BitStream, &BitLen, &foundclk);
if (st) {
*stCheck = st;
clk = (clk == 0) ? foundclk : clk;
if (verbose || g_debugMode) PrintAndLog("\nFound Sequence Terminator");
}
int errCnt = askdemod(BitStream, &BitLen, &clk, &invert, maxErr, askAmp, askType);
if (errCnt<0 || BitLen<16){ //if fatal error (or -1)
if (g_debugMode) PrintAndLog("DEBUG: no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
return 0;
}
if (errCnt>maxErr){
if (errCnt > maxErr){
if (g_debugMode) PrintAndLog("DEBUG: Too many errors found, errors:%d, bits:%d, clock:%d",errCnt, BitLen, clk);
return 0;
}
@ -358,6 +371,10 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
}
return 1;
}
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
bool st = false;
return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st);
}
//by marshmellow
//takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
@ -367,7 +384,8 @@ int Cmdaskmandemod(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: data rawdemod am [clock] <invert> [maxError] [maxLen] [amplify]");
PrintAndLog("Usage: data rawdemod am <s> [clock] <invert> [maxError] [maxLen] [amplify]");
PrintAndLog(" ['s'] optional, check for Sequence Terminator");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect");
PrintAndLog(" <invert>, 1 to invert output");
PrintAndLog(" [set maximum allowed errors], default = 100");
@ -381,7 +399,13 @@ int Cmdaskmandemod(const char *Cmd)
PrintAndLog(" : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
return 0;
}
return ASKDemod(Cmd, TRUE, TRUE, 1);
bool st = TRUE;
if (Cmd[0]=='s')
return ASKDemod_ext(Cmd++, TRUE, TRUE, 1, &st);
else if (Cmd[1] == 's')
return ASKDemod_ext(Cmd+=2, TRUE, TRUE, 1, &st);
else
return ASKDemod(Cmd, TRUE, TRUE, 1);
}
//by marshmellow
@ -567,7 +591,7 @@ int Cmdaskbiphdemod(const char *Cmd)
int CmdG_Prox_II_Demod(const char *Cmd)
{
if (!ASKbiphaseDemod(Cmd, FALSE)){
if (g_debugMode) PrintAndLog("ASKbiphaseDemod failed 1st try");
if (g_debugMode) PrintAndLog("Error gProxII: ASKbiphaseDemod failed 1st try");
return 0;
}
size_t size = DemodBufferLen;
@ -577,46 +601,32 @@ int CmdG_Prox_II_Demod(const char *Cmd)
if (g_debugMode) PrintAndLog("Error gProxII_Demod");
return 0;
}
//got a good demod
uint32_t ByteStream[65] = {0x00};
//got a good demod of 96 bits
uint8_t ByteStream[8] = {0x00};
uint8_t xorKey=0;
uint8_t keyCnt=0;
uint8_t bitCnt=0;
uint8_t ByteCnt=0;
size_t startIdx = ans + 6; //start after preamble
for (size_t idx = 0; idx<size-6; idx++){
if ((idx+1) % 5 == 0){
//spacer bit - should be 0
if (DemodBuffer[startIdx+idx] != 0) {
if (g_debugMode) PrintAndLog("Error spacer not 0: %d, pos: %d",DemodBuffer[startIdx+idx],startIdx+idx);
return 0;
}
continue;
}
if (keyCnt<8){ //lsb first
xorKey = xorKey | (DemodBuffer[startIdx+idx]<<keyCnt);
keyCnt++;
if (keyCnt==8 && g_debugMode) PrintAndLog("xorKey Found: %02x", xorKey);
continue;
}
//lsb first
ByteStream[ByteCnt] = ByteStream[ByteCnt] | (DemodBuffer[startIdx+idx]<<bitCnt);
bitCnt++;
if (bitCnt % 8 == 0){
if (g_debugMode) PrintAndLog("byte %d: %02x",ByteCnt,ByteStream[ByteCnt]);
bitCnt=0;
ByteCnt++;
}
size_t startIdx = ans + 6; //start after 6 bit preamble
uint8_t bits_no_spacer[90];
//so as to not mess with raw DemodBuffer copy to a new sample array
memcpy(bits_no_spacer, DemodBuffer + startIdx, 90);
// remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run
if (bitLen != 72) {
if (g_debugMode) PrintAndLog("Error gProxII: spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx);
return 0;
}
for (uint8_t i = 0; i < ByteCnt; i++){
ByteStream[i] ^= xorKey; //xor
if (g_debugMode) PrintAndLog("byte %d after xor: %02x", i, ByteStream[i]);
// get key and then get all 8 bytes of payload decoded
xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
for (size_t idx = 0; idx < 8; idx++) {
ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey;
if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]);
}
//now ByteStream contains 64 bytes of decrypted raw tag data
//now ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data
//
uint8_t fmtLen = ByteStream[0]>>2;
uint32_t FC = 0;
uint32_t Card = 0;
//get raw 96 bits to print
uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
@ -624,19 +634,46 @@ int CmdG_Prox_II_Demod(const char *Cmd)
if (fmtLen==36){
FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1);
Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
} else if(fmtLen==26){
FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7);
Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
} else {
PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",fmtLen);
PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen);
PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8));
}
PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3);
setDemodBuf(DemodBuffer+ans, 96, 0);
return 1;
}
//by marshmellow
//see ASKDemod for what args are accepted
int CmdVikingDemod(const char *Cmd)
{
if (!ASKDemod(Cmd, false, false, 1)) {
if (g_debugMode) PrintAndLog("ASKDemod failed");
return 0;
}
size_t size = DemodBufferLen;
//call lfdemod.c demod for Viking
int ans = VikingDemod_AM(DemodBuffer, &size);
if (ans < 0) {
if (g_debugMode) PrintAndLog("Error Viking_Demod %d", ans);
return 0;
}
//got a good demod
uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32);
uint8_t checksum = bytebits_to_byte(DemodBuffer+ans+32+24, 8);
PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, (unsigned int) checksum);
PrintAndLog("Raw: %08X%08X", raw1,raw2);
setDemodBuf(DemodBuffer+ans, 64, 0);
return 1;
}
//by marshmellow - see ASKDemod
int Cmdaskrawdemod(const char *Cmd)
{
@ -797,16 +834,18 @@ int CmdUndec(const char *Cmd)
uint8_t factor = param_get8ex(Cmd, 0,2, 10);
//We have memory, don't we?
int swap[MAX_GRAPH_TRACE_LEN] = { 0 };
uint32_t g_index = 0 ,s_index = 0;
while(g_index < GraphTraceLen && s_index < MAX_GRAPH_TRACE_LEN)
uint32_t g_index = 0, s_index = 0;
while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN)
{
int count = 0;
for(count = 0; count < factor && s_index+count < MAX_GRAPH_TRACE_LEN; count ++)
for(count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++)
swap[s_index+count] = GraphBuffer[g_index];
s_index+=count;
s_index += count;
g_index++;
}
memcpy(GraphBuffer,swap, s_index * sizeof(int));
memcpy(GraphBuffer, swap, s_index * sizeof(int));
GraphTraceLen = s_index;
RepaintGraphWindow();
return 0;
@ -840,13 +879,15 @@ int CmdGraphShiftZero(const char *Cmd)
int CmdAskEdgeDetect(const char *Cmd)
{
int thresLen = 25;
int Last = 0;
sscanf(Cmd, "%i", &thresLen);
for(int i = 1; i<GraphTraceLen; i++){
if (GraphBuffer[i]-GraphBuffer[i-1]>=thresLen) //large jump up
GraphBuffer[i-1] = 127;
Last = 127;
else if(GraphBuffer[i]-GraphBuffer[i-1]<=-1*thresLen) //large jump down
GraphBuffer[i-1] = -127;
Last = -127;
GraphBuffer[i-1] = Last;
}
RepaintGraphWindow();
return 0;
@ -886,19 +927,21 @@ int CmdDetectClockRate(const char *Cmd)
char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert)
{
char *fskType;
static char fType[8];
memset(fType, 0x00, 8);
char *fskType = fType;
if (fchigh==10 && fclow==8){
if (invert) //fsk2a
fskType = "FSK2a";
memcpy(fskType, "FSK2a", 5);
else //fsk2
fskType = "FSK2";
memcpy(fskType, "FSK2", 4);
} else if (fchigh == 8 && fclow == 5) {
if (invert)
fskType = "FSK1";
memcpy(fskType, "FSK1", 4);
else
fskType = "FSK1a";
memcpy(fskType, "FSK1a", 5);
} else {
fskType = "FSK??";
memcpy(fskType, "FSK??", 5);
}
return fskType;
}
@ -910,55 +953,53 @@ char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert)
int FSKrawDemod(const char *Cmd, bool verbose)
{
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
uint8_t rfLen, invert, fchigh, fclow;
//set defaults
int rfLen = 0;
int invert = 0;
int fchigh = 0;
int fclow = 0;
//set options from parameters entered with the command
sscanf(Cmd, "%i %i %i %i", &rfLen, &invert, &fchigh, &fclow);
rfLen = param_get8(Cmd, 0);
invert = param_get8(Cmd, 1);
fchigh = param_get8(Cmd, 2);
fclow = param_get8(Cmd, 3);
if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
if (rfLen==1){
if (rfLen==1) {
invert = 1; //if invert option only is used
rfLen = 0;
}
}
}
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
size_t BitLen = getFromGraphBuf(BitStream);
if (BitLen==0) return 0;
//get field clock lengths
uint16_t fcs=0;
if (fchigh==0 || fclow == 0){
if (!fchigh || !fclow) {
fcs = countFC(BitStream, BitLen, 1);
if (fcs==0){
fchigh=10;
fclow=8;
}else{
fchigh = (fcs >> 8) & 0xFF;
fclow = fcs & 0xFF;
if (!fcs) {
fchigh = 10;
fclow = 8;
} else {
fchigh = (fcs >> 8) & 0x00FF;
fclow = fcs & 0x00FF;
}
}
//get bit clock length
if (rfLen==0){
if (!rfLen) {
rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow);
if (rfLen == 0) rfLen = 50;
if (!rfLen) rfLen = 50;
}
int size = fskdemod(BitStream,BitLen,(uint8_t)rfLen,(uint8_t)invert,(uint8_t)fchigh,(uint8_t)fclow);
if (size>0){
int size = fskdemod(BitStream, BitLen, rfLen, invert, fchigh, fclow);
if (size > 0) {
setDemodBuf(BitStream,size,0);
// Now output the bitstream to the scrollback by line of 16 bits
if (verbose || g_debugMode) {
PrintAndLog("\nUsing Clock:%d, invert:%d, fchigh:%d, fclow:%d", rfLen, invert, fchigh, fclow);
PrintAndLog("\nUsing Clock:%u, invert:%u, fchigh:%u, fclow:%u", (unsigned int)rfLen, (unsigned int)invert, (unsigned int)fchigh, (unsigned int)fclow);
PrintAndLog("%s decoded bitstream:",GetFSKType(fchigh,fclow,invert));
printDemodBuff();
}
return 1;
} else{
} else {
if (g_debugMode) PrintAndLog("no FSK data found");
}
return 0;
@ -1130,8 +1171,6 @@ int CmdFSKdemodParadox(const char *Cmd)
//print ioprox ID and some format details
int CmdFSKdemodIO(const char *Cmd)
{
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
//set defaults
int idx=0;
//something in graphbuffer?
if (GraphTraceLen < 65) {
@ -1220,11 +1259,6 @@ int CmdFSKdemodIO(const char *Cmd)
//print full AWID Prox ID and some bit format details if found
int CmdFSKdemodAWID(const char *Cmd)
{
//int verbose=1;
//sscanf(Cmd, "%i", &verbose);
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
size_t size = getFromGraphBuf(BitStream);
if (size==0) return 0;
@ -1232,7 +1266,7 @@ int CmdFSKdemodAWID(const char *Cmd)
//get binary from fsk wave
int idx = AWIDdemodFSK(BitStream, &size);
if (idx<=0){
if (g_debugMode==1){
if (g_debugMode){
if (idx == -1)
PrintAndLog("DEBUG: Error - not enough samples");
else if (idx == -2)
@ -1270,7 +1304,7 @@ int CmdFSKdemodAWID(const char *Cmd)
size = removeParity(BitStream, idx+8, 4, 1, 88);
if (size != 66){
if (g_debugMode==1) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
if (g_debugMode) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
return 0;
}
// ok valid card found!
@ -1330,7 +1364,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
//get binary from fsk wave
int idx = PyramiddemodFSK(BitStream, &size);
if (idx < 0){
if (g_debugMode==1){
if (g_debugMode){
if (idx == -5)
PrintAndLog("DEBUG: Error - not enough samples");
else if (idx == -1)
@ -1386,7 +1420,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
size = removeParity(BitStream, idx+8, 8, 1, 120);
if (size != 105){
if (g_debugMode==1)
if (g_debugMode)
PrintAndLog("DEBUG: Error at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %x",size, idx, rawHi3);
return 0;
}
@ -1423,7 +1457,6 @@ int CmdFSKdemodPyramid(const char *Cmd)
uint32_t fc = 0;
uint32_t cardnum = 0;
uint32_t code1 = 0;
//uint32_t code2 = 0;
if (fmtLen==26){
fc = bytebits_to_byte(BitStream+73, 8);
cardnum = bytebits_to_byte(BitStream+81, 16);
@ -1463,6 +1496,17 @@ int CmdFSKdemodPyramid(const char *Cmd)
// NATIONAL CODE, ICAR database
// COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf
// FLAG (animal/non-animal)
/*
38 IDbits
10 country code
1 extra app bit
14 reserved bits
1 animal bit
16 ccitt CRC chksum over 64bit ID CODE.
24 appli bits.
-- sample: 985121004515220 [ 37FF65B88EF94 ]
*/
int CmdFDXBdemodBI(const char *Cmd){
int invert = 1;
@ -1489,6 +1533,10 @@ int CmdFDXBdemodBI(const char *Cmd){
if (g_debugMode) PrintAndLog("Error FDXBDemod , no startmarker found :: %d",preambleIndex);
return 0;
}
if (size != 128) {
if (g_debugMode) PrintAndLog("Error incorrect data length found");
return 0;
}
setDemodBuf(BitStream, 128, preambleIndex);
@ -1558,6 +1606,9 @@ int PSKDemod(const char *Cmd, bool verbose)
//invalid carrier
return 0;
}
if (g_debugMode){
PrintAndLog("Carrier: rf/%d",carrier);
}
int errCnt=0;
errCnt = pskRawDemod(BitStream, &BitLen, &clk, &invert);
if (errCnt > maxErr){
@ -1592,66 +1643,38 @@ int CmdIndalaDecode(const char *Cmd)
}
if (!ans){
if (g_debugMode==1)
if (g_debugMode)
PrintAndLog("Error1: %d",ans);
return 0;
}
uint8_t invert=0;
ans = indala26decode(DemodBuffer, &DemodBufferLen, &invert);
if (ans < 1) {
if (g_debugMode==1)
size_t size = DemodBufferLen;
int startIdx = indala26decode(DemodBuffer, &size, &invert);
if (startIdx < 0 || size > 224) {
if (g_debugMode)
PrintAndLog("Error2: %d",ans);
return -1;
}
char showbits[251]={0x00};
setDemodBuf(DemodBuffer, size, (size_t)startIdx);
if (invert)
if (g_debugMode==1)
if (g_debugMode)
PrintAndLog("Had to invert bits");
PrintAndLog("BitLen: %d",DemodBufferLen);
//convert UID to HEX
uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
int idx;
uid1=0;
uid2=0;
PrintAndLog("BitLen: %d",DemodBufferLen);
if (DemodBufferLen==64){
for( idx=0; idx<64; idx++) {
uid1=(uid1<<1)|(uid2>>31);
if (DemodBuffer[idx] == 0) {
uid2=(uid2<<1)|0;
showbits[idx]='0';
} else {
uid2=(uid2<<1)|1;
showbits[idx]='1';
}
}
showbits[idx]='\0';
PrintAndLog("Indala UID=%s (%x%08x)", showbits, uid1, uid2);
}
else {
uid3=0;
uid4=0;
uid5=0;
uid6=0;
uid7=0;
for( idx=0; idx<DemodBufferLen; idx++) {
uid1=(uid1<<1)|(uid2>>31);
uid2=(uid2<<1)|(uid3>>31);
uid3=(uid3<<1)|(uid4>>31);
uid4=(uid4<<1)|(uid5>>31);
uid5=(uid5<<1)|(uid6>>31);
uid6=(uid6<<1)|(uid7>>31);
if (DemodBuffer[idx] == 0) {
uid7=(uid7<<1)|0;
showbits[idx]='0';
}
else {
uid7=(uid7<<1)|1;
showbits[idx]='1';
}
}
showbits[idx]='\0';
PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
uid1=bytebits_to_byte(DemodBuffer,32);
uid2=bytebits_to_byte(DemodBuffer+32,32);
if (DemodBufferLen==64) {
PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2);
} else {
uid3=bytebits_to_byte(DemodBuffer+64,32);
uid4=bytebits_to_byte(DemodBuffer+96,32);
uid5=bytebits_to_byte(DemodBuffer+128,32);
uid6=bytebits_to_byte(DemodBuffer+160,32);
uid7=bytebits_to_byte(DemodBuffer+192,32);
PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)",
sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7);
}
if (g_debugMode){
PrintAndLog("DEBUG: printing demodbuffer:");
@ -1721,7 +1744,7 @@ int NRZrawDemod(const char *Cmd, bool verbose)
size_t BitLen = getFromGraphBuf(BitStream);
if (BitLen==0) return 0;
int errCnt=0;
errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert, maxErr);
errCnt = nrzRawDemod(BitStream, &BitLen, &clk, &invert);
if (errCnt > maxErr){
if (g_debugMode) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
return 0;
@ -1967,10 +1990,7 @@ int getSamples(const char *Cmd, bool silent)
int n = strtol(Cmd, NULL, 0);
if (n == 0)
n = sizeof(got);
if (n > sizeof(got))
if (n == 0 || n > sizeof(got))
n = sizeof(got);
PrintAndLog("Reading %d bytes from device memory\n", n);
@ -2018,10 +2038,20 @@ int CmdSamples(const char *Cmd)
int CmdTuneSamples(const char *Cmd)
{
int timeout = 0;
int timeout = 0, arg = FLAG_TUNE_ALL;
if(*Cmd == 'l') {
arg = FLAG_TUNE_LF;
} else if (*Cmd == 'h') {
arg = FLAG_TUNE_HF;
} else if (*Cmd != '\0') {
PrintAndLog("use 'tune' or 'tune l' or 'tune h'");
return 0;
}
printf("\nMeasuring antenna characteristics, please wait...");
UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING};
UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {arg, 0, 0}};
SendCommand(&c);
UsbCommand resp;
@ -2304,9 +2334,8 @@ int Cmdbin2hex(const char *Cmd)
return 0;
}
int usage_data_hex2bin(){
PrintAndLog("Usage: data bin2hex <binary_digits>");
int usage_data_hex2bin() {
PrintAndLog("Usage: data hex2bin <hex_digits>");
PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
return 0;
@ -2353,6 +2382,7 @@ static command_t CommandTable[] =
{"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ask demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"},
{"askem410xdemod", CmdAskEM410xDemod, 1, "[clock] [invert<0|1>] [maxErr] -- Demodulate an EM410x tag from GraphBuffer (args optional)"},
{"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"},
{"askvikingdemod", CmdVikingDemod, 1, "Demodulate a Viking tag from GraphBuffer"},
{"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"},
{"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
{"bin2hex", Cmdbin2hex, 1, "bin2hex <digits> -- Converts binary to hexadecimal"},
@ -2379,14 +2409,14 @@ static command_t CommandTable[] =
{"manrawdecode", Cmdmandecoderaw, 1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"},
{"norm", CmdNorm, 1, "Normalize max/min to +/-128"},
{"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"},
{"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] <offset> -- print the data in the DemodBuffer - 'x' for hex output"},
{"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] <offset> [l] <length> -- print the data in the DemodBuffer - 'x' for hex output"},
{"pskindalademod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"},
{"psknexwatchdemod",CmdPSKNexWatch, 1, "Demodulate a NexWatch tag (nexkey, quadrakey) (PSK1) from GraphBuffer"},
{"rawdemod", CmdRawDemod, 1, "[modulation] ... <options> -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"},
{"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"},
{"save", CmdSave, 1, "<filename> -- Save trace (from graph window)"},
{"scale", CmdScale, 1, "<int> -- Set cursor display scale"},
{"setdebugmode", CmdSetDebugMode, 1, "<0|1> -- Turn on or off Debugging Mode for demods"},
{"setdebugmode", CmdSetDebugMode, 1, "<0|1|2> -- Turn on or off Debugging Level for lf demods"},
{"shiftgraphzero", CmdGraphShiftZero, 1, "<shift> -- Shift 0 for Graphed wave + or - shift value"},
{"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
{"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"},

View file

@ -11,12 +11,19 @@
#ifndef CMDDATA_H__
#define CMDDATA_H__
#include <stdlib.h> //size_t
#include <stdint.h> //uint_32+
#include <stdbool.h> //bool
#include "cmdparser.h" // for command_t
command_t * CmdDataCommands();
int CmdData(const char *Cmd);
void printDemodBuff(void);
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
int CmdAskEM410xDemod(const char *Cmd);
int CmdVikingDemod(const char *Cmd);
int CmdG_Prox_II_Demod(const char *Cmd);
int Cmdaskrawdemod(const char *Cmd);
int Cmdaskmandemod(const char *Cmd);
@ -62,6 +69,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo );
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose);
int ASKbiphaseDemod(const char *Cmd, bool verbose);
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType);
int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck);
int FSKrawDemod(const char *Cmd, bool verbose);
int PSKDemod(const char *Cmd, bool verbose);
int NRZrawDemod(const char *Cmd, bool verbose);

View file

@ -23,6 +23,7 @@
#include "cmdhficlass.h"
#include "cmdhfmf.h"
#include "cmdhfmfu.h"
#include "cmdhftopaz.h"
#include "protocols.h"
static int CmdHelp(const char *Cmd);
@ -187,6 +188,26 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
}
}
void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
{
switch(cmd[0]) {
case TOPAZ_REQA :snprintf(exp, size, "REQA");break;
case TOPAZ_WUPA :snprintf(exp, size, "WUPA");break;
case TOPAZ_RID :snprintf(exp, size, "RID");break;
case TOPAZ_RALL :snprintf(exp, size, "RALL");break;
case TOPAZ_READ :snprintf(exp, size, "READ");break;
case TOPAZ_WRITE_E :snprintf(exp, size, "WRITE-E");break;
case TOPAZ_WRITE_NE :snprintf(exp, size, "WRITE-NE");break;
case TOPAZ_RSEG :snprintf(exp, size, "RSEG");break;
case TOPAZ_READ8 :snprintf(exp, size, "READ8");break;
case TOPAZ_WRITE_E8 :snprintf(exp, size, "WRITE-E8");break;
case TOPAZ_WRITE_NE8 :snprintf(exp, size, "WRITE-NE8");break;
default: snprintf(exp,size,"?"); break;
}
}
/**
06 00 = INITIATE
0E xx = SELECT ID (xx = Chip-ID)
@ -218,7 +239,34 @@ void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
}
/**
* @brief iso14443B_CRC_Ok Checks CRC in command or response
* @brief iso14443A_CRC_check Checks CRC in command or response
* @param isResponse
* @param data
* @param len
* @return 0 : CRC-command, CRC not ok
* 1 : CRC-command, CRC ok
* 2 : Not crc-command
*/
uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
{
uint8_t b1,b2;
if(len <= 2) return 2;
if(isResponse & (len < 6)) return 2;
ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2);
if (b1 != data[len-2] || b2 != data[len-1]) {
return 0;
} else {
return 1;
}
}
/**
* @brief iso14443B_CRC_check Checks CRC in command or response
* @param isResponse
* @param data
* @param len
@ -235,9 +283,10 @@ uint8_t iso14443B_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2);
if(b1 != data[len-2] || b2 != data[len-1]) {
return 0;
return 0;
} else {
return 1;
}
return 1;
}
/**
@ -301,11 +350,66 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
}
}
uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen)
{
return(tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen);
}
bool next_record_is_response(uint16_t tracepos, uint8_t *trace)
{
uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t)));
return(next_records_datalen & 0x8000);
}
bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len)
{
#define MAX_TOPAZ_READER_CMD_LEN 16
uint32_t last_timestamp = timestamp + *duration;
if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false;
memcpy(topaz_reader_command, frame, *data_len);
while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) {
uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos));
*tracepos += sizeof(uint32_t);
uint16_t next_duration = *((uint16_t *)(trace + *tracepos));
*tracepos += sizeof(uint16_t);
uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF;
*tracepos += sizeof(uint16_t);
uint8_t *next_frame = (trace + *tracepos);
*tracepos += next_data_len;
if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) {
memcpy(topaz_reader_command + *data_len, next_frame, next_data_len);
*data_len += next_data_len;
last_timestamp = next_timestamp + next_duration;
} else {
// rewind and exit
*tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t);
break;
}
uint16_t next_parity_len = (next_data_len-1)/8 + 1;
*tracepos += next_parity_len;
}
*duration = last_timestamp - timestamp;
return true;
}
uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes)
{
bool isResponse;
uint16_t duration, data_len, parity_len;
uint16_t data_len, parity_len;
uint32_t duration;
uint8_t topaz_reader_command[9];
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
char explanation[30] = {0};
@ -336,29 +440,31 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
uint8_t *parityBytes = trace + tracepos;
tracepos += parity_len;
if (protocol == TOPAZ && !isResponse) {
// topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
// merge them:
if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) {
frame = topaz_reader_command;
}
}
//Check the CRC status
uint8_t crcStatus = 2;
if (data_len > 2) {
uint8_t b1, b2;
if(protocol == ICLASS)
{
crcStatus = iclass_CRC_check(isResponse, frame, data_len);
}else if (protocol == ISO_14443B)
{
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
}
else if (protocol == ISO_14443A){//Iso 14443a
ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
if(!(isResponse & (data_len < 6)))
{
crcStatus = 0;
}
}
switch (protocol) {
case ICLASS:
crcStatus = iclass_CRC_check(isResponse, frame, data_len);
break;
case ISO_14443B:
case TOPAZ:
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
break;
case ISO_14443A:
crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
break;
default:
break;
}
}
//0 CRC-command, CRC not ok
@ -380,19 +486,22 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
uint8_t parityBits = parityBytes[j>>3];
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 {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]);
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
}
}
if(crcStatus == 1)
{//CRC-command
char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1;
(*pos1) = '[';
char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2;
(*pos2) = ']';
if (markCRCBytes) {
if(crcStatus == 0 || crcStatus == 1)
{//CRC-command
char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4);
(*pos1) = '[';
char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4);
sprintf(pos2, "%c", ']');
}
}
if(data_len == 0)
{
if(data_len == 0){
@ -407,18 +516,19 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
if(!isResponse)
{
if(protocol == ICLASS)
annotateIclass(explanation,sizeof(explanation),frame,data_len);
else if (protocol == ISO_14443A)
annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
else if(protocol == ISO_14443B)
annotateIso14443b(explanation,sizeof(explanation),frame,data_len);
switch(protocol) {
case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break;
case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break;
case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break;
case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break;
default: break;
}
}
int num_lines = MIN((data_len - 1)/16 + 1, 16);
for (int j = 0; j < num_lines ; j++) {
if (j == 0) {
PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s",
(timestamp - first_timestamp),
(EndOfTransmissionTimestamp - first_timestamp),
(isResponse ? "Tag" : "Rdr"),
@ -426,26 +536,22 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
(j == num_lines-1) ? crc : " ",
(j == num_lines-1) ? explanation : "");
} else {
PrintAndLog(" | | | %-64s| %s| %s",
PrintAndLog(" | | |%-64s | %s| %s",
line[j],
(j == num_lines-1)?crc:" ",
(j == num_lines-1) ? crc : " ",
(j == num_lines-1) ? explanation : "");
}
}
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
if (is_last_record(tracepos, trace, traceLen)) return traceLen;
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
if (showWaitCycles && !isResponse && next_isResponse) {
if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
if (next_timestamp != 0x44444444) {
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
(EndOfTransmissionTimestamp - first_timestamp),
(next_timestamp - first_timestamp),
" ",
(next_timestamp - EndOfTransmissionTimestamp));
}
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
(EndOfTransmissionTimestamp - first_timestamp),
(next_timestamp - first_timestamp),
" ",
(next_timestamp - EndOfTransmissionTimestamp));
}
return tracepos;
@ -455,49 +561,52 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
int CmdHFList(const char *Cmd)
{
bool showWaitCycles = false;
bool markCRCBytes = false;
char type[40] = {0};
int tlen = param_getstr(Cmd,0,type);
char param = param_getchar(Cmd, 1);
char param1 = param_getchar(Cmd, 1);
char param2 = param_getchar(Cmd, 2);
bool errors = false;
uint8_t protocol = 0;
//Validate params
if(tlen == 0)
{
if(tlen == 0) {
errors = true;
}
if(param == 'h' || (param !=0 && param != 'f'))
{
if(param1 == 'h'
|| (param1 != 0 && param1 != 'f' && param1 != 'c')
|| (param2 != 0 && param2 != 'f' && param2 != 'c')) {
errors = true;
}
if(!errors)
{
if(strcmp(type, "iclass") == 0)
{
if(!errors) {
if(strcmp(type, "iclass") == 0) {
protocol = ICLASS;
}else if(strcmp(type, "14a") == 0)
{
} else if(strcmp(type, "14a") == 0) {
protocol = ISO_14443A;
}
else if(strcmp(type, "14b") == 0)
{
} else if(strcmp(type, "14b") == 0) {
protocol = ISO_14443B;
}else if(strcmp(type,"raw")== 0)
{
} else if(strcmp(type,"topaz")== 0) {
protocol = TOPAZ;
} else if(strcmp(type,"raw")== 0) {
protocol = -1;//No crc, no annotations
}else{
} else {
errors = true;
}
}
if (errors) {
PrintAndLog("List protocol data in trace buffer.");
PrintAndLog("Usage: hf list <protocol> [f]");
PrintAndLog("Usage: hf list <protocol> [f][c]");
PrintAndLog(" f - show frame delay times as well");
PrintAndLog(" c - mark CRC bytes");
PrintAndLog("Supported <protocol> values:");
PrintAndLog(" raw - just show raw data without annotations");
PrintAndLog(" 14a - interpret data as iso14443a communications");
PrintAndLog(" 14b - interpret data as iso14443b communications");
PrintAndLog(" iclass - interpret data as iclass communications");
PrintAndLog(" topaz - interpret data as topaz communications");
PrintAndLog("");
PrintAndLog("example: hf list 14a f");
PrintAndLog("example: hf list iclass");
@ -505,10 +614,13 @@ int CmdHFList(const char *Cmd)
}
if (param == 'f') {
if (param1 == 'f' || param2 == 'f') {
showWaitCycles = true;
}
if (param1 == 'c' || param2 == 'c') {
markCRCBytes = true;
}
uint8_t *trace;
uint16_t tracepos = 0;
@ -537,12 +649,12 @@ int CmdHFList(const char *Cmd)
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
PrintAndLog("iClass - Timings are not as accurate");
PrintAndLog("");
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
while(tracepos < traceLen)
{
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
}
free(trace);
@ -557,16 +669,16 @@ int CmdHFSearch(const char *Cmd){
PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
return ans;
}
ans = HF14BInfo(false);
if (ans) {
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
return ans;
}
ans = HFiClassReader("", false, false);
if (ans) {
PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
return ans;
}
ans = HF14BInfo(false);
if (ans) {
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
return ans;
}
ans = HF15Reader("", false);
if (ans) {
PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n");
@ -576,21 +688,31 @@ int CmdHFSearch(const char *Cmd){
return 0;
}
int CmdHFSnoop(const char *Cmd)
{
char * pEnd;
UsbCommand c = {CMD_HF_SNIFFER, {strtol(Cmd, &pEnd,0),strtol(pEnd, &pEnd,0),0}};
SendCommand(&c);
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
{"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"},
{NULL, NULL, 0, NULL}
{"help", CmdHelp, 1, "This help"},
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
{"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"},
{"snoop", CmdHFSnoop, 0, "<samples to skip (10000)> <triggers to skip (1)> Generic HF Snoop"},
{NULL, NULL, 0, NULL}
};
int CmdHF(const char *Cmd)

View file

@ -141,7 +141,7 @@ int CmdHF14AReader(const char *Cmd)
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if(select_status == 0) {
if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
@ -352,16 +352,16 @@ int CmdHF14AReader(const char *Cmd)
PrintAndLog(" x0 -> <1 kByte");
break;
case 0x01:
PrintAndLog(" x0 -> 1 kByte");
PrintAndLog(" x1 -> 1 kByte");
break;
case 0x02:
PrintAndLog(" x0 -> 2 kByte");
PrintAndLog(" x2 -> 2 kByte");
break;
case 0x03:
PrintAndLog(" x0 -> 4 kByte");
PrintAndLog(" x3 -> 4 kByte");
break;
case 0x04:
PrintAndLog(" x0 -> 8 kByte");
PrintAndLog(" x4 -> 8 kByte");
break;
}
switch (card.ats[pos + 3] & 0xf0) {
@ -565,20 +565,22 @@ int CmdHF14ASnoop(const char *Cmd) {
return 0;
}
int CmdHF14ACmdRaw(const char *cmd) {
UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
uint8_t reply=1;
uint8_t crc=0;
uint8_t power=0;
uint8_t active=0;
uint8_t active_select=0;
uint16_t numbits=0;
uint32_t timeout=0;
uint8_t bTimeout=0;
bool reply=1;
bool crc = FALSE;
bool power = FALSE;
bool active = FALSE;
bool active_select = FALSE;
uint16_t numbits = 0;
bool bTimeout = FALSE;
uint32_t timeout = 0;
bool topazmode = FALSE;
char buf[5]="";
int i=0;
int i = 0;
uint8_t data[USB_CMD_DATA_SIZE];
uint16_t datalen=0;
uint16_t datalen = 0;
uint32_t temp;
if (strlen(cmd)<2) {
@ -590,9 +592,11 @@ int CmdHF14ACmdRaw(const char *cmd) {
PrintAndLog(" -s active signal field ON with select");
PrintAndLog(" -b number of bits to send. Useful for send partial byte");
PrintAndLog(" -t timeout in ms");
PrintAndLog(" -T use Topaz protocol to send command");
return 0;
}
// strip
while (*cmd==' ' || *cmd=='\t') cmd++;
@ -601,19 +605,19 @@ int CmdHF14ACmdRaw(const char *cmd) {
if (cmd[i]=='-') {
switch (cmd[i+1]) {
case 'r':
reply=0;
reply = FALSE;
break;
case 'c':
crc=1;
crc = TRUE;
break;
case 'p':
power=1;
power = TRUE;
break;
case 'a':
active=1;
active = TRUE;
break;
case 's':
active_select=1;
active_select = TRUE;
break;
case 'b':
sscanf(cmd+i+2,"%d",&temp);
@ -623,13 +627,16 @@ int CmdHF14ACmdRaw(const char *cmd) {
i-=2;
break;
case 't':
bTimeout=1;
bTimeout = TRUE;
sscanf(cmd+i+2,"%d",&temp);
timeout = temp;
i+=3;
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i-=2;
break;
case 'T':
topazmode = TRUE;
break;
default:
PrintAndLog("Invalid option");
return 0;
@ -659,10 +666,15 @@ int CmdHF14ACmdRaw(const char *cmd) {
PrintAndLog("Invalid char on input");
return 0;
}
if(crc && datalen>0 && datalen<sizeof(data)-2)
{
uint8_t first, second;
ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
if (topazmode) {
ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
} else {
ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
}
data[datalen++] = first;
data[datalen++] = second;
}
@ -675,7 +687,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
}
if(bTimeout){
#define MAX_TIMEOUT 40542464 // (2^32-1) * (8*16) / 13560000Hz * 1000ms/s =
#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
c.arg[0] |= ISO14A_SET_TIMEOUT;
if(timeout > MAX_TIMEOUT) {
timeout = MAX_TIMEOUT;
@ -683,11 +695,16 @@ int CmdHF14ACmdRaw(const char *cmd) {
}
c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
}
if(power)
c.arg[0] |= ISO14A_NO_DISCONNECT;
if(datalen>0)
if(datalen > 0)
c.arg[0] |= ISO14A_RAW;
if(topazmode)
c.arg[0] |= ISO14A_TOPAZMODE;
// Max buffer is USB_CMD_DATA_SIZE
c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
memcpy(c.d.asBytes,data,datalen);
@ -703,6 +720,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
return 0;
}
static void waitCmd(uint8_t iSelect)
{
uint8_t *recv;
@ -712,7 +730,7 @@ static void waitCmd(uint8_t iSelect)
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
recv = resp.d.asBytes;
uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0];
PrintAndLog("received %i octets",iLen);
PrintAndLog("received %i octets", iLen);
if(!iLen)
return;
hexout = (char *)malloc(iLen * 3 + 1);

View file

@ -58,6 +58,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
}
// print nonce
PrintAndLog("Length: %d, Nonce: %s", nonce_length, nonce);
free(nonce);
}
if (i < n - 1) {
sleep(d);

File diff suppressed because it is too large Load diff

View file

@ -14,11 +14,26 @@
int CmdHFiClass(const char *Cmd);
int CmdHFiClassSnoop(const char *Cmd);
int CmdHFiClassSim(const char *Cmd);
int CmdHFiClassCalcNewKey(const char *Cmd);
int CmdHFiClassCloneTag(const char *Cmd);
int CmdHFiClassDecrypt(const char *Cmd);
int CmdHFiClassEncryptBlk(const char *Cmd);
int CmdHFiClassELoad(const char *Cmd);
int CmdHFiClassList(const char *Cmd);
int HFiClassReader(const char *Cmd, bool loop, bool verbose);
int CmdHFiClassReader(const char *Cmd);
int CmdHFiClassReader_Dump(const char *Cmd);
int CmdHFiClassReader_Replay(const char *Cmd);
int CmdHFiClassReadKeyFile(const char *filename);
int CmdHFiClassReadTagFile(const char *Cmd);
int CmdHFiClass_ReadBlock(const char *Cmd);
int CmdHFiClass_TestMac(const char *Cmd);
int CmdHFiClassManageKeys(const char *Cmd);
int CmdHFiClass_loclass(const char *Cmd);
int CmdHFiClassSnoop(const char *Cmd);
int CmdHFiClassSim(const char *Cmd);
int CmdHFiClassWriteKeyFile(const char *Cmd);
int CmdHFiClass_WriteBlock(const char *Cmd);
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize);
void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite);
#endif

View file

@ -58,7 +58,7 @@ int CmdLegicDecode(const char *Cmd)
int crc = 0;
int wrp = 0;
int wrc = 0;
uint8_t data_buf[1024]; // receiver buffer
uint8_t data_buf[1052]; // receiver buffer
char out_string[3076]; // just use big buffer - bad practice
char token_type[4];

View file

@ -9,6 +9,7 @@
//-----------------------------------------------------------------------------
#include "cmdhfmf.h"
#include "./nonce2key/nonce2key.h"
static int CmdHelp(const char *Cmd);
@ -28,7 +29,7 @@ int CmdHF14AMifare(const char *Cmd)
printf("-------------------------------------------------------------------------\n");
start:
start:
clearCommandBuffer();
SendCommand(&c);
@ -58,6 +59,8 @@ start:
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;
case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;
case -4 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown");
PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break;
default: ;
}
break;
@ -1013,72 +1016,273 @@ int CmdHF14AMfChk(const char *Cmd)
return 0;
}
int CmdHF14AMf1kSim(const char *Cmd)
{
uint8_t uid[7] = {0, 0, 0, 0, 0, 0, 0};
void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {
#define ATTACK_KEY_COUNT 8 // keep same as define in iso14443a.c -> Mifare1ksim()
uint64_t key = 0;
typedef struct {
uint64_t keyA;
uint64_t keyB;
} st_t;
st_t sector_trailer[ATTACK_KEY_COUNT];
memset(sector_trailer, 0x00, sizeof(sector_trailer));
uint8_t stSector[ATTACK_KEY_COUNT];
memset(stSector, 0x00, sizeof(stSector));
uint8_t key_cnt[ATTACK_KEY_COUNT];
memset(key_cnt, 0x00, sizeof(key_cnt));
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {
if (ar_resp[i].ar2 > 0) {
//PrintAndLog("DEBUG: Trying sector %d, cuid %08x, nt %08x, ar %08x, nr %08x, ar2 %08x, nr2 %08x",ar_resp[i].sector, ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2);
if (mfkey32(ar_resp[i], &key)) {
PrintAndLog(" Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));
for (uint8_t ii = 0; ii<ATTACK_KEY_COUNT; ii++) {
if (key_cnt[ii]==0 || stSector[ii]==ar_resp[i].sector) {
if (ar_resp[i].keytype==0) {
//keyA
sector_trailer[ii].keyA = key;
stSector[ii] = ar_resp[i].sector;
key_cnt[ii]++;
break;
} else {
//keyB
sector_trailer[ii].keyB = key;
stSector[ii] = ar_resp[i].sector;
key_cnt[ii]++;
break;
}
}
}
}
}
}
//set emulator memory for keys
if (setEmulatorMem) {
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {
if (key_cnt[i]>0) {
uint8_t memBlock[16];
memset(memBlock, 0x00, sizeof(memBlock));
char cmd1[36];
memset(cmd1,0x00,sizeof(cmd1));
snprintf(cmd1,sizeof(cmd1),"%04x%08xFF078069%04x%08x",(uint32_t) (sector_trailer[i].keyA>>32), (uint32_t) (sector_trailer[i].keyA &0xFFFFFFFF),(uint32_t) (sector_trailer[i].keyB>>32), (uint32_t) (sector_trailer[i].keyB &0xFFFFFFFF));
PrintAndLog("Setting Emulator Memory Block %02d: [%s]",stSector[i]*4+3, cmd1);
if (param_gethex(cmd1, 0, memBlock, 32)) {
PrintAndLog("block data must include 32 HEX symbols");
return;
}
UsbCommand c = {CMD_MIFARE_EML_MEMSET, {(stSector[i]*4+3), 1, 0}};
memcpy(c.d.asBytes, memBlock, 16);
clearCommandBuffer();
SendCommand(&c);
}
}
}
/*
//un-comment to use as well moebius attack
for (uint8_t i = ATTACK_KEY_COUNT; i<ATTACK_KEY_COUNT*2; i++) {
if (ar_resp[i].ar2 > 0) {
if (tryMfk32_moebius(ar_resp[i], &key)) {
PrintAndLog("M-Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));
}
}
}*/
}
int usage_hf14_mf1ksim(void) {
PrintAndLog("Usage: hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x");
PrintAndLog("options:");
PrintAndLog(" h this help");
PrintAndLog(" u (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used");
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
PrintAndLog(" e (Optional) set keys found from 'reader attack' to emulator memory (implies x and i)");
PrintAndLog(" f (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)");
PrintAndLog("samples:");
PrintAndLog(" hf mf sim u 0a0a0a0a");
PrintAndLog(" hf mf sim u 11223344556677");
PrintAndLog(" hf mf sim u 112233445566778899AA");
PrintAndLog(" hf mf sim f uids.txt");
PrintAndLog(" hf mf sim u 0a0a0a0a e");
return 0;
}
int CmdHF14AMf1kSim(const char *Cmd) {
UsbCommand resp;
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t exitAfterNReads = 0;
uint8_t flags = 0;
uint8_t cmdp = param_getchar(Cmd, 0);
if (cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: hf mf sim u <uid (8 hex symbols)> n <numreads> i x");
PrintAndLog(" h this help");
PrintAndLog(" u (Optional) UID. If not specified, the UID from emulator memory will be used");
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
PrintAndLog("");
PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");
return 0;
}
int uidlen = 0;
uint8_t pnr = 0;
if (param_getchar(Cmd, pnr) == 'u') {
if(param_gethex(Cmd, pnr+1, uid, 8) == 0)
{
flags |= FLAG_4B_UID_IN_DATA; // UID from packet
} else if(param_gethex(Cmd,pnr+1,uid,14) == 0) {
flags |= FLAG_7B_UID_IN_DATA;// UID from packet
} else {
PrintAndLog("UID, if specified, must include 8 or 14 HEX symbols");
bool setEmulatorMem = false;
bool attackFromFile = false;
FILE *f;
char filename[FILE_PATH_SIZE];
memset(filename, 0x00, sizeof(filename));
int len = 0;
char buf[64];
uint8_t cmdp = 0;
bool errors = false;
while(param_getchar(Cmd, cmdp) != 0x00) {
switch(param_getchar(Cmd, cmdp)) {
case 'e':
case 'E':
setEmulatorMem = true;
//implies x and i
flags |= FLAG_INTERACTIVE;
flags |= FLAG_NR_AR_ATTACK;
cmdp++;
break;
case 'f':
case 'F':
len = param_getstr(Cmd, cmdp+1, filename);
if (len < 1) {
PrintAndLog("error no filename found");
return 0;
}
attackFromFile = true;
//implies x and i
flags |= FLAG_INTERACTIVE;
flags |= FLAG_NR_AR_ATTACK;
cmdp += 2;
break;
case 'h':
case 'H':
return usage_hf14_mf1ksim();
case 'i':
case 'I':
flags |= FLAG_INTERACTIVE;
cmdp++;
break;
case 'n':
case 'N':
exitAfterNReads = param_get8(Cmd, pnr+1);
cmdp += 2;
break;
case 'u':
case 'U':
param_gethex_ex(Cmd, cmdp+1, uid, &uidlen);
switch(uidlen) {
case 20: flags = FLAG_10B_UID_IN_DATA; break; //not complete
case 14: flags = FLAG_7B_UID_IN_DATA; break;
case 8: flags = FLAG_4B_UID_IN_DATA; break;
default: return usage_hf14_mf1ksim();
}
cmdp += 2;
break;
case 'x':
case 'X':
flags |= FLAG_NR_AR_ATTACK;
cmdp++;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
if(errors) break;
}
//Validations
if(errors) return usage_hf14_mf1ksim();
//get uid from file
if (attackFromFile) {
int count = 0;
// open file
f = fopen(filename, "r");
if (f == NULL) {
PrintAndLog("File %s not found or locked", filename);
return 1;
}
pnr +=2;
}
if (param_getchar(Cmd, pnr) == 'n') {
exitAfterNReads = param_get8(Cmd,pnr+1);
pnr += 2;
}
if (param_getchar(Cmd, pnr) == 'i' ) {
//Using a flag to signal interactiveness, least significant bit
flags |= FLAG_INTERACTIVE;
pnr++;
}
PrintAndLog("Loading file and simulating. Press keyboard to abort");
while(!feof(f) && !ukbhit()){
memset(buf, 0, sizeof(buf));
memset(uid, 0, sizeof(uid));
if (param_getchar(Cmd, pnr) == 'x' ) {
//Using a flag to signal interactiveness, least significant bit
flags |= FLAG_NR_AR_ATTACK;
}
PrintAndLog(" uid:%s, numreads:%d, flags:%d (0x%02x) ",
if (fgets(buf, sizeof(buf), f) == NULL) {
if (count > 0) break;
PrintAndLog("File reading error.");
fclose(f);
return 2;
}
if(!strlen(buf) && feof(f)) break;
uidlen = strlen(buf)-1;
switch(uidlen) {
case 20: flags |= FLAG_10B_UID_IN_DATA; break; //not complete
case 14: flags |= FLAG_7B_UID_IN_DATA; break;
case 8: flags |= FLAG_4B_UID_IN_DATA; break;
default:
PrintAndLog("uid in file wrong length at %d (length: %d) [%s]",count, uidlen, buf);
fclose(f);
return 2;
}
for (uint8_t i = 0; i < uidlen; i += 2) {
sscanf(&buf[i], "%02x", (unsigned int *)&uid[i / 2]);
}
PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) - press button to abort",
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7):
flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"
, exitAfterNReads, flags, flags);
UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};
memcpy(c.d.asBytes, uid, sizeof(uid));
clearCommandBuffer();
SendCommand(&c);
while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
}
//got a response
nonces_t ar_resp[ATTACK_KEY_COUNT*2];
memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));
readerAttack(ar_resp, setEmulatorMem);
if ((bool)resp.arg[1]) {
PrintAndLog("Device button pressed - quitting");
fclose(f);
return 4;
}
count++;
}
fclose(f);
} else { //not from file
PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) ",
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): "N/A"
, exitAfterNReads, flags,flags);
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7):
flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"
, exitAfterNReads, flags, flags);
UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};
memcpy(c.d.asBytes, uid, sizeof(uid));
clearCommandBuffer();
SendCommand(&c);
UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};
memcpy(c.d.asBytes, uid, sizeof(uid));
SendCommand(&c);
if(flags & FLAG_INTERACTIVE)
{
UsbCommand resp;
PrintAndLog("Press pm3-button to abort simulation");
while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
if(flags & FLAG_INTERACTIVE) {
PrintAndLog("Press pm3-button to abort simulation");
while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
}
//got a response
if (flags & FLAG_NR_AR_ATTACK) {
nonces_t ar_resp[ATTACK_KEY_COUNT*2];
memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));
readerAttack(ar_resp, setEmulatorMem);
}
}
}
return 0;
}
@ -1949,6 +2153,13 @@ int CmdHF14AMfSniff(const char *Cmd){
return 0;
}
//needs nt, ar, at, Data to decrypt
int CmdDecryptTraceCmds(const char *Cmd){
uint8_t data[50];
int len = 0;
param_gethex_ex(Cmd,3,data,&len);
return tryDecryptWord(param_get32ex(Cmd,0,0,16),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),data,len/2);
}
static command_t CommandTable[] =
{
@ -1977,6 +2188,7 @@ static command_t CommandTable[] =
{"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},
{"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},
{"decrypt", CmdDecryptTraceCmds,1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
{NULL, NULL, 0, NULL}
};

571
client/cmdhftopaz.c Normal file
View file

@ -0,0 +1,571 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2015 Piwi
//
// 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.
//-----------------------------------------------------------------------------
// High frequency Topaz (NFC Type 1) commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "cmdmain.h"
#include "cmdparser.h"
#include "cmdhftopaz.h"
#include "cmdhf14a.h"
#include "ui.h"
#include "mifare.h"
#include "proxmark3.h"
#include "iso14443crc.h"
#include "protocols.h"
#define TOPAZ_STATIC_MEMORY (0x0f * 8) // 15 blocks with 8 Bytes each
// a struct to describe a memory area which contains lock bits and the corresponding lockable memory area
typedef struct dynamic_lock_area {
struct dynamic_lock_area *next;
uint16_t byte_offset; // the address of the lock bits
uint16_t size_in_bits;
uint16_t first_locked_byte; // the address of the lockable area
uint16_t bytes_locked_per_bit;
} dynamic_lock_area_t;
static struct {
uint8_t HR01[2];
uint8_t uid[7];
uint16_t size;
uint8_t data_blocks[TOPAZ_STATIC_MEMORY/8][8]; // this memory is always there
uint8_t *dynamic_memory; // this memory can be there
dynamic_lock_area_t *dynamic_lock_areas; // lock area descriptors
} topaz_tag;
static void topaz_switch_on_field(void)
{
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, 0, 0}};
SendCommand(&c);
}
static void topaz_switch_off_field(void)
{
UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
SendCommand(&c);
}
// send a raw topaz command, returns the length of the response (0 in case of error)
static int topaz_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response)
{
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, len, 0}};
memcpy(c.d.asBytes, cmd, len);
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK, &resp);
if (resp.arg[0] > 0) {
memcpy(response, resp.d.asBytes, resp.arg[0]);
}
return resp.arg[0];
}
// calculate CRC bytes and send topaz command, returns the length of the response (0 in case of error)
static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response)
{
if (len > 1) {
uint8_t first, second;
ComputeCrc14443(CRC_14443_B, cmd, len-2, &first, &second);
cmd[len-2] = first;
cmd[len-1] = second;
}
return topaz_send_cmd_raw(cmd, len, response);
}
// select a topaz tag. Send WUPA and RID.
static int topaz_select(uint8_t *atqa, uint8_t *rid_response)
{
// ToDo: implement anticollision
uint8_t wupa_cmd[] = {TOPAZ_WUPA};
uint8_t rid_cmd[] = {TOPAZ_RID, 0, 0, 0, 0, 0, 0, 0, 0};
topaz_switch_on_field();
if (!topaz_send_cmd(wupa_cmd, sizeof(wupa_cmd), atqa)) {
topaz_switch_off_field();
return -1; // WUPA failed
}
if (!topaz_send_cmd(rid_cmd, sizeof(rid_cmd), rid_response)) {
topaz_switch_off_field();
return -2; // RID failed
}
return 0; // OK
}
// read all of the static memory of a selected Topaz tag.
static int topaz_rall(uint8_t *uid, uint8_t *response)
{
uint8_t rall_cmd[] = {TOPAZ_RALL, 0, 0, 0, 0, 0, 0, 0, 0};
memcpy(&rall_cmd[3], uid, 4);
if (!topaz_send_cmd(rall_cmd, sizeof(rall_cmd), response)) {
topaz_switch_off_field();
return -1; // RALL failed
}
return 0;
}
// read a block (8 Bytes) of a selected Topaz tag.
static int topaz_read_block(uint8_t *uid, uint8_t blockno, uint8_t *block_data)
{
uint8_t read8_cmd[] = {TOPAZ_READ8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t read8_response[11];
read8_cmd[1] = blockno;
memcpy(&read8_cmd[10], uid, 4);
if (!topaz_send_cmd(read8_cmd, sizeof(read8_cmd), read8_response)) {
topaz_switch_off_field();
return -1; // READ8 failed
}
memcpy(block_data, &read8_response[1], 8);
return 0;
}
// read a segment (16 blocks = 128 Bytes) of a selected Topaz tag. Works only for tags with dynamic memory.
static int topaz_read_segment(uint8_t *uid, uint8_t segno, uint8_t *segment_data)
{
uint8_t rseg_cmd[] = {TOPAZ_RSEG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t rseg_response[131];
rseg_cmd[1] = segno << 4;
memcpy(&rseg_cmd[10], uid, 4);
if (!topaz_send_cmd(rseg_cmd, sizeof(rseg_cmd), rseg_response)) {
topaz_switch_off_field();
return -1; // RSEG failed
}
memcpy(segment_data, &rseg_response[1], 128);
return 0;
}
// search for the lock area descriptor for the lockable area including byteno
static dynamic_lock_area_t *get_dynamic_lock_area(uint16_t byteno)
{
dynamic_lock_area_t *lock_area;
lock_area = topaz_tag.dynamic_lock_areas;
while (lock_area != NULL) {
if (byteno < lock_area->first_locked_byte) {
lock_area = lock_area->next;
} else {
return lock_area;
}
}
return NULL;
}
// check if a memory byte is locked.
static bool topaz_byte_is_locked(uint16_t byteno)
{
uint8_t *lockbits;
uint16_t locked_bytes_per_bit;
dynamic_lock_area_t *lock_area;
if (byteno < TOPAZ_STATIC_MEMORY) {
lockbits = &topaz_tag.data_blocks[0x0e][0];
locked_bytes_per_bit = 8;
} else {
lock_area = get_dynamic_lock_area(byteno);
if (lock_area == NULL) {
return false;
} else {
lockbits = &topaz_tag.dynamic_memory[lock_area->byte_offset - TOPAZ_STATIC_MEMORY];
locked_bytes_per_bit = lock_area->bytes_locked_per_bit;
byteno = byteno - lock_area->first_locked_byte;
}
}
uint16_t blockno = byteno / locked_bytes_per_bit;
if(lockbits[blockno/8] & (0x01 << (blockno % 8))) {
return true;
} else {
return false;
}
}
// read and print the Capability Container
static int topaz_print_CC(uint8_t *data)
{
if(data[0] != 0xe1) {
topaz_tag.size = TOPAZ_STATIC_MEMORY;
return -1; // no NDEF message
}
PrintAndLog("Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
PrintAndLog(" %02x: NDEF Magic Number", data[0]);
PrintAndLog(" %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f);
uint16_t memsize = (data[2] + 1) * 8;
topaz_tag.size = memsize;
topaz_tag.dynamic_memory = malloc(memsize - TOPAZ_STATIC_MEMORY);
PrintAndLog(" %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize);
PrintAndLog(" %02x: %s / %s", data[3],
(data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security",
(data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)");
return 0;
}
// return type, length and value of a TLV, starting at memory position *TLV_ptr
static void get_TLV(uint8_t **TLV_ptr, uint8_t *TLV_type, uint16_t *TLV_length, uint8_t **TLV_value)
{
*TLV_length = 0;
*TLV_value = NULL;
*TLV_type = **TLV_ptr;
*TLV_ptr += 1;
switch (*TLV_type) {
case 0x00: // NULL TLV.
case 0xFE: // Terminator TLV.
break;
case 0x01: // Lock Control TLV
case 0x02: // Reserved Memory TLV
case 0x03: // NDEF message TLV
case 0xFD: // proprietary TLV
*TLV_length = **TLV_ptr;
*TLV_ptr += 1;
if (*TLV_length == 0xff) {
*TLV_length = **TLV_ptr << 8;
*TLV_ptr += 1;
*TLV_length |= **TLV_ptr;
*TLV_ptr += 1;
}
*TLV_value = *TLV_ptr;
*TLV_ptr += *TLV_length;
break;
default: // RFU
break;
}
}
// lock area TLVs contain no information on the start of the respective lockable area. Lockable areas
// do not include the lock bits and reserved memory. We therefore need to adjust the start of the
// respective lockable areas accordingly
static void adjust_lock_areas(uint16_t block_start, uint16_t block_size)
{
dynamic_lock_area_t *lock_area = topaz_tag.dynamic_lock_areas;
while (lock_area != NULL) {
if (lock_area->first_locked_byte <= block_start) {
lock_area->first_locked_byte += block_size;
}
lock_area = lock_area->next;
}
}
// read and print the lock area and reserved memory TLVs
static void topaz_print_control_TLVs(uint8_t *memory)
{
uint8_t *TLV_ptr = memory;
uint8_t TLV_type = 0;
uint16_t TLV_length;
uint8_t *TLV_value;
bool lock_TLV_present = false;
bool reserved_memory_control_TLV_present = false;
uint16_t next_lockable_byte = 0x0f * 8; // first byte after static memory area
while(*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) {
// all Lock Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV)
get_TLV(&TLV_ptr, &TLV_type, &TLV_length, &TLV_value);
if (TLV_type == 0x01) { // a Lock Control TLV
uint8_t pages_addr = TLV_value[0] >> 4;
uint8_t byte_offset = TLV_value[0] & 0x0f;
uint16_t size_in_bits = TLV_value[1] ? TLV_value[1] : 256;
uint16_t size_in_bytes = (size_in_bits + 7)/8;
uint16_t bytes_per_page = 1 << (TLV_value[2] & 0x0f);
uint16_t bytes_locked_per_bit = 1 << (TLV_value[2] >> 4);
uint16_t area_start = pages_addr * bytes_per_page + byte_offset;
PrintAndLog("Lock Area of %d bits at byte offset 0x%04x. Each Lock Bit locks %d bytes.",
size_in_bits,
area_start,
bytes_locked_per_bit);
lock_TLV_present = true;
dynamic_lock_area_t *old = topaz_tag.dynamic_lock_areas;
dynamic_lock_area_t *new = topaz_tag.dynamic_lock_areas;
if (old == NULL) {
new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t));
} else {
while(old->next != NULL) {
old = old->next;
}
new = old->next = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t));
}
new->next = NULL;
if (area_start <= next_lockable_byte) {
// lock areas are not lockable
next_lockable_byte += size_in_bytes;
}
new->first_locked_byte = next_lockable_byte;
new->byte_offset = area_start;
new->size_in_bits = size_in_bits;
new->bytes_locked_per_bit = bytes_locked_per_bit;
next_lockable_byte += size_in_bits * bytes_locked_per_bit;
}
if (TLV_type == 0x02) { // a Reserved Memory Control TLV
uint8_t pages_addr = TLV_value[0] >> 4;
uint8_t byte_offset = TLV_value[0] & 0x0f;
uint8_t size_in_bytes = TLV_value[1] ? TLV_value[1] : 256;
uint8_t bytes_per_page = 1 << (TLV_value[2] & 0x0f);
uint16_t area_start = pages_addr * bytes_per_page + byte_offset;
PrintAndLog("Reserved Memory of %d bytes at byte offset 0x%02x.",
size_in_bytes,
area_start);
reserved_memory_control_TLV_present = true;
adjust_lock_areas(area_start, size_in_bytes); // reserved memory areas are not lockable
if (area_start <= next_lockable_byte) {
next_lockable_byte += size_in_bytes;
}
}
}
if (!lock_TLV_present) {
PrintAndLog("(No Lock Control TLV present)");
}
if (!reserved_memory_control_TLV_present) {
PrintAndLog("(No Reserved Memory Control TLV present)");
}
}
// read all of the dynamic memory
static int topaz_read_dynamic_data(void)
{
// first read the remaining block of segment 0
if(topaz_read_block(topaz_tag.uid, 0x0f, &topaz_tag.dynamic_memory[0]) == -1) {
PrintAndLog("Error while reading dynamic memory block %02x. Aborting...", 0x0f);
return -1;
}
// read the remaining segments
uint8_t max_segment = topaz_tag.size / 128 - 1;
for(uint8_t segment = 1; segment <= max_segment; segment++) {
if(topaz_read_segment(topaz_tag.uid, segment, &topaz_tag.dynamic_memory[(segment-1)*128+8]) == -1) {
PrintAndLog("Error while reading dynamic memory block %02x. Aborting...", 0x0f);
return -1;
}
}
return 0;
}
// read and print the dynamic memory
static void topaz_print_dynamic_data(void)
{
if (topaz_tag.size > TOPAZ_STATIC_MEMORY) {
PrintAndLog("Dynamic Data blocks:");
if (topaz_read_dynamic_data() == 0) {
PrintAndLog("block# | offset | Data | Locked(y/n)");
char line[80];
for (uint16_t blockno = 0x0f; blockno < topaz_tag.size/8; blockno++) {
uint8_t *block_data = &topaz_tag.dynamic_memory[(blockno-0x0f)*8];
char lockbits[9];
for (uint16_t j = 0; j < 8; j++) {
sprintf(&line[3*j], "%02x ", block_data[j]);
lockbits[j] = topaz_byte_is_locked(blockno*8+j) ? 'y' : 'n';
}
lockbits[8] = '\0';
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", blockno, blockno*8, line, lockbits);
}
}
}
}
static void topaz_print_lifecycle_state(uint8_t *data)
{
// to be done
}
static void topaz_print_NDEF(uint8_t *data)
{
// to be done.
}
// read a Topaz tag and print some usefull information
int CmdHFTopazReader(const char *Cmd)
{
int status;
uint8_t atqa[2];
uint8_t rid_response[8];
uint8_t *uid_echo = &rid_response[2];
uint8_t rall_response[124];
status = topaz_select(atqa, rid_response);
if (status == -1) {
PrintAndLog("Error: couldn't receive ATQA");
return -1;
}
PrintAndLog("ATQA : %02x %02x", atqa[1], atqa[0]);
if (atqa[1] != 0x0c && atqa[0] != 0x00) {
PrintAndLog("Tag doesn't support the Topaz protocol.");
topaz_switch_off_field();
return -1;
}
if (status == -2) {
PrintAndLog("Error: tag didn't answer to RID");
topaz_switch_off_field();
return -1;
}
topaz_tag.HR01[0] = rid_response[0];
topaz_tag.HR01[1] = rid_response[1];
// ToDo: CRC check
PrintAndLog("HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0],
(rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
(rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
(rid_response[0] & 0x0F) == 0x10 ? "static" : "dynamic");
PrintAndLog("HR1 : %02x", rid_response[1]);
status = topaz_rall(uid_echo, rall_response);
if(status == -1) {
PrintAndLog("Error: tag didn't answer to RALL");
topaz_switch_off_field();
return -1;
}
memcpy(topaz_tag.uid, rall_response+2, 7);
PrintAndLog("UID : %02x %02x %02x %02x %02x %02x %02x",
topaz_tag.uid[6],
topaz_tag.uid[5],
topaz_tag.uid[4],
topaz_tag.uid[3],
topaz_tag.uid[2],
topaz_tag.uid[1],
topaz_tag.uid[0]);
PrintAndLog(" UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s",
topaz_tag.uid[6],
getTagInfo(topaz_tag.uid[6]));
memcpy(topaz_tag.data_blocks, rall_response+2, 0x0f*8);
PrintAndLog("");
PrintAndLog("Static Data blocks 00 to 0c:");
PrintAndLog("block# | offset | Data | Locked(y/n)");
char line[80];
for (uint16_t i = 0; i <= 0x0c; i++) {
char lockbits[9];
for (uint16_t j = 0; j < 8; j++) {
sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[i][j] /*rall_response[2 + 8*i + j]*/);
lockbits[j] = topaz_byte_is_locked(i*8+j) ? 'y' : 'n';
}
lockbits[8] = '\0';
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", i, i*8, line, lockbits);
}
PrintAndLog("");
PrintAndLog("Static Reserved block 0d:");
for (uint16_t j = 0; j < 8; j++) {
sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0d][j]);
}
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", 0x0d, 0x0d*8, line, "n/a");
PrintAndLog("");
PrintAndLog("Static Lockbits and OTP Bytes:");
for (uint16_t j = 0; j < 8; j++) {
sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0e][j]);
}
PrintAndLog(" 0x%02x | 0x%04x | %s| %-3s", 0x0e, 0x0e*8, line, "n/a");
PrintAndLog("");
status = topaz_print_CC(&topaz_tag.data_blocks[1][0]);
if (status == -1) {
PrintAndLog("No NDEF message data present");
topaz_switch_off_field();
return 0;
}
PrintAndLog("");
topaz_print_control_TLVs(&topaz_tag.data_blocks[1][4]);
PrintAndLog("");
topaz_print_dynamic_data();
topaz_print_lifecycle_state(&topaz_tag.data_blocks[1][0]);
topaz_print_NDEF(&topaz_tag.data_blocks[1][0]);
topaz_switch_off_field();
return 0;
}
int CmdHFTopazCmdRaw(const char *Cmd)
{
PrintAndLog("not yet implemented. Use hf 14 raw with option -T.");
return 0;
}
static int CmdHelp(const char *Cmd);
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"reader", CmdHFTopazReader, 0, "Act like a Topaz reader"},
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop a Topaz reader-tag communication"},
{"raw", CmdHFTopazCmdRaw, 0, "Send raw hex data to tag"},
{NULL, NULL, 0, NULL}
};
int CmdHFTopaz(const char *Cmd) {
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
// parse
CmdsParse(CommandTable, Cmd);
return 0;
}
static int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

16
client/cmdhftopaz.h Normal file
View file

@ -0,0 +1,16 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2015 Piwi
//
// 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.
//-----------------------------------------------------------------------------
// High frequency Topaz (NFC Type 1) commands
//-----------------------------------------------------------------------------
#ifndef CMDHFTOPAZ_H__
#define CMDHFTOPAZ_H__
int CmdHFTopaz(const char *Cmd);
#endif

View file

@ -467,7 +467,7 @@ static command_t CommandTable[] =
{"reset", CmdReset, 0, "Reset the Proxmark3"},
{"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
{"setmux", CmdSetMux, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
{"tune", CmdTune, 0, "Measure antenna tuning"},
{"tune", CmdTune, 0, "['l'|'h'] -- Measure antenna tuning (option 'l' or 'h' to limit to LF or HF)"},
{"version", CmdVersion, 0, "Show version information about the connected Proxmark"},
{"status", CmdStatus, 0, "Show runtime status information about the connected Proxmark"},
{"ping", CmdPing, 0, "Test if the pm3 is responsive"},

View file

@ -13,37 +13,104 @@
#include <string.h>
#include <limits.h>
#include "proxmark3.h"
#include "data.h"
#include "graph.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdmain.h"
#include "cmddata.h"
#include "util.h"
#include "cmdlf.h"
#include "cmdlfhid.h"
#include "cmdlfawid.h"
#include "cmdlfti.h"
#include "cmdlfem4x.h"
#include "cmdlfhitag.h"
#include "cmdlft55xx.h"
#include "cmdlfpcf7931.h"
#include "cmdlfio.h"
#include "lfdemod.h"
#include "lfdemod.h" // for psk2TOpsk1
#include "util.h" // for parsing cli command utils
#include "ui.h" // for show graph controls
#include "graph.h" // for graph data
#include "cmdparser.h" // for getting cli commands included in cmdmain.h
#include "cmdmain.h" // for sending cmds to device
#include "data.h" // for GetFromBigBuf
#include "cmddata.h" // for `lf search`
#include "cmdlfawid.h" // for awid menu
#include "cmdlfem4x.h" // for em4x menu
#include "cmdlfhid.h" // for hid menu
#include "cmdlfhitag.h" // for hitag menu
#include "cmdlfio.h" // for ioprox menu
#include "cmdlft55xx.h" // for t55xx menu
#include "cmdlfti.h" // for ti menu
#include "cmdlfpresco.h" // for presco menu
#include "cmdlfpcf7931.h"// for pcf7931 menu
#include "cmdlfpyramid.h"// for pyramid menu
#include "cmdlfviking.h" // for viking menu
static int CmdHelp(const char *Cmd);
int usage_lf_cmdread()
{
PrintAndLog("Usage: lf cmdread d <delay period> z <zero period> o <one period> c <cmdbytes> [H] ");
PrintAndLog("Options: ");
PrintAndLog(" h This help");
PrintAndLog(" L Low frequency (125 KHz)");
PrintAndLog(" H High frequency (134 KHz)");
PrintAndLog(" d <delay> delay OFF period");
PrintAndLog(" z <zero> time period ZERO");
PrintAndLog(" o <one> time period ONE");
PrintAndLog(" c <cmd> Command bytes");
PrintAndLog(" ************* All periods in microseconds");
PrintAndLog("Examples:");
PrintAndLog(" lf cmdread d 80 z 100 o 200 c 11000");
PrintAndLog(" lf cmdread d 80 z 100 o 100 c 11000 H");
return 0;
}
/* send a command before reading */
int CmdLFCommandRead(const char *Cmd)
{
static char dummy[3];
dummy[0]= ' ';
static char dummy[3] = {0x20,0x00,0x00};
UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
// in case they specified 'h'
bool errors = FALSE;
//uint8_t divisor = 95; //125khz
uint8_t cmdp = 0;
while(param_getchar(Cmd, cmdp) != 0x00)
{
switch(param_getchar(Cmd, cmdp))
{
case 'h':
return usage_lf_cmdread();
case 'H':
//divisor = 88;
dummy[1]='h';
cmdp++;
break;
case 'L':
cmdp++;
break;
case 'c':
param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes);
cmdp+=2;
break;
case 'd':
c.arg[0] = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp+=2;
break;
case 'z':
c.arg[1] = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp+=2;
break;
case 'o':
c.arg[2] = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp+=2;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = 1;
break;
}
if(errors) break;
}
// No args
if(cmdp == 0) errors = 1;
//Validations
if(errors) return usage_lf_cmdread();
// in case they specified 'H'
strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@ -59,7 +126,7 @@ int CmdFlexdemod(const char *Cmd)
}
}
#define LONG_WAIT 100
#define LONG_WAIT 100
int start;
for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
int first = GraphBuffer[start];
@ -141,10 +208,13 @@ int CmdIndalaDemod(const char *Cmd)
uint8_t rawbits[4096];
int rawbit = 0;
int worst = 0, worstPos = 0;
// PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
// PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
// loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2)
for (i = 0; i < GraphTraceLen-1; i += 2) {
count += 1;
if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
// appears redundant - marshmellow
if (state == 0) {
for (j = 0; j < count - 8; j += 16) {
rawbits[rawbit++] = 0;
@ -157,6 +227,7 @@ int CmdIndalaDemod(const char *Cmd)
state = 1;
count = 0;
} else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
//appears redundant
if (state == 1) {
for (j = 0; j < count - 8; j += 16) {
rawbits[rawbit++] = 1;
@ -354,6 +425,7 @@ int CmdIndalaClone(const char *Cmd)
c.arg[1] = uid2;
}
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@ -468,7 +540,7 @@ int CmdLFSetConfig(const char *Cmd)
return usage_lf_config();
}
//Bps is limited to 8, so fits in lower half of arg1
if(bps >> 8) bps = 8;
if(bps >> 4) bps = 8;
sample_config config = {
decimation,bps,averaging,divisor,trigger_threshold
@ -476,6 +548,7 @@ int CmdLFSetConfig(const char *Cmd)
//Averaging is a flag on high-bit of arg[1]
UsbCommand c = {CMD_SET_LF_SAMPLING_CONFIG};
memcpy(c.d.asBytes,&config,sizeof(sample_config));
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@ -492,8 +565,14 @@ int CmdLFRead(const char *Cmd)
if (param_getchar(Cmd, cmdp) == 's') arg1 = true; //suppress print
//And ship it to device
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}};
clearCommandBuffer();
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
//WaitForResponse(CMD_ACK,NULL);
if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
PrintAndLog("command execution time out");
return 1;
}
return 0;
}
@ -506,6 +585,7 @@ int CmdLFSnoop(const char *Cmd)
}
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
clearCommandBuffer();
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
return 0;
@ -552,6 +632,7 @@ int CmdLFSim(const char *Cmd)
printf("\n");
PrintAndLog("Starting to simulate");
UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@ -583,7 +664,7 @@ int usage_lf_simask(void)
PrintAndLog(" b sim ask/biphase");
PrintAndLog(" m sim ask/manchester - Default");
PrintAndLog(" r sim ask/raw");
PrintAndLog(" s TBD- -to enable a gap between playback repetitions - default: no gap");
PrintAndLog(" s add t55xx Sequence Terminator gap - default: no gaps (only manchester)");
PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
return 0;
}
@ -701,6 +782,7 @@ int CmdLFfskSim(const char *Cmd)
UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
memcpy(c.d.asBytes, DemodBuffer, size);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@ -794,6 +876,7 @@ int CmdLFaskSim(const char *Cmd)
UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
PrintAndLog("preparing to sim ask data: %d bits", size);
memcpy(c.d.asBytes, DemodBuffer, size);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@ -901,6 +984,7 @@ int CmdLFpskSim(const char *Cmd)
UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}};
PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size);
memcpy(c.d.asBytes, DemodBuffer, size);
clearCommandBuffer();
SendCommand(&c);
return 0;
@ -1054,13 +1138,6 @@ int CmdLFfind(const char *Cmd)
return 1;
}
//add psk and indala
ans=CmdIndalaDecode("");
if (ans>0) {
PrintAndLog("\nValid Indala ID Found!");
return 1;
}
ans=CmdAskEM410xDemod("");
if (ans>0) {
PrintAndLog("\nValid EM410x ID Found!");
@ -1085,6 +1162,18 @@ int CmdLFfind(const char *Cmd)
return 1;
}
ans=CmdVikingDemod("");
if (ans>0) {
PrintAndLog("\nValid Viking ID Found!");
return 1;
}
ans=CmdIndalaDecode("");
if (ans>0) {
PrintAndLog("\nValid Indala ID Found!");
return 1;
}
ans=CmdPSKNexWatch("");
if (ans>0) {
PrintAndLog("\nValid NexWatch ID Found!");
@ -1105,7 +1194,8 @@ int CmdLFfind(const char *Cmd)
return 1;
}
}
ans=ASKDemod("0 0 0",TRUE,FALSE,1);
bool st = TRUE;
ans=ASKDemod_ext("0 0 0",TRUE,FALSE,1,&st);
if (ans>0) {
PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
@ -1126,28 +1216,31 @@ int CmdLFfind(const char *Cmd)
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
{"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"},
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
{"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"},
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
{"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"},
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"viking", CmdLFViking, 1, "{ Viking tags... }"},
{"cmdread", CmdLFCommandRead, 0, "<d period> <z period> <o period> <c command> ['H'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'H' for 134)"},
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
{"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"},
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
{"read", CmdLFRead, 0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
{"search", CmdLFfind, 1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
{"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
{"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [biphase/manchester/raw <'b'|'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
{"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
{"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
{"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"},
{NULL, NULL, 0, NULL}
};

View file

@ -16,9 +16,11 @@
#include "cmdparser.h" // CmdsParse, CmdsHelp
#include "cmdlfawid.h" // AWID function declarations
#include "lfdemod.h" // parityTest
#include "util.h" // weigandparity
#include "protocols.h" // for T55xx config register definitions
#include "cmdmain.h"
static int CmdHelp(const char *Cmd);
static int CmdHelp(const char *Cmd);
int usage_lf_awid_fskdemod(void) {
PrintAndLog("Enables AWID26 compatible reader mode printing details of scanned AWID26 tags.");
@ -26,11 +28,11 @@ int usage_lf_awid_fskdemod(void) {
PrintAndLog("If the ['1'] option is provided, reader mode is exited after reading a single AWID26 card.");
PrintAndLog("");
PrintAndLog("Usage: lf awid fskdemod ['1']");
PrintAndLog(" Options : ");
PrintAndLog("Options : ");
PrintAndLog(" 1 : (optional) stop after reading a single card");
PrintAndLog("");
PrintAndLog(" sample : lf awid fskdemod");
PrintAndLog(" : lf awid fskdemod 1");
PrintAndLog("Samples : lf awid fskdemod");
PrintAndLog(" : lf awid fskdemod 1");
return 0;
}
@ -40,11 +42,11 @@ int usage_lf_awid_sim(void) {
PrintAndLog("Per AWID26 format, the facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.");
PrintAndLog("");
PrintAndLog("Usage: lf awid sim <Facility-Code> <Card-Number>");
PrintAndLog(" Options : ");
PrintAndLog("Options : ");
PrintAndLog(" <Facility-Code> : 8-bit value representing the AWID facility code");
PrintAndLog(" <Card Number> : 16-bit value representing the AWID card number");
PrintAndLog("");
PrintAndLog(" sample : lf awid sim 224 1337");
PrintAndLog("Sample : lf awid sim 224 1337");
return 0;
}
@ -54,133 +56,91 @@ int usage_lf_awid_clone(void) {
PrintAndLog("Per AWID26 format, the facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.");
PrintAndLog("");
PrintAndLog("Usage: lf awid clone <Facility-Code> <Card-Number>");
PrintAndLog(" Options : ");
PrintAndLog("Options : ");
PrintAndLog(" <Facility-Code> : 8-bit value representing the AWID facility code");
PrintAndLog(" <Card Number> : 16-bit value representing the AWID card number");
PrintAndLog(" Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
PrintAndLog("");
PrintAndLog(" sample : lf awid clone 224 1337");
PrintAndLog("Sample : lf awid clone 224 1337");
return 0;
}
int CmdAWIDDemodFSK(const char *Cmd)
{
int CmdAWIDDemodFSK(const char *Cmd) {
int findone=0;
if(Cmd[0]=='1') findone=1;
if (Cmd[0]=='h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod();
UsbCommand c={CMD_AWID_DEMOD_FSK};
c.arg[0]=findone;
if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod();
if (Cmd[0] == '1') findone = 1;
UsbCommand c = {CMD_AWID_DEMOD_FSK, {findone, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
return 0;
}
int getAWIDBits(unsigned int fc, unsigned int cn, uint8_t *AWIDBits)
{
int i;
uint32_t fcode=(fc & 0x000000FF), cnum=(cn & 0x0000FFFF), uBits=0;
if (fcode != fc)
PrintAndLog("NOTE: Facility code truncated for AWID26 format (8-bit facility code)");
if (cnum!=cn)
PrintAndLog("NOTE: Card number was truncated for AWID26 format (16-bit card number)");
//refactored by marshmellow
int getAWIDBits(uint32_t fc, uint32_t cn, uint8_t *AWIDBits) {
uint8_t pre[66];
memset(pre, 0, sizeof(pre));
AWIDBits[7]=1;
num_to_bytebits(26, 8, pre);
AWIDBits[0] = 0x01; // 6-bit Preamble with 2 parity bits
AWIDBits[1] = 0x1D; // First byte from card format (26-bit) plus parity bits
AWIDBits[2] = 0x80; // Set the next two bits as 0b10 to finish card format
uBits = (fcode<<4) + (cnum>>12);
if (!parityTest(uBits,12,0))
AWIDBits[2] |= (1<<5); // If not already even parity, set bit to make even
uBits = AWIDBits[2]>>5;
if (!parityTest(uBits, 3, 1))
AWIDBits[2] |= (1<<4);
uBits = fcode>>5; // first 3 bits of facility-code
AWIDBits[2] += (uBits<<1);
if (!parityTest(uBits, 3, 1))
AWIDBits[2]++; // Set parity bit to make odd parity
uBits = (fcode & 0x1C)>>2;
AWIDBits[3] = 0;
if (!parityTest(uBits,3,1))
AWIDBits[3] |= (1<<4);
AWIDBits[3] += (uBits<<5);
uBits = ((fcode & 0x3)<<1) + ((cnum & 0x8000)>>15); // Grab/shift 2 LSBs from facility code and add shifted MSB from cardnum
if (!parityTest(uBits,3,1))
AWIDBits[3]++; // Set LSB for parity
AWIDBits[3]+= (uBits<<1);
uBits = (cnum & 0x7000)>>12;
AWIDBits[4] = uBits<<5;
if (!parityTest(uBits,3,1))
AWIDBits[4] |= (1<<4);
uBits = (cnum & 0x0E00)>>9;
AWIDBits[4] += (uBits<<1);
if (!parityTest(uBits,3,1))
AWIDBits[4]++; // Set LSB for parity
uBits = (cnum & 0x1C0)>>6; // Next bits from card number
AWIDBits[5]=(uBits<<5);
if (!parityTest(uBits,3,1))
AWIDBits[5] |= (1<<4); // Set odd parity bit as needed
uBits = (cnum & 0x38)>>3;
AWIDBits[5]+= (uBits<<1);
if (!parityTest(uBits,3,1))
AWIDBits[5]++; // Set odd parity bit as needed
uBits = (cnum & 0x7); // Last three bits from card number!
AWIDBits[6] = (uBits<<5);
if (!parityTest(uBits,3,1))
AWIDBits[6] |= (1<<4);
uBits = (cnum & 0x0FFF);
if (!parityTest(uBits,12,1))
AWIDBits[6] |= (1<<3);
else
AWIDBits[6]++;
for (i = 7; i<12; i++)
AWIDBits[i]=0x11;
uint8_t wiegand[24];
num_to_bytebits(fc, 8, wiegand);
num_to_bytebits(cn, 16, wiegand+8);
wiegand_add_parity(pre+8, wiegand, 24);
size_t bitLen = addParity(pre, AWIDBits+8, 66, 4, 1);
if (bitLen != 88) return 0;
//for (uint8_t i = 0; i<3; i++){
// PrintAndLog("DEBUG: %08X", bytebits_to_byte(AWIDBits+(32*i),32));
//}
return 1;
}
int CmdAWIDSim(const char *Cmd)
{
uint32_t fcode = 0, cnum = 0, fc=0, cn=0, i=0;
uint8_t *BS, BitStream[12];
int CmdAWIDSim(const char *Cmd) {
uint32_t fcode = 0, cnum = 0, fc=0, cn=0;
uint8_t BitStream[96];
uint8_t *bs = BitStream;
size_t size = sizeof(BitStream);
memset(bs, 0, size);
uint64_t arg1 = (10<<8) + 8; // fcHigh = 10, fcLow = 8
uint64_t arg2 = 50; // clk RF/50 invert=0
BS = BitStream;
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) {
return usage_lf_awid_sim();
}
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_awid_sim();
fcode = (fc & 0x000000FF);
cnum = (cn & 0x0000FFFF);
if (fc != fcode) PrintAndLog("Facility-Code (%u) truncated to 8-bits: %u",fc,fcode);
if (cn != cnum) PrintAndLog("Card number (%u) truncated to 16-bits: %u",cn,cnum);
fcode=(fc & 0x000000FF);
cnum=(cn & 0x0000FFFF);
if (fc!=fcode)
PrintAndLog("Facility-Code (%u) truncated to 8-bits: %u",fc,fcode);
if (cn!=cnum)
PrintAndLog("Card number (%u) truncated to 16-bits: %u",cn,cnum);
PrintAndLog("Emulating AWID26 -- FC: %u; CN: %u\n",fcode,cnum);
PrintAndLog("Press pm3-button to abort simulation or run another command");
if (!getAWIDBits(fc, cn, bs)) {
PrintAndLog("Error with tag bitstream generation.");
return 1;
}
// AWID uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0
if (getAWIDBits(fc, cn, BS)) {
PrintAndLog("Running 'lf simfsk c 50 H 10 L 8 d %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'",
BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6],
BS[7],BS[8],BS[9],BS[10],BS[11]);
} else
PrintAndLog("Error with tag bitstream generation.");
UsbCommand c;
c.cmd = CMD_FSK_SIM_TAG;
c.arg[0] = arg1; // fcHigh<<8 + fcLow
c.arg[1] = arg2; // Inversion and clk setting
c.arg[2] = 96; // Bitstream length: 96-bits == 12 bytes
for (i=0; i < 96; i++)
c.d.asBytes[i] = (BS[i/8] & (1<<(7-(i%8))))?1:0;
UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
memcpy(c.d.asBytes, bs, size);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
int CmdAWIDClone(const char *Cmd)
{
uint32_t fc=0,cn=0,blocks[4] = {0x00107060, 0, 0, 0x11111111}, i=0;
uint8_t BitStream[12];
uint8_t *BS=BitStream;
UsbCommand c, resp;
int CmdAWIDClone(const char *Cmd) {
uint32_t blocks[4] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 3<<T55x7_MAXBLOCK_SHIFT, 0, 0, 0};
uint32_t fc=0,cn=0;
uint8_t BitStream[96];
uint8_t *bs=BitStream;
memset(bs,0,sizeof(BitStream));
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) {
return usage_lf_awid_clone();
}
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_awid_clone();
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 3<<T5555_MAXBLOCK_SHIFT;
if ((fc & 0xFF) != fc) {
fc &= 0xFF;
@ -190,48 +150,58 @@ int CmdAWIDClone(const char *Cmd)
cn &= 0xFFFF;
PrintAndLog("Card Number Truncated to 16-bits (AWID26): %u", cn);
}
if (getAWIDBits(fc,cn,BS)) {
PrintAndLog("Preparing to clone AWID26 to T55x7 with FC: %u, CN: %u (Raw: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x)",
fc,cn, BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6],BS[7],BS[8],BS[9],BS[10],BS[11]);
blocks[1] = (BS[0]<<24) + (BS[1]<<16) + (BS[2]<<8) + (BS[3]);
blocks[2] = (BS[4]<<24) + (BS[5]<<16) + (BS[6]<<8) + (BS[7]);
PrintAndLog("Block 0: 0x%08x", blocks[0]);
PrintAndLog("Block 1: 0x%08x", blocks[1]);
PrintAndLog("Block 2: 0x%08x", blocks[2]);
PrintAndLog("Block 3: 0x%08x", blocks[3]);
for (i=0; i<4; i++) {
c.cmd = CMD_T55XX_WRITE_BLOCK;
c.arg[0] = blocks[i];
c.arg[1] = i;
c.arg[2] = 0;
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
PrintAndLog("Error occurred, device did not respond during write operation.");
return -1;
}
if ( !getAWIDBits(fc, cn, bs)) {
PrintAndLog("Error with tag bitstream generation.");
return 1;
}
blocks[1] = bytebits_to_byte(bs,32);
blocks[2] = bytebits_to_byte(bs+32,32);
blocks[3] = bytebits_to_byte(bs+64,32);
PrintAndLog("Preparing to clone AWID26 to T55x7 with FC: %u, CN: %u",
fc, cn);
PrintAndLog("Blk | Data ");
PrintAndLog("----+------------");
PrintAndLog(" 00 | 0x%08x", blocks[0]);
PrintAndLog(" 01 | 0x%08x", blocks[1]);
PrintAndLog(" 02 | 0x%08x", blocks[2]);
PrintAndLog(" 03 | 0x%08x", blocks[3]);
UsbCommand resp;
UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
for (uint8_t i=0; i<4; i++) {
c.cmd = CMD_T55XX_WRITE_BLOCK;
c.arg[0] = blocks[i];
c.arg[1] = i;
c.arg[2] = 0;
clearCommandBuffer();
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
PrintAndLog("Error occurred, device did not respond during write operation.");
return -1;
}
}
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"fskdemod", CmdAWIDDemodFSK, 0, "['1'] Realtime AWID FSK demodulator (option '1' for one tag only)"},
{"sim", CmdAWIDSim, 0, "<Facility-Code> <Card Number> -- AWID tag simulator"},
{"clone", CmdAWIDClone, 0, "<Facility-Code> <Card Number> -- Clone AWID to T55x7 (tag must be in range of antenna)"},
{"clone", CmdAWIDClone, 0, "<Facility-Code> <Card Number> <Q5> -- Clone AWID to T55x7 (tag must be in range of antenna)"},
{NULL, NULL, 0, NULL}
};
int CmdLFAWID(const char *Cmd)
{
int CmdLFAWID(const char *Cmd) {
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

View file

@ -21,8 +21,6 @@
#include "cmdlfem4x.h"
#include "lfdemod.h"
#define llx PRIx64
char *global_em410xId;
static int CmdHelp(const char *Cmd);
@ -58,7 +56,7 @@ int CmdEM410xRead(const char *Cmd)
return 0;
}
char id[12] = {0x00};
sprintf(id, "%010llx",lo);
sprintf(id, "%010"PRIx64,lo);
global_em410xId = id;
return 1;
@ -73,22 +71,23 @@ int CmdEM410xSim(const char *Cmd)
uint8_t uid[5] = {0x00};
if (cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf em4x 410xsim <UID>");
PrintAndLog("Usage: lf em4x em410xsim <UID> <clock>");
PrintAndLog("");
PrintAndLog(" sample: lf em4x 410xsim 0F0368568B");
PrintAndLog(" sample: lf em4x em410xsim 0F0368568B");
return 0;
}
/* clock is 64 in EM410x tags */
uint8_t clock = 64;
if (param_gethex(Cmd, 0, uid, 10)) {
PrintAndLog("UID must include 10 HEX symbols");
return 0;
}
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]);
param_getdec(Cmd,1, &clock);
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock);
PrintAndLog("Press pm3-button to about simulation");
/* clock is 64 in EM410x tags */
int clock = 64;
/* clear our graph */
ClearGraph(0);
@ -197,21 +196,13 @@ int CmdEM410xWrite(const char *Cmd)
}
// Check Clock
if (card == 1)
{
// Default: 64
if (clock == 0)
clock = 64;
// Default: 64
if (clock == 0)
clock = 64;
// Allowed clock rates: 16, 32 and 64
if ((clock != 16) && (clock != 32) && (clock != 64)) {
PrintAndLog("Error! Clock rate %d not valid. Supported clock rates are 16, 32 and 64.\n", clock);
return 0;
}
}
else if (clock != 0)
{
PrintAndLog("Error! Clock rate is only supported on T55x7 tags.\n");
// Allowed clock rates: 16, 32, 40 and 64
if ((clock != 16) && (clock != 32) && (clock != 64) && (clock != 40)) {
PrintAndLog("Error! Clock rate %d not valid. Supported clock rates are 16, 32, 40 and 64.\n", clock);
return 0;
}
@ -221,11 +212,11 @@ int CmdEM410xWrite(const char *Cmd)
// provide for backwards-compatibility for older firmware, and to avoid
// having to add another argument to CMD_EM410X_WRITE_TAG, we just store
// the clock rate in bits 8-15 of the card value
card = (card & 0xFF) | (((uint64_t)clock << 8) & 0xFF00);
}
else if (card == 0)
card = (card & 0xFF) | ((clock << 8) & 0xFF00);
} else if (card == 0) {
PrintAndLog("Writing %s tag with UID 0x%010" PRIx64, "T5555", id, clock);
else {
card = (card & 0xFF) | ((clock << 8) & 0xFF00);
} else {
PrintAndLog("Error! Bad card type selected.\n");
return 0;
}
@ -608,7 +599,7 @@ static command_t CommandTable[] =
{"help", CmdHelp, 1, "This help"},
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
{"em410xsim", CmdEM410xSim, 0, "<UID> [clock rate] -- Simulate EM410x tag"},
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
{"em410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},

View file

@ -18,6 +18,7 @@
#include "common.h"
#include "util.h"
#include "hitag2.h"
#include "hitagS.h"
#include "sleep.h"
#include "cmdmain.h"
@ -190,14 +191,20 @@ int CmdLFHitagSim(const char *Cmd) {
}
int CmdLFHitagReader(const char *Cmd) {
// UsbCommand c = {CMD_READER_HITAG};
// param_get32ex(Cmd,1,0,16);
UsbCommand c = {CMD_READER_HITAG};//, {param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),param_get32ex(Cmd,3,0,16)}};
hitag_data* htd = (hitag_data*)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd,0,0,10);
switch (htf) {
case 01: { //RHTSF_CHALLENGE
c = (UsbCommand){ CMD_READ_HITAG_S };
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
} break;
case 02: { //RHTSF_KEY
c = (UsbCommand){ CMD_READ_HITAG_S };
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
} break;
case RHT2F_PASSWORD: {
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password);
} break;
@ -216,6 +223,8 @@ int CmdLFHitagReader(const char *Cmd) {
PrintAndLog("Error: unkown reader function %d",htf);
PrintAndLog("Hitag reader functions");
PrintAndLog(" HitagS (0*)");
PrintAndLog(" 01 <nr> <ar> (Challenge) read all pages from a Hitag S tag");
PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) read all pages from a Hitag S tag");
PrintAndLog(" Hitag1 (1*)");
PrintAndLog(" Hitag2 (2*)");
PrintAndLog(" 21 <password> (password mode)");
@ -257,14 +266,126 @@ int CmdLFHitagReader(const char *Cmd) {
return 0;
}
int CmdLFHitagSimS(const char *Cmd) {
UsbCommand c = { CMD_SIMULATE_HITAG_S };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
bool tag_mem_supplied;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE)
len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
if ((pf = fopen(filename, "rb+")) == NULL) {
PrintAndLog("Error: Could not open file [%s]", filename);
return 1;
}
tag_mem_supplied = true;
if (fread(c.d.asBytes, 4*64, 1, pf) == 0) {
PrintAndLog("Error: File reading error");
fclose(pf);
return 1;
}
fclose(pf);
} else {
tag_mem_supplied = false;
}
// Does the tag comes with memory
c.arg[0] = (uint32_t) tag_mem_supplied;
SendCommand(&c);
return 0;
}
int CmdLFHitagCheckChallenges(const char *Cmd) {
UsbCommand c = { CMD_TEST_HITAGS_TRACES };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
bool file_given;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
return 1;
}
file_given = true;
if (fread(c.d.asBytes,8*60,1,pf) == 0) {
PrintAndLog("Error: File reading error");
fclose(pf);
return 1;
}
fclose(pf);
} else {
file_given = false;
}
//file with all the challenges to try
c.arg[0] = (uint32_t)file_given;
SendCommand(&c);
return 0;
}
int CmdLFHitagWP(const char *Cmd) {
UsbCommand c = { CMD_WR_HITAG_S };
hitag_data* htd = (hitag_data*)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd,0,0,10);
switch (htf) {
case 03: { //WHTSF_CHALLENGE
num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr);
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data);
} break;
case 04: { //WHTSF_KEY
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->crypto.data);
} break;
default: {
PrintAndLog("Error: unkown writer function %d",htf);
PrintAndLog("Hitag writer functions");
PrintAndLog(" HitagS (0*)");
PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" Hitag1 (1*)");
PrintAndLog(" Hitag2 (2*)");
return 1;
} break;
}
// Copy the hitag function into the first argument
c.arg[0] = htf;
// Send the command to the proxmark
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
// Check the return status, stored in the first argument
if (resp.arg[0] == false) return 1;
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"},
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
{NULL, NULL, 0, NULL}
{"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"},
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
{"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" },
{"simS", CmdLFHitagSimS, 1, "<hitagS.hts> Simulate HitagS transponder" },
{"checkChallenges", CmdLFHitagCheckChallenges, 1, "<challenges.cc> test all challenges" }, {
NULL,NULL, 0, NULL }
};
int CmdLFHitag(const char *Cmd)

View file

@ -67,9 +67,9 @@ int CmdIOClone(const char *Cmd)
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
//{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
//{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
{"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
{"clone", CmdIOClone, 0, "Clone ioProx Tag"},
{"clone", CmdIOClone, 0, "Clone ioProx Tag"},
{NULL, NULL, 0, NULL}
};

View file

@ -8,11 +8,11 @@
//-----------------------------------------------------------------------------
// Low frequency PCF7931 commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
@ -22,115 +22,158 @@
static int CmdHelp(const char *Cmd);
struct pcf7931_config configPcf = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},17500,{0,0}};
#define PCF7931_DEFAULT_INITDELAY 17500
#define PCF7931_DEFAULT_OFFSET_WIDTH 0
#define PCF7931_DEFAULT_OFFSET_POSITION 0
int CmdLFPCF7931Read(const char *Cmd)
{
UsbCommand c = {CMD_PCF7931_READ};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
return 0;
// Default values - Configuration
struct pcf7931_config configPcf = {
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
PCF7931_DEFAULT_INITDELAY,
PCF7931_DEFAULT_OFFSET_WIDTH,
PCF7931_DEFAULT_OFFSET_POSITION
};
// Resets the configuration settings to default values.
int pcf7931_resetConfig(){
memset(configPcf.Pwd, 0xFF, sizeof(configPcf.Pwd) );
configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY;
configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH;
configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION;
return 0;
}
int CmdLFPCF7931Config(const char *Cmd)
{
int res = 0;
res = sscanf(Cmd, "%02x %02x %02x %02x %02x %02x %02x %d %d %d", &configPcf.password[0], &configPcf.password[1], &configPcf.password[2], &configPcf.password[3], &configPcf.password[4], &configPcf.password[5], &configPcf.password[6], &configPcf.init_delay, &configPcf.offset[0], &configPcf.offset[1]);
if (res >= 7 || res < 1){
if(res == 7) configPcf.init_delay = 17500; //default value
if(res<=8){
configPcf.offset[0] = 0; //default value
configPcf.offset[1] = 0; //default value
}
if(res < 1){
PrintAndLog("Usage: <password byte 1 (in hex, lsb first)> <password byte 2 (in hex, lsb first)> [...] <password byte 7 (in hex, lsb first)> <tag initialization delay (in us)> <optional : offset on the low pulses width (in us)> <optional : offset on the low pulses position (in us)>");
PrintAndLog("The time offsets could be usefull to correct slew rate generated by the antenna.");
}
PrintAndLog("Current configuration :");
PrintAndLog("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", configPcf.password[0], configPcf.password[1], configPcf.password[2], configPcf.password[3], configPcf.password[4], configPcf.password[5], configPcf.password[6]);
PrintAndLog("Tag initialization delay : %d us", configPcf.init_delay);
PrintAndLog("Offsets : %d us on the low pulses width, %d us on the low pulses positions", configPcf.offset[0], configPcf.offset[1]);
return 0;
}
//default values
configPcf.password[0] = 0xFF;
configPcf.password[1] = 0xFF;
configPcf.password[2] = 0xFF;
configPcf.password[3] = 0xFF;
configPcf.password[4] = 0xFF;
configPcf.password[5] = 0xFF;
configPcf.password[6] = 0xFF;
configPcf.init_delay = 17500;
configPcf.offset[0] = 0;
configPcf.offset[1] = 0;
PrintAndLog("Incorrect format");
PrintAndLog("Examples of right usage : lf pcf7931 config 11 22 33 44 55 66 77 20000");
PrintAndLog(" lf pcf7931 config FF FF FF FF FF FF FF 17500 -10 30");
return 0;
int pcf7931_printConfig(){
PrintAndLog("Password (LSB first on bytes) : %s", sprint_hex( configPcf.Pwd, sizeof(configPcf.Pwd)));
PrintAndLog("Tag initialization delay : %d us", configPcf.InitDelay);
PrintAndLog("Offset low pulses width : %d us", configPcf.OffsetWidth);
PrintAndLog("Offset low pulses position : %d us", configPcf.OffsetPosition);
return 0;
}
int CmdLFPCF7931Write(const char *Cmd)
{
UsbCommand c = {CMD_PCF7931_WRITE};
int res = 0;
res = sscanf(Cmd, "%x %x %x", &c.arg[0], &c.arg[1], &c.arg[2]);
if(res < 1) {
PrintAndLog("Please specify the block address in hex");
return 0;
}
if (res == 1){
PrintAndLog("Please specify the byte address in hex");
return 0;
}
if(res == 2) {
PrintAndLog("Please specify the data in hex (1 byte)");
return 0;
}
if(res == 3) {
uint8_t n=0;
for(n=0;n<7;n++) c.d.asDwords[n] = configPcf.password[n];
c.d.asDwords[7] = (configPcf.offset[0]+128);
c.d.asDwords[8] = (configPcf.offset[1]+128);
c.d.asDwords[9] = configPcf.init_delay;
SendCommand(&c);
return 0;
}
PrintAndLog("INCORRECT FORMAT");
return 0;
int usage_pcf7931_read(){
PrintAndLog("Usage: lf pcf7931 read [h] ");
PrintAndLog("This command tries to read a PCF7931 tag.");
PrintAndLog("Options:");
PrintAndLog(" h This help");
PrintAndLog("Examples:");
PrintAndLog(" lf pcf7931 read");
return 0;
}
int usage_pcf7931_write(){
PrintAndLog("Usage: lf pcf7931 write [h] <block address> <byte address> <data>");
PrintAndLog("This command tries to write a PCF7931 tag.");
PrintAndLog("Options:");
PrintAndLog(" h This help");
PrintAndLog(" blockaddress Block to save [0-7]");
PrintAndLog(" byteaddress Index of byte inside block to write [0-15]");
PrintAndLog(" data one byte of data (hex)");
PrintAndLog("Examples:");
PrintAndLog(" lf pcf7931 write 2 1 FF");
return 0;
}
int usage_pcf7931_config(){
PrintAndLog("Usage: lf pcf7931 config [h] [r] <pwd> <delay> <offset width> <offset position>");
PrintAndLog("This command tries to set the configuration used with PCF7931 commands");
PrintAndLog("The time offsets could be useful to correct slew rate generated by the antenna");
PrintAndLog("Caling without some parameter will print the current configuration.");
PrintAndLog("Options:");
PrintAndLog(" h This help");
PrintAndLog(" r Reset configuration to default values");
PrintAndLog(" pwd Password, hex, 7bytes, LSB-order");
PrintAndLog(" delay Tag initialization delay (in us) decimal");
PrintAndLog(" offset Low pulses width (in us) decimal");
PrintAndLog(" offset Low pulses position (in us) decimal");
PrintAndLog("Examples:");
PrintAndLog(" lf pcf7931 config");
PrintAndLog(" lf pcf7931 config r");
PrintAndLog(" lf pcf7931 config 11223344556677 20000");
PrintAndLog(" lf pcf7931 config 11223344556677 17500 -10 30");
return 0;
}
int CmdLFPCF7931Read(const char *Cmd){
uint8_t ctmp = param_getchar(Cmd, 0);
if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_read();
UsbCommand resp;
UsbCommand c = {CMD_PCF7931_READ, {0, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) {
PrintAndLog("command execution time out");
return 1;
}
return 0;
}
int CmdLFPCF7931Config(const char *Cmd){
uint8_t ctmp = param_getchar(Cmd, 0);
if ( ctmp == 0) return pcf7931_printConfig();
if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_config();
if ( ctmp == 'R' || ctmp == 'r' ) return pcf7931_resetConfig();
if ( param_gethex(Cmd, 0, configPcf.Pwd, 14) ) return usage_pcf7931_config();
configPcf.InitDelay = (param_get32ex(Cmd,1,0,10) & 0xFFFF);
configPcf.OffsetWidth = (int)(param_get32ex(Cmd,2,0,10) & 0xFFFF);
configPcf.OffsetPosition = (int)(param_get32ex(Cmd,3,0,10) & 0xFFFF);
pcf7931_printConfig();
return 0;
}
int CmdLFPCF7931Write(const char *Cmd){
uint8_t ctmp = param_getchar(Cmd, 0);
if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_pcf7931_write();
uint8_t block = 0, bytepos = 0, data = 0;
if ( param_getdec(Cmd, 0, &block) ) return usage_pcf7931_write();
if ( param_getdec(Cmd, 1, &bytepos) ) return usage_pcf7931_write();
if ( (block > 7) || (bytepos > 15) ) return usage_pcf7931_write();
data = param_get8ex(Cmd, 2, 0, 16);
PrintAndLog("Writing block: %d", block);
PrintAndLog(" pos: %d", bytepos);
PrintAndLog(" data: 0x%02X", data);
UsbCommand c = {CMD_PCF7931_WRITE, { block, bytepos, data} };
memcpy(c.d.asDwords, configPcf.Pwd, sizeof(configPcf.Pwd) );
c.d.asDwords[7] = (configPcf.OffsetWidth + 128);
c.d.asDwords[8] = (configPcf.OffsetPosition + 128);
c.d.asDwords[9] = configPcf.InitDelay;
clearCommandBuffer();
SendCommand(&c);
//no ack?
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"},
{"write", CmdLFPCF7931Write, 1, "Write data on a PCF7931 transponder. Usage : lf pcf7931 write <bloc address> <byte address> <data>"},
{"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"},
{NULL, NULL, 0, NULL}
{"help", CmdHelp, 1, "This help"},
{"read", CmdLFPCF7931Read, 0, "Read content of a PCF7931 transponder"},
{"write", CmdLFPCF7931Write, 0, "Write data on a PCF7931 transponder."},
{"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"},
{NULL, NULL, 0, NULL}
};
int CmdLFPCF7931(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);
return 0;
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
CmdsHelp(CommandTable);
return 0;
}

View file

@ -13,17 +13,23 @@
#define CMDLFPCF7931_H__
struct pcf7931_config{
uint8_t password[7];
uint16_t init_delay;
int16_t offset[2];
uint8_t Pwd[7];
uint16_t InitDelay;
int16_t OffsetWidth;
int16_t OffsetPosition;
};
int pcf7931_resetConfig();
int pcf7931_printConfig();
int usage_pcf7931_read();
int usage_pcf7931_write();
int usage_pcf7931_config();
int CmdLFPCF7931(const char *Cmd);
int CmdLFPCF7931Read(const char *Cmd);
int CmdLFPCF7931Write(const char *Cmd);
int CmdLFPCF7931Config(const char *Cmd);
#endif

263
client/cmdlfpresco.c Normal file
View file

@ -0,0 +1,263 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency Presco tag commands
//-----------------------------------------------------------------------------
#include <string.h>
#include <inttypes.h>
#include "cmdlfpresco.h"
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdmain.h"
#include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
static int CmdHelp(const char *Cmd);
int usage_lf_presco_clone(void){
PrintAndLog("clone a Presco tag to a T55x7 tag.");
PrintAndLog("Usage: lf presco clone d <Card-ID> H <hex-ID> <Q5>");
PrintAndLog("Options :");
PrintAndLog(" d <Card-ID> : 9 digit presco card ID");
PrintAndLog(" H <hex-ID> : 8 digit hex card number");
PrintAndLog(" <Q5> : specify write to Q5 (t5555 instead of t55x7)");
PrintAndLog("");
PrintAndLog("Sample : lf presco clone d 123456789");
return 0;
}
int usage_lf_presco_sim(void) {
PrintAndLog("Enables simulation of presco card with specified card number.");
PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
PrintAndLog("");
PrintAndLog("Usage: lf presco sim d <Card-ID> or H <hex-ID>");
PrintAndLog("Options :");
PrintAndLog(" d <Card-ID> : 9 digit presco card number");
PrintAndLog(" H <hex-ID> : 8 digit hex card number");
PrintAndLog("");
PrintAndLog("Sample : lf presco sim d 123456789");
return 0;
}
// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) {
uint8_t val = 0;
bool hex = false, errors = false;
uint8_t cmdp = 0;
char id[11];
int stringlen = 0;
while(param_getchar(Cmd, cmdp) != 0x00) {
switch(param_getchar(Cmd, cmdp)) {
case 'h':
return -1;
case 'H':
hex = true;
//get hex
*fullcode = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp+=2;
break;
case 'P':
case 'p':
//param get string int param_getstr(const char *line, int paramnum, char * str)
stringlen = param_getstr(Cmd, cmdp+1, id);
if (stringlen < 2) return -1;
cmdp+=2;
break;
case 'Q':
case 'q':
*Q5 = true;
cmdp++;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = 1;
break;
}
if(errors) break;
}
// No args
if(cmdp == 0) errors = 1;
//Validations
if(errors) return -1;
if (!hex) {
for (int index =0; index < strlen(id); ++index) {
// Get value from number string.
if ( id[index] == '*' ) val = 10;
if ( id[index] == '#') val = 11;
if ( id[index] >= 0x30 && id[index] <= 0x39 )
val = id[index] - 0x30;
*fullcode += val;
// last digit is only added, not multipled.
if ( index < strlen(id)-1 )
*fullcode *= 12;
}
}
*usercode = *fullcode & 0x0000FFFF; //% 65566
*sitecode = (*fullcode >> 24) & 0x000000FF; // /= 16777216;
return 0;
}
// calc not certain - intended to get bitstream for programming / sim
int GetPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
num_to_bytebits(0x10D00000, 32, prescoBits);
num_to_bytebits(0x00000000, 32, prescoBits+32);
num_to_bytebits(0x00000000, 32, prescoBits+64);
num_to_bytebits(fullcode , 32, prescoBits+96);
return 1;
}
//see ASKDemod for what args are accepted
int CmdPrescoDemod(const char *Cmd) {
if (!ASKDemod(Cmd, false, false, 1)) {
if (g_debugMode) PrintAndLog("ASKDemod failed");
return 0;
}
size_t size = DemodBufferLen;
//call lfdemod.c demod for Viking
int ans = PrescoDemod(DemodBuffer, &size);
if (ans < 0) {
if (g_debugMode) PrintAndLog("Error Presco_Demod %d", ans);
return 0;
}
//got a good demod
uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
uint32_t raw4 = bytebits_to_byte(DemodBuffer+ans+96, 32);
uint32_t cardid = raw4;
PrintAndLog("Presco Tag Found: Card ID %08X", cardid);
PrintAndLog("Raw: %08X%08X%08X%08X", raw1,raw2,raw3,raw4);
setDemodBuf(DemodBuffer+ans, 128, 0);
uint32_t sitecode = 0, usercode = 0, fullcode = 0;
bool Q5=false;
char cmd[12] = {0};
sprintf(cmd, "H %08X", cardid);
GetWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
PrintAndLog("SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode);
return 1;
}
//see ASKDemod for what args are accepted
int CmdPrescoRead(const char *Cmd) {
// Presco Number: 123456789 --> Sitecode 30 | usercode 8665
// read lf silently
CmdLFRead("s");
// get samples silently
getSamples("30000",false);
// demod and output Presco ID
return CmdPrescoDemod(Cmd);
}
// takes base 12 ID converts to hex
// Or takes 8 digit hex ID
int CmdPrescoClone(const char *Cmd) {
bool Q5 = false;
uint32_t sitecode=0, usercode=0, fullcode=0;
uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4<<T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 5};
// get wiegand from printed number.
if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
if (Q5)
blocks[0] = T5555_MODULATION_MANCHESTER | 32<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
if ((sitecode & 0xFF) != sitecode) {
sitecode &= 0xFF;
PrintAndLog("Facility-Code Truncated to 8-bits (Presco): %u", sitecode);
}
if ((usercode & 0xFFFF) != usercode) {
usercode &= 0xFFFF;
PrintAndLog("Card Number Truncated to 16-bits (Presco): %u", usercode);
}
blocks[1] = 0x10D00000; //preamble
blocks[2] = 0x00000000;
blocks[3] = 0x00000000;
blocks[4] = fullcode;
PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
PrintAndLog("Blk | Data ");
PrintAndLog("----+------------");
PrintAndLog(" 00 | 0x%08x", blocks[0]);
PrintAndLog(" 01 | 0x%08x", blocks[1]);
PrintAndLog(" 02 | 0x%08x", blocks[2]);
PrintAndLog(" 03 | 0x%08x", blocks[3]);
PrintAndLog(" 04 | 0x%08x", blocks[4]);
UsbCommand resp;
UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
for (int i=4; i>=0; i--) {
c.arg[0] = blocks[i];
c.arg[1] = i;
clearCommandBuffer();
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
PrintAndLog("Error occurred, device did not respond during write operation.");
return -1;
}
}
return 0;
}
// takes base 12 ID converts to hex
// Or takes 8 digit hex ID
int CmdPrescoSim(const char *Cmd) {
uint32_t sitecode=0, usercode=0, fullcode=0;
bool Q5=false;
// get wiegand from printed number.
if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_sim();
uint8_t clk = 32, encoding = 1, separator = 1, invert = 0;
uint16_t arg1, arg2;
size_t size = 128;
arg1 = clk << 8 | encoding;
arg2 = invert << 8 | separator;
PrintAndLog("Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode);
UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
GetPrescoBits(fullcode, c.d.asBytes);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"read", CmdPrescoRead, 0, "Attempt to read and Extract tag data"},
{"clone", CmdPrescoClone, 0, "d <9 digit ID> or h <hex> [Q5] clone presco tag"},
{"sim", CmdPrescoSim, 0, "d <9 digit ID> or h <hex> simulate presco tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFPresco(const char *Cmd) {
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

24
client/cmdlfpresco.h Normal file
View file

@ -0,0 +1,24 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency T55xx commands
//-----------------------------------------------------------------------------
#ifndef CMDLFPRESCO_H__
#define CMDLFPRESCO_H__
#include <stdint.h> //uint_32+
#include <stdbool.h> //bool
int CmdLFPresco(const char *Cmd);
int CmdPrescoClone(const char *Cmd);
int CmdPrescoSim(const char *Cmd);
int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5);
int usage_lf_presco_clone(void);
int usage_lf_presco_sim(void);
#endif

199
client/cmdlfpyramid.c Normal file
View file

@ -0,0 +1,199 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency Farpoint / Pyramid tag commands
//-----------------------------------------------------------------------------
#include <string.h>
#include <inttypes.h>
#include "cmdlfpyramid.h"
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdmain.h"
#include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
#include "crc.h"
static int CmdHelp(const char *Cmd);
int usage_lf_pyramid_clone(void){
PrintAndLog("clone a Farpointe/Pyramid tag to a T55x7 tag.");
PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
PrintAndLog("Currently work only on 26bit");
PrintAndLog("");
PrintAndLog("Usage: lf pyramid clone <Facility-Code> <Card-Number>");
PrintAndLog("Options :");
PrintAndLog(" <Facility-Code> : 8-bit value facility code");
PrintAndLog(" <Card Number> : 16-bit value card number");
PrintAndLog(" Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
PrintAndLog("");
PrintAndLog("Sample : lf pyramid clone 123 11223");
return 0;
}
int usage_lf_pyramid_sim(void) {
PrintAndLog("Enables simulation of Farpointe/Pyramid card with specified card number.");
PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.");
PrintAndLog("Currently work only on 26bit");
PrintAndLog("");
PrintAndLog("Usage: lf pyramid sim <Card-Number>");
PrintAndLog("Options :");
PrintAndLog(" <Facility-Code> : 8-bit value facility code");
PrintAndLog(" <Card Number> : 16-bit value card number");
PrintAndLog("");
PrintAndLog("Sample : lf pyramid sim 123 11223");
return 0;
}
// Works for 26bits.
int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) {
uint8_t pre[128];
memset(pre, 0x00, sizeof(pre));
// format start bit
pre[79] = 1;
// Get 26 wiegand from FacilityCode, CardNumber
uint8_t wiegand[24];
memset(wiegand, 0x00, sizeof(wiegand));
num_to_bytebits(fc, 8, wiegand);
num_to_bytebits(cn, 16, wiegand+8);
// add wiegand parity bits (dest, source, len)
wiegand_add_parity(pre+80, wiegand, 24);
// add paritybits (bitsource, dest, sourcelen, paritylen, parityType (odd, even,)
addParity(pre+8, pyramidBits+8, 102, 8, 1);
// add checksum
uint8_t csBuff[13];
for (uint8_t i = 0; i < 13; i++)
csBuff[i] = bytebits_to_byte(pyramidBits + 16 + (i*8), 8);
uint32_t crc = CRC8Maxim(csBuff, 13);
num_to_bytebits(crc, 8, pyramidBits+120);
return 1;
}
int CmdPyramidRead(const char *Cmd) {
CmdLFRead("s");
getSamples("30000",false);
return CmdFSKdemodPyramid("");
}
int CmdPyramidClone(const char *Cmd) {
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_clone();
uint32_t facilitycode=0, cardnumber=0, fc = 0, cn = 0;
uint32_t blocks[5];
uint8_t i;
uint8_t bs[128];
memset(bs, 0x00, sizeof(bs));
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_clone();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
PrintAndLog("Error with tag bitstream generation.");
return 1;
}
//Pyramid - compat mode, FSK2a, data rate 50, 4 data blocks
blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4<<T55x7_MAXBLOCK_SHIFT;
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT;
blocks[1] = bytebits_to_byte(bs,32);
blocks[2] = bytebits_to_byte(bs+32,32);
blocks[3] = bytebits_to_byte(bs+64,32);
blocks[4] = bytebits_to_byte(bs+96,32);
PrintAndLog("Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
PrintAndLog("Blk | Data ");
PrintAndLog("----+------------");
for ( i = 0; i<5; ++i )
PrintAndLog(" %02d | %08" PRIx32, i, blocks[i]);
UsbCommand resp;
UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
for ( i = 0; i<5; ++i ) {
c.arg[0] = blocks[i];
c.arg[1] = i;
clearCommandBuffer();
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
PrintAndLog("Error occurred, device did not respond during write operation.");
return -1;
}
}
return 0;
}
int CmdPyramidSim(const char *Cmd) {
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_sim();
uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
uint8_t bs[128];
size_t size = sizeof(bs);
memset(bs, 0x00, size);
// Pyramid uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0
uint64_t arg1, arg2;
arg1 = (10 << 8) + 8;
arg2 = 50 | 0;
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_sim();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
PrintAndLog("Error with tag bitstream generation.");
return 1;
}
PrintAndLog("Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber );
UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
memcpy(c.d.asBytes, bs, size);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"read", CmdPyramidRead, 0, "Attempt to read and extract tag data"},
{"clone", CmdPyramidClone, 0, "<Facility-Code> <Card Number> clone pyramid tag"},
{"sim", CmdPyramidSim, 0, "<Facility-Code> <Card Number> simulate pyramid tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFPyramid(const char *Cmd) {
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

19
client/cmdlfpyramid.h Normal file
View file

@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency T55xx commands
//-----------------------------------------------------------------------------
#ifndef CMDLFPYRAMID_H__
#define CMDLFPYRAMID_H__
int CmdLFPyramid(const char *Cmd);
int CmdPyramidClone(const char *Cmd);
int CmdPyramidSim(const char *Cmd);
int usage_lf_pyramid_clone(void);
int usage_lf_pyramid_sim(void);
#endif

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,30 @@
#ifndef CMDLFT55XX_H__
#define CMDLFT55XX_H__
typedef struct {
uint32_t bl1;
uint32_t bl2;
uint32_t acl;
uint32_t mfc;
uint32_t cid;
uint32_t year;
uint32_t quarter;
uint32_t icr;
uint32_t lotid;
uint32_t wafer;
uint32_t dw;
} t55x7_tracedata_t;
typedef struct {
uint32_t bl1;
uint32_t bl2;
uint32_t icr;
char lotidc;
uint32_t lotid;
uint32_t wafer;
uint32_t dw;
} t5555_tracedata_t;
typedef struct {
enum {
DEMOD_NRZ = 0x00,
@ -38,15 +62,23 @@ typedef struct {
RF_100 = 0x06,
RF_128 = 0x07,
} bitrate;
bool Q5;
bool ST;
} t55xx_conf_block_t;
t55xx_conf_block_t Get_t55xx_Config();
void Set_t55xx_Config(t55xx_conf_block_t conf);
int CmdLFT55XX(const char *Cmd);
int CmdT55xxBruteForce(const char *Cmd);
int CmdT55xxSetConfig(const char *Cmd);
int CmdT55xxReadBlock(const char *Cmd);
int CmdT55xxWriteBlock(const char *Cmd);
int CmdT55xxReadTrace(const char *Cmd);
int CmdT55xxInfo(const char *Cmd);
int CmdT55xxDetect(const char *Cmd);
int CmdResetRead(const char *Cmd);
int CmdT55xxWipe(const char *Cmd);
char * GetBitRateStr(uint32_t id);
char * GetSaferStr(uint32_t id);
@ -54,13 +86,17 @@ char * GetModulationStr( uint32_t id);
char * GetModelStrFromCID(uint32_t cid);
char * GetSelectedModulationStr( uint8_t id);
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream);
void printT5xxHeader(uint8_t page);
void printT55xxBlock(const char *demodStr);
void printConfiguration( t55xx_conf_block_t b);
int printConfiguration( t55xx_conf_block_t b);
bool DecodeT55xxBlock();
bool tryDetectModulation();
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate);
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5);
int special(const char *Cmd);
int AquireData( uint8_t block );
int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password );
void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat );
void printT5555Trace( t5555_tracedata_t data, uint8_t repeat );
#endif

127
client/cmdlfviking.c Normal file
View file

@ -0,0 +1,127 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency Viking tag commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdmain.h"
#include "cmdlf.h"
#include "cmdlfviking.h"
#include "lfdemod.h"
static int CmdHelp(const char *Cmd);
int usage_lf_viking_clone(void) {
PrintAndLog("clone a Viking AM tag to a T55x7 tag.");
PrintAndLog("Usage: lf viking clone <Card ID - 8 hex digits> <Q5>");
PrintAndLog("Options :");
PrintAndLog(" <Card Number> : 8 digit hex viking card number");
PrintAndLog(" <Q5> : specify write to Q5 (t5555 instead of t55x7)");
PrintAndLog("");
PrintAndLog("Sample : lf viking clone 1A337 Q5");
return 0;
}
int usage_lf_viking_sim(void) {
PrintAndLog("Enables simulation of viking card with specified card number.");
PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLog("Per viking format, the card number is 8 digit hex number. Larger values are truncated.");
PrintAndLog("");
PrintAndLog("Usage: lf viking sim <Card-Number>");
PrintAndLog("Options :");
PrintAndLog(" <Card Number> : 8 digit hex viking card number");
PrintAndLog("");
PrintAndLog("Sample : lf viking sim 1A337");
return 0;
}
uint64_t getVikingBits(uint32_t id) {
//calc checksum
uint8_t checksum = ((id>>24) & 0xFF) ^ ((id>>16) & 0xFF) ^ ((id>>8) & 0xFF) ^ (id & 0xFF) ^ 0xF2 ^ 0xA8;
return ((uint64_t)0xF2 << 56) | ((uint64_t)id << 8) | checksum;
}
//by marshmellow
//see ASKDemod for what args are accepted
int CmdVikingRead(const char *Cmd) {
// read lf silently
CmdLFRead("s");
// get samples silently
getSamples("30000",false);
// demod and output viking ID
return CmdVikingDemod(Cmd);
}
int CmdVikingClone(const char *Cmd) {
uint32_t id = 0;
uint64_t rawID = 0;
bool Q5 = false;
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_viking_clone();
id = param_get32ex(Cmd, 0, 0, 16);
if (id == 0) return usage_lf_viking_clone();
if (param_getchar(Cmd, 1)=='Q' || param_getchar(Cmd, 1)=='q')
Q5 = true;
rawID = getVikingBits(id);
PrintAndLog("Cloning - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF));
UsbCommand c = {CMD_VIKING_CLONE_TAG,{rawID >> 32, rawID & 0xFFFFFFFF, Q5}};
clearCommandBuffer();
SendCommand(&c);
//check for ACK
WaitForResponse(CMD_ACK,NULL);
return 0;
}
int CmdVikingSim(const char *Cmd) {
uint32_t id = 0;
uint64_t rawID = 0;
uint8_t clk = 32, encoding = 1, separator = 0, invert = 0;
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_viking_sim();
id = param_get32ex(Cmd, 0, 0, 16);
if (id == 0) return usage_lf_viking_sim();
rawID = getVikingBits(id);
uint16_t arg1, arg2;
size_t size = 64;
arg1 = clk << 8 | encoding;
arg2 = invert << 8 | separator;
UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
PrintAndLog("preparing to sim ask data: %d bits", size);
num_to_bytebits(rawID, 64, c.d.asBytes);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"read", CmdVikingRead, 0, "Attempt to read and Extract tag data"},
{"clone", CmdVikingClone, 0, "<8 digit ID number> clone viking tag"},
{"sim", CmdVikingSim, 0, "<8 digit ID number> simulate viking tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFViking(const char *Cmd) {
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

16
client/cmdlfviking.h Normal file
View file

@ -0,0 +1,16 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency T55xx commands
//-----------------------------------------------------------------------------
#ifndef CMDLFVIKING_H__
#define CMDLFVIKING_H__
int CmdLFViking(const char *Cmd);
int CmdVikingRead(const char *Cmd);
int CmdVikingClone(const char *Cmd);
int CmdVikingSim(const char *Cmd);
#endif

View file

@ -42,15 +42,15 @@ static int cmd_tail;//Starts as 0
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
{"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
{"hw", CmdHW, 1, "{ Hardware commands... }"},
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
{"script", CmdScript, 1,"{ Scripting commands }"},
{"quit", CmdQuit, 1, "Exit program"},
{"exit", CmdQuit, 1, "Exit program"},
{NULL, NULL, 0, NULL}
{"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
{"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
{"hw", CmdHW, 1, "{ Hardware commands... }"},
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
{"script", CmdScript, 1, "{ Scripting commands }"},
{"quit", CmdQuit, 1, "Exit program"},
{"exit", CmdQuit, 1, "Exit program"},
{NULL, NULL, 0, NULL}
};
command_t* getTopLevelCommandTable()
@ -65,8 +65,7 @@ int CmdHelp(const char *Cmd)
int CmdQuit(const char *Cmd)
{
exit(0);
return 0;
return 99;
}
/**
* @brief This method should be called when sending a new command to the pm3. In case any old
@ -164,8 +163,8 @@ bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
// Entry point into our code: called whenever the user types a command and
// then presses Enter, which the full command line that they typed.
//-----------------------------------------------------------------------------
void CommandReceived(char *Cmd) {
CmdsParse(CommandTable, Cmd);
int CommandReceived(char *Cmd) {
return CmdsParse(CommandTable, Cmd);
}
@ -178,10 +177,11 @@ void UsbCommandReceived(UsbCommand *UC)
switch(UC->cmd) {
// First check if we are handling a debug message
case CMD_DEBUG_PRINT_STRING: {
char s[USB_CMD_DATA_SIZE+1] = {0x00};
char s[USB_CMD_DATA_SIZE+1];
memset(s, 0x00, sizeof(s));
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
memcpy(s,UC->d.asBytes,len);
PrintAndLog("#db# %s ", s);
PrintAndLog("#db# %s", s);
return;
} break;

View file

@ -14,7 +14,7 @@
#include "usb_cmd.h"
#include "cmdparser.h"
void UsbCommandReceived(UsbCommand *UC);
void CommandReceived(char *Cmd);
int CommandReceived(char *Cmd);
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
bool WaitForResponse(uint32_t cmd, UsbCommand* response);
void clearCommandBuffer();

View file

@ -15,6 +15,7 @@
#include "cmdparser.h"
#include "proxmark3.h"
void CmdsHelp(const command_t Commands[])
{
if (Commands[0].Name == NULL)
@ -28,48 +29,51 @@ void CmdsHelp(const command_t Commands[])
}
}
void CmdsParse(const command_t Commands[], const char *Cmd)
int CmdsParse(const command_t Commands[], const char *Cmd)
{
if(strcmp( Cmd, "XX_internal_command_dump_XX") == 0)
{// Help dump children
dumpCommandsRecursive(Commands, 0);
return;
}
if(strcmp( Cmd, "XX_internal_command_dump_markdown_XX") == 0)
{// Markdown help dump children
dumpCommandsRecursive(Commands, 1);
return;
}
char cmd_name[32];
int len = 0;
memset(cmd_name, 0, 32);
sscanf(Cmd, "%31s%n", cmd_name, &len);
int i = 0;
while (Commands[i].Name && strcmp(Commands[i].Name, cmd_name))
++i;
if(strcmp( Cmd, "XX_internal_command_dump_XX") == 0)
{// Help dump children
dumpCommandsRecursive(Commands, 0);
return 0;
}
if(strcmp( Cmd, "XX_internal_command_dump_markdown_XX") == 0)
{// Markdown help dump children
dumpCommandsRecursive(Commands, 1);
return 0;
}
char cmd_name[32];
int len = 0;
memset(cmd_name, 0, 32);
sscanf(Cmd, "%31s%n", cmd_name, &len);
int i = 0;
while (Commands[i].Name && strcmp(Commands[i].Name, cmd_name))
++i;
/* try to find exactly one prefix-match */
if(!Commands[i].Name) {
int last_match = 0;
int matches = 0;
/* try to find exactly one prefix-match */
if(!Commands[i].Name) {
int last_match = 0;
int matches = 0;
for(i=0;Commands[i].Name;i++) {
if( !strncmp(Commands[i].Name, cmd_name, strlen(cmd_name)) ) {
last_match = i;
matches++;
}
}
if(matches == 1) i=last_match;
}
for(i=0;Commands[i].Name;i++) {
if( !strncmp(Commands[i].Name, cmd_name, strlen(cmd_name)) ) {
last_match = i;
matches++;
}
}
if(matches == 1) i=last_match;
}
if (Commands[i].Name) {
while (Cmd[len] == ' ')
++len;
Commands[i].Parse(Cmd + len);
} else {
// show help for selected hierarchy or if command not recognised
CmdsHelp(Commands);
}
if (Commands[i].Name) {
while (Cmd[len] == ' ')
++len;
return Commands[i].Parse(Cmd + len);
} else {
// show help for selected hierarchy or if command not recognised
CmdsHelp(Commands);
}
return 0;
}
char pparent[512] = {0};

View file

@ -24,7 +24,7 @@ typedef struct command_s
// Print help for each command in the command array
void CmdsHelp(const command_t Commands[]);
// Parse a command line
void CmdsParse(const command_t Commands[], const char *Cmd);
int CmdsParse(const command_t Commands[], const char *Cmd);
void dumpCommandsRecursive(const command_t cmds[], int markdown);
#endif

75
client/default_pwd.dic Normal file
View file

@ -0,0 +1,75 @@
# known cloners
# ref. http://www.proxmark.org/forum/viewtopic.php?id=2022
51243648,
000D8787,
# Default pwd, simple:
00000000,
11111111,
22222222,
33333333,
44444444,
55555555,
66666666,
77777777,
88888888,
99999999,
AAAAAAAA,
BBBBBBBB,
CCCCCCCC,
DDDDDDDD,
EEEEEEEE,
FFFFFFFF,
a0a1a2a3,
b0b1b2b3,
aabbccdd,
bbccddee,
ccddeeff,
00000001,
00000002,
0000000a,
0000000b,
01020304,
02030405,
03040506,
04050607,
05060708,
06070809,
0708090A,
08090A0B,
090A0B0C,
0A0B0C0D,
0B0C0D0E,
0C0D0E0F,
01234567,
12345678,
10000000,
20000000,
30000000,
40000000,
50000000,
60000000,
70000000,
80000000,
90000000,
A0000000,
B0000000,
C0000000,
D0000000,
E0000000,
F0000000,
10101010,
01010101,
11223344,
22334455,
33445566,
44556677,
55667788,
66778899,
778899AA,
8899AABB,
99AABBCC,
AABBCCDD,
BBCCDDEE,
CCDDEEFF,
0CB7E7FC, //rfidler?
FABADA11, //china?

View file

@ -91,6 +91,7 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile)
for(uint16_t j = 0; j < num_infiles; j++) {
fclose(infile[j]);
}
free(fpga_config);
return(EXIT_FAILURE);
}
@ -112,7 +113,7 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile)
compressed_fpga_stream.avail_in = i;
compressed_fpga_stream.zalloc = fpga_deflate_malloc;
compressed_fpga_stream.zfree = fpga_deflate_free;
compressed_fpga_stream.opaque = Z_NULL;
ret = deflateInit2(&compressed_fpga_stream,
COMPRESS_LEVEL,
Z_DEFLATED,
@ -187,6 +188,7 @@ int zlib_decompress(FILE *infile, FILE *outfile)
compressed_fpga_stream.avail_out = DECOMPRESS_BUF_SIZE;
compressed_fpga_stream.zalloc = fpga_deflate_malloc;
compressed_fpga_stream.zfree = fpga_deflate_free;
compressed_fpga_stream.opaque = Z_NULL;
ret = inflateInit2(&compressed_fpga_stream, 0);
@ -195,9 +197,9 @@ int zlib_decompress(FILE *infile, FILE *outfile)
compressed_fpga_stream.next_in = inbuf;
uint16_t i = 0;
do {
uint8_t c = fgetc(infile);
int c = fgetc(infile);
if (!feof(infile)) {
inbuf[i++] = c;
inbuf[i++] = c & 0xFF;
compressed_fpga_stream.avail_in++;
} else {
break;

View file

@ -143,9 +143,13 @@ int GetAskClock(const char str[], bool printAns, bool verbose)
PrintAndLog("Failed to copy from graphbuffer");
return -1;
}
int start = DetectASKClock(grph, size, &clock, 20);
bool st = DetectST(grph, &size, &clock);
int start = 0;
if (st == false) {
start = DetectASKClock(grph, size, &clock, 20);
}
// Only print this message if we're not looping something
if (printAns){
if (printAns) {
PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start);
}
return clock;

View file

@ -73,7 +73,7 @@ typedef struct {
#define CMD_INDALA_CLONE_TAG_L 0x0213
#define CMD_T55XX_READ_BLOCK 0x0214
#define CMD_T55XX_WRITE_BLOCK 0x0215
#define CMD_T55XX_READ_TRACE 0x0216
#define CMD_T55XX_RESET_READ 0x0216
#define CMD_PCF7931_READ 0x0217
#define CMD_EM4X_READ_WORD 0x0218
#define CMD_EM4X_WRITE_WORD 0x0219
@ -85,6 +85,8 @@ typedef struct {
#define CMD_ASK_SIM_TAG 0x021F
#define CMD_PSK_SIM_TAG 0x0220
#define CMD_AWID_DEMOD_FSK 0x0221
#define CMD_VIKING_CLONE_TAG 0x0223
#define CMD_T55XX_WAKEUP 0x0224
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
@ -105,6 +107,12 @@ typedef struct {
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
#define CMD_SIMULATE_HITAG_S 0x0368
#define CMD_TEST_HITAGS_TRACES 0x0367
#define CMD_READ_HITAG_S 0x0373
#define CMD_WR_HITAG_S 0x0375
#define CMD_EMU_HITAG_S 0x0376
#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
@ -115,9 +123,17 @@ typedef struct {
#define CMD_WRITER_LEGIC_RF 0x0389
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
#define CMD_ICLASS_READCHECK 0x038F
#define CMD_ICLASS_CLONE 0x0390
#define CMD_ICLASS_DUMP 0x0391
#define CMD_SNOOP_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394
#define CMD_READER_ICLASS_REPLAY 0x0395
#define CMD_ICLASS_READBLOCK 0x0396
#define CMD_ICLASS_WRITEBLOCK 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398
#define CMD_ICLASS_AUTHENTICATION 0x0399
// For measurements of the antenna tuning
#define CMD_MEASURE_ANTENNA_TUNING 0x0400

View file

@ -224,23 +224,44 @@ void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out)
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
{
uint8_t cc_nr[13] = { 0 };
uint8_t div_key[8];
uint8_t div_key[8];
//cc_nr=(uint8_t*)malloc(length+1);
memcpy(cc_nr,cc_nr_p,12);
memcpy(div_key,div_key_p,8);
memcpy(cc_nr, cc_nr_p, 12);
memcpy(div_key, div_key_p, 8);
reverse_arraybytes(cc_nr,12);
BitstreamIn bitstream = {cc_nr,12 * 8,0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key,bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
BitstreamIn bitstream = {cc_nr, 12 * 8, 0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key,bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
//free(cc_nr);
return;
return;
}
void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4])
{
uint8_t *address_data;
uint8_t div_key[8];
address_data = (uint8_t*) malloc(address_data_size);
memcpy(address_data, address_data_p, address_data_size);
memcpy(div_key, div_key_p, 8);
reverse_arraybytes(address_data, address_data_size);
BitstreamIn bitstream = {address_data, address_data_size * 8, 0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key, bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
free(address_data);
return;
}
#ifndef ON_DEVICE
int testMAC()
{

View file

@ -42,6 +42,8 @@
#include <stdint.h>
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
void doMAC_N(uint8_t *address_data_p,uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]);
#ifndef ON_DEVICE
int testMAC();
#endif

View file

@ -171,6 +171,7 @@ void printarr(char * name, uint8_t* arr, int len)
}
cx += snprintf(output+cx,outsize-cx,"};");
prnlog(output);
free(output);
}
void printvar(char * name, uint8_t* arr, int len)
@ -188,6 +189,7 @@ void printvar(char * name, uint8_t* arr, int len)
}
prnlog(output);
free(output);
}
void printarr_human_readable(char * title, uint8_t* arr, int len)

View file

@ -522,8 +522,8 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[])
errors += bruteforceItem(*attack, keytable);
}
free(attack);
clock_t t2 = clock();
float diff = (((float)t2 - (float)t1) / CLOCKS_PER_SEC );
t1 = clock() - t1;
float diff = ((float)t1 / CLOCKS_PER_SEC );
prnlog("\nPerformed full crack in %f seconds",diff);
// Pick out the first 16 bytes of the keytable.
@ -563,15 +563,23 @@ int bruteforceFile(const char *filename, uint16_t keytable[])
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
if (fsize < 0) {
prnlog("Error, when getting fsize");
fclose(f);
return 1;
}
uint8_t *dump = malloc(fsize);
size_t bytes_read = fread(dump, 1, fsize, f);
fclose(f);
if (bytes_read < fsize)
{
prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
}
return bruteforceDump(dump,fsize,keytable);
if (bytes_read < fsize) {
prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
}
uint8_t res = bruteforceDump(dump,fsize,keytable);
free(dump);
return res;
}
/**
*

View file

@ -69,7 +69,7 @@ int showHelp()
prnlog("-h Show this help");
prnlog("-f <filename> Bruteforce iclass dumpfile");
prnlog(" An iclass dumpfile is assumed to consist of an arbitrary number of malicious CSNs, and their protocol responses");
prnlog(" The the binary format of the file is expected to be as follows: ");
prnlog(" The binary format of the file is expected to be as follows: ");
prnlog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
prnlog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
prnlog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");

View file

@ -44,7 +44,7 @@ local _commands = {
CMD_INDALA_CLONE_TAG_L = 0x0213,
CMD_T55XX_READ_BLOCK = 0x0214,
CMD_T55XX_WRITE_BLOCK = 0x0215,
CMD_T55XX_READ_TRACE = 0x0216,
CMD_T55XX_RESET_READ = 0x0216,
CMD_PCF7931_READ = 0x0217,
CMD_EM4X_READ_WORD = 0x0218,
CMD_EM4X_WRITE_WORD = 0x0219,
@ -56,7 +56,8 @@ local _commands = {
CMD_ASK_SIM_TAG = 0x021F,
CMD_PSK_SIM_TAG = 0x0220,
CMD_AWID_DEMOD_FSK = 0x0221,
CMD_VIKING_CLONE_TAG = 0x0223,
CMD_T55XX_WAKEUP = 0x0224,
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
--// For the 13.56 MHz tags
@ -88,11 +89,17 @@ local _commands = {
CMD_EPA_PACE_COLLECT_NONCE = 0x038A,
--//CMD_EPA_ = 0x038B,
CMD_ICLASS_READCHECK = 0x038F,
CMD_ICLASS_CLONE = 0x0390,
CMD_ICLASS_DUMP = 0x0391,
CMD_SNOOP_ICLASS = 0x0392,
CMD_SIMULATE_TAG_ICLASS = 0x0393,
CMD_READER_ICLASS = 0x0394,
CMD_READER_ICLASS_REPLAY = 0x0395,
CMD_ICLASS_ISO14443A_WRITE = 0x0397,
CMD_READER_ICLASS_REPLAY = 0x0395,
CMD_ICLASS_READBLOCK = 0x0396,
CMD_ICLASS_WRITEBLOCK = 0x0397,
CMD_ICLASS_EML_MEMSET = 0x0398,
CMD_ICLASS_AUTHENTICATION = 0x0399,
--// For measurements of the antenna tuning
CMD_MEASURE_ANTENNA_TUNING = 0x0400,

View file

@ -106,7 +106,7 @@ local _keys = {
'776974687573', -- RKF ÖstgötaTrafiken Key B
--[[
The keys below are taken from from https://code.google.com/p/mifare-key-cracker/downloads/list
The keys below are taken from https://code.google.com/p/mifare-key-cracker/downloads/list
--]]
'bd493a3962b6',
@ -129,7 +129,7 @@ local _keys = {
'123456789abc',
--[[
The keys below are taken from from https://github.com/4ZM/mfterm/blob/master/dictionary.txt
The keys below are taken from https://github.com/4ZM/mfterm/blob/master/dictionary.txt
--]]
'abcdef123456', -- Key from ladyada.net
@ -199,7 +199,7 @@ local function uniq(list)
table.insert(foobar, value);
end
end
--print("final list length length ", #foobar)
--print("final list length ", #foobar)
return foobar
end

View file

@ -619,3 +619,23 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
return 0;
}
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){
/*
uint32_t nt; // tag challenge
uint32_t ar_enc; // encrypted reader response
uint32_t at_enc; // encrypted tag response
*/
if (traceCrypto1) {
crypto1_destroy(traceCrypto1);
}
ks2 = ar_enc ^ prng_successor(nt, 64);
ks3 = at_enc ^ prng_successor(nt, 96);
traceCrypto1 = lfsr_recovery64(ks2, ks3);
mf_crypto1_decrypt(traceCrypto1, data, len, 0);
PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) );
crypto1_destroy(traceCrypto1);
return 0;
}

View file

@ -67,3 +67,4 @@ int isBlockEmpty(int blockN);
int isBlockTrailer(int blockN);
int loadTraceCard(uint8_t *tuid);
int saveTraceCard(void);
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);

View file

@ -149,3 +149,140 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_
return 1;
}
// 32 bit recover key from 2 nonces
bool mfkey32(nonces_t data, uint64_t *outputkey) {
struct Crypto1State *s,*t;
uint64_t outkey = 0;
uint64_t key=0; // recovered key
uint32_t uid = data.cuid;
uint32_t nt = data.nonce; // first tag challenge (nonce)
uint32_t nr0_enc = data.nr; // first encrypted reader challenge
uint32_t ar0_enc = data.ar; // first encrypted reader response
uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
uint32_t ar1_enc = data.ar2; // second encrypted reader response
clock_t t1 = clock();
bool isSuccess = FALSE;
uint8_t counter=0;
s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
for(t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
lfsr_rollback_word(t, nr0_enc, 1);
lfsr_rollback_word(t, uid ^ nt, 0);
crypto1_get_lfsr(t, &key);
crypto1_word(t, uid ^ nt, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
//PrintAndLog("Found Key: [%012"llx"]",key);
outkey = key;
counter++;
if (counter==20) break;
}
}
isSuccess = (counter == 1);
t1 = clock() - t1;
//if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.0f ticks \nFound %d possible keys", (float)t1, counter);
*outputkey = ( isSuccess ) ? outkey : 0;
crypto1_destroy(s);
/* //un-comment to save all keys to a stats.txt file
FILE *fout;
if ((fout = fopen("stats.txt","ab")) == NULL) {
PrintAndLog("Could not create file name stats.txt");
return 1;
}
fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
fclose(fout);
*/
return isSuccess;
}
bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey) {
struct Crypto1State *s, *t;
uint64_t outkey = 0;
uint64_t key = 0; // recovered key
uint32_t uid = data.cuid;
uint32_t nt0 = data.nonce; // first tag challenge (nonce)
uint32_t nr0_enc = data.nr; // first encrypted reader challenge
uint32_t ar0_enc = data.ar; // first encrypted reader response
uint32_t nt1 = data.nonce2; // second tag challenge (nonce)
uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
uint32_t ar1_enc = data.ar2; // second encrypted reader response
bool isSuccess = FALSE;
int counter = 0;
//PrintAndLog("Enter mfkey32_moebius");
clock_t t1 = clock();
s = lfsr_recovery32(ar0_enc ^ prng_successor(nt0, 64), 0);
for(t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
lfsr_rollback_word(t, nr0_enc, 1);
lfsr_rollback_word(t, uid ^ nt0, 0);
crypto1_get_lfsr(t, &key);
crypto1_word(t, uid ^ nt1, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt1, 64))) {
//PrintAndLog("Found Key: [%012"llx"]",key);
outkey=key;
++counter;
if (counter==20)
break;
}
}
isSuccess = (counter == 1);
t1 = clock() - t1;
//if ( t1 > 0 ) PrintAndLog("Time in mfkey32_moebius: %.0f ticks \nFound %d possible keys", (float)t1,counter);
*outputkey = ( isSuccess ) ? outkey : 0;
crypto1_destroy(s);
/* // un-comment to output all keys to stats.txt
FILE *fout;
if ((fout = fopen("stats.txt","ab")) == NULL) {
PrintAndLog("Could not create file name stats.txt");
return 1;
}
fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
fclose(fout);
*/
return isSuccess;
}
int tryMfk64_ex(uint8_t *data, uint64_t *outputkey){
uint32_t uid = le32toh(data);
uint32_t nt = le32toh(data+4); // tag challenge
uint32_t nr_enc = le32toh(data+8); // encrypted reader challenge
uint32_t ar_enc = le32toh(data+12); // encrypted reader response
uint32_t at_enc = le32toh(data+16); // encrypted tag response
return tryMfk64(uid, nt, nr_enc, ar_enc, at_enc, outputkey);
}
int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey){
uint64_t key = 0; // recovered key
uint32_t ks2; // keystream used to encrypt reader response
uint32_t ks3; // keystream used to encrypt tag response
struct Crypto1State *revstate;
PrintAndLog("Enter mfkey64");
clock_t t1 = clock();
// Extract the keystream from the messages
ks2 = ar_enc ^ prng_successor(nt, 64);
ks3 = at_enc ^ prng_successor(nt, 96);
revstate = lfsr_recovery64(ks2, ks3);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, nr_enc, 1);
lfsr_rollback_word(revstate, uid ^ nt, 0);
crypto1_get_lfsr(revstate, &key);
PrintAndLog("Found Key: [%012"llx"]", key);
crypto1_destroy(revstate);
*outputkey = key;
t1 = clock() - t1;
if ( t1 > 0 ) PrintAndLog("Time in mfkey64: %.0f ticks \n", (float)t1);
return 0;
}

View file

@ -17,7 +17,26 @@
#include <stdlib.h>
#include "crapto1.h"
#include "common.h"
//#include <stdbool.h> //for bool
typedef struct {
uint32_t cuid;
uint8_t sector;
uint8_t keytype;
uint32_t nonce;
uint32_t ar;
uint32_t nr;
uint32_t nonce2;
uint32_t ar2;
uint32_t nr2;
} nonces_t;
int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key);
bool mfkey32(nonces_t data, uint64_t *outputkey);
bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey);
int tryMfk64_ex(uint8_t *data, uint64_t *outputkey);
int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey);
//uint64_t mfkey32(uint32_t uid, uint32_t nt, uint32_t nr0_enc, uint32_t ar0_enc, uint32_t nr1_enc, uint32_t ar1_enc);
#endif

View file

@ -19,7 +19,7 @@ void MainGraphics(void);
void InitGraphics(int argc, char **argv);
void ExitGraphics(void);
#define MAX_GRAPH_TRACE_LEN (1024*128)
#define MAX_GRAPH_TRACE_LEN (40000*8)
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
extern int GraphTraceLen;
extern double CursorScaleFactor;

View file

@ -155,12 +155,11 @@ static void *main_loop(void *targ) {
cmd[strlen(cmd) - 1] = 0x00;
if (cmd[0] != 0x00) {
if (strncmp(cmd, "quit", 4) == 0) {
exit(0);
int ret = CommandReceived(cmd);
add_history(cmd);
if (ret == 99) { // exit or quit
break;
}
CommandReceived(cmd);
add_history(cmd);
}
free(cmd);
} else {
@ -223,7 +222,7 @@ int main(int argc, char* argv[]) {
.usb_present = 0,
.script_cmds_file = NULL
};
pthread_t main_loop_t;
pthread_t main_loop_threat;
sp = uart_open(argv[1]);
@ -258,18 +257,20 @@ int main(int argc, char* argv[]) {
// create a mutex to avoid interlacing print commands from our different threads
pthread_mutex_init(&print_lock, NULL);
pthread_create(&main_loop_t, NULL, &main_loop, &marg);
pthread_create(&main_loop_threat, NULL, &main_loop, &marg);
InitGraphics(argc, argv);
MainGraphics();
pthread_join(main_loop_t, NULL);
pthread_join(main_loop_threat, NULL);
// Clean up the port
uart_close(sp);
if (offline == 0) {
uart_close(sp);
}
// clean up mutex
pthread_mutex_destroy(&print_lock);
return 0;
exit(0);
}

View file

@ -16,6 +16,7 @@
#include <inttypes.h>
#define llx PRIx64
#define lli PRIi64
#define llu PRIu64
#define hhu PRIu8
#include "usb_cmd.h"

View file

@ -18,6 +18,7 @@
#include "util.h"
#include "nonce2key/nonce2key.h"
#include "../common/iso15693tools.h"
#include "iso14443crc.h"
#include "../common/crc16.h"
#include "../common/crc64.h"
#include "../common/sha1.h"
@ -228,6 +229,27 @@ static int l_iso15693_crc(lua_State *L)
return 1;
}
static int l_iso14443b_crc(lua_State *L)
{
/* void ComputeCrc14443(int CrcType,
const unsigned char *Data, int Length,
unsigned char *TransmitFirst,
unsigned char *TransmitSecond)
*/
unsigned char buf[USB_CMD_DATA_SIZE];
size_t len = 0;
const char *data = luaL_checklstring(L, 1, &len);
if (USB_CMD_DATA_SIZE < len)
len = USB_CMD_DATA_SIZE-2;
for (int i = 0; i < len; i += 2) {
sscanf(&data[i], "%02x", (unsigned int *)&buf[i / 2]);
}
ComputeCrc14443(CRC_14443_B, buf, len, &buf[len], &buf[len+1]);
lua_pushlstring(L, (const char *)&buf, len+2);
return 1;
}
/*
Simple AES 128 cbc hook up to OpenSSL.
params: key, input
@ -426,6 +448,7 @@ int set_pm3_libraries(lua_State *L)
{"clearCommandBuffer", l_clearCommandBuffer},
{"console", l_CmdConsole},
{"iso15693_crc", l_iso15693_crc},
{"iso14443b_crc", l_iso14443b_crc},
{"aes128_decrypt", l_aes128decrypt_cbc},
{"aes128_decrypt_ecb", l_aes128decrypt_ecb},
{"aes128_encrypt", l_aes128encrypt_cbc},

View file

@ -112,6 +112,8 @@ function mfcrack_inner()
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 == 0xFFFFFFFC then
return nil, "The card's random number generator behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK ~= 1 then
return nil, "Error occurred"
end

View file

@ -9,11 +9,13 @@
//-----------------------------------------------------------------------------
#include "util.h"
#define MAX_BIN_BREAK_LENGTH (3072+384+1)
#ifndef _WIN32
#include <termios.h>
#include <sys/ioctl.h>
int ukbhit(void)
{
int cnt = 0;
@ -21,7 +23,7 @@ int ukbhit(void)
static struct termios Otty, Ntty;
tcgetattr( 0, &Otty);
if ( tcgetattr( 0, &Otty) == -1 ) return -1;
Ntty = Otty;
Ntty.c_iflag = 0; /* input mode */
@ -92,7 +94,7 @@ void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext, int byteCount)
memset(fileName, 0x00, 200);
for (int j = 0; j < byteCount; j++, fnameptr += 2)
sprintf(fnameptr, "%02x", uid[j]);
sprintf(fnameptr, "%02x", (unsigned int) uid[j]);
sprintf(fnameptr, "%s", ext);
}
@ -117,22 +119,37 @@ char *sprint_hex(const uint8_t *data, const size_t len) {
size_t i;
for (i=0; i < maxLen; ++i, tmp += 3)
sprintf(tmp, "%02x ", data[i]);
sprintf(tmp, "%02x ", (unsigned int) data[i]);
return buf;
}
char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) {
int maxLen = ( len > 1020) ? 1020 : len;
static char buf[1024];
memset(buf, 0x00, 1024);
// make sure we don't go beyond our char array memory
int max_len;
if (breaks==0)
max_len = ( len > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len;
else
max_len = ( len+(len/breaks) > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len+(len/breaks);
static char buf[MAX_BIN_BREAK_LENGTH]; // 3072 + end of line characters if broken at 8 bits
//clear memory
memset(buf, 0x00, sizeof(buf));
char *tmp = buf;
for (size_t i=0; i < maxLen; ++i){
sprintf(tmp++, "%u", data[i]);
if (breaks > 0 && !((i+1) % breaks))
size_t in_index = 0;
// loop through the out_index to make sure we don't go too far
for (size_t out_index=0; out_index < max_len; out_index++) {
// set character - (should be binary but verify it isn't more than 1 digit)
if (data[in_index]<10)
sprintf(tmp++, "%u", (unsigned int) data[in_index]);
// check if a line break is needed and we have room to print it in our array
if ( (breaks > 0) && !((in_index+1) % breaks) && (out_index+1 != max_len) ) {
// increment and print line break
out_index++;
sprintf(tmp++, "%s","\n");
}
in_index++;
}
return buf;
@ -160,6 +177,13 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
return num;
}
void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) {
while (len--) {
dest[len] = n & 1;
n >>= 1;
}
}
// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
// to
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
@ -191,7 +215,7 @@ char * printBits(size_t const size, void const * const ptr)
{
byte = b[i] & (1<<j);
byte >>= j;
sprintf(tmp, "%u", byte);
sprintf(tmp, "%u", (unsigned int)byte);
tmp++;
}
}
@ -248,7 +272,7 @@ char param_getchar(const char *line, int paramnum)
uint8_t param_get8(const char *line, int paramnum)
{
return param_get8ex(line, paramnum, 10, 0);
return param_get8ex(line, paramnum, 0, 10);
}
/**
@ -333,7 +357,28 @@ int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
return 0;
}
int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt)
{
int bg, en, temp, i;
//if (hexcnt % 2)
// return 1;
if (param_getptr(line, &bg, &en, paramnum)) return 1;
*hexcnt = en - bg + 1;
if (*hexcnt % 2) //error if not complete hex bytes
return 1;
for(i = 0; i < *hexcnt; i += 2) {
if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) ) return 1;
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
data[i / 2] = temp & 0xff;
}
return 0;
}
int param_getstr(const char *line, int paramnum, char * str)
{
int bg, en;
@ -406,7 +451,7 @@ int binarraytohex(char *target,char *source, int length)
{
for(i= x= 0 ; i < 4 ; ++i)
x += ( source[i] << (3 - i));
sprintf(target,"%X", x);
sprintf(target,"%X", (unsigned int)x);
++target;
source += 4;
j -= 4;
@ -425,7 +470,7 @@ void binarraytobinstring(char *target, char *source, int length)
}
// return parity bit required to match type
uint8_t GetParity( char *bits, uint8_t type, int length)
uint8_t GetParity( uint8_t *bits, uint8_t type, int length)
{
int x;
@ -437,7 +482,7 @@ uint8_t GetParity( char *bits, uint8_t type, int length)
}
// add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
void wiegand_add_parity(char *target, char *source, char length)
void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
{
*(target++)= GetParity(source, EVEN, length / 2);
memcpy(target, source, length);
@ -453,3 +498,16 @@ void xor(unsigned char *dst, unsigned char *src, size_t len) {
int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0];
}
uint32_t le32toh (uint8_t *data) {
return (uint32_t)( (data[3]<<24) | (data[2]<<16) | (data[1]<<8) | data[0]);
}
// RotateLeft - Ultralight, Desfire, works on byte level
// 00-01-02 >> 01-02-00
void rol(uint8_t *data, const size_t len){
uint8_t first = data[0];
for (size_t i = 0; i < len-1; i++) {
data[i] = data[i+1];
}
data[len-1] = first;
}

View file

@ -9,14 +9,16 @@
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdint.h> //included in data.h
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "data.h"
#include "data.h" //for FILE_PATH_SIZE
#ifndef ROTR
# define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n))))
#endif
#ifndef MIN
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
@ -43,6 +45,7 @@ char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t bre
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);
void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest);
char * printBits(size_t const size, void const * const ptr);
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
@ -55,14 +58,17 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
uint8_t param_isdec(const char *line, int paramnum);
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt);
int param_getstr(const char *line, int paramnum, char * str);
int hextobinarray( char *target, char *source);
int hextobinstring( char *target, char *source);
int binarraytohex( char *target, char *source, int length);
void binarraytobinstring(char *target, char *source, int length);
uint8_t GetParity( char *string, uint8_t type, int length);
void wiegand_add_parity(char *target, char *source, char length);
uint8_t GetParity( uint8_t *string, uint8_t type, int length);
void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length);
void xor(unsigned char *dst, unsigned char *src, size_t len);
int32_t le24toh(uint8_t data[3]);
uint32_t le32toh (uint8_t *data);
void rol(uint8_t *data, const size_t len);

View file

@ -67,7 +67,7 @@ VPATH = . ../common ../fpga ../zlib
INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES)
CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os
CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 -Os $(APP_CFLAGS)
LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
LIBS = -lgcc

View file

@ -26,7 +26,7 @@ typedef struct crc {
* final_xor is XORed onto the state before returning it from crc_result(). */
extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor);
/* Update the crc state. data is the data of length data_width bits (only the the
/* Update the crc state. data is the data of length data_width bits (only the
* data_width lower-most bits are used).
*/
extern void crc_update(crc_t *crc, uint32_t data, int data_width);

View file

@ -2,7 +2,7 @@
/* This is the default version.c file that Makefile.common falls back to if perl is not available */
const struct version_information __attribute__((section(".version_information"))) version_information = {
VERSION_INFORMATION_MAGIC,
1, /* version version 1 */
1, /* version 1 */
0, /* version information not present */
2, /* cleanliness couldn't be determined */
/* Remaining fields: zero */

File diff suppressed because it is too large Load diff

View file

@ -13,9 +13,11 @@
#ifndef LFDEMOD_H__
#define LFDEMOD_H__
#include <stdint.h>
#include <stdint.h> // for uint_32+
#include <stdbool.h> // for bool
//generic
size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType);
int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType);
int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
@ -27,12 +29,13 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t f
int DetectNRZClock(uint8_t dest[], size_t size, int clock);
int DetectPSKClock(uint8_t dest[], size_t size, int clock);
int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
bool DetectST(uint8_t buffer[], size_t *size, int *foundclock);
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
uint32_t manchesterEncode2Bytes(uint16_t datain);
int ManchesterEncode(uint8_t *BitStream, size_t size);
int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert);
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr);
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert);
uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
@ -41,13 +44,15 @@ void psk1TOpsk2(uint8_t *BitStream, size_t size);
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
//tag specific
int FDXBdemodBI(uint8_t *dest, size_t *size);
int AWIDdemodFSK(uint8_t *dest, size_t *size);
uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
int FDXBdemodBI(uint8_t *dest, size_t *size);
int gProxII_Demod(uint8_t BitStream[], size_t *size);
int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
int IOdemodFSK(uint8_t *dest, size_t size);
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
int PyramiddemodFSK(uint8_t *dest, size_t *size);
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
int PyramiddemodFSK(uint8_t *dest, size_t *size);
int VikingDemod_AM(uint8_t *dest, size_t *size);
int PrescoDemod(uint8_t *dest, size_t *size);
#endif

View file

@ -1,25 +1,46 @@
#include <strings.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include "protocols.h"
// ATA55xx shared presets & routines
uint32_t GetT55xxClockBit(uint32_t clock) {
switch (clock) {
case 128:
return T55x7_BITRATE_RF_128;
case 100:
return T55x7_BITRATE_RF_100;
case 64:
return T55x7_BITRATE_RF_64;
case 50:
return T55x7_BITRATE_RF_50;
case 40:
return T55x7_BITRATE_RF_40;
case 32:
return T55x7_BITRATE_RF_32;
case 16:
return T55x7_BITRATE_RF_16;
case 8:
return T55x7_BITRATE_RF_8;
default:
return 0;
}
}
#ifndef ON_DEVICE
#include "ui.h"
#define prnt PrintAndLog
#endif
// iclass / picopass chip config structures and shared routines
typedef struct {
uint8_t app_limit;
uint8_t otp[2];
uint8_t block_writelock;
uint8_t chip_config;
uint8_t mem_config;
uint8_t eas;
uint8_t fuses;
}picopass_conf_block;
uint8_t app_limit; //[8]
uint8_t otp[2]; //[9-10]
uint8_t block_writelock;//[11]
uint8_t chip_config; //[12]
uint8_t mem_config; //[13]
uint8_t eas; //[14]
uint8_t fuses; //[15]
} picopass_conf_block;
typedef struct {
uint8_t csn[8];
@ -28,32 +49,17 @@ typedef struct {
uint8_t key_d[8];
uint8_t key_c[8];
uint8_t app_issuer_area[8];
} picopass_hdr;
}picopass_hdr;
//#define prnt printf
/*void prnt(char *fmt,...)
{
va_list argptr;
va_start(argptr, fmt);
vprintf(fmt, argptr);
printf(" "); // cleaning prompt
va_end(argptr);
printf("\n");
}
*/
uint8_t isset(uint8_t val, uint8_t mask)
{
uint8_t isset(uint8_t val, uint8_t mask) {
return (val & mask);
}
uint8_t notset(uint8_t val, uint8_t mask){
uint8_t notset(uint8_t val, uint8_t mask) {
return !(val & mask);
}
void fuse_config(const picopass_hdr *hdr)
{
void fuse_config(const picopass_hdr *hdr) {
uint8_t fuses = hdr->conf.fuses;
if (isset(fuses,FUSE_FPERS))prnt(" Mode: Personalization [Programmable]");
@ -74,42 +80,68 @@ void fuse_config(const picopass_hdr *hdr)
if( isset( fuses, FUSE_RA)) prnt(" RA: Read access enabled");
else prnt(" RA: Read access not enabled");
}
void mem_config(const picopass_hdr *hdr)
{
uint8_t mem = hdr->conf.mem_config;
if( isset (mem, 0x80)) prnt(" Mem: 16KBits (255 * 8 bytes)");
else prnt(" Mem: 2 KBits ( 32 * 8 bytes)");
void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) {
// mem-bit 5, mem-bit 7, chip-bit 4: defines chip type
if(isset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
*kb = 2;
*app_areas = 2;
*max_blk = 31;
} else if(isset(chip_cfg, 0x10) && isset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
*kb = 16;
*app_areas = 2;
*max_blk = 255; //16kb
} else if(notset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && notset(mem_cfg, 0x20)) {
*kb = 16;
*app_areas = 16;
*max_blk = 255; //16kb
} else if(isset(chip_cfg, 0x10) && isset(mem_cfg, 0x80) && isset(mem_cfg, 0x20)) {
*kb = 32;
*app_areas = 3;
*max_blk = 255; //16kb
} else if(notset(chip_cfg, 0x10) && notset(mem_cfg, 0x80) && isset(mem_cfg, 0x20)) {
*kb = 32;
*app_areas = 17;
*max_blk = 255; //16kb
} else {
*kb = 32;
*app_areas = 2;
*max_blk = 255;
}
}
void applimit_config(const picopass_hdr *hdr)
{
void mem_app_config(const picopass_hdr *hdr) {
uint8_t mem = hdr->conf.mem_config;
uint8_t chip = hdr->conf.chip_config;
uint8_t applimit = hdr->conf.app_limit;
prnt(" AA1: blocks 6-%d", applimit);
prnt(" AA2: blocks %d-", (applimit+1));
if (applimit < 6) applimit = 26;
uint8_t kb = 2;
uint8_t app_areas = 2;
uint8_t max_blk = 31;
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
prnt(" Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem);
prnt(" AA1: blocks 06-%02X", applimit);
prnt(" AA2: blocks %02X-%02X", applimit+1, max_blk);
}
void print_picopass_info(const picopass_hdr *hdr)
{
void print_picopass_info(const picopass_hdr *hdr) {
fuse_config(hdr);
mem_config(hdr);
applimit_config(hdr);
mem_app_config(hdr);
}
void printIclassDumpInfo(uint8_t* iclass_dump)
{
// picopass_hdr hdr;
// memcpy(&hdr, iclass_dump, sizeof(picopass_hdr));
void printIclassDumpInfo(uint8_t* iclass_dump) {
print_picopass_info((picopass_hdr *) iclass_dump);
}
/*
void test()
{
void test() {
picopass_hdr hdr = {0x27,0xaf,0x48,0x01,0xf9,0xff,0x12,0xe0,0x12,0xff,0xff,0xff,0x7f,0x1f,0xff,0x3c};
prnt("Picopass configuration:");
print_picopass_info(&hdr);
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
test();
return 0;
}
*/
#endif
//ON_DEVICE

View file

@ -99,7 +99,7 @@ NXP/Philips CUSTOM COMMANDS
#define ICLASS_CMD_CHECK 0x05
#define ICLASS_CMD_DETECT 0x0F
#define ICLASS_CMD_HALT 0x00
#define ICLASS_CMD_UPDATE 0x87
#define ICLASS_CMD_UPDATE 0x87
#define ICLASS_CMD_ACT 0x8E
#define ICLASS_CMD_READ4 0x06
@ -109,20 +109,25 @@ NXP/Philips CUSTOM COMMANDS
#define ISO14443A_CMD_WUPA 0x52
#define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93
#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95
#define ISO14443A_CMD_ANTICOLL_OR_SELECT_3 0x97
#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
#define ISO14443A_CMD_HALT 0x50
#define ISO14443A_CMD_RATS 0xE0
#define MIFARE_AUTH_KEYA 0x60
#define MIFARE_AUTH_KEYB 0x61
#define MIFARE_MAGICWUPC1 0x40
#define MIFARE_MAGICWUPC2 0x43
#define MIFARE_MAGICWIPEC 0x41
#define MIFARE_AUTH_KEYA 0x60
#define MIFARE_AUTH_KEYB 0x61
#define MIFARE_MAGICWUPC1 0x40
#define MIFARE_MAGICWUPC2 0x43
#define MIFARE_MAGICWIPEC 0x41
#define MIFARE_CMD_INC 0xC0
#define MIFARE_CMD_DEC 0xC1
#define MIFARE_CMD_RESTORE 0xC2
#define MIFARE_CMD_TRANSFER 0xB0
#define MIFARE_EV1_PERSONAL_UID 0x40
#define MIFARE_EV1_SETMODE 0x43
#define MIFARE_ULC_WRITE 0xA2
//#define MIFARE_ULC__COMP_WRITE 0xA0
#define MIFARE_ULC_AUTH_1 0x1A
@ -180,9 +185,25 @@ NXP/Philips CUSTOM COMMANDS
#define ISO15693_READ_MULTI_SECSTATUS 0x2C
#define ISO_14443A 0
#define ICLASS 1
#define ISO_14443B 2
// Topaz command set:
#define TOPAZ_REQA 0x26 // Request
#define TOPAZ_WUPA 0x52 // WakeUp
#define TOPAZ_RID 0x78 // Read ID
#define TOPAZ_RALL 0x00 // Read All (all bytes)
#define TOPAZ_READ 0x01 // Read (a single byte)
#define TOPAZ_WRITE_E 0x53 // Write-with-erase (a single byte)
#define TOPAZ_WRITE_NE 0x1a // Write-no-erase (a single byte)
// additional commands for Dynamic Memory Model
#define TOPAZ_RSEG 0x10 // Read segment
#define TOPAZ_READ8 0x02 // Read (eight bytes)
#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes)
#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes)
#define ISO_14443A 0
#define ICLASS 1
#define ISO_14443B 2
#define TOPAZ 3
//-- Picopass fuses
#define FUSE_FPERS 0x80
@ -194,7 +215,60 @@ NXP/Philips CUSTOM COMMANDS
#define FUSE_FPROD0 0x02
#define FUSE_RA 0x01
void printIclassDumpInfo(uint8_t* iclass_dump);
void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb);
#endif // PROTOCOLS_H
/* T55x7 configuration register definitions */
#define T55x7_POR_DELAY 0x00000001
#define T55x7_ST_TERMINATOR 0x00000008
#define T55x7_PWD 0x00000010
#define T55x7_MAXBLOCK_SHIFT 5
#define T55x7_AOR 0x00000200
#define T55x7_PSKCF_RF_2 0
#define T55x7_PSKCF_RF_4 0x00000400
#define T55x7_PSKCF_RF_8 0x00000800
#define T55x7_MODULATION_DIRECT 0
#define T55x7_MODULATION_PSK1 0x00001000
#define T55x7_MODULATION_PSK2 0x00002000
#define T55x7_MODULATION_PSK3 0x00003000
#define T55x7_MODULATION_FSK1 0x00004000
#define T55x7_MODULATION_FSK2 0x00005000
#define T55x7_MODULATION_FSK1a 0x00006000
#define T55x7_MODULATION_FSK2a 0x00007000
#define T55x7_MODULATION_MANCHESTER 0x00008000
#define T55x7_MODULATION_BIPHASE 0x00010000
#define T55x7_MODULATION_DIPHASE 0x00018000
#define T55x7_BITRATE_RF_8 0
#define T55x7_BITRATE_RF_16 0x00040000
#define T55x7_BITRATE_RF_32 0x00080000
#define T55x7_BITRATE_RF_40 0x000C0000
#define T55x7_BITRATE_RF_50 0x00100000
#define T55x7_BITRATE_RF_64 0x00140000
#define T55x7_BITRATE_RF_100 0x00180000
#define T55x7_BITRATE_RF_128 0x001C0000
/* T5555 (Q5) configuration register definitions */
#define T5555_ST_TERMINATOR 0x00000001
#define T5555_MAXBLOCK_SHIFT 0x00000001
#define T5555_MODULATION_MANCHESTER 0
#define T5555_MODULATION_PSK1 0x00000010
#define T5555_MODULATION_PSK2 0x00000020
#define T5555_MODULATION_PSK3 0x00000030
#define T5555_MODULATION_FSK1 0x00000040
#define T5555_MODULATION_FSK2 0x00000050
#define T5555_MODULATION_BIPHASE 0x00000060
#define T5555_MODULATION_DIRECT 0x00000070
#define T5555_INVERT_OUTPUT 0x00000080
#define T5555_PSK_RF_2 0
#define T5555_PSK_RF_4 0x00000100
#define T5555_PSK_RF_8 0x00000200
#define T5555_USE_PWD 0x00000400
#define T5555_USE_AOR 0x00000800
#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2
#define T5555_FAST_WRITE 0x00004000
#define T5555_PAGE_SELECT 0x00008000
uint32_t GetT55xxClockBit(uint32_t clock);
#endif
// PROTOCOLS_H

View file

@ -362,7 +362,7 @@ uint32_t usb_write(const byte_t* data, const size_t len) {
cpt = MIN(length, AT91C_EP_IN_SIZE-1);
length -= cpt;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
// Wait for the the first bank to be sent
// Wait for the first bank to be sent
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
if (!usb_check()) return length;
}

View file

@ -5,7 +5,7 @@ clean:
$(DELETE) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp
$(DELETE) *.map *.ngc *.xrpt *.pcf *.rbt *_auto_* *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst xst
fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v
fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v
$(DELETE) $@
$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr

Binary file not shown.

View file

@ -17,6 +17,7 @@
`include "hi_read_rx_xcorr.v"
`include "hi_simulate.v"
`include "hi_iso14443a.v"
`include "hi_sniffer.v"
`include "util.v"
module fpga_hf(
@ -122,25 +123,36 @@ hi_iso14443a hisn(
hi_simulate_mod_type
);
hi_sniffer he(
pck0, ck_1356meg, ck_1356megb,
he_pwr_lo, he_pwr_hi, he_pwr_oe1, he_pwr_oe2, he_pwr_oe3, he_pwr_oe4,
adc_d, he_adc_clk,
he_ssp_frame, he_ssp_din, ssp_dout, he_ssp_clk,
cross_hi, cross_lo,
he_dbg,
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
);
// Major modes:
// 000 -- HF reader, transmitting to tag; modulation depth selectable
// 001 -- HF reader, receiving from tag, correlating as it goes; frequency selectable
// 010 -- HF simulated tag
// 011 -- HF ISO14443-A
// 100 -- HF Snoop
// 111 -- everything off
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, 1'b0, 1'b0, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, 1'b0, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, 1'b0, 1'b0, 1'b0);
// In all modes, let the ADC's outputs be enabled.
assign adc_noe = 1'b0;

57
fpga/hi_sniffer.v Normal file
View file

@ -0,0 +1,57 @@
module hi_sniffer(
pck0, ck_1356meg, ck_1356megb,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
adc_d, adc_clk,
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg,
xcorr_is_848, snoop, xcorr_quarter_freq // not used.
);
input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo;
output dbg;
input xcorr_is_848, snoop, xcorr_quarter_freq; // not used.
// We are only snooping, all off.
assign pwr_hi = 1'b0;
assign pwr_lo = 1'b0;
assign pwr_oe1 = 1'b0;
assign pwr_oe2 = 1'b0;
assign pwr_oe3 = 1'b0;
assign pwr_oe4 = 1'b0;
reg ssp_frame;
reg [7:0] adc_d_out = 8'd0;
reg [2:0] ssp_cnt = 3'd0;
assign adc_clk = ck_1356meg;
assign ssp_clk = ~ck_1356meg;
always @(posedge ssp_clk)
begin
if(ssp_cnt[2:0] == 3'd7)
ssp_cnt[2:0] <= 3'd0;
else
ssp_cnt <= ssp_cnt + 1;
if(ssp_cnt[2:0] == 3'b000) // set frame length
begin
adc_d_out[7:0] <= adc_d;
ssp_frame <= 1'b1;
end
else
begin
adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]};
ssp_frame <= 1'b0;
end
end
assign ssp_din = adc_d_out[0];
endmodule

View file

@ -24,6 +24,10 @@ typedef unsigned char byte_t;
#ifndef MAX
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef ABS
# define ABS(a) ( ((a)<0) ? -(a) : (a) )
#endif
#define RAMFUNC __attribute((long_call, section(".ramfunc")))

View file

@ -7,11 +7,17 @@
//-----------------------------------------------------------------------------
// Hitag2 type prototyping
//-----------------------------------------------------------------------------
// HitagS added
//-----------------------------------------------------------------------------
#ifndef _HITAG2_H_
#define _HITAG2_H_
typedef enum {
RHTSF_CHALLENGE = 01,
RHTSF_KEY = 02,
WHTSF_CHALLENGE = 03,
WHTSF_KEY = 04,
RHT2F_PASSWORD = 21,
RHT2F_AUTHENTICATE = 22,
RHT2F_CRYPTO = 23,
@ -24,10 +30,12 @@ typedef struct {
typedef struct {
byte_t NrAr[8];
byte_t data[4];
} PACKED rht2d_authenticate;
typedef struct {
byte_t key[4];
byte_t key[6];
byte_t data[4];
} PACKED rht2d_crypto;
typedef union {

53
include/hitagS.h Normal file
View file

@ -0,0 +1,53 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// HitagS emulation (preliminary test version)
//
// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
// <info@os-s.de>
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include <hitag2.h>
#ifndef _HITAGS_H_
#define _HITAGS_H_
typedef enum PROTO_STATE {READY=0,INIT,AUTHENTICATE,SELECTED,QUIET,TTF,FAIL} PSTATE; //protocol-state
typedef enum TAG_STATE {NO_OP=0,READING_PAGE,WRITING_PAGE_ACK,WRITING_PAGE_DATA,WRITING_BLOCK_DATA} TSATE; //tag-state
typedef enum SOF_TYPE {STANDARD=0,ADVANCED,FAST_ADVANCED,ONE,NO_BITS} stype; //number of start-of-frame bits
struct hitagS_tag {
PSTATE pstate; //protocol-state
TSATE tstate; //tag-state
uint32_t uid;
uint32_t pages[16][4];
uint64_t key;
byte_t pwdl0,pwdl1,pwdh0;
//con0
int max_page;
stype mode;
//con1
bool auth; //0=Plain 1=Auth
bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase
int TTFDR; //data rate in TTF Mode
int TTFM; //the number of pages that are sent to the RWD
bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP
bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode
//con2
//0=read write 1=read only
bool LCK7; //page4/5
bool LCK6; //page6/7
bool LCK5; //page8-11
bool LCK4; //page12-15
bool LCK3; //page16-23
bool LCK2; //page24-31
bool LCK1; //page32-47
bool LCK0; //page48-63
} ;
#endif

View file

@ -26,14 +26,15 @@ typedef struct {
} __attribute__((__packed__)) iso14a_card_select_t;
typedef enum ISO14A_COMMAND {
ISO14A_CONNECT = 1,
ISO14A_NO_DISCONNECT = 2,
ISO14A_APDU = 4,
ISO14A_RAW = 8,
ISO14A_REQUEST_TRIGGER = 0x10,
ISO14A_APPEND_CRC = 0x20,
ISO14A_SET_TIMEOUT = 0x40,
ISO14A_NO_SELECT = 0x80
ISO14A_CONNECT = (1 << 0),
ISO14A_NO_DISCONNECT = (1 << 1),
ISO14A_APDU = (1 << 2),
ISO14A_RAW = (1 << 3),
ISO14A_REQUEST_TRIGGER = (1 << 4),
ISO14A_APPEND_CRC = (1 << 5),
ISO14A_SET_TIMEOUT = (1 << 6),
ISO14A_NO_SELECT = (1 << 7),
ISO14A_TOPAZMODE = (1 << 8)
} iso14a_command_t;
#endif // _MIFARE_H_

View file

@ -85,7 +85,7 @@ typedef struct{
#define CMD_INDALA_CLONE_TAG_L 0x0213
#define CMD_T55XX_READ_BLOCK 0x0214
#define CMD_T55XX_WRITE_BLOCK 0x0215
#define CMD_T55XX_READ_TRACE 0x0216
#define CMD_T55XX_RESET_READ 0x0216
#define CMD_PCF7931_READ 0x0217
#define CMD_PCF7931_WRITE 0x0222
#define CMD_EM4X_READ_WORD 0x0218
@ -99,6 +99,8 @@ typedef struct{
#define CMD_ASK_SIM_TAG 0x021F
#define CMD_PSK_SIM_TAG 0x0220
#define CMD_AWID_DEMOD_FSK 0x0221
#define CMD_VIKING_CLONE_TAG 0x0223
#define CMD_T55XX_WAKEUP 0x0224
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
@ -122,6 +124,13 @@ typedef struct{
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
#define CMD_SIMULATE_HITAG_S 0x0368
#define CMD_TEST_HITAGS_TRACES 0x0367
#define CMD_READ_HITAG_S 0x0373
#define CMD_WR_HITAG_S 0x0375
#define CMD_EMU_HITAG_S 0x0376
#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
@ -133,12 +142,17 @@ typedef struct{
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
#define CMD_EPA_PACE_REPLAY 0x038B
#define CMD_ICLASS_READCHECK 0x038F
#define CMD_ICLASS_CLONE 0x0390
#define CMD_ICLASS_DUMP 0x0391
#define CMD_SNOOP_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394
#define CMD_READER_ICLASS_REPLAY 0x0395
#define CMD_ICLASS_ISO14443A_WRITE 0x0397
#define CMD_ICLASS_READBLOCK 0x0396
#define CMD_ICLASS_WRITEBLOCK 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398
#define CMD_ICLASS_AUTHENTICATION 0x0399
// For measurements of the antenna tuning
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
@ -192,14 +206,17 @@ typedef struct{
#define CMD_MIFARE_DESFIRE_INFO 0x072d
#define CMD_MIFARE_DESFIRE 0x072e
#define CMD_HF_SNIFFER 0x0800
#define CMD_UNKNOWN 0xFFFF
//Mifare simulation flags
#define FLAG_INTERACTIVE 0x01
#define FLAG_4B_UID_IN_DATA 0x02
#define FLAG_7B_UID_IN_DATA 0x04
#define FLAG_NR_AR_ATTACK 0x08
#define FLAG_INTERACTIVE 0x01
#define FLAG_4B_UID_IN_DATA 0x02
#define FLAG_7B_UID_IN_DATA 0x04
#define FLAG_10B_UID_IN_DATA 0x08
#define FLAG_NR_AR_ATTACK 0x10
//Iclass reader flags
@ -209,8 +226,14 @@ typedef struct{
#define FLAG_ICLASS_READER_CONF 0x08
#define FLAG_ICLASS_READER_AA 0x10
#define FLAG_ICLASS_READER_ONE_TRY 0x20
#define FLAG_ICLASS_READER_CEDITKEY 0x40
//hw tune args
#define FLAG_TUNE_LF 1
#define FLAG_TUNE_HF 2
#define FLAG_TUNE_ALL 3
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
/* Whether a bootloader that understands the common_area is present */

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more