MFU dump UL-C with key

adding UL-C auth and keys to dump cmd
swapped endian for input of hf mfu crdbl to match output of hf mfu info
cmd and tag info app
This commit is contained in:
marshmellow42 2015-05-03 23:17:11 -04:00
parent b3125340f3
commit f9848fd647
3 changed files with 98 additions and 32 deletions

View file

@ -12,6 +12,7 @@
#include "cmdhfmf.h"
#include "cmdhf14a.h"
#include "mifare.h"
#include "util.h"
#define MAX_UL_BLOCKS 0x0f
#define MAX_ULC_BLOCKS 0x2f
@ -87,8 +88,8 @@ uint8_t GetHF14AMfU_Type(void){
// EV1 GetVersion
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t version[10] = {0,0,0,0,0,0,0,0};
memcpy(&version, resp.d.asBytes, sizeof(version));
uint8_t version[10] = {0,0,0,0,0,0,0,0,0,0};
memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version));
uint8_t len = resp.arg[0] & 0xff;
if ( len == 0x0A && version[6] == 0x0B )
@ -324,10 +325,9 @@ int usage_hf_mfu_dump(void)
PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1");
PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`");
PrintAndLog("It autodetects card type.\n");
PrintAndLog("Usage: hf mfu dump <filename w/o .bin>");
PrintAndLog("Usage: hf mfu dump k <key> n <filename w/o .bin>");
PrintAndLog(" sample : hf mfu dump");
PrintAndLog(" : hf mfu dump myfile");
PrintAndLog(" : hf mfu dump 1 myfile");
PrintAndLog(" : hf mfu dump n myfile");
return 0;
}
//
@ -337,26 +337,66 @@ int usage_hf_mfu_dump(void)
// TODO: take a password to read UL-C / UL-EV1 tags.
int CmdHF14AMfUDump(const char *Cmd){
char cmdp = param_getchar(Cmd, 0);
if (cmdp == 'h' || cmdp == 'H')
return usage_hf_mfu_dump();
FILE *fout;
char filename[FILE_PATH_SIZE] = {0x00};
char *fnameptr = filename;
char *str = "Dumping Ultralight%s%s Card Data...";
uint8_t *lockbytes_t = NULL;
uint8_t lockbytes[2] = {0x00};
uint8_t *lockbytes_t2 = NULL;
uint8_t lockbytes2[2] = {0x00};
bool bit[16] = {0x00};
bool bit2[16] = {0x00};
uint8_t data[176] = {0x00};
uint8_t data[1024] = {0x00};
bool hasPwd = false;
int i = 0;
int Pages = 16;
bool tmplockbit = false;
uint8_t dataLen=0;
uint8_t cmdp =0;
uint8_t *key= NULL;
size_t fileNlen = 0;
bool errors = FALSE;
while(param_getchar(Cmd, cmdp) != 0x00)
{
switch(param_getchar(Cmd, cmdp))
{
case 'h':
case 'H':
return usage_hf_mfu_dump();
case 'k':
case 'K':
dataLen = param_gethex(Cmd, cmdp+1, data, 32);
if (dataLen) {
errors = true;
} else {
key = SwapEndian64(data, 16);
PrintAndLog("3des key: %s",sprint_hex(key, 16));
}
cmdp += 2;
hasPwd = true;
break;
case 'n':
case 'N':
fileNlen = param_getstr(Cmd, cmdp+1, filename);
if (!fileNlen) errors = true;
if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5;
cmdp += 2;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
if(errors) break;
}
//Validations
if(errors)
{
return usage_hf_mfu_dump();
}
TagTypeUL_t tagtype = GetHF14AMfU_Type();
if (tagtype == UL_ERROR) return -1;
@ -381,21 +421,29 @@ int CmdHF14AMfUDump(const char *Cmd){
PrintAndLog("Dumping unknown Ultralight, using default values.");
}
UsbCommand c = {CMD_MIFAREU_READCARD, {0,Pages}};
SendCommand(&c);
UsbCommand resp;
for (uint8_t i = 0; i<Pages; i++){
//Read Block
UsbCommand c = {CMD_MIFAREU_READBL, {i}};
if ( hasPwd ) {
c.arg[1] = 1;
memcpy(c.d.asBytes,key,16);
}
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
PrintAndLog("Command execute time-out");
return 0;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
if (isOK) {
memcpy(data + (i*4), resp.d.asBytes, 4);
}
else {
PrintAndLog("Failed reading block: (%02x)", i);
}
} else {
PrintAndLog("Command execute time-out");
}
}
if (!resp.arg[0] ) {
PrintAndLog("Read command failed");
return 0;
}
memcpy(data, resp.d.asBytes, sizeof(data));
// Load lock bytes.
int j = 0;
@ -416,6 +464,11 @@ int CmdHF14AMfUDump(const char *Cmd){
}
}
// add keys
if (hasPwd){
memcpy(data + Pages*4, key, 16);
Pages += 4;
}
for (i = 0; i < Pages; ++i) {
if ( i < 3 ) {
PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
@ -468,17 +521,13 @@ int CmdHF14AMfUDump(const char *Cmd){
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),tmplockbit);
}
int len = param_getstr(Cmd,0,filename);
if (len > FILE_PATH_SIZE-5)
len = FILE_PATH_SIZE-5;
// user supplied filename?
if (len < 1) {
if (fileNlen < 1) {
// UID = data 0-1-2 4-5-6-7 (skips a beat)
sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin",
data[0],data[1], data[2], data[4],data[5],data[6], data[7]);
} else {
sprintf(fnameptr + len," .bin");
sprintf(fnameptr + fileNlen," .bin");
}
if ((fout = fopen(filename,"wb")) == NULL) {
@ -707,6 +756,7 @@ int CmdTestDES(const char * cmd)
return 0;
}
**/
//
// Ultralight C Read Single Block
//
@ -715,7 +765,7 @@ int CmdHF14AMfUCRdBl(const char *Cmd)
UsbCommand resp;
bool hasPwd = FALSE;
uint8_t blockNo = -1;
unsigned char key[16];
uint8_t key[16];
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
@ -746,12 +796,13 @@ int CmdHF14AMfUCRdBl(const char *Cmd)
hasPwd = TRUE;
}
}
uint8_t *key2 = SwapEndian64(key, 16);
//Read Block
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
if ( hasPwd ) {
c.arg[1] = 1;
memcpy(c.d.asBytes,key,16);
memcpy(c.d.asBytes,key2,16);
}
SendCommand(&c);

View file

@ -158,6 +158,20 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
return num;
}
// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
// to
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
// up to 64 bytes or 512 bits
uint8_t *SwapEndian64(uint8_t *src, size_t len){
static uint8_t temp[64]={0};
for (uint8_t block=0; block < (uint8_t)len/8; block++){
for (size_t i = 0; i < 8; i++){
temp[i+(8*block)] = src[(7-i)+(8*block)];
}
}
return temp;
}
//assumes little endian
char * printBits(size_t const size, void const * const ptr)
{

View file

@ -44,6 +44,7 @@ char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t bre
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);
char * printBits(size_t const size, void const * const ptr);
uint8_t *SwapEndian64(uint8_t *src, size_t len);
char param_getchar(const char *line, int paramnum);
uint8_t param_get8(const char *line, int paramnum);