hf mf wrbl, restore - changed the logic of --force param. It is now used to override warnings about BLOCK0 and bad ACL block data and allow the user to write it regardless of its consequences.\n You can easily brick sectors on genuine or Gen2 cards.\n Be aware, here be dragons!

This commit is contained in:
iceman1001 2023-01-10 22:08:59 +01:00
commit 73a80fb07d

View file

@ -507,7 +507,10 @@ static int CmdHF14AMfWrBl(const char *Cmd) {
"Sector 0 / Block 0 - Manufacturer block\n" "Sector 0 / Block 0 - Manufacturer block\n"
"When writing to block 0 you must use a VALID block 0 data (UID, BCC, SAK, ATQA)\n" "When writing to block 0 you must use a VALID block 0 data (UID, BCC, SAK, ATQA)\n"
"Writing an invalid block 0 means rendering your Magic GEN2 card undetectable. \n" "Writing an invalid block 0 means rendering your Magic GEN2 card undetectable. \n"
"Look in the magic_cards_notes.md file for help to resolve it.", "Look in the magic_cards_notes.md file for help to resolve it.\n"
" \n"
"`--force` param is used to override warnings like bad ACL and BLOCK 0 writes.\n"
" if not specified, it will exit if detected",
"hf mf wrbl --blk 1 -k FFFFFFFFFFFF -d 000102030405060708090a0b0c0d0e0f" "hf mf wrbl --blk 1 -k FFFFFFFFFFFF -d 000102030405060708090a0b0c0d0e0f"
); );
void *argtable[] = { void *argtable[] = {
@ -515,7 +518,7 @@ static int CmdHF14AMfWrBl(const char *Cmd) {
arg_int1(NULL, "blk", "<dec>", "block number"), arg_int1(NULL, "blk", "<dec>", "block number"),
arg_lit0("a", NULL, "input key type is key A (def)"), arg_lit0("a", NULL, "input key type is key A (def)"),
arg_lit0("b", NULL, "input key type is key B"), arg_lit0("b", NULL, "input key type is key B"),
arg_lit0(NULL, "force", "enforce block0 writes"), arg_lit0(NULL, "force", "override warnings"),
arg_str0("k", "key", "<hex>", "key, 6 hex bytes"), arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"), arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
@ -553,6 +556,8 @@ static int CmdHF14AMfWrBl(const char *Cmd) {
if (b > 255) { if (b > 255) {
return PM3_EINVARG; return PM3_EINVARG;
} }
// BLOCK 0 detection
if (b == 0 && force == false) { if (b == 0 && force == false) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Targeting Sector 0 / Block 0 - Manufacturer block"); PrintAndLogEx(INFO, "Targeting Sector 0 / Block 0 - Manufacturer block");
@ -564,13 +569,14 @@ static int CmdHF14AMfWrBl(const char *Cmd) {
uint8_t blockno = (uint8_t)b; uint8_t blockno = (uint8_t)b;
// Warn if ACL is strict read-only // Sector trailer sanity checks.
// Warn if ACL is strict read-only, or invalid ACL.
if (mfIsSectorTrailer(blockno)) { if (mfIsSectorTrailer(blockno)) {
PrintAndLogEx(INFO, "Sector trailer (ST) write detected"); PrintAndLogEx(INFO, "Sector trailer (ST) write detected");
// ensure access right isn't messed up. // ensure access right isn't messed up.
if (mfValidateAccessConditions(&block[6]) == false) { if (mfValidateAccessConditions(&block[6]) == false) {
PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing by default values"); PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing with default values");
memcpy(block + 6, "\xFF\x07\x80\x69", 4); memcpy(block + 6, "\xFF\x07\x80\x69", 4);
} }
@ -583,8 +589,13 @@ static int CmdHF14AMfWrBl(const char *Cmd) {
} }
} }
if (ro_detected) { if (ro_detected) {
if (force) {
PrintAndLogEx(WARNING, " --force override, continuing...");
} else {
PrintAndLogEx(INFO, "Exiting, please run `" _YELLOW_("hf mf acl -d %s") "` to understand", sprint_hex_inrow(&block[6], 3)); PrintAndLogEx(INFO, "Exiting, please run `" _YELLOW_("hf mf acl -d %s") "` to understand", sprint_hex_inrow(&block[6], 3));
PrintAndLogEx(INFO, "Use `" _YELLOW_("--force") "` to override and write this data");
return PM3_EINVARG; return PM3_EINVARG;
}
} else { } else {
PrintAndLogEx(SUCCESS, "ST passed checks, continuing..."); PrintAndLogEx(SUCCESS, "ST passed checks, continuing...");
} }
@ -1079,9 +1090,11 @@ static int CmdHF14AMfRestore(const char *Cmd) {
"If access rights in dump file is all zeros, it will be replaced with default values\n" "If access rights in dump file is all zeros, it will be replaced with default values\n"
"\n" "\n"
"`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n" "`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n"
" If not specified, it will read the card uid instead.\n" " if not specified, it will read the card uid instead.\n"
" `--ka` param you can indicate that the key file should be used for authentication instead.\n" " `--ka` param you can indicate that the key file should be used for authentication instead.\n"
" if so we also try both B/A keys", " if so we also try both B/A keys\n"
"`--force` param is used to override warnings and allow bad ACL block writes.\n"
" if not specified, it will skip blocks with bad ACL.\n",
"hf mf restore\n" "hf mf restore\n"
"hf mf restore --1k --uid 04010203\n" "hf mf restore --1k --uid 04010203\n"
"hf mf restore --1k --uid 04010203 -k hf-mf-AABBCCDD-key.bin\n" "hf mf restore --1k --uid 04010203 -k hf-mf-AABBCCDD-key.bin\n"
@ -1098,6 +1111,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
arg_str0("f", "file", "<fn>", "specify dump filename (bin/eml/json)"), arg_str0("f", "file", "<fn>", "specify dump filename (bin/eml/json)"),
arg_str0("k", "kfn", "<fn>", "key filename"), arg_str0("k", "kfn", "<fn>", "key filename"),
arg_lit0(NULL, "ka", "use specified keyfile to authenticate"), arg_lit0(NULL, "ka", "use specified keyfile to authenticate"),
arg_lit0(NULL, "force", "override warnings"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1120,6 +1134,8 @@ static int CmdHF14AMfRestore(const char *Cmd) {
CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)keyfilename, FILE_PATH_SIZE, &keyfnlen); CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)keyfilename, FILE_PATH_SIZE, &keyfnlen);
bool use_keyfile_for_auth = arg_get_lit(ctx, 8); bool use_keyfile_for_auth = arg_get_lit(ctx, 8);
bool force = arg_get_lit(ctx, 9);
CLIParserFree(ctx); CLIParserFree(ctx);
// validations // validations
@ -1256,7 +1272,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
// ensure access right isn't messed up. // ensure access right isn't messed up.
if (mfValidateAccessConditions(&bldata[6]) == false) { if (mfValidateAccessConditions(&bldata[6]) == false) {
PrintAndLogEx(WARNING, "Invalid Access Conditions on sector %i, replacing by default values", s); PrintAndLogEx(WARNING, "Invalid Access Conditions on sector %i, replacing with default values", s);
memcpy(bldata + 6, "\xFF\x07\x80\x69", 4); memcpy(bldata + 6, "\xFF\x07\x80\x69", 4);
} }
@ -1264,6 +1280,12 @@ static int CmdHF14AMfRestore(const char *Cmd) {
for (uint8_t foo = 0; foo < mfNumBlocksPerSector(s); foo++) { for (uint8_t foo = 0; foo < mfNumBlocksPerSector(s); foo++) {
if (mfReadOnlyAccessConditions(foo, &bldata[6])) { if (mfReadOnlyAccessConditions(foo, &bldata[6])) {
PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", foo); PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", foo);
// if --force isn't used, skip writing this block
if (force == false) {
PrintAndLogEx(INFO, "Skipping, use `" _YELLOW_("--force") "` to override and write this data");
continue;
}
} }
} }
} }