A lot of changes...

.. ntag simulation stuff from @marshmellows branch "ntag/sim"
.. hf mf mifare fixes from @pwpivi.
.. hw status command
.. speedtest function from @pwpivi
.. Viking Functionalities,   (not a proper DEMOD, but a start)
.. GetCountUS  better precision from @pwpivi
.. bin2hex,  hex2bin  from @holiman

...
starting with getting the T55x7 CONFIGURATION_BLOCK for different clone situations. Ripped from Adam Lauries RFidler,   nothing working or finished..
...
Started working with the T55x7 read command with password actually performs a write block...  See Issue #136  https://github.com/Proxmark/proxmark3/issues/136    Not solved yet.

...
Started add SHA256..   not working yet..
This commit is contained in:
iceman1001
2015-10-04 18:01:33 +02:00
parent 05beaa8dd8
commit 0de8e3874d
41 changed files with 2222 additions and 237 deletions

View File

@@ -119,6 +119,7 @@ CMDSRCS = nonce2key/crapto1.c\
cmdlfem4x.c \
cmdlfhitag.c \
cmdlfti.c \
cmdlfviking.c\
cmdparser.c \
cmdmain.c \
cmdlft55xx.c \
@@ -130,6 +131,7 @@ CMDSRCS = nonce2key/crapto1.c\
aes.c\
protocols.c\
sha1.c\
sha256.c\
cmdcrc.c\
reveng/reveng.c\
reveng/cli.c\

View File

@@ -24,6 +24,7 @@
#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=0;
@@ -1881,6 +1882,54 @@ int CmdRawDemod(const char *Cmd)
return ans;
}
int AmVikingDecode(const uint8_t *id){
// searching the buffer for the id
//uint8_t id_bits[32];
// convert 4 bytes of id to 32 bits present in 32 bytes data;
//bytes_to_bits(id,4,id_bits,sizeof(id_bits));
//print_arraybinary(id_bits,sizeof(id_bits));
PrintAndLog(" binary: %s", printBits(4, id) );
//size_t idx = 0;
size_t BitLen = DemodBufferLen;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
memcpy(BitStream, DemodBuffer, BitLen);
// if (VikingDecode(BitStream,BitLen,&idx,id_bits,sizeof(id_bits)) == 1)
// {
// setDemodBuf(BitStream,64, idx);
// PrintAndLog("Found Viking tag\n");
// CmdPrintDemodBuff("x");
// }
// else
// {
// PrintAndLog("Not found Viking tag\n");
// }
return 0;
}
int AMVikingDemod(const uint8_t *id){
// demod am clock 32 fail
if (!ASKDemod("32",g_debugMode,false,1))
return 0;
// search for the card id from bitstream.
return AmVikingDecode(id);
}
//by Gusto
// takes 1 argument <8 bytes of Hex number on the card
// print binary found and saves in grapbuffer for further commands
int CmdAMVikingDemod(const char *Cmd){
uint8_t id[4];
if (param_gethex(Cmd,0,id,8) == 1)
{
PrintAndLog("Usage: data vikingdemod CardID 8 bytes of hex number");
return 0;
}
PrintAndLog("Card ID : %02X%02X%02X%02X\n",id[0],id[1],id[2],id[3]);
// try to demod AMViking
return AMVikingDemod(id);
}
int CmdGrid(const char *Cmd)
{
sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
@@ -1954,11 +2003,6 @@ int CmdHpf(const char *Cmd)
RepaintGraphWindow();
return 0;
}
typedef struct {
uint8_t * buffer;
uint32_t numbits;
uint32_t position;
} BitstreamOut;
bool _headBit( BitstreamOut *stream)
{
@@ -2276,6 +2320,99 @@ 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"},
@@ -2284,12 +2421,14 @@ static command_t CommandTable[] =
{"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II 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"},
{"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
{"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"},
{"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"},
{"vikingdemod", CmdAMVikingDemod, 1, "Demodulate a Viking AM tag from GraphBuffer"},
//{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"},
{"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"},
{"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"},
@@ -2298,6 +2437,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"},

View File

@@ -67,7 +67,8 @@ int PSKDemod(const char *Cmd, bool verbose);
int NRZrawDemod(const char *Cmd, bool verbose);
void printEM410x(uint32_t hi, uint64_t id);
int getSamples(const char *Cmd, bool silent);
int AMVikingDemod(const uint8_t *cardid);
int CmdAMVikingDemod(const char *cmd);
#define MAX_DEMOD_BUF_LEN (1024*128)
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];

View File

@@ -531,7 +531,7 @@ 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 {

View File

@@ -34,7 +34,7 @@ start:
SendCommand(&c);
//flush queue
while (ukbhit()) getchar();
while (ukbhit()) getchar();
// wait cycle
while (true) {
@@ -59,6 +59,7 @@ start:
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;
case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;
case -4 : PrintAndLog("The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). This needs to be fixed.\n"); break;
default: ;
}
break;
@@ -80,7 +81,7 @@ start:
} else {
isOK = 0;
printf("------------------------------------------------------------------\n");
PrintAndLog("Found valid key:%012"llx" \n", r_key);
PrintAndLog("Found valid key: %012"llx" \n", r_key);
}
PrintAndLog("");
@@ -1210,13 +1211,13 @@ int CmdHF14AMfELoad(const char *Cmd)
uint8_t buf8[64] = {0x00};
int i, len, blockNum, numBlocks;
int nameParamNo = 1;
uint8_t blockWidth = 32;
char ctmp = param_getchar(Cmd, 0);
if ( ctmp == 'h' || ctmp == 0x00) {
PrintAndLog("It loads emul dump from the file `filename.eml`");
PrintAndLog("Usage: hf mf eload [card memory] <file name w/o `.eml`>");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL");
PrintAndLog("");
PrintAndLog(" sample: hf mf eload filename");
PrintAndLog(" hf mf eload 4 filename");
@@ -1229,6 +1230,8 @@ int CmdHF14AMfELoad(const char *Cmd)
case '\0': numBlocks = 16*4; break;
case '2' : numBlocks = 32*4; break;
case '4' : numBlocks = 256; break;
case 'U' : // fall through
case 'u' : numBlocks = 255; blockWidth = 8; break;
default: {
numBlocks = 16*4;
nameParamNo = 0;
@@ -1263,19 +1266,18 @@ int CmdHF14AMfELoad(const char *Cmd)
return 2;
}
if (strlen(buf) < 32){
if (strlen(buf) < blockWidth){
if(strlen(buf) && feof(f))
break;
PrintAndLog("File content error. Block data must include 32 HEX symbols");
PrintAndLog("File content error. Block data must include %d HEX symbols", blockWidth);
fclose(f);
return 2;
}
for (i = 0; i < 32; i += 2) {
for (i = 0; i < blockWidth; i += 2) {
sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]);
}
if (mfEmlSetMem(buf8, blockNum, 1)) {
if (mfEmlSetMem_xt(buf8, blockNum, 1, blockWidth/2)) {
PrintAndLog("Cant set emul block: %3d", blockNum);
fclose(f);
return 3;

View File

@@ -58,12 +58,21 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = {
};
#define MAX_UL_TYPES 18
uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203,
NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL};
uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {
UNKNOWN, UL, UL_C,
UL_EV1_48, UL_EV1_128, NTAG,
NTAG_203, NTAG_210, NTAG_212,
NTAG_213, NTAG_215, NTAG_216,
MY_D, MY_D_NFC, MY_D_MOVE,
MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL};
uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS,
MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213,
MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS};
uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {
MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS,
MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS, MAX_NTAG_203,
MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212,
MAX_NTAG_213, MAX_NTAG_215, MAX_NTAG_216,
MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE,
MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS};
static int CmdHelp(const char *Cmd);
@@ -799,6 +808,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
}
}
// Read signature
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) {
uint8_t ulev1_signature[32] = {0x00};
status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature));
@@ -814,6 +824,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
}
}
// Get Version
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) {
uint8_t version[10] = {0x00};
status = ulev1_getVersion(version, sizeof(version));

View File

@@ -405,6 +405,7 @@ int CmdTune(const char *Cmd)
int CmdVersion(const char *Cmd)
{
clearCommandBuffer();
UsbCommand c = {CMD_VERSION};
static UsbCommand resp = {0, {0, 0, 0}};
@@ -430,13 +431,11 @@ int CmdStatus(const char *Cmd)
{
uint8_t speed_test_buffer[USB_CMD_DATA_SIZE];
sample_buf = speed_test_buffer;
#define USB_SPEED_TEST_SIZE (100*USB_CMD_DATA_SIZE)
clearCommandBuffer();
UsbCommand c = {CMD_STATUS, {USB_SPEED_TEST_SIZE}};
UsbCommand c = {CMD_STATUS};
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) {
PrintAndLog("Status command failed. USB Speed Test timed out");
}
return 0;
@@ -449,40 +448,39 @@ int CmdPing(const char *Cmd)
UsbCommand resp;
UsbCommand c = {CMD_PING};
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
if (WaitForResponseTimeout(CMD_ACK,&resp,1000))
PrintAndLog("Ping successfull");
}else{
PrintAndLog("Ping failed");
}
return 0;
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"},
{"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}
{NULL, NULL, 0, NULL}
};
int CmdHW(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

@@ -30,22 +30,69 @@
#include "cmdlfpcf7931.h"
#include "cmdlfio.h"
#include "lfdemod.h"
#include "cmdlfviking.h"
static int CmdHelp(const char *Cmd);
int usage_lf_cmdread()
{
PrintAndLog("Usage: lf cmdread <delay off> <zero> <one> <cmdbytes> [H] ");
PrintAndLog("Options: ");
PrintAndLog(" h This help");
PrintAndLog(" L Low frequency (125 KHz)");
PrintAndLog(" H High frequency (134 KHz)");
PrintAndLog(" H delay OFF");
PrintAndLog(" H time period ZERO");
PrintAndLog(" H time period ONE");
PrintAndLog("Examples:");
PrintAndLog(" lf cmdread 80 100 200 11000");
PrintAndLog(" lf cmdread 80 100 100 11000 H");
return 0;
}
/* send a command before reading */
int CmdLFCommandRead(const char *Cmd)
{
static char dummy[3];
static char dummy[3] = {0x20,0x00,0x00};
bool errors = FALSE;
uint8_t divisor = 0; //125khz
uint8_t cmdp =0;
while(param_getchar(Cmd, cmdp) != 0x00)
{
switch(param_getchar(Cmd, cmdp))
{
case 'h':
return usage_lf_cmdread();
case 'H':
divisor = 88;
cmdp++;
break;
case 'a':
//param_getchar(Cmd, cmdp+1) == '1';
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;
dummy[0]= ' ';
//Validations
if(errors) return usage_lf_cmdread();
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'
strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
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'
strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
SendCommand(&c);
return 0;
PrintAndLog("ICE: %d %s -- %s", strlen((char *)c.d.asBytes) ,dummy, c.d.asBytes);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
int CmdFlexdemod(const char *Cmd)
@@ -1074,7 +1121,7 @@ int CmdLFfind(const char *Cmd)
ans=CmdG_Prox_II_Demod("");
if (ans>0) {
PrintAndLog("\nValid G Prox II ID Found!");
PrintAndLog("\nValid Guardall G-Prox II ID Found!");
return 1;
}
@@ -1165,7 +1212,7 @@ static command_t CommandTable[] =
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"t55xx", CmdLFT55XX, 1, "{ T55X7 RFIDs... }"},
{"viking", CmdLFViking, 1, "{ Viking RFIDs... }"},
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h' 134] \n\t\t-- Modulate LF reader field to send command before read (all periods in microseconds)"},

View File

@@ -368,6 +368,7 @@ bool tryDetectModulation(){
}
} else {
clk = GetAskClock("", FALSE, FALSE);
if (clk>0) {
sprintf(cmdStr,"%d", clk/2);
CmdLtrim(cmdStr);

View File

@@ -10,6 +10,26 @@
#ifndef CMDLFT55XX_H__
#define CMDLFT55XX_H__
// config blocks
#define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // compat mode, data rate 32, manchester, ST, 7 data blocks
#define T55X7_RAW_CONFIG_BLOCK 0x000880E0 // compat mode, data rate 32, manchester, 7 data blocks
#define T55X7_EM_UNIQUE_CONFIG_BLOCK 0x00148040 // emulate em4x02/unique - compat mode, manchester, data rate 64, 2 data blocks
// FDXB requires data inversion and BiPhase 57 is simply BipHase 50 inverted, so we can either do it using the modulation scheme or the inversion flag
// we've done both below to prove that it works either way, and the modulation value for BiPhase 50 in the Atmel data sheet of binary "10001" (17) is a typo,
// and it should actually be "10000" (16)
// #define T55X7_FDXB_CONFIG_BLOCK 903F8080 // emulate fdx-b - xtended mode, BiPhase ('57), data rate 32, 4 data blocks
#define T55X7_FDXB_CONFIG_BLOCK 0x903F0082 // emulate fdx-b - xtended mode, BiPhase ('50), invert data, data rate 32, 4 data blocks
#define T55X7_HID_26_CONFIG_BLOCK 0x00107060 // hid 26 bit - compat mode, FSK2a, data rate 50, 3 data blocks
#define T55X7_INDALA_64_CONFIG_BLOCK 0x00081040 // emulate indala 64 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 2
#define T55X7_INDALA_224_CONFIG_BLOCK 0x000810E0 // emulate indala 224 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 7
#define T55X7_GUARDPROXII_CONFIG_BLOCK 0x00150060 // bitrate 64pcb, Direct modulation, Biphase, 3 data blocks
#define T55X7_VIKING_CONFIG_BLOCK 0x00088040 // compat mode, data rate 32, Manchester, 2 data blocks
#define T55X7_bin 0b0010
typedef struct {
enum {
DEMOD_NRZ = 0x00,

65
client/cmdlfviking.c Normal file
View File

@@ -0,0 +1,65 @@
#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 CmdVikingDemod(const char *Cmd)
{
uint8_t id[4];
if (param_gethex(Cmd,0,id,8) == 1)
{
PrintAndLog("Usage: lf viking demod <CardID 8 bytes of hex number>");
return 0;
}
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {false,0,0}};
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
getSamples("40000",true);
// try to demod AMViking
return AMVikingDemod(id);
}
int CmdVikingClone(const char *Cmd)
{
uint32_t b1,b2;
// get the tag number 64 bits (8 bytes) in hex
uint8_t id[8];
if (param_gethex(Cmd,0,id,16) == 1)
{
PrintAndLog("Usage: lf viking clone <Card ID 16 bytes of hex number>");
return 0;
}
b1 = bytes_to_num(id,sizeof(uint32_t));
b2 = bytes_to_num(id + sizeof(uint32_t),sizeof(uint32_t));
UsbCommand c = {CMD_VIKING_CLONE_TAG,{b1,b2}};
SendCommand(&c);
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"demod",CmdVikingDemod ,1, "<8 digits tag id> -- Extract tag data"},
{"clone", CmdVikingClone, 1, "<16 digits card data> clone 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;
}

7
client/cmdlfviking.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef CMDLFVIKING_H__
#define CMDLFVIKING_H__
int CmdLFViking(const char *Cmd);
int CmdVikingDemod(const char *Cmd);
int CmdVikingClone(const char *Cmd);
#endif

View File

@@ -36,6 +36,7 @@ static int CmdRev(const char *Cmd);
static int CmdLS(const char *Cmd);
//For storing command that are received from the device
#define CMD_BUFFER_SIZE 50
static UsbCommand cmdBuffer[CMD_BUFFER_SIZE];
//Points to the next empty position to write to
static int cmd_head;//Starts as 0
@@ -149,9 +150,9 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou
response = &resp;
// Wait until the command is received
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
for ( size_t dm_seconds = 0; dm_seconds < ms_timeout/10; dm_seconds++ ) {
while(getCommand(response)) {
while( getCommand(response) ) {
if(response->cmd == cmd){
return true;
}
@@ -166,7 +167,7 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou
}
bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
return WaitForResponseTimeout(cmd,response,-1);
return WaitForResponseTimeout(cmd, response, -1);
}
//-----------------------------------------------------------------------------
@@ -203,8 +204,10 @@ void UsbCommandReceived(UsbCommand *UC)
return;
} break;
default: break;
}
default:
storeCommand(UC);
break;
}
}

View File

@@ -98,6 +98,7 @@ typedef struct{
#define CMD_ASK_SIM_TAG 0x021F
#define CMD_PSK_SIM_TAG 0x0220
#define CMD_AWID_DEMOD_FSK 0x0221
#define CMD_VIKING_CLONE_TAG 0x0222
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */

View File

@@ -56,7 +56,8 @@ local _commands = {
CMD_ASK_SIM_TAG = 0x021F,
CMD_PSK_SIM_TAG = 0x0220,
CMD_AWID_DEMOD_FSK = 0x0221,
CMD_VIKING_CLONE_TAG = 0x0222,
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
--// For the 13.56 MHz tags
@@ -198,7 +199,7 @@ Command = {
return o
end,
parse = function(packet)
local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH512', packet)
local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet)
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
end

View File

@@ -93,16 +93,16 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
return resp.arg[0]; // error during nested
}
memcpy(&uid, resp.d.asBytes, 4);
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);
}
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
@@ -190,8 +190,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
}
free(statelists[0].head.slhead);
free(statelists[1].head.slhead);
free(statelists[1].head.slhead);
return 0;
}
@@ -201,8 +200,9 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}};
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) return 1;
if ((resp.arg[0] & 0xff) != 0x01) return 2;
@@ -214,8 +214,8 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1;
memcpy(data, resp.d.asBytes, blocksCount * 16);
@@ -223,8 +223,14 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
}
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};
memcpy(c.d.asBytes, data, blocksCount * 16);
return mfEmlSetMem_xt(data, blockNum, blocksCount, 16);
}
int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, blockBtWidth}};
memcpy(c.d.asBytes, data, blocksCount * blockBtWidth);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
@@ -264,8 +270,9 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
uint8_t isOK = 0;
UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};
memcpy(c.d.asBytes, data, 16);
SendCommand(&c);
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
isOK = resp.arg[0] & 0xff;
@@ -284,9 +291,10 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
uint8_t isOK = 0;
UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
isOK = resp.arg[0] & 0xff;
memcpy(data, resp.d.asBytes, 16);

