mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
Merge branch 'master' into feature/iso15693-standalone
This commit is contained in:
commit
d0f2f6622b
31 changed files with 352 additions and 299 deletions
|
@ -4,6 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
|
||||
## [unreleased][unreleased]
|
||||
- Added `HF_TMUDFORD` standalone mode that reads and emulates ISO15693 UID (@tmudford)
|
||||
- Changed `hf mf wipe` - now supports enforcing sector 0 / block 0 writes (@iceman1001)
|
||||
- Added `data asn1` - a command to decode ASN1 byte arrays (@iceman1001)
|
||||
- Added `hf 15 disableprivacy` - from @g3gg0 fork *WIP* (@iceman1001)
|
||||
- Added `lf_ident_json.lua` - script to identify t55xx json dump files (@iceman1001)
|
||||
|
|
|
@ -5786,23 +5786,28 @@ static int CmdHf14AMfSuperCard(const char *Cmd) {
|
|||
static int CmdHF14AMfWipe(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf wipe",
|
||||
"Wipe card to zeros and default keys/acc. This command taks a key file to wipe card\n"
|
||||
"New A/B keys FF FF FF FF FF FF\n"
|
||||
"New acc FF 07 80\n"
|
||||
"New GDB 69",
|
||||
"hf mf wipe"
|
||||
"Wipe card to zeros and default keys/acc. This command takes a key file to wipe card\n"
|
||||
"Will use UID from card to generate keyfile name if not specified.\n"
|
||||
"New A/B keys..... FF FF FF FF FF FF\n"
|
||||
"New acc rights... FF 07 80\n"
|
||||
"New GPB.......... 69",
|
||||
"hf mf wipe --> reads card uid to generate file name\n"
|
||||
"hf mf wipe --gen2 --> force write to S0, B0 manufacture block\n"
|
||||
"hf mf wipe -f mykey.bin --> use mykey.bin\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("f", "file", "<fn>", "key filename"),
|
||||
arg_lit0(NULL, "gen2", "force write to Sector 0, block 0 (GEN2)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
int keyfnlen = 0;
|
||||
char keyFilename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen);
|
||||
|
||||
bool gen2 = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
char *fptr;
|
||||
|
@ -5826,12 +5831,14 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
uint8_t keyB[MIFARE_4K_MAXSECTOR * 6];
|
||||
uint8_t num_sectors = 0;
|
||||
|
||||
uint8_t mf[MFBLOCK_SIZE];
|
||||
switch (keyslen) {
|
||||
case (MIFARE_MINI_MAXSECTOR * 2 * 6): {
|
||||
PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic Mini 320b");
|
||||
memcpy(keyA, keys, (MIFARE_MINI_MAXSECTOR * 6));
|
||||
memcpy(keyB, keys + (MIFARE_MINI_MAXSECTOR * 6), (MIFARE_MINI_MAXSECTOR * 6));
|
||||
num_sectors = NumOfSectors('0');
|
||||
memcpy(mf, "\x11\x22\x33\x44\x44\x09\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
|
||||
break;
|
||||
}
|
||||
case (MIFARE_1K_MAXSECTOR * 2 * 6): {
|
||||
|
@ -5839,6 +5846,8 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
memcpy(keyA, keys, (MIFARE_1K_MAXSECTOR * 6));
|
||||
memcpy(keyB, keys + (MIFARE_1K_MAXSECTOR * 6), (MIFARE_1K_MAXSECTOR * 6));
|
||||
num_sectors = NumOfSectors('1');
|
||||
|
||||
memcpy(mf, "\x11\x22\x33\x44\x44\x08\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
|
||||
break;
|
||||
}
|
||||
case (MIFARE_4K_MAXSECTOR * 2 * 6): {
|
||||
|
@ -5846,6 +5855,7 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
memcpy(keyA, keys, (MIFARE_4K_MAXSECTOR * 6));
|
||||
memcpy(keyB, keys + (MIFARE_4K_MAXSECTOR * 6), (MIFARE_4K_MAXSECTOR * 6));
|
||||
num_sectors = NumOfSectors('4');
|
||||
memcpy(mf, "\x11\x22\x33\x44\x44\x18\x02\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -5854,6 +5864,12 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
if (gen2)
|
||||
PrintAndLogEx(INFO, "Forcing overwrite of sector 0 / block 0 ");
|
||||
else
|
||||
PrintAndLogEx(INFO, "Skipping sector 0 / block 0");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
uint8_t zeros[MFBLOCK_SIZE] = {0};
|
||||
memset(zeros, 0x00, sizeof(zeros));
|
||||
uint8_t st[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
@ -5863,6 +5879,11 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
|
||||
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
|
||||
|
||||
// Skipp write to manufacture block if not enforced
|
||||
if (s == 0 && b == 0 && gen2 == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t data[26];
|
||||
memset(data, 0, sizeof(data));
|
||||
if (mfIsSectorTrailer(b)) {
|
||||
|
@ -5871,6 +5892,11 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
memcpy(data + 10, zeros, sizeof(zeros));
|
||||
}
|
||||
|
||||
// add correct manufacture block if UID Gen2
|
||||
if (s == 0 && b == 0 && gen2) {
|
||||
memcpy(data + 10, mf, sizeof(mf));
|
||||
}
|
||||
|
||||
// try both A/B keys, start with B key first
|
||||
for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
|
||||
|
||||
|
@ -5879,16 +5905,16 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
else
|
||||
memcpy(data, keyB + (s * 6), 6);
|
||||
|
||||
PrintAndLogEx(INFO, "block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE));
|
||||
PrintAndLogEx(INFO, "block %3d: %s" NOLF, FirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE));
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, kt, 0, data, sizeof(data));
|
||||
PacketResponseNG resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
uint8_t isOK = resp.oldarg[0] & 0xff;
|
||||
if (isOK == 0) {
|
||||
PrintAndLogEx(FAILED, "isOk: %02x", isOK);
|
||||
PrintAndLogEx(NORMAL, "( " _RED_("fail") " )");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "( " _GREEN_("ok") " )");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -5898,6 +5924,7 @@ static int CmdHF14AMfWipe(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
out:
|
||||
free(keys);
|
||||
|
|
|
@ -154,7 +154,7 @@ static void ul_switch_on_field(void) {
|
|||
|
||||
static int ul_send_cmd_raw(uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength) {
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC | ISO14A_NO_RATS, cmdlen, 0, cmd, cmdlen);
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC | ISO14A_NO_RATS, cmdlen, 0, cmd, cmdlen);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
|
||||
if (!resp.oldarg[0] && responseLength) return -1;
|
||||
|
@ -3293,16 +3293,19 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||
|
||||
lock_on = true;
|
||||
|
||||
if ((phase_begin_clear == -1) && (bitcount32(*(uint32_t *)pre) > bitcount32(*(uint32_t *)post)))
|
||||
uint32_t post32 = bytes_to_num(post, 4);
|
||||
uint32_t pre32 = bytes_to_num(pre, 4);
|
||||
|
||||
if ((phase_begin_clear == -1) && (bitcount32(pre32) > bitcount32(post32)))
|
||||
phase_begin_clear = current;
|
||||
|
||||
if ((phase_begin_clear > -1) && (phase_end_clear == -1) && (bitcount32(*(uint32_t *)post) == 0))
|
||||
if ((phase_begin_clear > -1) && (phase_end_clear == -1) && (bitcount32(post32) == 0))
|
||||
phase_end_clear = current;
|
||||
|
||||
if ((current == start) && (phase_end_clear > -1))
|
||||
skip_phase1 = true;
|
||||
// new write phase must be atleast 100us later..
|
||||
if (((bitcount32(*(uint32_t *)pre) == 0) || (phase_end_clear > -1)) && (phase_begin_newwr == -1) && (bitcount32(*(uint32_t *)post) != 0) && (skip_phase1 || (current > (phase_end_clear + 100))))
|
||||
if (((bitcount32(pre32) == 0) || (phase_end_clear > -1)) && (phase_begin_newwr == -1) && (bitcount32(post32) != 0) && (skip_phase1 || (current > (phase_end_clear + 100))))
|
||||
phase_begin_newwr = current;
|
||||
|
||||
if ((phase_begin_newwr > -1) && (phase_end_newwr == -1) && (memcmp(post, teardata, sizeof(teardata)) == 0))
|
||||
|
|
|
@ -35,6 +35,7 @@ enum asn1_tag_t {
|
|||
ASN1_TAG_UTC_TIME,
|
||||
ASN1_TAG_STR_TIME,
|
||||
ASN1_TAG_OBJECT_ID,
|
||||
ASN1_TAG_HEX,
|
||||
};
|
||||
|
||||
struct asn1_tag {
|
||||
|
@ -157,8 +158,11 @@ static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag
|
|||
}
|
||||
|
||||
static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, int level) {
|
||||
PrintAndLogEx(NORMAL, " value: '" NOLF);
|
||||
PrintAndLogEx(NORMAL, "%s'", sprint_hex(tlv->value, tlv->len));
|
||||
PrintAndLogEx(NORMAL, " value: '%s'", sprint_hex(tlv->value, tlv->len));
|
||||
}
|
||||
|
||||
static void asn1_tag_dump_hex(const struct tlv *tlv, const struct asn1_tag *tag, int level) {
|
||||
PrintAndLogEx(NORMAL, " value: '%s'", sprint_hex_inrow(tlv->value, tlv->len));
|
||||
}
|
||||
|
||||
static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_tag *tag, int level, bool *needdump) {
|
||||
|
@ -170,7 +174,7 @@ static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_
|
|||
}
|
||||
|
||||
if (*needdump) {
|
||||
PrintAndLogEx(NORMAL, "'");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " " NOLF);
|
||||
asn1_tag_dump_string(tlv, tag, level);
|
||||
|
@ -314,8 +318,15 @@ bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump) {
|
|||
|
||||
const struct asn1_tag *tag = asn1_get_tag(tlv);
|
||||
|
||||
/*
|
||||
if ((tlv->tag & 0x20) == 0x20 ) {
|
||||
} else if ((tlv->tag & 0x80) == 0x80 ) {
|
||||
} else {
|
||||
}
|
||||
*/
|
||||
|
||||
PrintAndLogEx(INFO,
|
||||
"%*s-- %2x [%02zx] '"_YELLOW_("%s") "' :" NOLF
|
||||
"%*s-- %2x [%02zx] '"_YELLOW_("%s") "'" NOLF
|
||||
, (level * 4)
|
||||
, " "
|
||||
, tlv->tag
|
||||
|
@ -326,6 +337,7 @@ bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump) {
|
|||
switch (tag->type) {
|
||||
case ASN1_TAG_GENERIC:
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
// maybe print number of elements?
|
||||
break;
|
||||
case ASN1_TAG_STRING:
|
||||
asn1_tag_dump_string(tlv, tag, level);
|
||||
|
@ -352,6 +364,10 @@ bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump) {
|
|||
asn1_tag_dump_object_id(tlv, tag, level);
|
||||
*candump = false;
|
||||
break;
|
||||
case ASN1_TAG_HEX:
|
||||
asn1_tag_dump_hex(tlv, tag, level);
|
||||
*candump = false;
|
||||
break;
|
||||
};
|
||||
|
||||
return true;
|
||||
|
|
|
@ -65,7 +65,7 @@ static void asn1_print_cb(void *data, const struct tlv *tlv, int level, bool is_
|
|||
bool candump = true;
|
||||
asn1_tag_dump(tlv, level, &candump);
|
||||
if (is_leaf && candump) {
|
||||
print_buffer(tlv->value, tlv->len, level);
|
||||
print_buffer(tlv->value, tlv->len, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ Check column "offline" for their availability.
|
|||
|`data zerocrossings `|Y |`Count time between zero-crossings`
|
||||
|`data convertbitstream `|Y |`Convert GraphBuffer's 0/1 values to 127 / -127`
|
||||
|`data getbitstream `|Y |`Convert GraphBuffer's >=1 values to 1 and <1 to 0`
|
||||
|`data asn1 `|Y |`asn1 decoder`
|
||||
|`data bin2hex `|Y |`Converts binary to hexadecimal`
|
||||
|`data bitsamples `|N |`Get raw samples as bitstring`
|
||||
|`data clear `|Y |`Clears bigbuf on deviceside and graph window`
|
||||
|
@ -225,6 +226,7 @@ Check column "offline" for their availability.
|
|||
|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO-15693 tag`
|
||||
|`hf 15 samples `|N |`Acquire samples as reader (enables carrier, sends inquiry)`
|
||||
|`hf 15 sim `|N |`Fake an ISO-15693 tag`
|
||||
|`hf 15 slixdisable `|N |`Disable privacy mode on SLIX ISO-15693 tag`
|
||||
|`hf 15 wrbl `|N |`Write a block`
|
||||
|`hf 15 findafi `|N |`Brute force AFI of an ISO-15693 tag`
|
||||
|`hf 15 writeafi `|N |`Writes the AFI on an ISO-15693 tag`
|
||||
|
@ -807,6 +809,8 @@ Check column "offline" for their availability.
|
|||
|`lf idteck help `|Y |`This help`
|
||||
|`lf idteck demod `|Y |`demodulate an Idteck tag from the GraphBuffer`
|
||||
|`lf idteck reader `|N |`attempt to read and extract tag data`
|
||||
|`lf idteck clone `|N |`clone Idteck tag to T55x7 or Q5/T5555`
|
||||
|`lf idteck sim `|N |`simulate Idteck tag`
|
||||
|
||||
|
||||
### lf indala
|
||||
|
|
|
@ -330,6 +330,8 @@ Android compatible
|
|||
|
||||
```
|
||||
hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869
|
||||
|
||||
hf mf wipe --gen2
|
||||
```
|
||||
|
||||
When "soft-bricked" (by writing invalid data in block0), these ones may help:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue