#include "cmdhfmf.h"
#include "cmdhf14a.h"
#include "mifare.h"
+#include "util.h"
#define MAX_UL_BLOCKS 0x0f
#define MAX_ULC_BLOCKS 0x2f
// 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 )
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;
}
//
// 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;
PrintAndLog("Dumping unknown Ultralight, using default values.");
}
- UsbCommand c = {CMD_MIFAREU_READCARD, {0,Pages}};
- SendCommand(&c);
- UsbCommand resp;
-
- if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
- PrintAndLog("Command execute time-out");
- return 0;
- }
+ 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 (!resp.arg[0] ) {
- PrintAndLog("Read command failed");
- 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");
+ }
}
- memcpy(data, resp.d.asBytes, sizeof(data));
// Load lock bytes.
int j = 0;
}
}
+ // 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));
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) {
return 0;
}
**/
+
//
// Ultralight C Read Single Block
//
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') {
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);
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)
{