View File

@@ -54,6 +54,7 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe);
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params);

View File

@@ -29,50 +29,48 @@ int compar_state(const void * a, const void * b) {
}
int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key) {
struct Crypto1State *state;
uint32_t i, pos, rr, nr_diff, key_count;//, ks1, ks2;
byte_t bt, ks3x[8], par[8][8];
uint64_t key_recovered;
int64_t *state_s;
static uint32_t last_uid;
static int64_t *last_keylist;
rr = 0;
struct Crypto1State *state;
uint32_t i, pos, rr, nr_diff, key_count;//, ks1, ks2;
byte_t bt, ks3x[8], par[8][8];
uint64_t key_recovered;
int64_t *state_s;
static uint32_t last_uid;
static int64_t *last_keylist;
rr = 0;
if (last_uid != uid && last_keylist != NULL)
{
free(last_keylist);
last_keylist = NULL;
}
last_uid = uid;
if (last_uid != uid && last_keylist != NULL) {
free(last_keylist);
last_keylist = NULL;
}
last_uid = uid;
// Reset the last three significant bits of the reader nonce
nr &= 0xffffff1f;
// Reset the last three significant bits of the reader nonce
nr &= 0xffffff1f;
PrintAndLog("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx") nr(%08"llx")\n\n",uid,nt,par_info,ks_info,nr);
PrintAndLog("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx") nr(%08"llx")\n\n", uid, nt, par_info, ks_info, nr);
for (pos=0; pos<8; pos++)
{
ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
bt = (par_info >> (pos*8)) & 0xff;
for (i=0; i<8; i++)
{
par[7-pos][i] = (bt >> i) & 0x01;
}
}
for (pos=0; pos<8; pos++) {
ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
bt = (par_info >> (pos*8)) & 0xff;
for (i=0; i<8; i++) {
par[7-pos][i] = (bt >> i) & 0x01;
}
}
printf("|diff|{nr} |ks3|ks3^5|parity |\n");
printf("+----+--------+---+-----+---------------+\n");
for (i=0; i<8; i++)
{
nr_diff = nr | i << 5;
printf("| %02x |%08x|",i << 5, nr_diff);
printf(" %01x | %01x |",ks3x[i], ks3x[i]^5);
for (pos=0; pos<7; pos++) printf("%01x,", par[i][pos]);
printf("%01x|\n", par[i][7]);
}
if (par_info==0)
PrintAndLog("parity is all zero,try special attack!just wait for few more seconds...");
printf("|diff|{nr} |ks3|ks3^5|parity |\n");
printf("+----+--------+---+-----+---------------+\n");
for (i=0; i<8; i++) {
nr_diff = nr | i << 5;
printf("| %02x |%08x|", i << 5, nr_diff);
printf(" %01x | %01x |", ks3x[i], ks3x[i]^5);
for (pos=0; pos<7; pos++)
printf("%01x,", par[i][pos]);
printf("%01x|\n", par[i][7]);
}
printf("+----+--------+---+-----+---------------+\n");
if ( par_info == 0 )
PrintAndLog("Parity is all zero, try special attack! Wait for few more seconds...");
state = lfsr_common_prefix(nr, rr, ks3x, par, par_info==0);
state_s = (int64_t*)state;
@@ -97,56 +95,58 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_
*(state_s + i) = -1;
//Create the intersection:
if (par_info == 0 )
if ( last_keylist != NULL)
{
if (par_info == 0 ) {
if ( last_keylist != NULL) {
int64_t *p1, *p2, *p3;
p1 = p3 = last_keylist;
p2 = state_s;
while ( *p1 != -1 && *p2 != -1 ) {
if (compar_state(p1, p2) == 0) {
printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n",(uint64_t)(p1-last_keylist),(uint64_t)(p2-state_s),(uint64_t)(p3-last_keylist),*p1);
printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n",
(uint64_t)(p1-last_keylist),
(uint64_t)(p2-state_s),
(uint64_t)(p3-last_keylist),
*p1);
*p3++ = *p1++;
p2++;
}
else {
} else {
while (compar_state(p1, p2) == -1) ++p1;
while (compar_state(p1, p2) == 1) ++p2;
}
}
key_count = p3 - last_keylist;;
}
else
key_count = p3 - last_keylist;
} else {
key_count = 0;
else
{
}
} else {
last_keylist = state_s;
key_count = i;
}
printf("key_count:%d\n", key_count);
printf("key candidates count: %d\n", key_count);
// The list may still contain several key candidates. Test each of them with mfCheckKeys
int res;
uint8_t keyBlock[6];
uint64_t key64;
for (i = 0; i < key_count; i++) {
uint8_t keyBlock[6];
uint64_t key64;
key64 = *(last_keylist + i);
num_to_bytes(key64, 6, keyBlock);
key64 = 0;
if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) {
res = mfCheckKeys(0, 0, false, 1, keyBlock, &key64);
if (!res) {
*key = key64;
free(last_keylist);
last_keylist = NULL;
if (par_info ==0)
if (par_info == 0)
free(state);
return 0;
}
}
free(last_keylist);
last_keylist = state_s;
return 1;
}
@@ -243,7 +243,6 @@ int tryMfk32_moebius(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){
return isSuccess;
}
int tryMfk64(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){
struct Crypto1State *revstate;

View File

@@ -0,0 +1,122 @@
-- The getopt-functionality is loaded from pm3/getopt.lua
-- Have a look there for further details
getopt = require('getopt')
bin = require('bin')
example = "script run dumptoemul -i dumpdata-foobar.bin"
author = "Martin Holst Swende"
usage = "script run dumptoemul [-i <file>] [-o <file>]"
desc =[[
This script takes a dumpfile from 'hf mf dump' and converts it to a format that can be used
by the emulator
Arguments:
-h This help
-i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
-o <filename> Specifies the output file. If omitted, <uid>.eml is used.
]]
-------------------------------
-- Some utilities
-------------------------------
---
-- A debug printout-function
function dbg(args)
if DEBUG then
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
end
local function convert_to_ascii(hexdata)
if string.len(hexdata) % 8 ~= 0 then
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
end
local js,i = "[";
for i = 1, string.len(hexdata),8 do
js = js .."'" ..string.sub(hexdata,i,i+7).."',\n"
end
js = js .. "]"
return js
end
local function readdump(infile)
t = infile:read("*all")
--print(string.len(t))
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
--print(len,hex)
return hex
end
local function convert_to_emulform(hexdata)
if string.len(hexdata) % 8 ~= 0 then
return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
end
local ascii,i = "";
for i = 1, string.len(hexdata),8 do
ascii = ascii ..string.sub(hexdata,i,i+7).."\n"
end
return string.sub(ascii,1,-1)
end
local function main(args)
local input = "dumpdata.bin"
local output
for o, a in getopt.getopt(args, 'i:o:h') do
if o == "h" then return help() end
if o == "i" then input = a end
if o == "o" then output = a end
end
-- Validate the parameters
local infile = io.open(input, "rb")
if infile == nil then
return oops("Could not read file ", input)
end
local dumpdata = readdump(infile)
-- The hex-data is now in ascii-format,
-- But first, check the uid
local uid = string.sub(dumpdata,1,8)
output = output or (uid .. ".eml")
-- Format some linebreaks
dumpdata = convert_to_emulform(dumpdata)
local outfile = io.open(output, "w")
if outfile == nil then
return oops("Could not write to file ", output)
end
outfile:write(dumpdata:lower())
io.close(outfile)
print(("Wrote an emulator-dump to the file %s"):format(output))
end
--[[
In the future, we may implement so that scripts are invoked directly
into a 'main' function, instead of being executed blindly. For future
compatibility, I have done so, but I invoke my main from here.
--]]
main(args)

View File

@@ -112,6 +112,8 @@ function mfcrack_inner()
return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK == 0xFFFFFFFD then
return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK == 0xFFFFFFFC then
return nil, "The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK ~= 1 then
return nil, "Error occurred"
end

View File

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