Merge remote-tracking branch 'upstream/master' into pm3+reveng

This commit is contained in:
marshmellow42 2016-02-15 14:13:49 -05:00
commit 7f0d592636
144 changed files with 110614 additions and 2774 deletions

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,10 +85,12 @@ CMDSRCS = nonce2key/crapto1.c\
cmdhficlass.c \
cmdhfmf.c \
cmdhfmfu.c \
cmdhftopaz.c \
cmdhw.c \
cmdlf.c \
cmdlfio.c \
cmdlfhid.c \
cmdlfawid.c \
cmdlfem4x.c \
cmdlfhitag.c \
cmdlfti.c \
@ -96,6 +98,7 @@ CMDSRCS = nonce2key/crapto1.c\
cmdmain.c \
cmdlft55xx.c \
cmdlfpcf7931.c\
cmdlfviking.c\
pm3_binlib.c\
scripting.c\
cmdscript.c\

View file

@ -24,10 +24,11 @@
#include "usb_cmd.h"
#include "crc.h"
#include "crc16.h"
#include "loclass/cipherutils.h"
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
uint8_t g_debugMode;
size_t DemodBufferLen;
uint8_t g_debugMode=0;
size_t DemodBufferLen=0;
static int CmdHelp(const char *Cmd);
//set the demod buffer with given array of binary (one bit per byte)
@ -57,11 +58,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;
}
@ -86,7 +88,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)
{
@ -102,10 +105,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;
@ -115,18 +124,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;
}
@ -314,7 +322,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;
@ -636,6 +644,32 @@ int CmdG_Prox_II_Demod(const char *Cmd)
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, checksum);
PrintAndLog("Raw: %08X%08X", raw1,raw2);
setDemodBuf(DemodBuffer+ans, 64, 0);
return 1;
}
//by marshmellow - see ASKDemod
int Cmdaskrawdemod(const char *Cmd)
{
@ -909,55 +943,52 @@ 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){
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){
fcs = countFC(BitStream, BitLen, 1);
if (fcs==0){
fchigh=10;
fclow=8;
}else{
fchigh = (fcs >> 8) & 0xFF;
fclow = fcs & 0xFF;
uint8_t fc1=0, fc2=0, rf1=0;
if (!fchigh || !fclow) {
uint8_t ans = fskClocks(&fc1, &fc2, &rf1, false);
if (ans == 0) {
if (g_debugMode) PrintAndLog("\nError: cannot detect valid fsk field clocks");
return 0; // can't detect field clock
}
fchigh = fc1;
fclow = fc2;
if (rfLen == 0) rfLen = rf1;
}
//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:%hu, invert:%hu, fchigh:%hu, fclow:%hu", rfLen, invert, fchigh, fclow);
PrintAndLog("%s decoded bitstream:",GetFSKType(fchigh,fclow,invert));
printDemodBuff();
}
return 1;
} else{
} else {
if (g_debugMode) PrintAndLog("no FSK data found");
}
return 0;
@ -1129,8 +1160,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) {
@ -1219,11 +1248,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;
@ -1422,7 +1446,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);
@ -1462,6 +1485,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;
@ -1488,12 +1522,16 @@ 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);
// remove but don't verify parity. (pType = 2)
// remove marker bits (1's every 9th digit after preamble) (pType = 2)
size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117);
if ( size <= 103 ) {
if ( size != 104 ) {
if (g_debugMode) PrintAndLog("Error removeParity:: %d", size);
return 0;
}
@ -1557,6 +1595,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){
@ -1596,61 +1637,33 @@ int CmdIndalaDecode(const char *Cmd)
return 0;
}
uint8_t invert=0;
ans = indala26decode(DemodBuffer, &DemodBufferLen, &invert);
if (ans < 1) {
size_t size = DemodBufferLen;
size_t startIdx = indala26decode(DemodBuffer, &size, &invert);
if (startIdx < 1 || size > 224) {
if (g_debugMode==1)
PrintAndLog("Error2: %d",ans);
return -1;
}
char showbits[251]={0x00};
setDemodBuf(DemodBuffer, size, startIdx);
if (invert)
if (g_debugMode==1)
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:");
@ -1720,7 +1733,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;
@ -1943,26 +1956,14 @@ int CmdHpf(const char *Cmd)
RepaintGraphWindow();
return 0;
}
typedef struct {
uint8_t * buffer;
uint32_t numbits;
uint32_t position;
}BitstreamOut;
bool _headBit( BitstreamOut *stream)
{
int bytepos = stream->position >> 3; // divide by 8
int bitpos = (stream->position++) & 7; // mask out 00000111
return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1;
}
uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b)
uint8_t getByte(uint8_t bits_per_sample, BitstreamIn* b)
{
int i;
uint8_t val = 0;
for(i =0 ; i < bits_per_sample; i++)
{
val |= (_headBit(b) << (7-i));
val |= (headBit(b) << (7-i));
}
return val;
}
@ -1978,10 +1979,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);
@ -2002,7 +2000,7 @@ int getSamples(const char *Cmd, bool silent)
if(bits_per_sample < 8)
{
PrintAndLog("Unpacking...");
BitstreamOut bout = { got, bits_per_sample * n, 0};
BitstreamIn bout = { got, bits_per_sample * n, 0};
int j =0;
for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) {
uint8_t sample = getByte(bits_per_sample, &bout);
@ -2265,14 +2263,109 @@ int CmdZerocrossings(const char *Cmd)
return 0;
}
int usage_data_bin2hex(){
PrintAndLog("Usage: data bin2hex <binary_digits>");
PrintAndLog(" This function will ignore all characters not 1 or 0 (but stop reading on whitespace)");
return 0;
}
/**
* @brief Utility for conversion via cmdline.
* @param Cmd
* @return
*/
int Cmdbin2hex(const char *Cmd)
{
int bg =0, en =0;
if(param_getptr(Cmd, &bg, &en, 0))
{
return usage_data_bin2hex();
}
//Number of digits supplied as argument
size_t length = en - bg +1;
size_t bytelen = (length+7) / 8;
uint8_t* arr = (uint8_t *) malloc(bytelen);
memset(arr, 0, bytelen);
BitstreamOut bout = { arr, 0, 0 };
for(; bg <= en ;bg++)
{
char c = Cmd[bg];
if( c == '1') pushBit(&bout, 1);
else if( c == '0') pushBit(&bout, 0);
else PrintAndLog("Ignoring '%c'", c);
}
if(bout.numbits % 8 != 0)
{
printf("[padded with %d zeroes]\n", 8-(bout.numbits % 8));
}
//Uses printf instead of PrintAndLog since the latter
// adds linebreaks to each printout - this way was more convenient since we don't have to
// allocate a string and write to that first...
for(size_t x = 0; x < bytelen ; x++)
{
printf("%02X", arr[x]);
}
printf("\n");
free(arr);
return 0;
}
int usage_data_hex2bin(){
PrintAndLog("Usage: data bin2hex <binary_digits>");
PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
return 0;
}
int Cmdhex2bin(const char *Cmd)
{
int bg =0, en =0;
if(param_getptr(Cmd, &bg, &en, 0))
{
return usage_data_hex2bin();
}
while(bg <= en )
{
char x = Cmd[bg++];
// capitalize
if (x >= 'a' && x <= 'f')
x -= 32;
// convert to numeric value
if (x >= '0' && x <= '9')
x -= '0';
else if (x >= 'A' && x <= 'F')
x -= 'A' - 10;
else
continue;
//Uses printf instead of PrintAndLog since the latter
// adds linebreaks to each printout - this way was more convenient since we don't have to
// allocate a string and write to that first...
for(int i= 0 ; i < 4 ; ++i)
printf("%d",(x >> (3 - i)) & 1);
}
printf("\n");
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"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"},
{"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
{"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
{"dec", CmdDec, 1, "Decimate samples"},
@ -2287,6 +2380,7 @@ static command_t CommandTable[] =
{"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"},
{"grid", CmdGrid, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
{"hexsamples", CmdHexsamples, 0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
{"hex2bin", Cmdhex2bin, 1, "hex2bin <hexadecimal> -- Converts hexadecimal to binary"},
{"hide", CmdHide, 1, "Hide graph window"},
{"hpf", CmdHpf, 1, "Remove DC offset from trace"},
{"load", CmdLoad, 1, "<filename> -- Load trace (to graph window"},
@ -2295,14 +2389,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

@ -17,6 +17,7 @@ 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);

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
@ -378,21 +484,24 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else {
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

@ -132,17 +132,21 @@ int CmdHF14BCmdRaw (const char *Cmd) {
bool reply = true;
bool crc = false;
bool power = false;
bool select = false;
bool SRx = false;
char buf[5] = "";
uint8_t data[100] = {0x00};
uint8_t datalen = 0;
unsigned int temp;
int i = 0;
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>");
PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>");
PrintAndLog(" -r do not read response");
PrintAndLog(" -c calculate and append CRC");
PrintAndLog(" -p leave the field on after receive");
return 0;
PrintAndLog(" -s active signal field ON with select");
PrintAndLog(" -ss active signal field ON with select for SRx ST Microelectronics tags");
return 0;
}
// strip
@ -164,6 +168,14 @@ int CmdHF14BCmdRaw (const char *Cmd) {
case 'P':
power = true;
break;
case 's':
case 'S':
select = true;
if (Cmd[i+2]=='s' || Cmd[i+2]=='S') {
SRx = true;
i++;
}
break;
default:
PrintAndLog("Invalid option");
return 0;
@ -186,7 +198,7 @@ int CmdHF14BCmdRaw (const char *Cmd) {
continue;
}
PrintAndLog("Invalid char on input");
return 1;
return 0;
}
if (datalen == 0)
{
@ -194,11 +206,58 @@ int CmdHF14BCmdRaw (const char *Cmd) {
return 0;
}
if (select){ //auto select 14b tag
uint8_t cmd2[16];
bool crc2 = true;
uint8_t cmdLen;
if (SRx) {
// REQ SRx
cmdLen = 2;
cmd2[0] = 0x06;
cmd2[1] = 0x00;
} else {
cmdLen = 3;
// REQB
cmd2[0] = 0x05;
cmd2[1] = 0x00;
cmd2[2] = 0x08;
}
if (HF14BCmdRaw(true, &crc2, true, cmd2, &cmdLen, false)==0) return rawClose();
if ( SRx && (cmdLen != 3 || !crc2) ) return rawClose();
else if (cmd2[0] != 0x50 || cmdLen != 14 || !crc2) return rawClose();
uint8_t chipID = 0;
if (SRx) {
// select
chipID = cmd2[0];
cmd2[0] = 0x0E;
cmd2[1] = chipID;
cmdLen = 2;
} else {
// attrib
cmd2[0] = 0x1D;
// UID from cmd2[1 - 4]
cmd2[5] = 0x00;
cmd2[6] = 0x08;
cmd2[7] = 0x01;
cmd2[8] = 0x00;
cmdLen = 9;
}
if (HF14BCmdRaw(true, &crc2, true, cmd2, &cmdLen, false)==0) return rawClose();
if (cmdLen != 3 || !crc2) return rawClose();
if (SRx && cmd2[0] != chipID) return rawClose();
}
return HF14BCmdRaw(reply, &crc, power, data, &datalen, true);
}
// print full atqb info
static void print_atqb_resp(uint8_t *data){
PrintAndLog (" UID: %s", sprint_hex(data+1,4));
//PrintAndLog (" UID: %s", sprint_hex(data+1,4));
PrintAndLog (" App Data: %s", sprint_hex(data+5,4));
PrintAndLog (" Protocol: %s", sprint_hex(data+9,3));
uint8_t BitRate = data[9];
@ -233,18 +292,20 @@ static void print_atqb_resp(uint8_t *data){
else
maxFrame = 257;
PrintAndLog ("Max Frame Size: %d%s",maxFrame, (maxFrame == 257) ? "+ RFU" : "");
PrintAndLog ("Max Frame Size: %u%s",maxFrame, (maxFrame == 257) ? "+ RFU" : "");
uint8_t protocolT = data[10] & 0xF;
PrintAndLog (" Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " );
PrintAndLog ("Frame Wait Int: %d", data[11]>>4);
PrintAndLog ("Frame Wait Int: %u", data[11]>>4);
PrintAndLog (" App Data Code: Application is %s",(data[11]&4) ? "Standard" : "Proprietary");
PrintAndLog (" Frame Options: NAD is %ssupported",(data[11]&2) ? "" : "not ");
PrintAndLog (" Frame Options: CID is %ssupported",(data[11]&1) ? "" : "not ");
PrintAndLog ("Max Buf Length: %u (MBLI) %s",data[14]>>4, (data[14] & 0xF0) ? "" : "not supported");
return;
}
// get SRx chip model (from UID) // from ST Microelectronics
char *get_ST_Chip_Model(uint8_t data){
static char model[20];
char *retStr = model;
@ -263,20 +324,86 @@ char *get_ST_Chip_Model(uint8_t data){
return retStr;
}
static void print_st_info(uint8_t *data){
int print_ST_Lock_info(uint8_t model){
//assume connection open and tag selected...
uint8_t data[16] = {0x00};
uint8_t datalen = 2;
bool crc = true;
uint8_t resplen;
uint8_t blk1;
data[0] = 0x08;
if (model == 0x2) { //SR176 has special command:
data[1] = 0xf;
resplen = 4;
} else {
data[1] = 0xff;
resplen = 6;
}
//std read cmd
if (HF14BCmdRaw(true, &crc, true, data, &datalen, false)==0) return rawClose();
if (datalen != resplen || !crc) return rawClose();
PrintAndLog("Chip Write Protection Bits:");
// now interpret the data
switch (model){
case 0x0: //fall through (SRIX4K special)
case 0x3: //fall through (SRIx4K)
case 0x7: // (SRI4K)
//only need data[3]
blk1 = 9;
PrintAndLog(" raw: %s",printBits(1,data+3));
PrintAndLog(" 07/08:%slocked", (data[3] & 1) ? " not " : " " );
for (uint8_t i = 1; i<8; i++){
PrintAndLog(" %02u:%slocked", blk1, (data[3] & (1 << i)) ? " not " : " " );
blk1++;
}
break;
case 0x4: //fall through (SRIX512)
case 0x6: //fall through (SRI512)
case 0xC: // (SRT512)
//need data[2] and data[3]
blk1 = 0;
PrintAndLog(" raw: %s",printBits(2,data+2));
for (uint8_t b=2; b<4; b++){
for (uint8_t i=0; i<8; i++){
PrintAndLog(" %02u:%slocked", blk1, (data[b] & (1 << i)) ? " not " : " " );
blk1++;
}
}
break;
case 0x2: // (SR176)
//need data[2]
blk1 = 0;
PrintAndLog(" raw: %s",printBits(1,data+2));
for (uint8_t i = 0; i<8; i++){
PrintAndLog(" %02u/%02u:%slocked", blk1, blk1+1, (data[2] & (1 << i)) ? " " : " not " );
blk1+=2;
}
break;
default:
return rawClose();
}
return 1;
}
// print UID info from SRx chips (ST Microelectronics)
static void print_st_general_info(uint8_t *data){
//uid = first 8 bytes in data
PrintAndLog(" UID: %s", sprint_hex(SwapEndian64(data,8,8),8));
PrintAndLog(" MFG: %02X, %s", data[6], getTagInfo(data[6]));
PrintAndLog("Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2));
PrintAndLog(" UID: %s", sprint_hex(SwapEndian64(data,8,8),8));
PrintAndLog(" MFG: %02X, %s", data[6], getTagInfo(data[6]));
PrintAndLog(" Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2));
return;
}
int HF14BStdInfo(uint8_t *data, uint8_t *datalen){
// 14b get and print UID only (general info)
int HF14BStdReader(uint8_t *data, uint8_t *datalen){
//05 00 00 = find one tag in field
//1d xx xx xx xx 20 00 08 01 00 = attrib xx=crc
//a3 = ? (resp 03 e2 c2)
//02 = ? (resp 02 6a d3)
//1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0])
//a3 = ? (resp 03 [e2 c2])
//02 = ? (resp 02 [6a d3])
// 022b (resp 02 67 00 [29 5b])
// 0200a40400 (resp 02 67 00 [29 5b])
// 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b])
@ -289,24 +416,60 @@ int HF14BStdInfo(uint8_t *data, uint8_t *datalen){
//03 = ? (resp 03 [e3 c2])
//c2 = ? (resp c2 [66 15])
//b2 = ? (resp a3 [e9 67])
//a2 = ? (resp 02 [6a d3])
bool crc = true;
*datalen = 3;
//std read cmd
data[0] = 0x05;
data[1] = 0x00;
data[2] = 0x00;
data[2] = 0x08;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)==0) return 0;
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose();
if (data[0] != 0x50 || *datalen != 14 || !crc) return 0;
if (data[0] != 0x50 || *datalen != 14 || !crc) return rawClose();
PrintAndLog ("\n14443-3b tag found:");
PrintAndLog (" UID: %s", sprint_hex(data+1,4));
uint8_t cmd2[16];
uint8_t cmdLen = 3;
bool crc2 = true;
cmd2[0] = 0x1D;
// UID from data[1 - 4]
cmd2[1] = data[1];
cmd2[2] = data[2];
cmd2[3] = data[3];
cmd2[4] = data[4];
cmd2[5] = 0x00;
cmd2[6] = 0x08;
cmd2[7] = 0x01;
cmd2[8] = 0x00;
cmdLen = 9;
// attrib
if (HF14BCmdRaw(true, &crc2, true, cmd2, &cmdLen, false)==0) return rawClose();
if (cmdLen != 3 || !crc2) return rawClose();
// add attrib responce to data
data[14] = cmd2[0];
rawClose();
return 1;
}
// 14b get and print Full Info (as much as we know)
int HF14BStdInfo(uint8_t *data, uint8_t *datalen){
if (!HF14BStdReader(data,datalen)) return 0;
//add more info here
print_atqb_resp(data);
return 1;
}
int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){
// SRx get and print general info about SRx chip from UID
int HF14B_ST_Reader(uint8_t *data, uint8_t *datalen, bool closeCon){
bool crc = true;
*datalen = 2;
//wake cmd
@ -326,7 +489,6 @@ int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){
*datalen = 2;
//leave power on
// verbose on for now for testing - turn off when functional
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose();
if (*datalen != 3 || !crc || data[0] != chipID) return rawClose();
@ -335,19 +497,32 @@ int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){
data[0] = 0x0B;
*datalen = 1;
//power off
// verbose on for now for testing - turn off when functional
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return 0;
rawClose();
if (*datalen != 10 || !crc) return 0;
//leave power on
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose();
if (*datalen != 10 || !crc) return rawClose();
//power off ?
if (closeCon) rawClose();
PrintAndLog("\n14443-3b ST tag found:");
print_st_info(data);
print_st_general_info(data);
return 1;
}
// SRx get and print full info (needs more info...)
int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){
if (!HF14B_ST_Reader(data, datalen, false)) return 0;
//add locking bit information here.
if (print_ST_Lock_info(data[5]>>2))
rawClose();
return 1;
}
// test for other 14b type tags (mimic another reader - don't have tags to identify)
int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){
int HF14B_Other_Reader(uint8_t *data, uint8_t *datalen){
bool crc = true;
*datalen = 4;
//std read cmd
@ -356,11 +531,12 @@ int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){
data[2] = 0x3f;
data[3] = 0x80;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)!=0) {
if (*datalen > 2 || !crc) {
PrintAndLog ("\n14443-3b tag found:");
PrintAndLog ("Unknown tag type answered to a 0x000b3f80 command ans:");
PrintAndLog ("%s",sprint_hex(data,*datalen));
rawClose();
return 1;
}
}
@ -369,11 +545,12 @@ int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){
*datalen = 1;
data[0] = 0x0a;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)!=0) {
if (*datalen > 0) {
PrintAndLog ("\n14443-3b tag found:");
PrintAndLog ("Unknown tag type answered to a 0x0A command ans:");
PrintAndLog ("%s",sprint_hex(data,*datalen));
rawClose();
return 1;
}
}
@ -382,19 +559,20 @@ int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){
*datalen = 1;
data[0] = 0x0c;
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)!=0) {
if (*datalen > 0) {
PrintAndLog ("\n14443-3b tag found:");
PrintAndLog ("Unknown tag type answered to a 0x0C command ans:");
PrintAndLog ("%s",sprint_hex(data,*datalen));
rawClose();
return 1;
}
}
rawClose();
return 0;
}
// get and print all info known about any known 14b tag
int HF14BInfo(bool verbose){
uint8_t data[100];
uint8_t datalen = 5;
@ -407,16 +585,41 @@ int HF14BInfo(bool verbose){
// try unknown 14b read commands (to be identified later)
// could be read of calypso, CEPAS, moneo, or pico pass.
if (HF14B_Other_Info(data, &datalen)) return 1;
if (HF14B_Other_Reader(data, &datalen)) return 1;
if (verbose) PrintAndLog("no 14443B tag found");
return 0;
}
// menu command to get and print all info known about any known 14b tag
int CmdHF14Binfo(const char *Cmd){
return HF14BInfo(true);
}
// get and print general info about all known 14b chips
int HF14BReader(bool verbose){
uint8_t data[100];
uint8_t datalen = 5;
// try std 14b (atqb)
if (HF14BStdReader(data, &datalen)) return 1;
// try st 14b
if (HF14B_ST_Reader(data, &datalen, true)) return 1;
// try unknown 14b read commands (to be identified later)
// could be read of calypso, CEPAS, moneo, or pico pass.
if (HF14B_Other_Reader(data, &datalen)) return 1;
if (verbose) PrintAndLog("no 14443B tag found");
return 0;
}
// menu command to get and print general info about all known 14b chips
int CmdHF14BReader(const char *Cmd){
return HF14BReader(true);
}
int CmdSriWrite( const char *Cmd){
/*
* For SRIX4K blocks 00 - 7F
@ -487,8 +690,9 @@ int CmdSriWrite( const char *Cmd){
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"info", CmdHF14Binfo, 0, "Find and print info about a 14b type tag (HF ISO 14443b)"},
{"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"},
{"info", CmdHF14Binfo, 0, "Find and print details about a 14443B tag"},
{"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"},
{"reader", CmdHF14BReader, 0, "Act as a 14443B reader to identify a tag"},
{"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"},
{"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443B"},
{"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"},

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

@ -17,15 +17,14 @@ int CmdHF14AMifare(const char *Cmd)
uint32_t uid = 0;
uint32_t nt = 0, nr = 0;
uint64_t par_list = 0, ks_list = 0, r_key = 0;
uint8_t isOK = 0;
uint8_t keyBlock[8] = {0};
int16_t isOK = 0;
UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}};
// message
printf("-------------------------------------------------------------------------\n");
printf("Executing command. Expected execution time: 25sec on average :-)\n");
printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n");
printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n");
printf("-------------------------------------------------------------------------\n");
@ -47,15 +46,22 @@ start:
}
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
isOK = resp.arg[0] & 0xff;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
isOK = resp.arg[0];
uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4);
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
nr = bytes_to_num(resp.d.asBytes + 24, 4);
printf("\n\n");
if (!isOK) PrintAndLog("Proxmark can't get statistic info. Execution aborted.\n");
switch (isOK) {
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;
}
}
@ -69,22 +75,13 @@ start:
if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key)) {
isOK = 2;
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
} else {
printf("------------------------------------------------------------------\n");
PrintAndLog("Key found:%012"llx" \n", r_key);
num_to_bytes(r_key, 6, keyBlock);
isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key);
}
if (!isOK)
PrintAndLog("Found valid key:%012"llx, r_key);
else
{
if (isOK != 2) PrintAndLog("Found invalid key. ");
PrintAndLog("Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce...");
c.arg[0] = false;
goto start;
} else {
isOK = 0;
printf("------------------------------------------------------------------\n");
PrintAndLog("Found valid key:%012"llx" \n", r_key);
}
PrintAndLog("");
@ -622,8 +619,14 @@ int CmdHF14AMfNested(const char *Cmd)
if (cmdp == 'o') {
PrintAndLog("--target block no:%3d, target key type:%c ", trgBlockNo, trgKeyType?'B':'A');
if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true)) {
PrintAndLog("Nested error.");
int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true);
if (isOK) {
switch (isOK) {
case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break;
case -2 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break;
default : PrintAndLog("Unknown Error.\n");
}
return 2;
}
key64 = bytes_to_num(keyBlock, 6);
@ -678,7 +681,7 @@ int CmdHF14AMfNested(const char *Cmd)
for (j = 0; j < 2; j++) {
if (e_sector[i].foundKey[j]) continue;
res = mfCheckKeys(FirstBlockOfSector(i), j, 6, keyBlock, &key64);
res = mfCheckKeys(FirstBlockOfSector(i), j, true, 6, keyBlock, &key64);
if (!res) {
e_sector[i].Key[j] = key64;
@ -696,11 +699,17 @@ int CmdHF14AMfNested(const char *Cmd)
for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) {
if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
PrintAndLog("-----------------------------------------------");
if(mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate)) {
PrintAndLog("Nested error.\n");
int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
if(isOK) {
switch (isOK) {
case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break;
case -2 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break;
default : PrintAndLog("Unknown Error.\n");
}
free(e_sector);
return 2; }
else {
return 2;
} else {
calibrate = false;
}
@ -956,7 +965,7 @@ int CmdHF14AMfChk(const char *Cmd)
uint32_t max_keys = keycnt>USB_CMD_DATA_SIZE/6?USB_CMD_DATA_SIZE/6:keycnt;
for (uint32_t c = 0; c < keycnt; c+=max_keys) {
uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c;
res = mfCheckKeys(b, t, size, &keyBlock[6*c], &key64);
res = mfCheckKeys(b, t, true, size, &keyBlock[6*c], &key64);
if (res != 1) {
if (!res) {
PrintAndLog("Found valid key:[%012"llx"]",key64);
@ -1942,6 +1951,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[] =
{
@ -1970,6 +1986,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

@ -18,6 +18,7 @@
#include "cmdhw.h"
#include "cmdmain.h"
#include "cmddata.h"
#include "data.h"
/* low-level hardware control */
@ -405,39 +406,72 @@ int CmdTune(const char *Cmd)
int CmdVersion(const char *Cmd)
{
clearCommandBuffer();
UsbCommand c = {CMD_VERSION};
static UsbCommand resp = {0, {0, 0, 0}};
if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1000) && Cmd != NULL) {
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
PrintAndLog("Prox/RFID mark3 RFID instrument");
PrintAndLog((char*)resp.d.asBytes);
lookupChipID(resp.arg[0], resp.arg[1]);
}
} else if (Cmd != NULL) {
} else {
PrintAndLog("[[[ Cached information ]]]\n");
PrintAndLog("Prox/RFID mark3 RFID instrument");
PrintAndLog((char*)resp.d.asBytes);
lookupChipID(resp.arg[0], resp.arg[1]);
PrintAndLog("");
}
return 0;
}
int CmdStatus(const char *Cmd)
{
uint8_t speed_test_buffer[USB_CMD_DATA_SIZE];
sample_buf = speed_test_buffer;
clearCommandBuffer();
UsbCommand c = {CMD_STATUS};
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) {
PrintAndLog("Status command failed. USB Speed Test timed out");
}
return 0;
}
int CmdPing(const char *Cmd)
{
clearCommandBuffer();
UsbCommand resp;
UsbCommand c = {CMD_PING};
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
PrintAndLog("Ping successfull");
}else{
PrintAndLog("Ping failed");
}
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
{"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"},
{"lcd", CmdLCD, 0, "<HEX command> <count> -- Send command/data to LCD"},
{"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"},
{"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"},
{"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"},
{"version", CmdVersion, 0, "Show version information about the connected Proxmark"},
{NULL, NULL, 0, NULL}
{"help", CmdHelp, 1, "This help"},
{"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
{"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"},
{"lcd", CmdLCD, 0, "<HEX command> <count> -- Send command/data to LCD"},
{"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"},
{"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"},
{"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"},
{"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"},
{NULL, NULL, 0, NULL}
};
int CmdHW(const char *Cmd)

