mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-20 21:33:19 -07:00
1. fixed hf 14a mifare. added functionality to ignore one Nt
2. completed hf 14a nested 3. added hf 14a chk to check keys 5. added check keys to hf 14a mifare and hf 14a nested 6. added debug level to mifare commands 7. small bugs and improvements
This commit is contained in:
parent
50193c1e3e
commit
f397b5cc87
16 changed files with 877 additions and 317 deletions
197
client/mifarehost.c
Normal file
197
client/mifarehost.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
// Merlok, 2011
|
||||
// people from mifare@nethemba.com, 2010
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// High frequency ISO14443A commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "mifarehost.h"
|
||||
|
||||
|
||||
int compar_int(const void * a, const void * b) {
|
||||
return (*(uint64_t*)b - *(uint64_t*)a);
|
||||
}
|
||||
|
||||
// Compare countKeys structure
|
||||
int compar_special_int(const void * a, const void * b) {
|
||||
return (((countKeys *)b)->count - ((countKeys *)a)->count);
|
||||
}
|
||||
|
||||
countKeys * uniqsort(uint64_t * possibleKeys, uint32_t size) {
|
||||
int i, j = 0;
|
||||
int count = 0;
|
||||
countKeys *our_counts;
|
||||
|
||||
qsort(possibleKeys, size, sizeof (uint64_t), compar_int);
|
||||
|
||||
our_counts = calloc(size, sizeof(countKeys));
|
||||
if (our_counts == NULL) {
|
||||
PrintAndLog("Memory allocation error for our_counts");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (possibleKeys[i+1] == possibleKeys[i]) {
|
||||
count++;
|
||||
} else {
|
||||
our_counts[j].key = possibleKeys[i];
|
||||
our_counts[j].count = count;
|
||||
j++;
|
||||
count=0;
|
||||
}
|
||||
}
|
||||
qsort(our_counts, j, sizeof(countKeys), compar_special_int);
|
||||
return (our_counts);
|
||||
}
|
||||
|
||||
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKeys)
|
||||
{
|
||||
int i, m, len;
|
||||
uint8_t isEOF;
|
||||
uint32_t uid;
|
||||
fnVector * vector = NULL;
|
||||
countKeys *ck;
|
||||
int lenVector = 0;
|
||||
UsbCommand * resp = NULL;
|
||||
|
||||
memset(resultKeys, 0x00, 16 * 6);
|
||||
|
||||
// flush queue
|
||||
while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_NESTED, {blockNo, keyType, trgBlockNo + trgKeyType * 0x100}};
|
||||
memcpy(c.d.asBytes, key, 6);
|
||||
SendCommand(&c);
|
||||
|
||||
PrintAndLog("\n");
|
||||
|
||||
// wait cycle
|
||||
while (true) {
|
||||
printf(".");
|
||||
if (ukbhit()) {
|
||||
getchar();
|
||||
printf("\naborted via keyboard!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
resp = WaitForResponseTimeout(CMD_ACK, 1500);
|
||||
|
||||
if (resp != NULL) {
|
||||
isEOF = resp->arg[0] & 0xff;
|
||||
|
||||
if (isEOF) break;
|
||||
|
||||
len = resp->arg[1] & 0xff;
|
||||
if (len == 0) continue;
|
||||
|
||||
memcpy(&uid, resp->d.asBytes, 4);
|
||||
PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%x", uid, len, resp->arg[2] & 0xff, (resp->arg[2] >> 8) & 0xff);
|
||||
vector = (fnVector *) realloc((void *)vector, (lenVector + len) * sizeof(fnVector) + 200);
|
||||
if (vector == NULL) {
|
||||
PrintAndLog("Memory allocation error for fnVector. len: %d bytes: %d", lenVector + len, (lenVector + len) * sizeof(fnVector));
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
vector[lenVector + i].blockNo = resp->arg[2] & 0xff;
|
||||
vector[lenVector + i].keyType = (resp->arg[2] >> 8) & 0xff;
|
||||
vector[lenVector + i].uid = uid;
|
||||
|
||||
memcpy(&vector[lenVector + i].nt, (void *)(resp->d.asBytes + 8 + i * 8 + 0), 4);
|
||||
memcpy(&vector[lenVector + i].ks1, (void *)(resp->d.asBytes + 8 + i * 8 + 4), 4);
|
||||
}
|
||||
|
||||
lenVector += len;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lenVector) {
|
||||
PrintAndLog("Got 0 keys from proxmark.");
|
||||
return 1;
|
||||
}
|
||||
printf("------------------------------------------------------------------\n");
|
||||
|
||||
// calc keys
|
||||
struct Crypto1State* revstate = NULL;
|
||||
struct Crypto1State* revstate_start = NULL;
|
||||
uint64_t lfsr;
|
||||
int kcount = 0;
|
||||
pKeys *pk;
|
||||
|
||||
if ((pk = (void *) malloc(sizeof(pKeys))) == NULL) return 1;
|
||||
memset(pk, 0x00, sizeof(pKeys));
|
||||
|
||||
for (m = 0; m < lenVector; m++) {
|
||||
// And finally recover the first 32 bits of the key
|
||||
revstate = lfsr_recovery32(vector[m].ks1, vector[m].nt ^ vector[m].uid);
|
||||
if (revstate_start == NULL) revstate_start = revstate;
|
||||
|
||||
while ((revstate->odd != 0x0) || (revstate->even != 0x0)) {
|
||||
lfsr_rollback_word(revstate, vector[m].nt ^ vector[m].uid, 0);
|
||||
crypto1_get_lfsr(revstate, &lfsr);
|
||||
|
||||
// Allocate a new space for keys
|
||||
if (((kcount % MEM_CHUNK) == 0) || (kcount >= pk->size)) {
|
||||
pk->size += MEM_CHUNK;
|
||||
//fprintf(stdout, "New chunk by %d, sizeof %d\n", kcount, pk->size * sizeof(uint64_t));
|
||||
pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t));
|
||||
if (pk->possibleKeys == NULL) {
|
||||
PrintAndLog("Memory allocation error for pk->possibleKeys");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pk->possibleKeys[kcount] = lfsr;
|
||||
kcount++;
|
||||
revstate++;
|
||||
}
|
||||
free(revstate_start);
|
||||
revstate_start = NULL;
|
||||
|
||||
}
|
||||
|
||||
// Truncate
|
||||
if (kcount != 0) {
|
||||
pk->size = --kcount;
|
||||
if ((pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t))) == NULL) {
|
||||
PrintAndLog("Memory allocation error for pk->possibleKeys");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog("Total keys count:%d", kcount);
|
||||
ck = uniqsort(pk->possibleKeys, pk->size);
|
||||
|
||||
// fill key array
|
||||
for (i = 0; i < 16 ; i++) {
|
||||
num_to_bytes(ck[i].key, 6, (uint8_t*)(resultKeys + i * 6));
|
||||
}
|
||||
|
||||
// finalize
|
||||
free(pk->possibleKeys);
|
||||
free(pk);
|
||||
free(ck);
|
||||
free(vector);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){
|
||||
*key = 0;
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}};
|
||||
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
|
||||
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 3000);
|
||||
|
||||
if (resp == NULL) return 1;
|
||||
if ((resp->arg[0] & 0xff) != 0x01) return 2;
|
||||
*key = bytes_to_num(resp->d.asBytes, 6);
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue