hf mf eload - now uses cliparser, and fixes for block printing etc.

This commit is contained in:
iceman1001 2021-04-10 18:13:11 +02:00
commit 43c42a06a0

View file

@ -188,22 +188,6 @@ static int usage_hf14_decryptbytes(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf14_eset(void) {
PrintAndLogEx(NORMAL, "Usage: hf mf eset <block number> <block data (32 hex symbols)>");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eset 1 000102030405060708090a0b0c0d0e0f"));
return PM3_SUCCESS;
}
static int usage_hf14_eload(void) {
PrintAndLogEx(NORMAL, "It loads emul dump from the file `filename.eml`");
PrintAndLogEx(NORMAL, "Usage: hf mf eload [card memory] <file name w/o `.eml`> [numblocks]");
PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eload filename"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eload 4 filename"));
return PM3_SUCCESS;
}
static int usage_hf14_esave(void) { static int usage_hf14_esave(void) {
PrintAndLogEx(NORMAL, "It saves emul dump into the file `filename.eml` or `cardID.eml`"); PrintAndLogEx(NORMAL, "It saves emul dump into the file `filename.eml` or `cardID.eml`");
PrintAndLogEx(NORMAL, " Usage: hf mf esave [card memory] [file name w/o `.eml`]"); PrintAndLogEx(NORMAL, " Usage: hf mf esave [card memory] [file name w/o `.eml`]");
@ -215,7 +199,6 @@ static int usage_hf14_esave(void) {
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave 4 filename")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave 4 filename"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf14_ecfill(void) { static int usage_hf14_ecfill(void) {
PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory."); PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory.");
PrintAndLogEx(NORMAL, "Keys must be laid in the emulator memory. \n"); PrintAndLogEx(NORMAL, "Keys must be laid in the emulator memory. \n");
@ -274,7 +257,6 @@ static int usage_hf14_cload(void) {
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cload e")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cload e"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf14_csave(void) { static int usage_hf14_csave(void) {
PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`");
PrintAndLogEx(NORMAL, "or into emulator memory"); PrintAndLogEx(NORMAL, "or into emulator memory");
@ -536,20 +518,21 @@ static char GetFormatFromSector(uint8_t sectorNo) {
static void mf_print_block(uint8_t blockno, uint8_t *d) { static void mf_print_block(uint8_t blockno, uint8_t *d) {
if (blockno == 0) { if (blockno == 0) {
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(d + (blockno * 16), 16)); PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
} else if (mfIsSectorTrailer(blockno)) { } else if (mfIsSectorTrailer(blockno)) {
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(d + (blockno * 16), 16)); PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
} else { } else {
PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(d + (blockno * 16), 16)); PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
} }
} }
static void mf_print_blocks(uint16_t n, uint8_t *d) { static void mf_print_blocks(uint16_t n, uint8_t *d) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
PrintAndLogEx(INFO, "blk | data | ascii"); PrintAndLogEx(INFO, "blk | data | ascii");
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
for (uint16_t i = 0; i < n; i++) { for (uint16_t i = 0; i < n; i++) {
mf_print_block(i, d); mf_print_block(i, d + (i * MFBLOCK_SIZE));
} }
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -697,7 +680,6 @@ static int CmdHF14AMfRdBl(const char *Cmd) {
int keylen = 0; int keylen = 0;
uint8_t key[6] = {0}; uint8_t key[6] = {0};
CLIGetHexWithReturn(ctx, 4, key, &keylen); CLIGetHexWithReturn(ctx, 4, key, &keylen);
bool verbose = arg_get_lit(ctx, 5); bool verbose = arg_get_lit(ctx, 5);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -714,15 +696,9 @@ static int CmdHF14AMfRdBl(const char *Cmd) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector);
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
if (blockno == 0) { mf_print_block(blockno, data);
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); if (verbose) {
} else if (mfIsSectorTrailer(blockno)) { decode_print_st(blockno, data);
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data)));
if (verbose) {
decode_print_st(blockno, data);
}
} else {
PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data)));
} }
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -742,6 +718,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
arg_lit0("b", NULL, "input key specified is B key"), arg_lit0("b", NULL, "input key specified is B key"),
arg_str0("k", "key", "<hex>", "key specified as 6 hex bytes"), arg_str0("k", "key", "<hex>", "key specified as 6 hex bytes"),
arg_int1("s", "sec", "<dec>", "sector number"), arg_int1("s", "sec", "<dec>", "sector number"),
arg_lit0("v", "verbose", "verbose output"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -759,6 +736,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
CLIGetHexWithReturn(ctx, 3, key, &keylen); CLIGetHexWithReturn(ctx, 3, key, &keylen);
int s = arg_get_int_def(ctx, 4, 0); int s = arg_get_int_def(ctx, 4, 0);
bool verbose = arg_get_lit(ctx, 5);
CLIParserFree(ctx); CLIParserFree(ctx);
if (s > MIFARE_4K_MAXSECTOR) { if (s > MIFARE_4K_MAXSECTOR) {
@ -766,7 +744,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t sector = (uint8_t)s; uint8_t sector = (uint8_t)s;
uint8_t sc_size = mfNumBlocksPerSector(sector) * 16; uint8_t sc_size = mfNumBlocksPerSector(sector) * MFBLOCK_SIZE;
uint8_t *data = calloc(sc_size, sizeof(uint8_t)); uint8_t *data = calloc(sc_size, sizeof(uint8_t));
if (data == NULL) { if (data == NULL) {
PrintAndLogEx(ERR, "failed to allocate memory"); PrintAndLogEx(ERR, "failed to allocate memory");
@ -783,17 +761,15 @@ static int CmdHF14AMfRdSc(const char *Cmd) {
PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector);
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
for (int i = 0; i < blocks; i++) { for (int i = 0; i < blocks; i++) {
if (start + i == 0) { mf_print_block(start + i, data + (i * MFBLOCK_SIZE));
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data + (i * 16), 16));
} else if (mfIsSectorTrailer(i)) {
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data + (i * 16), 16));
} else {
PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data + (i * 16), 16));
}
} }
decode_print_st(start + blocks - 1, data + ((blocks - 1) * 16));
if (verbose) {
decode_print_st(start + blocks - 1, data + ((blocks - 1) * MFBLOCK_SIZE));
}
} }
free(data); free(data);
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -3772,8 +3748,8 @@ static int CmdHF14AMfEGetBlk(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf egetblk", CLIParserInit(&ctx, "hf mf egetblk",
"Get emulator memory block", "Get emulator memory block",
"hf mf egetblk -b 0 -> get block 0 (manufacturer)\n" "hf mf egetblk --blk 0 -> get block 0 (manufacturer)\n"
"hf mf egetblk -b 3 -v -> get block 3, decode sector trailer\n" "hf mf egetblk --blk 3 -v -> get block 3, decode sector trailer\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -3798,20 +3774,16 @@ static int CmdHF14AMfEGetBlk(const char *Cmd) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector);
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
if (blockno == 0) { mf_print_block(blockno, data);
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); }
} else if (mfIsSectorTrailer(blockno)) { if (verbose) {
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); decode_print_st(blockno, data);
if (verbose) { } else {
decode_print_st(blockno, data); PrintAndLogEx(NORMAL, "");
}
} else {
PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data)));
}
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHF14AMfEGetSc(const char *Cmd) { static int CmdHF14AMfEGetSc(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf egetsc", CLIParserInit(&ctx, "hf mf egetsc",
@ -3821,11 +3793,14 @@ static int CmdHF14AMfEGetSc(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_int1("s", "sec", "<dec>", "sector number"), arg_int1("s", "sec", "<dec>", "sector number"),
arg_lit0("v", "verbose", "verbose output"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int s = arg_get_int_def(ctx, 1, 0); int s = arg_get_int_def(ctx, 1, 0);
bool verbose = arg_get_lit(ctx, 2);
CLIParserFree(ctx); CLIParserFree(ctx);
if (s > 39) { if (s > 39) {
PrintAndLogEx(WARNING, "Sector number must be less then 40"); PrintAndLogEx(WARNING, "Sector number must be less then 40");
return PM3_EINVARG; return PM3_EINVARG;
@ -3844,16 +3819,14 @@ static int CmdHF14AMfEGetSc(const char *Cmd) {
for (int i = 0; i < blocks; i++) { for (int i = 0; i < blocks; i++) {
int res = mfEmlGetMem(data, start + i, 1); int res = mfEmlGetMem(data, start + i, 1);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
if (start + i == 0) { mf_print_block(start + i, data);
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data, sizeof(data)));
} else if (mfIsSectorTrailer(i)) {
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data, sizeof(data)));
} else {
PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data)));
}
} }
} }
decode_print_st(start + blocks - 1, data); if (verbose) {
decode_print_st(start + blocks - 1, data);
} else {
PrintAndLogEx(NORMAL, "");
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -3875,66 +3848,114 @@ static int CmdHF14AMfEClear(const char *Cmd) {
} }
static int CmdHF14AMfESet(const char *Cmd) { static int CmdHF14AMfESet(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 3 || c == 'h')
return usage_hf14_eset();
uint8_t memBlock[16]; CLIParserContext *ctx;
memset(memBlock, 0x00, sizeof(memBlock)); CLIParserInit(&ctx, "hf mf esetblk",
"Set emulator memory block",
"hf mf esetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
);
void *argtable[] = {
arg_param_begin,
arg_int1("b", "blk", "<dec>", "block number"),
arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t blockNo = param_get8(Cmd, 0); int b = arg_get_int_def(ctx, 1, 0);
if (param_gethex(Cmd, 1, memBlock, 32)) { uint8_t data[16] = {0x00};
PrintAndLogEx(WARNING, "block data must include 32 HEX symbols"); int datalen = 0;
return PM3_ESOFT; int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &datalen);
CLIParserFree(ctx);
if (res) {
PrintAndLogEx(FAILED, "Error parsing bytes");
return PM3_EINVARG;
}
if (b > 255) {
return PM3_EINVARG;
}
if (datalen != sizeof(data)) {
PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", datalen);
return PM3_EINVARG;
} }
// 1 - blocks count // 1 - blocks count
return mfEmlSetMem(memBlock, blockNo, 1); return mfEmlSetMem(data, b, 1);
} }
int CmdHF14AMfELoad(const char *Cmd) { int CmdHF14AMfELoad(const char *Cmd) {
size_t counter = 0; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf eload",
"Load emulator memory with data from `filename.eml` dump file",
"hf mf eload -f hf-mf-01020304.eml\n"
"hf mf eload --4k -f hf-mf-01020304.eml\n"
);
void *argtable[] = {
arg_param_begin,
arg_str1("f", "file", "<fn>", "filename of dump"),
arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
arg_lit0(NULL, "ul", "MIFARE Ultralight family"),
arg_int0(NULL, "blks", "<dec>", "manually set number of blocks (overrides)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int fnlen = 0;
char filename[FILE_PATH_SIZE]; char filename[FILE_PATH_SIZE];
int blockNum, numBlocks, nameParamNo = 1; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
uint8_t blockWidth = 16;
char c = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 2 && c == 'h') bool m0 = arg_get_lit(ctx, 2);
return usage_hf14_eload(); bool m1 = arg_get_lit(ctx, 3);
bool m2 = arg_get_lit(ctx, 4);
bool m4 = arg_get_lit(ctx, 5);
bool mu = arg_get_lit(ctx, 6);
switch (c) { int numblks = arg_get_int_def(ctx, 7, -1);
case '0' :
numBlocks = MIFARE_MINI_MAXBLOCK; CLIParserFree(ctx);
break;
case '1' : // validations
case '\0': if ((m0 + m1 + m2 + m4 + mu) > 1) {
numBlocks = MIFARE_1K_MAXBLOCK; PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
break; return PM3_EINVARG;
case '2' : } else if ((m0 + m1 + m2 + m4 + mu) == 0) {
numBlocks = MIFARE_2K_MAXBLOCK; m1 = true;
break;
case '4' :
numBlocks = MIFARE_4K_MAXBLOCK;
break;
case 'u' :
numBlocks = 255;
blockWidth = 4;
break;
default: {
numBlocks = MIFARE_1K_MAXBLOCK;
nameParamNo = 0;
}
} }
uint32_t numblk2 = param_get32ex(Cmd, 2, 0, 10);
if (numblk2 > 0)
numBlocks = numblk2;
if (0 == param_getstr(Cmd, nameParamNo, filename, sizeof(filename))) uint8_t block_width = 16;
return usage_hf14_eload(); uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
uint8_t *data = calloc(4096, sizeof(uint8_t)); if (m0) {
block_cnt = MIFARE_MINI_MAXBLOCK;
} else if (m1) {
block_cnt = MIFARE_1K_MAXBLOCK;
} else if (m2) {
block_cnt = MIFARE_2K_MAXBLOCK;
} else if (m4) {
block_cnt = MIFARE_4K_MAXBLOCK;
} else if (mu) {
block_cnt = 255;
block_width = 4;
} else {
PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "%d blocks ( %u bytes ) to upload", block_cnt, block_cnt * block_width);
if (numblks > 0) {
block_cnt = MIN(numblks, block_cnt);
PrintAndLogEx(INFO, "overriding number of blocks, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width);
}
uint8_t *data = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t));
if (data == NULL) { if (data == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC; return PM3_EMALLOC;
@ -3949,15 +3970,14 @@ int CmdHF14AMfELoad(const char *Cmd) {
} }
// 64 or 256 blocks. // 64 or 256 blocks.
if ((datalen % blockWidth) != 0) { if ((datalen % block_width) != 0) {
PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth "); PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth ");
free(data); free(data);
return PM3_ESOFT; return PM3_ESOFT;
} }
// convert plain or old mfu format to new format // convert plain or old mfu format to new format
if (blockWidth == 4) { if (block_width == 4) {
res = convert_mfu_dump_format(&data, &datalen, true); res = convert_mfu_dump_format(&data, &datalen, true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format"); PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
@ -3969,7 +3989,8 @@ int CmdHF14AMfELoad(const char *Cmd) {
printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0); printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0);
// update expected blocks to match converted data. // update expected blocks to match converted data.
numBlocks = datalen / 4; block_cnt = datalen / 4;
PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d ( %u bytes )", block_cnt, block_cnt * block_width);
} }
PrintAndLogEx(INFO, "Uploading to emulator memory"); PrintAndLogEx(INFO, "Uploading to emulator memory");
@ -3977,46 +3998,47 @@ int CmdHF14AMfELoad(const char *Cmd) {
// fast push mode // fast push mode
conn.block_after_ACK = true; conn.block_after_ACK = true;
blockNum = 0;
while (datalen) { size_t offset = 0;
if (datalen == blockWidth) { int cnt = 0;
while (datalen && cnt < block_cnt) {
if (datalen == block_width) {
// Disable fast mode on last packet // Disable fast mode on last packet
conn.block_after_ACK = false; conn.block_after_ACK = false;
} }
if (mfEmlSetMem_xt(data + counter, blockNum, 1, blockWidth) != PM3_SUCCESS) { if (mfEmlSetMem_xt(data + offset, cnt, 1, block_width) != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockNum); PrintAndLogEx(FAILED, "Can't set emulator mem at block: %3d", cnt);
free(data); free(data);
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(NORMAL, "." NOLF); PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout); fflush(stdout);
blockNum++; cnt++;
counter += blockWidth; offset += block_width;
datalen -= blockWidth; datalen -= block_width;
} }
free(data); free(data);
PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "\n");
if (blockWidth == 4) { if (block_width == 4) {
PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mfu sim h`")); PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mfu sim h`"));
// MFU / NTAG // MFU / NTAG
if ((blockNum != numBlocks)) { if ((cnt != block_cnt)) {
PrintAndLogEx(WARNING, "Warning, Ultralight/Ntag file content, Loaded %d blocks of expected %d blocks into emulator memory", blockNum, numBlocks); PrintAndLogEx(WARNING, "Warning, Ultralight/Ntag file content, Loaded %d blocks of expected %d blocks into emulator memory", cnt, block_cnt);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
} else { } else {
PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mf sim -h`")); PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mf sim -h`"));
// MFC // MFC
if ((blockNum != numBlocks)) { if ((cnt != block_cnt)) {
PrintAndLogEx(WARNING, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", blockNum, numBlocks); PrintAndLogEx(WARNING, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", cnt, block_cnt);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done!");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -4541,8 +4563,8 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) {
CLIParserInit(&ctx, "hf mf cgetblk", CLIParserInit(&ctx, "hf mf cgetblk",
"Get block data from magic Chinese card.\n" "Get block data from magic Chinese card.\n"
"Only works with magic gen1a cards", "Only works with magic gen1a cards",
"hf mf cgetblk -b 0 -> get block 0 (manufacturer)\n" "hf mf cgetblk --blk 0 --> get block 0 (manufacturer)\n"
"hf mf cgetblk -b 3 -v -> get block 3, decode sector trailer\n" "hf mf cgetblk --blk 3 -v --> get block 3, decode sector trailer\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -4567,22 +4589,17 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
uint8_t sector = GetSectorFromBlockNo(blockno); uint8_t sector = GetSectorFromBlockNo(blockno);
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector);
PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
if (blockno == 0) { mf_print_block(blockno, data);
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data)));
} else if (mfIsSectorTrailer(blockno)) { if (verbose) {
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); decode_print_st(blockno, data);
if (verbose) {
decode_print_st(blockno, data);
}
} else { } else {
PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data))); PrintAndLogEx(NORMAL, "");
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -4596,10 +4613,12 @@ static int CmdHF14AMfCGetSc(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_int1("s", "sec", "<dec>", "sector number"), arg_int1("s", "sec", "<dec>", "sector number"),
arg_lit0("v", "verbose", "verbose output"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int s = arg_get_int_def(ctx, 1, 0); int s = arg_get_int_def(ctx, 1, 0);
bool verbose = arg_get_lit(ctx, 2);
CLIParserFree(ctx); CLIParserFree(ctx);
if (s > 39) { if (s > 39) {
PrintAndLogEx(WARNING, "Sector number must be less then 40"); PrintAndLogEx(WARNING, "Sector number must be less then 40");
@ -4630,16 +4649,13 @@ static int CmdHF14AMfCGetSc(const char *Cmd) {
PrintAndLogEx(ERR, "Can't read block. %d error=%d", start + i, res); PrintAndLogEx(ERR, "Can't read block. %d error=%d", start + i, res);
return PM3_ESOFT; return PM3_ESOFT;
} }
mf_print_block(start + i, data);
if (start + i == 0) { }
PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); if (verbose) {
} else if (mfIsSectorTrailer(i)) { decode_print_st(start + blocks - 1, data);
PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); } else {
} else { PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data)));
}
} }
decode_print_st(start + blocks - 1, data);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -4858,6 +4874,7 @@ static int CmdHF14AMfCView(const char *Cmd) {
fflush(stdout); fflush(stdout);
} }
PrintAndLogEx(NORMAL, "");
mf_print_blocks(numblocks, dump); mf_print_blocks(numblocks, dump);
free(dump); free(dump);
return PM3_SUCCESS; return PM3_SUCCESS;
@ -5864,7 +5881,7 @@ static command_t CommandTable[] = {
{"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE Classic sector"}, {"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE Classic sector"},
{"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE Classic binary file to BLANK tag"}, {"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE Classic binary file to BLANK tag"},
{"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"}, {"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"},
{"view", CmdHF14AMfView, IfPm3Iso14443a, "Display content from tag dump file"}, {"view", CmdHF14AMfView, AlwaysAvailable, "Display content from tag dump file"},
{"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"}, {"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"},
{"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"}, {"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"},
@ -5878,16 +5895,16 @@ static command_t CommandTable[] = {
{"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from emulator memory"}, {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from emulator memory"},
{"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Load from file emul dump"}, {"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Load from file emul dump"},
{"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"}, {"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"},
{"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"}, {"esetblk", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"},
{"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emulator memory"}, {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emulator memory"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"},
{"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block"}, {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block from card"},
{"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector"}, {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector from card"},
{"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump"}, {"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump to card"},
{"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from card into file or emulator"}, {"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from card into file or emulator"},
{"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block"}, {"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block to card"},
{"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID"}, {"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID on card"},
{"cview", CmdHF14AMfCView, IfPm3Iso14443a, "view card"}, {"cview", CmdHF14AMfCView, IfPm3Iso14443a, "View card"},
{"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"}, {"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"},
{"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without manufacturer block"}, {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without manufacturer block"},