View file

@ -22,27 +22,94 @@
#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 "cmdlfviking.h"
#include "lfdemod.h"
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;
int strLength = 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':
strLength = 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;
}
@ -58,7 +125,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];
@ -140,10 +207,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;
@ -156,6 +226,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;
@ -353,6 +424,7 @@ int CmdIndalaClone(const char *Cmd)
c.arg[1] = uid2;
}
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@ -388,7 +460,7 @@ int usage_lf_config()
PrintAndLog(" b <bps> Sets resolution of bits per sample. Default (max): 8");
PrintAndLog(" d <decim> Sets decimation. A value of N saves only 1 in N samples. Default: 1");
PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1");
PrintAndLog(" t <threshold> Sets trigger threshold. 0 means no threshold");
PrintAndLog(" t <threshold> Sets trigger threshold. 0 means no threshold (range: 0-128)");
PrintAndLog("Examples:");
PrintAndLog(" lf config b 8 L");
PrintAndLog(" Samples at 125KHz, 8bps.");
@ -475,6 +547,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;
}
@ -491,8 +564,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;
}
@ -505,6 +584,7 @@ int CmdLFSnoop(const char *Cmd)
}
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
clearCommandBuffer();
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
return 0;
@ -551,6 +631,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;
}
@ -700,6 +781,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;
}
@ -793,6 +875,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;
}
@ -900,6 +983,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;
@ -1053,13 +1137,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!");
@ -1084,6 +1161,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!");
@ -1125,27 +1214,29 @@ 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... }"},
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 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... }"},
{"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}
};

