mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Merge pull request #3229 from team-orangeBlue/mfp_write_checker
Add ST check to `hf mfp wrbl`, fix ST RO checks for 16-block sectors
This commit is contained in:
+6
-4
@@ -3,7 +3,9 @@ All notable changes to this project will be documented in this file.
|
||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Added system code name annotation to 'hf felica info' and 'hf felica rqsyscode'
|
||||
- Fixed `hf mf wrbl` and `hf mfp wrbl` the ACL RO checks on 16-block sectors correct (@team-orangeBlue)
|
||||
- Changed `hf mfp wrbl` command to check for Sector Trailer errors that could potentially lock sectors out (@team-orangeBlue)
|
||||
- Changed `hf felica info` and `hf felica rqsyscode` system code name annotation (@team-orangeBlue)
|
||||
- Added `lf relay` command where it relays between two pm3 devices over internet. Thanks to Moerno for the code! (@iceman1001)
|
||||
- Changed `hf mf acl` command to have more recognized generic configurations (@team-orangeBlue)
|
||||
- Added `hf mfp acl` command (@team-orangeBlue)
|
||||
@@ -14,10 +16,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||
- Added `hf mfdes createdelegateapp` command (@kormax)
|
||||
- Optimized `hf iclass legbrute` throughput: replaced recursive `suc()`/`output()` cipher functions with iterative loops, added 256-entry LUT for the `select()` function eliminating redundant bit arithmetic and halving key lookups per state step, switched successor state to in-place pointer update removing per-call struct copies, added `doMAC_brute()` with byte-wise LSB-first processing and direct output bit packing eliminating all bitstream struct overhead and output reversal calls per key candidate, and replaced per-iteration 64-bit modulo progress check with a countdown counter (@antiklesys)
|
||||
- Improved `hf iclass legbrute` fixed multithreaded key-range partitioning so threads cover non-overlapping slices of the 40-bit keyspace, added ETA display, keyboard abort with resume hint, `_Atomic` correctness for shared state, `pthread_create` error handling, and thread count capped at available CPUs (@antiklesys)
|
||||
- Added wildcard support to `hf secc sim` payloads (@antiklesys)
|
||||
- Changed `hf secc sim` it nows supports wildcard to payloads (@antiklesys)
|
||||
- Added `hf secc` to build a base for simulating basic function of iclass SE config cards (@antiklesys)
|
||||
- Improved SIO parsing for `hf iclass view` based on Iceman's "Dismantling the SEOS Protocol" talk (@antiklesys)
|
||||
- Added live fc/cn update to `hf iclass tagsim` refreshing the csn with each update (@antiklesys)
|
||||
- Changed `hf iclass view` , improved SIO parsing for based on @Iceman1001's "Dismantling the SEOS Protocol" talk (@antiklesys)
|
||||
- Changed `hf iclass tagsim` added live fc/cn update to refreshing the csn with each update (@antiklesys)
|
||||
- Added `--live` option to `hf iclass lookup` command to perform a live recovery of the reader's key by simulating a tag and running the lookup command against both standard and elite dictionaries (@antiklesys)
|
||||
- Added `hf iclass tagsim` command to quickly simulate an iclass card based on facility code and card number(@antiklesys)
|
||||
- Added `-f` parameter to `hf iclass sam` command to use the sam to parse a card dump (@antiklesys)
|
||||
|
||||
@@ -869,10 +869,16 @@ static int mf_analyse_st_block(uint8_t blockno, uint8_t *block, bool force) {
|
||||
}
|
||||
|
||||
bool ro_detected = false;
|
||||
uint8_t bar = mfNumBlocksPerSector(mfSectorNum(blockno));
|
||||
//uint8_t bar = mfNumBlocksPerSector(mfSectorNum(blockno));
|
||||
uint8_t bar = 4;
|
||||
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);
|
||||
// WARNING: Sectors 33+ assume ACLs apply to groups of 4 blocks, not 1 block.
|
||||
// The code as-is is bugged and actually wastes iterations. If you have 16 blocks, it'll run all 16 but only error out like it's a 4-block sector.
|
||||
if (blockno<128)
|
||||
PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", blockno - bar + 1 + foo);
|
||||
else
|
||||
PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on blocks " _YELLOW_("%u-%u") " detected", blockno - bar*4 + 1 + foo*5, blockno - bar*4 + 1 + foo*5 + 4);
|
||||
ro_detected = true;
|
||||
}
|
||||
}
|
||||
|
||||
+57
-1
@@ -809,7 +809,7 @@ static int CmdHFMFPAcl(const char *Cmd) {
|
||||
" ACCESS = access bytes inside sector trailer block\n"
|
||||
" Increment, decrement, transfer, restore is for value blocks",
|
||||
"hf mf acl\n"
|
||||
"hf mf acl -d FF0780\n");
|
||||
"hf mf acl -d 0FFF0780\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
@@ -1180,6 +1180,49 @@ 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));
|
||||
uint8_t bar = 4;
|
||||
for (uint8_t foo = 0; foo < bar; foo++) {
|
||||
if (mfReadOnlyAccessConditions(foo, &block[6])) {
|
||||
// WARNING: Sectors 33+ assume ACLs apply to groups of 4 blocks, not 1 block.
|
||||
// The code as-is is bugged and actually wastes iterations. If you have 16 blocks, it'll run all 16 but only error out like it's a 4-block sector.
|
||||
if (blockno<128)
|
||||
PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", blockno - bar + 1 + foo);
|
||||
else
|
||||
PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on blocks " _YELLOW_("%u-%u") " detected", blockno - bar*4 + 1 + foo*5, blockno - bar*4 + 1 + foo*5 + 4);
|
||||
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 +1240,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 +1258,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 +1285,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