mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 02:27:26 -07:00
WIP - hf mfu countertear ...
This commit is contained in:
parent
acada02e37
commit
7cfbdcbae9
5 changed files with 197 additions and 7 deletions
|
@ -1473,6 +1473,15 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
MifareU_Otp_Tearoff(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MFU_COUNTER_TEAROFF: {
|
||||
struct p {
|
||||
uint8_t counter;
|
||||
uint32_t tearoff_time;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareU_Counter_Tearoff(payload->counter, payload->tearoff_time);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_STATIC_NONCE: {
|
||||
MifareHasStaticNonce();
|
||||
break;
|
||||
|
|
|
@ -2695,9 +2695,8 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
|
|||
//
|
||||
// Tear-off attack against MFU.
|
||||
// - Moebius et al
|
||||
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
|
||||
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t tearoff_time, uint8_t *datain) {
|
||||
uint8_t blockNo = arg0;
|
||||
uint32_t tearOffTime = arg1;
|
||||
uint8_t data_fullwrite[4] = {0x00};
|
||||
uint8_t data_testwrite[4] = {0x00};
|
||||
memcpy(data_fullwrite, datain, 4);
|
||||
|
@ -2705,8 +2704,8 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
|
|||
|
||||
if (DBGLEVEL >= DBG_DEBUG) DbpString("Preparing OTP tear-off");
|
||||
|
||||
if (tearOffTime > 43000)
|
||||
tearOffTime = 43000;
|
||||
if (tearoff_time > 43000)
|
||||
tearoff_time = 43000;
|
||||
|
||||
MifareUWriteBlock(blockNo, 0, data_fullwrite);
|
||||
|
||||
|
@ -2732,9 +2731,50 @@ void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain) {
|
|||
// Wait before cutting power. aka tear-off
|
||||
LED_D_ON();
|
||||
|
||||
SpinDelayUsPrecision(tearOffTime);
|
||||
SpinDelayUsPrecision(tearoff_time);
|
||||
if (DBGLEVEL >= DBG_DEBUG) Dbprintf(_YELLOW_("OTP tear-off triggered!"));
|
||||
switch_off();
|
||||
|
||||
reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Tear-off attack against MFU counter
|
||||
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time) {
|
||||
|
||||
if (tearoff_time > 43000)
|
||||
tearoff_time = 43000;
|
||||
|
||||
LEDsoff();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// Send MFU counter increase cmd
|
||||
uint8_t cmd[] = {
|
||||
MIFARE_ULEV1_INCR_CNT,
|
||||
counter,
|
||||
0, // lsb
|
||||
0,
|
||||
0, // msb
|
||||
0, // rfu
|
||||
0,
|
||||
0,
|
||||
};
|
||||
AddCrc14A(cmd, sizeof(cmd) - 2);
|
||||
|
||||
// anticollision / select card
|
||||
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
|
||||
if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
OnError(1);
|
||||
return;
|
||||
};
|
||||
|
||||
// send
|
||||
ReaderTransmit(cmd, sizeof(cmd), NULL);
|
||||
LED_D_ON();
|
||||
SpinDelayUsPrecision(tearoff_time);
|
||||
switch_off();
|
||||
|
||||
reply_ng(CMD_HF_MFU_COUNTER_TEAROFF, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
|
|
|
@ -64,5 +64,5 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
|
|||
|
||||
// Tear-off test for MFU
|
||||
void MifareU_Otp_Tearoff(uint8_t arg0, uint32_t arg1, uint8_t *datain);
|
||||
|
||||
void MifareU_Counter_Tearoff(uint8_t counter, uint32_t tearoff_time);
|
||||
#endif
|
||||
|
|
|
@ -878,7 +878,7 @@ static int ulev1_print_counters(void) {
|
|||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Counters"));
|
||||
uint8_t tear[1] = {0};
|
||||
uint8_t counter[3] = {0, 0, 0};
|
||||
uint16_t len = 0;
|
||||
int len = 0;
|
||||
for (uint8_t i = 0; i < 3; ++i) {
|
||||
ulev1_readTearing(i, tear, sizeof(tear));
|
||||
len = ulev1_readCounter(i, counter, sizeof(counter));
|
||||
|
@ -2832,10 +2832,12 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
return usage_hf_mfu_otp_tearoff();
|
||||
case 'b':
|
||||
blockNoUint = param_get8(Cmd, cmdp + 1);
|
||||
/*
|
||||
if (blockNoUint < 2) {
|
||||
PrintAndLogEx(WARNING, "Wrong block number");
|
||||
errors = true;
|
||||
}
|
||||
*/
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'i':
|
||||
|
@ -3037,6 +3039,141 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfu countertear",
|
||||
"Tear-off test against a Ev1 counter",
|
||||
"hf mfu countertear\n"
|
||||
"hf mfu countertear -s 200 -l 2500 -> target counter 0, start delay 200\n"
|
||||
"hf mfu countertear -i 2 -s 200 -l 400 -> target counter 0, start delay 200\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"),
|
||||
arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"),
|
||||
arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"),
|
||||
arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int counter = arg_get_int_def(ctx, 1, 0);
|
||||
int interval = arg_get_int_def(ctx, 2, 10);
|
||||
int time_limit = arg_get_int_def(ctx, 3, 3000);
|
||||
int start_time = arg_get_int_def(ctx, 4, 0);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// Validations
|
||||
if (start_time > (time_limit - interval)) {
|
||||
PrintAndLogEx(WARNING, "Wrong start time number");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (time_limit < interval) {
|
||||
PrintAndLogEx(WARNING, "Wrong time limit number");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (time_limit > 43000) {
|
||||
PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
uint8_t cnt_no = 0;
|
||||
if (counter < 0 || counter > 2) {
|
||||
PrintAndLogEx(WARNING, "Counter must 0, 1 or 2");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
cnt_no = (uint8_t)counter;
|
||||
|
||||
|
||||
PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------");
|
||||
PrintAndLogEx(INFO, "Starting counter tear-off test");
|
||||
PrintAndLogEx(INFO, "Target counter no: %u", counter);
|
||||
PrintAndLogEx(INFO, "----------------------------------------------------");
|
||||
|
||||
bool got_pre = false, got_post = false;
|
||||
uint8_t pre[3] = {0};
|
||||
uint8_t post[3] = {0};
|
||||
uint32_t actual_time = start_time;
|
||||
|
||||
iso14a_card_select_t card;
|
||||
|
||||
while (actual_time <= (time_limit - interval)) {
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
PrintAndLogEx(INFO, "\naborted via keyboard!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", actual_time);
|
||||
|
||||
if (ul_select(&card) == 0)
|
||||
return PM3_ESOFT;
|
||||
|
||||
got_pre = false;
|
||||
uint8_t cntresp[3] = {0, 0, 0};
|
||||
int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
|
||||
if ( rlen == sizeof(cntresp) ) {
|
||||
memcpy(pre, cntresp, sizeof(pre));
|
||||
got_pre = true;
|
||||
}
|
||||
DropField();
|
||||
|
||||
struct p {
|
||||
uint8_t counter;
|
||||
uint32_t tearoff_time;
|
||||
} PACKED payload;
|
||||
payload.counter = cnt_no;
|
||||
payload.tearoff_time = actual_time;
|
||||
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
|
||||
if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
|
||||
PrintAndLogEx(WARNING, "Failed");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
got_post = false;
|
||||
if (ul_select(&card) == 0)
|
||||
return PM3_ESOFT;
|
||||
|
||||
rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
|
||||
if ( rlen == sizeof(cntresp) ) {
|
||||
memcpy(post, cntresp, sizeof(post));
|
||||
got_post = true;
|
||||
}
|
||||
DropField();
|
||||
|
||||
if (got_pre && got_post) {
|
||||
|
||||
char prestr[20] = {0};
|
||||
snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
|
||||
char poststr[20] = {0};
|
||||
snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
|
||||
|
||||
if (memcmp(pre, post, sizeof(pre)) == 0) {
|
||||
PrintAndLogEx(INFO, "Current %d - %s", cnt_no, poststr);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, _CYAN_("Tear off occured") " : %d %s vs " _RED_("%s")
|
||||
, cnt_no, prestr, poststr);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (got_pre == false)
|
||||
PrintAndLogEx(FAILED, "Failed to read Counter BEFORE");
|
||||
if (got_post == false)
|
||||
PrintAndLogEx(FAILED, "Failed to read Counter AFTER");
|
||||
}
|
||||
|
||||
actual_time += interval;
|
||||
}
|
||||
DropField();
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int CmdHF14MfuNDEF(const char *Cmd) {
|
||||
|
||||
int keylen;
|
||||
|
@ -3167,6 +3304,7 @@ static command_t CommandTable[] = {
|
|||
{"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"},
|
||||
{"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
|
||||
{"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
|
||||
{"countertear", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1 Counter bits"},
|
||||
{"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
|
|
@ -650,6 +650,9 @@ typedef struct {
|
|||
|
||||
// MFU OTP TearOff
|
||||
#define CMD_HF_MFU_OTP_TEAROFF 0x0740
|
||||
// MFU_Ev1 Counter TearOff
|
||||
#define CMD_HF_MFU_COUNTER_TEAROFF 0x0741
|
||||
|
||||
|
||||
#define CMD_HF_SNIFF 0x0800
|
||||
#define CMD_HF_PLOT 0x0801
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue