mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
Merge branch 'RfidResearchGroup:master' into master
This commit is contained in:
commit
6d1b5b8e13
8 changed files with 175 additions and 66 deletions
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
#include "cmdhfmf.h"
|
#include "cmdhfmf.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "commonutil.h" // ARRAYLEN
|
#include "commonutil.h" // ARRAYLEN
|
||||||
#include "comms.h" // clearCommandBuffer
|
#include "comms.h" // clearCommandBuffer
|
||||||
|
@ -38,23 +37,6 @@
|
||||||
#include "wiegand_formats.h"
|
#include "wiegand_formats.h"
|
||||||
#include "wiegand_formatutils.h"
|
#include "wiegand_formatutils.h"
|
||||||
|
|
||||||
#define MIFARE_4K_MAXBLOCK 256
|
|
||||||
#define MIFARE_2K_MAXBLOCK 128
|
|
||||||
#define MIFARE_1K_MAXBLOCK 64
|
|
||||||
#define MIFARE_MINI_MAXBLOCK 20
|
|
||||||
|
|
||||||
#define MIFARE_4K_MAXSECTOR 40
|
|
||||||
#define MIFARE_2K_MAXSECTOR 32
|
|
||||||
#define MIFARE_1K_MAXSECTOR 16
|
|
||||||
#define MIFARE_MINI_MAXSECTOR 5
|
|
||||||
|
|
||||||
#define MIFARE_4K_MAX_BYTES 4096
|
|
||||||
#define MIFARE_2K_MAX_BYTES 2048
|
|
||||||
#define MIFARE_1K_MAX_BYTES 1024
|
|
||||||
#define MIFARE_MINI_MAX_BYTES 320
|
|
||||||
|
|
||||||
#define MIFARE_KEY_SIZE 6
|
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -152,12 +134,12 @@ static char *GenerateFilename(const char *prefix, const char *suffix) {
|
||||||
return fptr;
|
return fptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t initSectorTable(sector_t **src, int32_t items) {
|
static int initSectorTable(sector_t **src, size_t items) {
|
||||||
|
|
||||||
(*src) = calloc(items, sizeof(sector_t));
|
(*src) = calloc(items, sizeof(sector_t));
|
||||||
|
|
||||||
if (*src == NULL)
|
if (*src == NULL)
|
||||||
return -1;
|
return PM3_EMALLOC;
|
||||||
|
|
||||||
// empty e_sector
|
// empty e_sector
|
||||||
for (int i = 0; i < items; ++i) {
|
for (int i = 0; i < items; ++i) {
|
||||||
|
@ -166,7 +148,7 @@ static int32_t initSectorTable(sector_t **src, int32_t items) {
|
||||||
(*src)[i].foundKey[j] = false;
|
(*src)[i].foundKey[j] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_print_st(uint16_t blockno, uint8_t *data) {
|
static void decode_print_st(uint16_t blockno, uint8_t *data) {
|
||||||
|
@ -2373,7 +2355,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
||||||
// Attack key storage variables
|
// Attack key storage variables
|
||||||
uint8_t *keyBlock = NULL;
|
uint8_t *keyBlock = NULL;
|
||||||
uint32_t key_cnt = 0;
|
uint32_t key_cnt = 0;
|
||||||
sector_t *e_sector;
|
|
||||||
uint8_t tmp_key[6] = {0};
|
uint8_t tmp_key[6] = {0};
|
||||||
|
|
||||||
// Nested and Hardnested returned status
|
// Nested and Hardnested returned status
|
||||||
|
@ -2408,7 +2389,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
||||||
iso14a_card_select_t card;
|
iso14a_card_select_t card;
|
||||||
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||||
|
|
||||||
|
|
||||||
// detect MFC EV1 Signature
|
// detect MFC EV1 Signature
|
||||||
bool is_ev1 = detect_mfc_ev1_signature();
|
bool is_ev1 = detect_mfc_ev1_signature();
|
||||||
if (is_ev1) {
|
if (is_ev1) {
|
||||||
|
@ -2417,10 +2397,9 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create/initialize key storage structure
|
// create/initialize key storage structure
|
||||||
uint32_t e_sector_size = sector_cnt > sectorno ? sector_cnt : sectorno + 1;
|
sector_t *e_sector = NULL;
|
||||||
res = initSectorTable(&e_sector, e_sector_size);
|
uint32_t e_sector_cnt = (sector_cnt > sectorno) ? sector_cnt : sectorno + 1;
|
||||||
if (res != e_sector_size) {
|
if (initSectorTable(&e_sector, e_sector_cnt) != PM3_SUCCESS) {
|
||||||
free(e_sector);
|
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2859,7 +2838,7 @@ tryNested:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PM3_ESTATIC_NONCE:
|
case PM3_ESTATIC_NONCE: {
|
||||||
PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
|
PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
|
||||||
|
|
||||||
e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;;
|
e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;;
|
||||||
|
@ -2872,6 +2851,7 @@ tryNested:
|
||||||
free(e_sector);
|
free(e_sector);
|
||||||
free(fptr);
|
free(fptr);
|
||||||
return isOK;
|
return isOK;
|
||||||
|
}
|
||||||
case PM3_SUCCESS: {
|
case PM3_SUCCESS: {
|
||||||
calibrate = false;
|
calibrate = false;
|
||||||
e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, 6);
|
e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, 6);
|
||||||
|
@ -2896,6 +2876,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
|
||||||
slow ? "Yes" : "No");
|
slow ? "Yes" : "No");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foundkey = 0;
|
||||||
isOK = mfnestedhard(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL);
|
isOK = mfnestedhard(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL);
|
||||||
DropField();
|
DropField();
|
||||||
if (isOK) {
|
if (isOK) {
|
||||||
|
@ -3211,8 +3192,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
|
|
||||||
// create/initialize key storage structure
|
// create/initialize key storage structure
|
||||||
sector_t *e_sector = NULL;
|
sector_t *e_sector = NULL;
|
||||||
int32_t res = initSectorTable(&e_sector, sectorsCnt);
|
if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) {
|
||||||
if (res != sectorsCnt) {
|
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
@ -3247,7 +3227,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
if (size == keycnt - i)
|
if (size == keycnt - i)
|
||||||
lastChunk = true;
|
lastChunk = true;
|
||||||
|
|
||||||
res = mfCheckKeys_fast(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false);
|
int res = mfCheckKeys_fast(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false);
|
||||||
|
|
||||||
if (firstChunk)
|
if (firstChunk)
|
||||||
firstChunk = false;
|
firstChunk = false;
|
||||||
|
@ -3454,8 +3434,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
||||||
|
|
||||||
// create/initialize key storage structure
|
// create/initialize key storage structure
|
||||||
sector_t *e_sector = NULL;
|
sector_t *e_sector = NULL;
|
||||||
int32_t res = initSectorTable(&e_sector, SectorsCnt);
|
if (initSectorTable(&e_sector, SectorsCnt) != PM3_SUCCESS) {
|
||||||
if (res != SectorsCnt) {
|
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
@ -3613,28 +3592,24 @@ out:
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void showSectorTable(sector_t *k_sector, uint8_t k_sectorsCount) {
|
void showSectorTable(sector_t *k_sector, uint8_t k_sectors_cnt) {
|
||||||
if (k_sector != NULL) {
|
if (k_sector != NULL) {
|
||||||
printKeyTable(k_sectorsCount, k_sector);
|
printKeyTable(k_sectors_cnt, k_sector);
|
||||||
free(k_sector);
|
free(k_sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readerAttack(sector_t *k_sector, uint8_t k_sectorsCount, nonces_t data, bool setEmulatorMem, bool verbose) {
|
void readerAttack(sector_t *k_sector, uint8_t k_sectors_cnt, nonces_t data, bool setEmulatorMem, bool verbose) {
|
||||||
|
|
||||||
uint64_t key = 0;
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
|
// init if needed
|
||||||
if (k_sector == NULL) {
|
if (k_sector == NULL) {
|
||||||
int32_t res = initSectorTable(&k_sector, k_sectorsCount);
|
if (initSectorTable(&k_sector, k_sectors_cnt) != PM3_SUCCESS) {
|
||||||
if (res != k_sectorsCount) {
|
|
||||||
free(k_sector);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
success = mfkey32_moebius(&data, &key);
|
uint64_t key = 0;
|
||||||
if (success) {
|
if (mfkey32_moebius(&data, &key)) {
|
||||||
uint8_t sector = data.sector;
|
uint8_t sector = data.sector;
|
||||||
uint8_t keytype = data.keytype;
|
uint8_t keytype = data.keytype;
|
||||||
|
|
||||||
|
@ -3649,7 +3624,7 @@ void readerAttack(sector_t *k_sector, uint8_t k_sectorsCount, nonces_t data, boo
|
||||||
|
|
||||||
//set emulator memory for keys
|
//set emulator memory for keys
|
||||||
if (setEmulatorMem) {
|
if (setEmulatorMem) {
|
||||||
uint8_t memBlock[16] = {0, 0, 0, 0, 0, 0, 0xff, 0x0F, 0x80, 0x69, 0, 0, 0, 0, 0, 0};
|
uint8_t memBlock[16] = {0, 0, 0, 0, 0, 0, 0xFF, 0x07, 0x80, 0x69, 0, 0, 0, 0, 0, 0};
|
||||||
num_to_bytes(k_sector[sector].Key[0], 6, memBlock);
|
num_to_bytes(k_sector[sector].Key[0], 6, memBlock);
|
||||||
num_to_bytes(k_sector[sector].Key[1], 6, memBlock + 10);
|
num_to_bytes(k_sector[sector].Key[1], 6, memBlock + 10);
|
||||||
//iceman, guessing this will not work so well for 4K tags.
|
//iceman, guessing this will not work so well for 4K tags.
|
||||||
|
@ -3907,6 +3882,8 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto
|
||||||
PrintAndLogEx(SUCCESS, " Sec | Blk | key A |res| key B |res");
|
PrintAndLogEx(SUCCESS, " Sec | Blk | key A |res| key B |res");
|
||||||
PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
|
PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
|
||||||
|
|
||||||
|
uint64_t ndef_key = 0xD3F7D3F7D3F7;
|
||||||
|
bool has_ndef_key = false;
|
||||||
bool extended_legend = false;
|
bool extended_legend = false;
|
||||||
for (uint8_t i = 0; i < sectorscnt; i++) {
|
for (uint8_t i = 0; i < sectorscnt; i++) {
|
||||||
|
|
||||||
|
@ -3914,20 +3891,32 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto
|
||||||
extended_legend = true;
|
extended_legend = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e_sector[i].Key[0] == ndef_key || e_sector[i].Key[1] == ndef_key) {
|
||||||
|
has_ndef_key = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (e_sector[i].foundKey[0]) {
|
if (e_sector[i].foundKey[0]) {
|
||||||
snprintf(strA, sizeof(strA), _GREEN_("%012" PRIX64), e_sector[i].Key[0]);
|
snprintf(strA, sizeof(strA), _GREEN_("%012" PRIX64), e_sector[i].Key[0]);
|
||||||
|
if (extended_legend) {
|
||||||
snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[0]);
|
snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[0]);
|
||||||
|
} else {
|
||||||
|
snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%d"), e_sector[i].foundKey[0]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(strA, sizeof(strA), _RED_("%s"), "------------");
|
snprintf(strA, sizeof(strA), _RED_("%s"), "------------");
|
||||||
snprintf(resA, sizeof(resA), _RED_("%d"), 0);
|
snprintf(resA, sizeof(resA), _RED_("0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e_sector[i].foundKey[1]) {
|
if (e_sector[i].foundKey[1]) {
|
||||||
snprintf(strB, sizeof(strB), _GREEN_("%012" PRIX64), e_sector[i].Key[1]);
|
snprintf(strB, sizeof(strB), _GREEN_("%012" PRIX64), e_sector[i].Key[1]);
|
||||||
|
if (extended_legend) {
|
||||||
snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[1]);
|
snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[1]);
|
||||||
|
} else {
|
||||||
|
snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%d"), e_sector[i].foundKey[1]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(strB, sizeof(strB), _RED_("%s"), "------------");
|
snprintf(strB, sizeof(strB), _RED_("%s"), "------------");
|
||||||
snprintf(resB, sizeof(resB), _RED_("%d"), 0);
|
snprintf(resB, sizeof(resB), _RED_("0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep track if we use start_sector or i
|
// keep track if we use start_sector or i
|
||||||
|
@ -3964,9 +3953,13 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAD detection
|
// MAD detection
|
||||||
if (e_sector[MF_MAD1_SECTOR].foundKey[0] && e_sector[MF_MAD1_SECTOR].Key[MF_KEY_A] == 0xA0A1A2A3A4A5) {
|
if (e_sector[MF_MAD1_SECTOR].foundKey[0] && e_sector[MF_MAD1_SECTOR].Key[0] == 0xA0A1A2A3A4A5) {
|
||||||
PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
|
PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
|
||||||
}
|
}
|
||||||
|
// NDEF detection
|
||||||
|
if (has_ndef_key) {
|
||||||
|
PrintAndLogEx(HINT, "NDEF key detected. Try " _YELLOW_("`hf mf ndefread`") " for more details");
|
||||||
|
}
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4585,12 +4578,9 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
sector_t *e_sector = NULL;
|
|
||||||
|
|
||||||
// create/initialize key storage structure
|
// create/initialize key storage structure
|
||||||
int32_t res = initSectorTable(&e_sector, sectors_cnt);
|
sector_t *e_sector = NULL;
|
||||||
if (res != sectors_cnt) {
|
if (initSectorTable(&e_sector, sectors_cnt) != PM3_SUCCESS) {
|
||||||
free(e_sector);
|
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@ int CmdHFMFNDEFRead(const char *Cmd); // used by "nfc mf cread"
|
||||||
int CmdHFMFNDEFFormat(const char *Cmd); // used by "nfc mf cformat"
|
int CmdHFMFNDEFFormat(const char *Cmd); // used by "nfc mf cformat"
|
||||||
int CmdHFMFNDEFWrite(const char *Cmd); // used by "nfc mf cwrite"
|
int CmdHFMFNDEFWrite(const char *Cmd); // used by "nfc mf cwrite"
|
||||||
|
|
||||||
void showSectorTable(sector_t *k_sector, uint8_t k_sectorsCount);
|
void showSectorTable(sector_t *k_sector, uint8_t k_sectors_cnt);
|
||||||
void readerAttack(sector_t *k_sector, uint8_t k_sectorsCount, nonces_t data, bool setEmulatorMem, bool verbose);
|
void readerAttack(sector_t *k_sector, uint8_t k_sectors_cnt, nonces_t data, bool setEmulatorMem, bool verbose);
|
||||||
void printKeyTable(uint8_t sectorscnt, sector_t *e_sector);
|
void printKeyTable(uint8_t sectorscnt, sector_t *e_sector);
|
||||||
void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_sector);
|
void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_sector);
|
||||||
void printKeyTable_fast(uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo);
|
void printKeyTable_fast(uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo);
|
||||||
|
|
|
@ -118,8 +118,13 @@ static int CmdNfcDecode(const char *Cmd) {
|
||||||
PrintAndLogEx(SUCCESS, "MFC dump file detected. Converting...");
|
PrintAndLogEx(SUCCESS, "MFC dump file detected. Converting...");
|
||||||
uint8_t ndef[4096] = {0};
|
uint8_t ndef[4096] = {0};
|
||||||
uint16_t ndeflen = 0;
|
uint16_t ndeflen = 0;
|
||||||
uint8_t skip = (4 * MFBLOCK_SIZE);
|
|
||||||
convert_mfc_2_arr(dump + skip, bytes_read - skip, ndef, &ndeflen);
|
if (convert_mad_to_arr(dump, bytes_read, ndef, &ndeflen) != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(FAILED, "Failed converting, aborting...");
|
||||||
|
free(dump);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(dump, ndef, ndeflen);
|
memcpy(dump, ndef, ndeflen);
|
||||||
bytes_read = ndeflen;
|
bytes_read = ndeflen;
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,3 +421,51 @@ int DetectHID(uint8_t *d, uint16_t manufacture) {
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int convert_mad_to_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen) {
|
||||||
|
|
||||||
|
if (in == NULL || out == NULL || ilen == 0 ) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAD detection
|
||||||
|
if (HasMADKey(in) == false) {
|
||||||
|
PrintAndLogEx(FAILED, "No MAD key was detected in the dump file");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
|
||||||
|
uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
|
||||||
|
|
||||||
|
memcpy(sector0, in, sizeof(sector0));
|
||||||
|
if (ilen == MIFARE_4K_MAX_BYTES) {
|
||||||
|
memcpy(sector10, in + (MF_MAD2_SECTOR * 4 * MFBLOCK_SIZE), sizeof(sector10));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
|
||||||
|
size_t madlen = 0;
|
||||||
|
if (MADDecode(sector0, sector10, mad, &madlen, false)) {
|
||||||
|
PrintAndLogEx(ERR, "can't decode MAD");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ndef_aid = 0xE103;
|
||||||
|
for (int i = 0; i < madlen; i++) {
|
||||||
|
if (ndef_aid == mad[i]) {
|
||||||
|
uint8_t tmp[MFBLOCK_SIZE * 4] = {0};
|
||||||
|
memset(tmp, 0x00, sizeof(tmp));
|
||||||
|
|
||||||
|
// sector i dump (skip first sector +1)
|
||||||
|
memcpy(tmp, in + (i + 1) * sizeof(tmp), sizeof(tmp));
|
||||||
|
|
||||||
|
// debug print
|
||||||
|
// print_hex_noascii_break(tmp, sizeof(tmp) - MFBLOCK_SIZE, MFBLOCK_SIZE);
|
||||||
|
|
||||||
|
// copy to out (skip ST)
|
||||||
|
memcpy(out, tmp, sizeof(tmp) - MFBLOCK_SIZE);
|
||||||
|
out += sizeof(tmp) - MFBLOCK_SIZE;
|
||||||
|
*olen += sizeof(tmp) -MFBLOCK_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
|
@ -30,4 +30,5 @@ int MADCardHolderInfoDecode(uint8_t *data, size_t datalen, bool verbose);
|
||||||
void MADPrintHeader(void);
|
void MADPrintHeader(void);
|
||||||
bool HasMADKey(uint8_t *d);
|
bool HasMADKey(uint8_t *d);
|
||||||
int DetectHID(uint8_t *d, uint16_t manufacture);
|
int DetectHID(uint8_t *d, uint16_t manufacture);
|
||||||
|
int convert_mad_to_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen);
|
||||||
#endif // _MAD_H_
|
#endif // _MAD_H_
|
||||||
|
|
|
@ -24,6 +24,23 @@
|
||||||
#define MFKEY_SIZE 6
|
#define MFKEY_SIZE 6
|
||||||
#define MFBLOCK_SIZE 16
|
#define MFBLOCK_SIZE 16
|
||||||
|
|
||||||
|
#define MIFARE_4K_MAXBLOCK 256
|
||||||
|
#define MIFARE_2K_MAXBLOCK 128
|
||||||
|
#define MIFARE_1K_MAXBLOCK 64
|
||||||
|
#define MIFARE_MINI_MAXBLOCK 20
|
||||||
|
|
||||||
|
#define MIFARE_4K_MAXSECTOR 40
|
||||||
|
#define MIFARE_2K_MAXSECTOR 32
|
||||||
|
#define MIFARE_1K_MAXSECTOR 16
|
||||||
|
#define MIFARE_MINI_MAXSECTOR 5
|
||||||
|
|
||||||
|
#define MIFARE_4K_MAX_BYTES 4096
|
||||||
|
#define MIFARE_2K_MAX_BYTES 2048
|
||||||
|
#define MIFARE_1K_MAX_BYTES 1024
|
||||||
|
#define MIFARE_MINI_MAX_BYTES 320
|
||||||
|
|
||||||
|
#define MIFARE_KEY_SIZE 6
|
||||||
|
|
||||||
static const uint64_t g_mifare_default_keys[] = {
|
static const uint64_t g_mifare_default_keys[] = {
|
||||||
0xffffffffffff, // Default key (first key used by program if no user defined key)
|
0xffffffffffff, // Default key (first key used by program if no user defined key)
|
||||||
0x000000000000, // Blank key
|
0x000000000000, // Blank key
|
||||||
|
|
|
@ -499,6 +499,51 @@ static int ndefDecodePayloadDeviceInfo(uint8_t *payload, size_t len) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ndefDecodePayloadHandoverRequest(uint8_t *payload, size_t len) {
|
||||||
|
if (payload == NULL)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
if (len < 1)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, _CYAN_("Handover Request"));
|
||||||
|
uint8_t *p = payload;
|
||||||
|
uint8_t major = (*(p) >> 4) & 0x0F;
|
||||||
|
uint8_t minor = *(p) & 0x0F;
|
||||||
|
p++;
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Version....... " _YELLOW_("%u.%u"), major, minor);
|
||||||
|
if (major != 1 && minor != 2) {
|
||||||
|
PrintAndLogEx(FAILED, "Wrong version numbers");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t collision = MemBeToUint2byte(p);
|
||||||
|
p += 2;
|
||||||
|
PrintAndLogEx(INFO, "Collision Resolution... " _YELLOW_("%u"), collision);
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ndefDecodePayloadHandoverSelect(uint8_t *payload, size_t len) {
|
||||||
|
if (payload == NULL)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
if (len < 1)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, _CYAN_("Handover select"));
|
||||||
|
|
||||||
|
uint8_t *p = payload;
|
||||||
|
uint8_t major = (*(p) >> 4) & 0x0F;
|
||||||
|
uint8_t minor = *(p) & 0x0F;
|
||||||
|
p++;
|
||||||
|
PrintAndLogEx(INFO, "Version....... " _YELLOW_("%u.%u"), major, minor);
|
||||||
|
if (major != 1 && minor != 2) {
|
||||||
|
PrintAndLogEx(FAILED, "Wrong version numbers");
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int ndefDecodePayloadSmartPoster(uint8_t *ndef, size_t ndeflen, bool print, bool verbose) {
|
static int ndefDecodePayloadSmartPoster(uint8_t *ndef, size_t ndeflen, bool print, bool verbose) {
|
||||||
if (print) {
|
if (print) {
|
||||||
PrintAndLogEx(INFO, _YELLOW_("Well Known Record - Smartposter {"));
|
PrintAndLogEx(INFO, _YELLOW_("Well Known Record - Smartposter {"));
|
||||||
|
@ -817,7 +862,11 @@ static int ndefDecodeMime_bt(NDEFHeader_t *ndef) {
|
||||||
PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type);
|
PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type);
|
||||||
uint16_t ooblen = MemBeToUint2byte(ndef->Payload);
|
uint16_t ooblen = MemBeToUint2byte(ndef->Payload);
|
||||||
PrintAndLogEx(INFO, "OOB data len.... %u", ooblen);
|
PrintAndLogEx(INFO, "OOB data len.... %u", ooblen);
|
||||||
PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(ndef->Payload + 2, 6));
|
|
||||||
|
uint8_t rev[6] = {0};
|
||||||
|
reverse_array_copy(ndef->Payload + 2, 6, rev);
|
||||||
|
PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(rev, sizeof(rev)));
|
||||||
|
|
||||||
// Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit
|
// Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit
|
||||||
switch (ndef->Payload[8]) {
|
switch (ndef->Payload[8]) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
|
@ -942,13 +991,11 @@ static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp((char *)ndef->Type, "Hr", ndef->TypeLen)) {
|
if (!strncmp((char *)ndef->Type, "Hr", ndef->TypeLen)) {
|
||||||
PrintAndLogEx(INFO, _CYAN_("Handover request"));
|
ndefDecodePayloadHandoverRequest(ndef->Payload, ndef->PayloadLen);
|
||||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp((char *)ndef->Type, "Hs", ndef->TypeLen)) {
|
if (!strncmp((char *)ndef->Type, "Hs", ndef->TypeLen)) {
|
||||||
PrintAndLogEx(INFO, _CYAN_("Handover select"));
|
ndefDecodePayloadHandoverSelect(ndef->Payload, ndef->PayloadLen);
|
||||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp((char *)ndef->Type, "ac", ndef->TypeLen)) {
|
if (!strncmp((char *)ndef->Type, "ac", ndef->TypeLen)) {
|
||||||
|
|
|
@ -388,6 +388,7 @@ while true; do
|
||||||
if ! CheckExecute "nfc decode test - device info" "$CLIENTBIN -c 'nfc decode -d d1025744690004536f6e79010752432d533338300220426c61636b204e46432052656164657220636f6e6e656374656420746f2050430310123e4567e89b12d3a45642665544000004124e464320506f72742d3130302076312e3032'" "NFC Port-100 v1.02"; then break; fi
|
if ! CheckExecute "nfc decode test - device info" "$CLIENTBIN -c 'nfc decode -d d1025744690004536f6e79010752432d533338300220426c61636b204e46432052656164657220636f6e6e656374656420746f2050430310123e4567e89b12d3a45642665544000004124e464320506f72742d3130302076312e3032'" "NFC Port-100 v1.02"; then break; fi
|
||||||
if ! CheckExecute "nfc decode test - vcard" "$CLIENTBIN -c 'nfc decode -d d20ca3746578742f782d7643617264424547494e3a56434152440a56455253494f4e3a332e300a4e3a43687269733b4963656d616e3b3b3b0a464e3a476f7468656e627572670a5245563a323032312d30362d32345432303a31353a30385a0a6974656d322e582d4142444154453b747970653d707265663a323032302d30362d32340a4954454d322e582d41424c4142454c3a5f24213c416e6e69766572736172793e21245f0a454e443a56434152440a'" "END:VCARD"; then break; fi
|
if ! CheckExecute "nfc decode test - vcard" "$CLIENTBIN -c 'nfc decode -d d20ca3746578742f782d7643617264424547494e3a56434152440a56455253494f4e3a332e300a4e3a43687269733b4963656d616e3b3b3b0a464e3a476f7468656e627572670a5245563a323032312d30362d32345432303a31353a30385a0a6974656d322e582d4142444154453b747970653d707265663a323032302d30362d32340a4954454d322e582d41424c4142454c3a5f24213c416e6e69766572736172793e21245f0a454e443a56434152440a'" "END:VCARD"; then break; fi
|
||||||
if ! CheckExecute "nfc decode test - apple wallet" "$CLIENTBIN -c 'nfc decode -d 031AD10116550077616C6C65743A2F2F61637469766174652F6E6663FE'" "activate/nfc"; then break; fi
|
if ! CheckExecute "nfc decode test - apple wallet" "$CLIENTBIN -c 'nfc decode -d 031AD10116550077616C6C65743A2F2F61637469766174652F6E6663FE'" "activate/nfc"; then break; fi
|
||||||
|
if ! CheckExecute "nfc decode test - signature" "$CLIENTBIN -c 'nfc decode -d 03FF010194113870696C65742E65653A656B616172743A3266195F26063132303832325904202020205F28033233335F2701316E1B5A13333038363439303039303030323636343030355304EBF2CE704103000000AC536967010200803A2448FCA7D354A654A81BD021150D1A152D1DF4D7A55D2B771F12F094EAB6E5E10F2617A2F8DAD4FD38AFF8EA39B71C19BD42618CDA86EE7E144636C8E0E7CFC4096E19C3680E09C78A0CDBC05DA2D698E551D5D709717655E56FE3676880B897D2C70DF5F06ECE07C71435255144F8EE41AF110E7B180DA0E6C22FB8FDEF61800025687474703A2F2F70696C65742E65652F6372742F33303836343930302D303030312E637274FE'" "30864900-0001.crt"; then break; fi
|
||||||
|
|
||||||
echo -e "\n${C_BLUE}Testing LF:${C_NC}"
|
echo -e "\n${C_BLUE}Testing LF:${C_NC}"
|
||||||
if ! CheckExecute "lf AWID test" "$CLIENTBIN -c 'data load -f traces/lf_AWID-15-259.pm3;lf search -1'" "AWID ID found"; then break; fi
|
if ! CheckExecute "lf AWID test" "$CLIENTBIN -c 'data load -f traces/lf_AWID-15-259.pm3;lf search -1'" "AWID ID found"; then break; fi
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue