mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-06-07 00:11:46 +00:00
Add ST+ACL check to hf mfp wrbl
Sector trailers are now checked for errors. Writes should not go through if for whatever reason ACLs provided to write are invalid. Reminder that ACLs are checked on the 4-byte method of MFP with the encrypted-only exchange byte. Signed-off-by: team-orangeBlue <63470411+team-orangeBlue@users.noreply.github.com>
This commit is contained in:
@@ -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", "<hex>", "Data, 16 hex bytes"),
|
||||
arg_str0("k", "key", "<hex>", "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, "<data> 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);
|
||||
|
||||
Reference in New Issue
Block a user