+
+typedef struct {
+ uint8_t version[8];
+ uint8_t tbo[2];
+ uint8_t tbo1[1];
+ uint8_t pages; // max page number in dump
+ uint8_t signature[32];
+ uint8_t counter_tearing[3][4]; // 3 bytes counter, 1 byte tearing flag
+ uint8_t data[1024];
+} mfu_dump_t;
+
+
+static void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage, TagTypeUL_t tagtype) {
+
+ bool tmplockbit = false;
+ bool bit[16] = {false};
+ bool bit2[16] = {false};
+
+ // standard lock bits
+ for(int i = 0; i < 16; i++){
+ bit[i] = card->data[10+i/8] & (1 << (7-i%8));
+ }
+
+ // dynamic lock bits
+ // TODO -- FIGURE OUT LOCK BYTES FOR EV1 and/or NTAG
+ if (tagtype & UL_C) {
+ for (int i = 0; i < 16; i++) {
+ bit2[i] = card->data[40*4+i/8] & (1 << (7-i%8));
+ }
+ }
+
+ PrintAndLogEx(NORMAL, "\n Block# | Data |lck| Ascii");
+ PrintAndLogEx(NORMAL, "---------+-------------+---+------");
+
+ for (int i = startpage; i < startpage + pages; i++) {
+ if (i < 3) {
+ PrintAndLogEx(NORMAL, "%3d/0x%02X | %s| | ", i, i, sprint_hex(card->data + i * 4, 4));
+ continue;
+ }
+ switch(i){
+ case 3: tmplockbit = bit[4]; break;
+ case 4: tmplockbit = bit[3]; break;
+ case 5: tmplockbit = bit[2]; break;
+ case 6: tmplockbit = bit[1]; break;
+ case 7: tmplockbit = bit[0]; break;
+ case 8: tmplockbit = bit[15]; break;
+ case 9: tmplockbit = bit[14]; break;
+ case 10: tmplockbit = bit[13]; break;
+ case 11: tmplockbit = bit[12]; break;
+ case 12: tmplockbit = bit[11]; break;
+ case 13: tmplockbit = bit[10]; break;
+ case 14: tmplockbit = bit[9]; break;
+ case 15: tmplockbit = bit[8]; break;
+ case 16:
+ case 17:
+ case 18:
+ case 19: tmplockbit = bit2[6]; break;
+ case 20:
+ case 21:
+ case 22:
+ case 23: tmplockbit = bit2[5]; break;
+ case 24:
+ case 25:
+ case 26:
+ case 27: tmplockbit = bit2[4]; break;
+ case 28:
+ case 29:
+ case 30:
+ case 31: tmplockbit = bit2[2]; break;
+ case 32:
+ case 33:
+ case 34:
+ case 35: tmplockbit = bit2[1]; break;
+ case 36:
+ case 37:
+ case 38:
+ case 39: tmplockbit = bit2[0]; break;
+ case 40: tmplockbit = bit2[12]; break;
+ case 41: tmplockbit = bit2[11]; break;
+ case 42: tmplockbit = bit2[10]; break; //auth0
+ case 43: tmplockbit = bit2[9]; break; //auth1
+ default: break;
+ }
+
+ PrintAndLogEx(NORMAL, "%3d/0x%02X | %s| %d | %.4s", i, i, sprint_hex(card->data + i * 4, 4), tmplockbit, sprint_ascii(card->data + i * 4, 4));
+ }
+ PrintAndLogEx(NORMAL, "---------------------------------");
+}
+
+
+static int usage_hf_mfu_dump(void) {
+ PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1");
+ PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216");
+ PrintAndLogEx(NORMAL, "and saves binary dump into the file `filename.bin` or `cardUID.bin`");
+ PrintAndLogEx(NORMAL, "It autodetects card type.\n");
+ PrintAndLogEx(NORMAL, "Usage: hf mfu dump k <key> l n <filename w/o .bin>");
+ PrintAndLogEx(NORMAL, " Options : ");
+ PrintAndLogEx(NORMAL, " k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
+ PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness");
+ PrintAndLogEx(NORMAL, " f <FN > : filename w/o .bin to save the dump as");
+ PrintAndLogEx(NORMAL, " p <Pg > : starting Page number to manually set a page to start the dump at");
+ PrintAndLogEx(NORMAL, " q <qty> : number of Pages to manually set how many pages to dump");
+
+ PrintAndLogEx(NORMAL, "");
+ PrintAndLogEx(NORMAL, " sample : hf mfu dump");
+ PrintAndLogEx(NORMAL, " : hf mfu dump n myfile");
+ PrintAndLogEx(NORMAL, " : hf mfu dump k 00112233445566778899AABBCCDDEEFF");
+ PrintAndLogEx(NORMAL, " : hf mfu dump k AABBCCDDD\n");
+ return 0;
+}
+
+
+static int CmdHF14AMfUDump(const char *Cmd){
+
+ char filename[FILE_PATH_SIZE] = {'\0'};
+ size_t fileNameLen = 0;
+ uint8_t keybytes[16] = {0x00};
+ uint8_t *authenticationkey = keybytes;
+ int keyLen = 0;
+ bool hasAuthKey = false;
+ uint8_t cmdp = 0;
+ bool errors = false;