diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index b69bbf45f..b21fb2fdf 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -1180,6 +1180,43 @@ static int CmdHFMFPRdsc(const char *Cmd) { return PM3_SUCCESS; } +static int mfp_analyse_st_block(uint8_t blockno, uint8_t *block, bool force) { + + if (mfIsSectorTrailer(blockno) == false) { + return PM3_SUCCESS; + } + + PrintAndLogEx(INFO, "Sector trailer (ST) write detected"); + + // ensure access right isn't messed up. + if (mfValidateAccessConditions(block + 6) == false || ((block[5] >> 4) != ((~block[5]) & 0xF))) { + PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing with default values"); + memcpy(block + 5, "\x0F\xFF\x07\x80\x69", 5); + } + + bool ro_detected = false; + uint8_t bar = mfNumBlocksPerSector(mfSectorNum(blockno)); + for (uint8_t foo = 0; foo < bar; foo++) { + if (mfReadOnlyAccessConditions(foo, &block[6])) { + PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", blockno - bar + 1 + foo); + ro_detected = true; + } + } + 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, "Use `" _YELLOW_("--force") "` to override and write this data"); + return PM3_EINVARG; + } + } else { + PrintAndLogEx(SUCCESS, "ST checks ( " _GREEN_("ok") " )"); + } + + return PM3_SUCCESS; +} + static int CmdHFMFPWrbl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp wrbl", @@ -1197,6 +1234,7 @@ static int CmdHFMFPWrbl(const char *Cmd) { arg_lit0(NULL, "nmr", "Do not expect MAC in response"), arg_str1("d", "data", "", "Data, 16 hex bytes"), arg_str0("k", "key", "", "Key, 16 hex bytes"), + arg_lit0(NULL, "force", "Override warnings"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1214,6 +1252,8 @@ static int CmdHFMFPWrbl(const char *Cmd) { uint8_t key[250] = {0}; int keylen = 0; CLIGetHexWithReturn(ctx, 7, key, &keylen); + bool force = arg_get_lit(ctx, 8); + CLIParserFree(ctx); uint8_t keyn[2] = {0}; @@ -1239,6 +1279,16 @@ static int CmdHFMFPWrbl(const char *Cmd) { PrintAndLogEx(ERR, " must be 16 bytes. Got %d", datainlen); return PM3_EINVARG; } + // Necessary checks before doing any actual computing + tag interaction + // Block 0 detection + if (blockNum == 0) { + PrintAndLogEx(FAILED, "Cannot write block 0 on Mifare Plus"); + return PM3_EINVARG; + } + // ACL validity check + if (mfp_analyse_st_block(blockNum, datain, force) != PM3_SUCCESS) { + return PM3_EINVARG; + } uint8_t sectorNum = mfSectorNum(blockNum & 0xff); uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0);