read extra mf-ul EV1 blocks

This commit is contained in:
Adam Laurie 2017-03-23 16:04:02 +00:00
parent fe04b85678
commit c04dd91e98
2 changed files with 92 additions and 27 deletions

View file

@ -9,6 +9,7 @@
* Copyright (C) 2012-2013 Ludovic Rousseau
* See AUTHORS file for a more comprehensive list of contributors.
* Additional contributors of this file:
* Copyright (C) 2017 Adam Laurie
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -133,6 +134,19 @@ typedef struct {
uint8_t otp[4];
} mifareul_block_manufacturer;
// MIFARE Ultralight EV1 Config Pages
typedef struct {
uint8_t mod;
uint8_t rfui[2];
uint8_t auth0;
uint8_t access;
uint8_t vctid;
uint8_t rfui1[2];
uint8_t pwd[4];
uint8_t pack[2];
uint8_t rfui2[2];
} mifareul_block_config;
typedef struct {
uint8_t abtData[16];
} mifareul_block_data;
@ -140,12 +154,24 @@ typedef struct {
typedef union {
mifareul_block_manufacturer mbm;
mifareul_block_data mbd;
mifareul_block_config mbc;
} mifareul_block;
// standard UL tag - 1 manuf block + 3 user blocks
typedef struct {
mifareul_block amb[4];
} mifareul_tag;
// UL EV1 MF0UL11 tag - 1 manuf block + 3 user blocks + 1 config block
typedef struct {
mifareul_block amb[5];
} mifareul_ev1_mf0ul11_tag;
// UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1 config block
typedef struct {
mifareul_block amb[10];
} mifareul_ev1_mf0ul21_tag;
// Reset struct alignment to default
# pragma pack()

View file

@ -62,11 +62,19 @@
#define MAX_UID_LEN 10
#define BLOCK_COUNT 0xf
#define EV1_NONE 0
#define EV1_UL11 1
#define EV1_UL21 2
static nfc_device *pnd;
static nfc_target nt;
static mifare_param mp;
static mifareul_tag mtDump;
static const uint32_t uiBlocks = BLOCK_COUNT;
static mifareul_ev1_mf0ul21_tag mtDump; // use the largest tag type for internal storage
static uint32_t uiBlocks = BLOCK_COUNT;
static uint32_t uiReadPages = 0;
static uint8_t iPWD[4] = { 0x0 };
static uint8_t iPACK[2] = { 0x0 };
static uint8_t iEV1Type= EV1_NONE;
// special unlock command
uint8_t abtUnlock1[1] = { 0x40 };
@ -105,7 +113,6 @@ read_card(void)
{
uint32_t page;
bool bFailure = false;
uint32_t uiReadPages = 0;
uint32_t uiFailedPages = 0;
printf("Reading %d pages |", uiBlocks + 1);
@ -127,6 +134,21 @@ read_card(void)
printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks + 1, uiFailedPages);
fflush(stdout);
// copy EV1 secrets to dump data
switch(iEV1Type) {
case EV1_UL11:
memcpy(mtDump.amb[4].mbc.pwd, iPWD, 4);
memcpy(mtDump.amb[4].mbc.pack, iPACK, 2);
break;
case EV1_UL21:
memcpy(mtDump.amb[9].mbc.pwd, iPWD, 4);
memcpy(mtDump.amb[9].mbc.pack, iPACK, 2);
break;
case EV1_NONE:
default:
break;
}
return (!bFailure);
}
@ -445,7 +467,6 @@ main(int argc, const char *argv[])
{
int iAction = 0;
uint8_t iUID[MAX_UID_LEN] = { 0x0 };
uint8_t iPWD[4] = { 0x0 };
size_t szUID = 0;
bool bOTP = false;
bool bLock = false;
@ -569,8 +590,8 @@ main(int argc, const char *argv[])
nfc_exit(context);
exit(EXIT_FAILURE);
}
// Test if we are dealing with a MIFARE compatible tag
// Test if we are dealing with a MIFARE compatible tag
if (nt.nti.nai.abtAtqa[1] != 0x44) {
ERR("tag is not a MIFARE Ultralight card\n");
nfc_close(pnd);
@ -590,13 +611,28 @@ main(int argc, const char *argv[])
if(!bPWD)
printf("Tag is EV1 - PASSWORD may be required\n");
printf("EV1 storage size: ");
if(abtRx[6] == 0x0b)
if(abtRx[6] == 0x0b) {
printf("48 bytes\n");
else if(abtRx[6] == 0x0e)
uiBlocks= 0x13;
iEV1Type= EV1_UL11;
}
else if(abtRx[6] == 0x0e) {
printf("128 bytes\n");
uiBlocks= 0x28;
iEV1Type= EV1_UL21;
}
else
printf("unknown!\n");
}
else {
// re-init non EV1 tag
if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) {
ERR("no tag was found\n");
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
}
}
// EV1 login required
if(bPWD){
@ -606,31 +642,34 @@ main(int argc, const char *argv[])
ERR("AUTH failed!\n");
exit(EXIT_FAILURE);
}
else
else {
printf("Success - PACK: %02x%02x\n", abtRx[0], abtRx[1]);
memcpy(iPACK, abtRx, 2);
}
}
if (iAction == 1) {
if (read_card()) {
printf("Writing data to file: %s ... ", argv[2]);
fflush(stdout);
pfDump = fopen(argv[2], "wb");
if (pfDump == NULL) {
printf("Could not open file: %s\n", argv[2]);
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
}
if (fwrite(&mtDump, 1, sizeof(mtDump), pfDump) != sizeof(mtDump)) {
printf("Could not write to file: %s\n", argv[2]);
fclose(pfDump);
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
}
fclose(pfDump);
printf("Done.\n");
bool bRF= read_card();
printf("Writing data to file: %s ... ", argv[2]);
fflush(stdout);
pfDump = fopen(argv[2], "wb");
if (pfDump == NULL) {
printf("Could not open file: %s\n", argv[2]);
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
}
if (fwrite(&mtDump, 1, uiReadPages * 4, pfDump) != uiReadPages * 4) {
printf("Could not write to file: %s\n", argv[2]);
fclose(pfDump);
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
}
fclose(pfDump);
printf("Done.\n");
if(!bRF)
printf("Warning! Read failed - partial data written to file!\n");
} else if (iAction == 2) {
write_card(bOTP, bLock, bUID);
} else if (iAction == 3) {