207
client/cmdlfawid.c Normal file
View file

@ -0,0 +1,207 @@
//-----------------------------------------------------------------------------
// Authored by Craig Young <cyoung@tripwire.com> based on cmdlfhid.c structure
//
// cmdlfhid.c is Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
//
// 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 AWID26 commands
//-----------------------------------------------------------------------------
#include <stdio.h> // sscanf
#include "proxmark3.h" // Definitions, USB controls, etc
#include "ui.h" // PrintAndLog
#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);
int usage_lf_awid_fskdemod(void) {
PrintAndLog("Enables AWID26 compatible reader mode printing details of scanned AWID26 tags.");
PrintAndLog("By default, values are printed and logged until the button is pressed or another USB command is issued.");
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(" 1 : (optional) stop after reading a single card");
PrintAndLog("");
PrintAndLog("Samples : lf awid fskdemod");
PrintAndLog(" : lf awid fskdemod 1");
return 0;
}
int usage_lf_awid_sim(void) {
PrintAndLog("Enables simulation of AWID26 card with specified facility-code and card number.");
PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
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(" <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");
return 0;
}
int usage_lf_awid_clone(void) {
PrintAndLog("Enables cloning of AWID26 card with specified facility-code and card number onto T55x7.");
PrintAndLog("The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process.");
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(" <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");
return 0;
}
int CmdAWIDDemodFSK(const char *Cmd) {
int findone=0;
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;
}
//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);
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;
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
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);
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
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 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 (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;
PrintAndLog("Facility-Code Truncated to 8-bits (AWID26): %u", fc);
}
if ((cn & 0xFFFF) != cn) {
cn &= 0xFFFF;
PrintAndLog("Card Number Truncated to 16-bits (AWID26): %u", cn);
}
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"},
{"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> <Q5> -- Clone AWID to T55x7 (tag must be in range of antenna)"},
{NULL, NULL, 0, NULL}
};
int CmdLFAWID(const char *Cmd) {
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

24
client/cmdlfawid.h Normal file
View file

@ -0,0 +1,24 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
//
// 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 AWID commands
//-----------------------------------------------------------------------------
#ifndef CMDLFAWID_H__
#define CMDLFAWID_H__
int CmdLFAWID(const char *Cmd);
//int CmdAWIDDemod(const char *Cmd);
int CmdAWIDDemodFSK(const char *Cmd);
int CmdAWIDSim(const char *Cmd);
int CmdAWIDClone(const char *Cmd);
int getAWIDBits(unsigned int fc, unsigned int cn, uint8_t *AWIDBits);
int usage_lf_awid_fskdemod(void);
int usage_lf_awid_clone(void);
int usage_lf_awid_sim(void);
#endif

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

@ -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

@ -1,17 +1,18 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
//
// 2015 Dake <thomas.cayrou at gmail.com>
// 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 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"
@ -21,30 +22,158 @@
static int CmdHelp(const char *Cmd);
int CmdLFPCF7931Read(const char *Cmd)
{
UsbCommand c = {CMD_PCF7931_READ};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
return 0;
#define PCF7931_DEFAULT_INITDELAY 17500
#define PCF7931_DEFAULT_OFFSET_WIDTH 0
#define PCF7931_DEFAULT_OFFSET_POSITION 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 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 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"},
{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

@ -1,6 +1,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
//
// 2015 Dake <thomas.cayrou at gmail.com>
// 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.
@ -11,8 +12,24 @@
#ifndef CMDLFPCF7931_H__
#define CMDLFPCF7931_H__
struct pcf7931_config{
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

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,22 @@ typedef struct {
RF_100 = 0x06,
RF_128 = 0x07,
} bitrate;
bool Q5;
} 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 +85,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) ^ ((id>>16) & 0xFF) ^ ((id>>8) & 0xFF) ^ (id & 0xFF) ^ 0xF2 ^ 0xA8;
return ((uint64_t)0xF2 << 56) | (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

@ -68,8 +68,7 @@ int CmdHelp(const char *Cmd)
int CmdQuit(const char *Cmd)
{
exit(0);
return 0;
return 99;
}
int CmdRev(const char *Cmd)
@ -107,8 +106,9 @@ void storeCommand(UsbCommand *command)
memcpy(destination, command, sizeof(UsbCommand));
cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap
}
/**
* @brief getCommand gets a command from an internal circular buffer.
* @param response location to write command
@ -127,9 +127,9 @@ int getCommand(UsbCommand* response)
cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE;
return 1;
}
/**
* Waits for a certain response type. This method waits for a maximum of
* ms_timeout milliseconds for a specified response command.
@ -141,41 +141,43 @@ int getCommand(UsbCommand* response)
*/
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) {
UsbCommand resp;
UsbCommand resp;
if (response == NULL)
response = &resp;
// Wait until the command is received
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
while(getCommand(response)) {
if(response->cmd == cmd){
return true;
}
}
msleep(10); // XXX ugh
if (dm_seconds == 200) { // Two seconds elapsed
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
}
if (response == NULL) {
response = &resp;
}
return false;
// Wait until the command is received
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
while(getCommand(response)) {
if(response->cmd == cmd){
return true;
}
}
msleep(10); // XXX ugh
if (dm_seconds == 200) { // Two seconds elapsed
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
}
}
return false;
}
bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
return WaitForResponseTimeout(cmd,response,-1);
}
//-----------------------------------------------------------------------------
// 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);
}
//-----------------------------------------------------------------------------
// Entry point into our code: called whenever we received a packet over USB
// that we weren't necessarily expecting, for example a debug print.
@ -185,10 +187,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;
@ -199,12 +202,13 @@ void UsbCommandReceived(UsbCommand *UC)
case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
return;
} break;
default:
storeCommand(UC);
break;
}
storeCommand(UC);
}

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

@ -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
@ -84,6 +84,9 @@ typedef struct {
#define CMD_FSK_SIM_TAG 0x021E
#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 */
@ -114,9 +117,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

@ -20,7 +20,8 @@ local _commands = {
CMD_BUFF_CLEAR = 0x0105,
CMD_READ_MEM = 0x0106,
CMD_VERSION = 0x0107,
CMD_STATUS = 0x0108,
CMD_PING = 0x0109,
--// For low-frequency tags
CMD_READ_TI_TYPE = 0x0202,
CMD_WRITE_TI_TYPE = 0x0203,
@ -43,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,
@ -54,7 +55,9 @@ local _commands = {
CMD_FSK_SIM_TAG = 0x021E,
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
@ -86,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

@ -69,7 +69,7 @@ void* nested_worker_thread(void *arg)
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate)
{
uint16_t i, len;
uint16_t i;
uint32_t uid;
UsbCommand resp;
@ -77,31 +77,29 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
struct Crypto1State *p1, *p2, *p3, *p4;
// flush queue
WaitForResponseTimeout(CMD_ACK,NULL,100);
WaitForResponseTimeout(CMD_ACK, NULL, 100);
UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}};
memcpy(c.d.asBytes, key, 6);
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
len = resp.arg[1];
if (len == 2) {
memcpy(&uid, resp.d.asBytes, 4);
PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%x", uid, len, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);
for (i = 0; i < 2; i++) {
statelists[i].blockNo = resp.arg[2] & 0xff;
statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;
statelists[i].uid = uid;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
return -1;
}
memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);
memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);
}
}
else {
PrintAndLog("Got 0 keys from proxmark.");
return 1;
}
if (resp.arg[0]) {
return resp.arg[0]; // error during nested
}
memcpy(&uid, resp.d.asBytes, 4);
PrintAndLog("uid:%08x trgbl=%d trgkey=%x", uid, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);
for (i = 0; i < 2; i++) {
statelists[i].blockNo = resp.arg[2] & 0xff;
statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;
statelists[i].uid = uid;
memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);
memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);
}
// calc keys
@ -183,7 +181,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);
num_to_bytes(key64, 6, keyBlock);
key64 = 0;
if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, 1, keyBlock, &key64)) {
if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, 1, keyBlock, &key64)) {
num_to_bytes(key64, 6, resultKey);
break;
}
@ -195,11 +193,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
return 0;
}
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){
*key = 0;
UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}};
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}};
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
SendCommand(&c);
@ -621,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

@ -50,7 +50,7 @@ typedef struct {
extern char logHexFileName[FILE_PATH_SIZE];
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
@ -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

@ -133,7 +133,7 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_
key64 = *(last_keylist + i);
num_to_bytes(key64, 6, keyBlock);
key64 = 0;
if (!mfCheckKeys(0, 0, 1, keyBlock, &key64)) {
if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) {
*key = key64;
free(last_keylist);
last_keylist = NULL;

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"
@ -229,6 +230,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
@ -483,6 +505,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

@ -88,10 +88,35 @@ function mfcrack_inner()
while not core.ukbhit() do
local result = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
if result then
-- Unpacking the three arg-parameters
local count,cmd,isOK = bin.unpack('LL',result)
if isOK ~= 1 then return nil, "Error occurred" end
--[[
I don't understand, they cmd and args are defined as uint32_t, however,
looking at the returned data, they all look like 64-bit things:
print("result", bin.unpack("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH", result))
FF 00 00 00 00 00 00 00 <-- 64 bits of data
FE FF FF FF 00 00 00 00 <-- 64 bits of data
00 00 00 00 00 00 00 00 <-- 64 bits of data
00 00 00 00 00 00 00 00 <-- 64 bits of data
04 7F 12 E2 00 <-- this is where 'data' starts
So below I use LI to pick out the "FEFF FFFF", don't know why it works..
--]]
-- Unpacking the arg-parameters
local count,cmd,isOK = bin.unpack('LI',result)
--print("response", isOK)--FF FF FF FF
if isOK == 0xFFFFFFFF then
return nil, "Button pressed. Aborted."
elseif isOK == 0xFFFFFFFE then
return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK == 0xFFFFFFFD then
return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK == 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
-- The data-part is left

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 */
@ -123,16 +125,31 @@ char *sprint_hex(const uint8_t *data, const size_t len) {
}
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", 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
@ -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;
@ -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,13 @@ 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];
}
// 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

@ -17,6 +17,9 @@
#include <time.h>
#include "data.h"
#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,10 +46,12 @@ 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);
char param_getchar(const char *line, int paramnum);
int param_getptr(const char *line, int *bg, int *en, int paramnum);
uint8_t param_get8(const char *line, int paramnum);
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
@ -54,14 +59,16 @@ 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]);
void rol(uint8_t *data, const size_t len);