mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-30 19:40:09 -07:00
Merge branch 'master' into topaz
This commit is contained in:
commit
8e21541e77
43 changed files with 1519 additions and 231 deletions
|
@ -90,6 +90,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
cmdlf.c \
|
||||
cmdlfio.c \
|
||||
cmdlfhid.c \
|
||||
cmdlfawid.c \
|
||||
cmdlfem4x.c \
|
||||
cmdlfhitag.c \
|
||||
cmdlfti.c \
|
||||
|
|
122
client/cmddata.c
122
client/cmddata.c
|
@ -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)
|
||||
|
@ -1491,9 +1492,9 @@ int CmdFDXBdemodBI(const char *Cmd){
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -1943,26 +1944,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;
|
||||
}
|
||||
|
@ -2002,7 +1991,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,6 +2254,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"},
|
||||
|
@ -2273,6 +2355,7 @@ 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"},
|
||||
|
@ -2287,6 +2370,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"},
|
||||
|
|
|
@ -484,7 +484,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 {
|
||||
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -18,7 +18,6 @@ int CmdHF14AMifare(const char *Cmd)
|
|||
uint32_t nt = 0, nr = 0;
|
||||
uint64_t par_list = 0, ks_list = 0, r_key = 0;
|
||||
int16_t isOK = 0;
|
||||
uint8_t keyBlock[8] = {0};
|
||||
|
||||
UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}};
|
||||
|
||||
|
@ -74,22 +73,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("");
|
||||
|
@ -689,7 +679,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;
|
||||
|
@ -973,7 +963,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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "util.h"
|
||||
#include "cmdlf.h"
|
||||
#include "cmdlfhid.h"
|
||||
#include "cmdlfawid.h"
|
||||
#include "cmdlfti.h"
|
||||
#include "cmdlfem4x.h"
|
||||
#include "cmdlfhitag.h"
|
||||
|
@ -388,7 +389,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.");
|
||||
|
@ -1130,6 +1131,7 @@ static command_t CommandTable[] =
|
|||
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
|
||||
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
|
||||
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
||||
{"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"},
|
||||
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
||||
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
||||
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
|
||||
|
|
237
client/cmdlfawid.c
Normal file
237
client/cmdlfawid.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "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(" sample : 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("");
|
||||
PrintAndLog(" sample : lf awid clone 224 1337");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdAWIDDemodFSK(const char *Cmd)
|
||||
{
|
||||
int findone=0;
|
||||
if(Cmd[0]=='1') findone=1;
|
||||
if (Cmd[0]=='h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod();
|
||||
UsbCommand c={CMD_AWID_DEMOD_FSK};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getAWIDBits(unsigned int fc, unsigned int cn, uint8_t *AWIDBits)
|
||||
{
|
||||
int i;
|
||||
uint32_t fcode=(fc & 0x000000FF), cnum=(cn & 0x0000FFFF), uBits=0;
|
||||
if (fcode != fc)
|
||||
PrintAndLog("NOTE: Facility code truncated for AWID26 format (8-bit facility code)");
|
||||
if (cnum!=cn)
|
||||
PrintAndLog("NOTE: Card number was truncated for AWID26 format (16-bit card number)");
|
||||
|
||||
AWIDBits[0] = 0x01; // 6-bit Preamble with 2 parity bits
|
||||
AWIDBits[1] = 0x1D; // First byte from card format (26-bit) plus parity bits
|
||||
AWIDBits[2] = 0x80; // Set the next two bits as 0b10 to finish card format
|
||||
uBits = (fcode<<4) + (cnum>>12);
|
||||
if (!parityTest(uBits,12,0))
|
||||
AWIDBits[2] |= (1<<5); // If not already even parity, set bit to make even
|
||||
uBits = AWIDBits[2]>>5;
|
||||
if (!parityTest(uBits, 3, 1))
|
||||
AWIDBits[2] |= (1<<4);
|
||||
uBits = fcode>>5; // first 3 bits of facility-code
|
||||
AWIDBits[2] += (uBits<<1);
|
||||
if (!parityTest(uBits, 3, 1))
|
||||
AWIDBits[2]++; // Set parity bit to make odd parity
|
||||
uBits = (fcode & 0x1C)>>2;
|
||||
AWIDBits[3] = 0;
|
||||
if (!parityTest(uBits,3,1))
|
||||
AWIDBits[3] |= (1<<4);
|
||||
AWIDBits[3] += (uBits<<5);
|
||||
uBits = ((fcode & 0x3)<<1) + ((cnum & 0x8000)>>15); // Grab/shift 2 LSBs from facility code and add shifted MSB from cardnum
|
||||
if (!parityTest(uBits,3,1))
|
||||
AWIDBits[3]++; // Set LSB for parity
|
||||
AWIDBits[3]+= (uBits<<1);
|
||||
uBits = (cnum & 0x7000)>>12;
|
||||
AWIDBits[4] = uBits<<5;
|
||||
if (!parityTest(uBits,3,1))
|
||||
AWIDBits[4] |= (1<<4);
|
||||
uBits = (cnum & 0x0E00)>>9;
|
||||
AWIDBits[4] += (uBits<<1);
|
||||
if (!parityTest(uBits,3,1))
|
||||
AWIDBits[4]++; // Set LSB for parity
|
||||
uBits = (cnum & 0x1C0)>>6; // Next bits from card number
|
||||
AWIDBits[5]=(uBits<<5);
|
||||
if (!parityTest(uBits,3,1))
|
||||
AWIDBits[5] |= (1<<4); // Set odd parity bit as needed
|
||||
uBits = (cnum & 0x38)>>3;
|
||||
AWIDBits[5]+= (uBits<<1);
|
||||
if (!parityTest(uBits,3,1))
|
||||
AWIDBits[5]++; // Set odd parity bit as needed
|
||||
uBits = (cnum & 0x7); // Last three bits from card number!
|
||||
AWIDBits[6] = (uBits<<5);
|
||||
if (!parityTest(uBits,3,1))
|
||||
AWIDBits[6] |= (1<<4);
|
||||
uBits = (cnum & 0x0FFF);
|
||||
if (!parityTest(uBits,12,1))
|
||||
AWIDBits[6] |= (1<<3);
|
||||
else
|
||||
AWIDBits[6]++;
|
||||
for (i = 7; i<12; i++)
|
||||
AWIDBits[i]=0x11;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdAWIDSim(const char *Cmd)
|
||||
{
|
||||
uint32_t fcode = 0, cnum = 0, fc=0, cn=0, i=0;
|
||||
uint8_t *BS, BitStream[12];
|
||||
uint64_t arg1 = (10<<8) + 8; // fcHigh = 10, fcLow = 8
|
||||
uint64_t arg2 = 50; // clk RF/50 invert=0
|
||||
BS = BitStream;
|
||||
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) {
|
||||
return usage_lf_awid_sim();
|
||||
}
|
||||
|
||||
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");
|
||||
// AWID uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0
|
||||
if (getAWIDBits(fc, cn, BS)) {
|
||||
PrintAndLog("Running 'lf simfsk c 50 H 10 L 8 d %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'",
|
||||
BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6],
|
||||
BS[7],BS[8],BS[9],BS[10],BS[11]);
|
||||
} else
|
||||
PrintAndLog("Error with tag bitstream generation.");
|
||||
UsbCommand c;
|
||||
c.cmd = CMD_FSK_SIM_TAG;
|
||||
c.arg[0] = arg1; // fcHigh<<8 + fcLow
|
||||
c.arg[1] = arg2; // Inversion and clk setting
|
||||
c.arg[2] = 96; // Bitstream length: 96-bits == 12 bytes
|
||||
for (i=0; i < 96; i++)
|
||||
c.d.asBytes[i] = (BS[i/8] & (1<<(7-(i%8))))?1:0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdAWIDClone(const char *Cmd)
|
||||
{
|
||||
uint32_t fc=0,cn=0,blocks[4] = {0x00107060, 0, 0, 0x11111111}, i=0;
|
||||
uint8_t BitStream[12];
|
||||
uint8_t *BS=BitStream;
|
||||
UsbCommand c, resp;
|
||||
|
||||
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) {
|
||||
return usage_lf_awid_clone();
|
||||
}
|
||||
|
||||
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("Preparing to clone AWID26 to T55x7 with FC: %u, CN: %u (Raw: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x)",
|
||||
fc,cn, BS[0],BS[1],BS[2],BS[3],BS[4],BS[5],BS[6],BS[7],BS[8],BS[9],BS[10],BS[11]);
|
||||
blocks[1] = (BS[0]<<24) + (BS[1]<<16) + (BS[2]<<8) + (BS[3]);
|
||||
blocks[2] = (BS[4]<<24) + (BS[5]<<16) + (BS[6]<<8) + (BS[7]);
|
||||
PrintAndLog("Block 0: 0x%08x", blocks[0]);
|
||||
PrintAndLog("Block 1: 0x%08x", blocks[1]);
|
||||
PrintAndLog("Block 2: 0x%08x", blocks[2]);
|
||||
PrintAndLog("Block 3: 0x%08x", blocks[3]);
|
||||
for (i=0; i<4; i++) {
|
||||
c.cmd = CMD_T55XX_WRITE_BLOCK;
|
||||
c.arg[0] = blocks[i];
|
||||
c.arg[1] = i;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
|
||||
PrintAndLog("Error occurred, device did not respond during write operation.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
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> -- 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
24
client/cmdlfawid.h
Normal 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
|
|
@ -242,6 +242,7 @@ int CmdT55xxReadBlock(const char *Cmd) {
|
|||
c.d.asBytes[0] = 0x1;
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
|
||||
PrintAndLog("command execution time out");
|
||||
|
@ -670,6 +671,7 @@ int CmdT55xxWriteBlock(const char *Cmd)
|
|||
}
|
||||
|
||||
UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}};
|
||||
UsbCommand resp;
|
||||
c.d.asBytes[0] = 0x0;
|
||||
|
||||
PrintAndLog("Writing to block: %d data : 0x%08X", block, data);
|
||||
|
@ -680,7 +682,12 @@ int CmdT55xxWriteBlock(const char *Cmd)
|
|||
c.d.asBytes[0] = 0x1;
|
||||
PrintAndLog("pwd : 0x%08X", password);
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
|
||||
PrintAndLog("Error occurred, device did not ACK write operation. (May be due to old firmware)");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -878,6 +885,7 @@ int AquireData( uint8_t block ){
|
|||
// c.d.asBytes[0] = 0x1;
|
||||
// }
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
|
||||
PrintAndLog("command execution time out");
|
||||
|
|
|
@ -97,8 +97,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
|
||||
|
@ -117,9 +118,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.
|
||||
|
@ -131,33 +132,34 @@ 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.
|
||||
|
@ -166,6 +168,7 @@ void CommandReceived(char *Cmd) {
|
|||
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.
|
||||
|
@ -189,12 +192,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ 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
|
||||
|
||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -54,6 +55,7 @@ local _commands = {
|
|||
CMD_FSK_SIM_TAG = 0x021E,
|
||||
CMD_ASK_SIM_TAG = 0x021F,
|
||||
CMD_PSK_SIM_TAG = 0x0220,
|
||||
CMD_AWID_DEMOD_FSK = 0x0221,
|
||||
|
||||
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
|
|
|
@ -181,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;
|
||||
}
|
||||
|
@ -193,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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -88,10 +88,33 @@ 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 ~= 1 then
|
||||
return nil, "Error occurred"
|
||||
end
|
||||
|
||||
|
||||
-- The data-part is left
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue