mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-01-30 03:53:26 +08:00
Merge branch 'RfidResearchGroup-master' into mf-supercard
This commit is contained in:
commit
00b7091178
9 changed files with 257 additions and 28 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -4,6 +4,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
|
||||
## [unreleased][unreleased]
|
||||
- Changed `hf mf supercard` - Support editing UID and recovery of keys from second generation card (@AloneLiberty)
|
||||
- Added `hf mf gdmgetblk` - Support Gen4 GDM read configuration block (@iceman1001)
|
||||
- Changed magic note to include a section about GDM tags (@iceman1001)
|
||||
- Added `hf mf gdmsetblk` - Support Gen4 GDM write block (@iceman1001)
|
||||
- Changed `hf 14a info` - detect Gen GDM magic tags (@iceman1001)
|
||||
- Changed CLI max string argument length limit from 512 to 4096 (@iceman1001)
|
||||
|
@ -20,7 +22,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Fixed `pm3` script for passing arguments (@doegox)
|
||||
- Fixed python paths to include current directory (@jmichelp)
|
||||
- Fixed infinite loops in spindelayus (@lnv42)
|
||||
- Add ICECLASS standalone read/sim mode (@natesales)
|
||||
- Changed ICECLASS standalone to support a read/sim mode (@natesales)
|
||||
- Changed `hf iclass encode` - added verbose flag (@natesales)
|
||||
- Changed `hf waveshare` - now identify 1.54 nfc epaper correct (@ah01)
|
||||
- Fixed `Makefile` regression that broke `make install` (@henrygab)
|
||||
|
@ -32,12 +34,13 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Added `--back` option to `clear` command to clear the scrollback buffer (@wh201906)
|
||||
- Changed `hf iclass decrypt` - mark credentials as decrypted in the dump (@natesales)
|
||||
- Changed `hf iclass view` - show credentials on a decrypted dump (@natesales)
|
||||
- Show NTAG213TT tamper info in `hf mfu info` and add commands for configuring it's tamper feature (@mjaksn)
|
||||
- Add Mifare Classic EV1 signature write support to gen4 magic tag lua script (@augustozanellato)
|
||||
- Changed `hf mfu info` - NTAG213TT tamper info (mjaksn)
|
||||
- Added commands for configuring NTAG213TT tamper featue (@mjaksn)
|
||||
- Added Mifare Classic EV1 signature write support to gen4 magic tag lua script (@augustozanellato)
|
||||
- Added XOR key extraction and flag to Guardall G-Prox II (@GuruSteve)
|
||||
- Changed verbiage on `hf iclass info` KeyAccess area to be congruent with AA1 and AA2 areas (@GuruSteve)
|
||||
- Added `hf legic info` command for other sources: `hf legic einfo`, `hf legic view` (@0xdeb)
|
||||
-
|
||||
|
||||
|
||||
## [Nitride.4.16191][2023-01-29]
|
||||
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)
|
||||
|
|
|
@ -1735,7 +1735,16 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
MifareG4WriteBlk(payload->blockno, payload->pwd, payload->data, payload->workFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_HF_MIFARE_G4_GDM_RDBL: {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t keytype;
|
||||
uint8_t key[6];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareReadBlockGDM(payload->blockno, payload->keytype, payload->key);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_G4_GDM_WRBL: {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
|
|
|
@ -214,6 +214,65 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
|||
LEDsoff();
|
||||
}
|
||||
|
||||
void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key) {
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
|
||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
if (par == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
uint8_t *uid = BigBuf_malloc(10);
|
||||
if (uid == NULL) {
|
||||
retval = PM3_EMALLOC;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// variables
|
||||
uint32_t cuid = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
uint64_t ui64key = bytes_to_num(key, 6);
|
||||
uint8_t outbuf[16] = {0x00};
|
||||
|
||||
if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
}
|
||||
|
||||
if (mifare_classic_authex_2(pcs, cuid, blockno, keytype, ui64key, AUTH_FIRST, NULL, NULL, true)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
if (mifare_classic_readblock_ex(pcs, cuid, blockno, outbuf, true)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
if (mifare_classic_halt(pcs, cuid)) {
|
||||
retval = PM3_ESOFT;
|
||||
goto OUT;
|
||||
};
|
||||
|
||||
OUT:
|
||||
crypto1_deinit(pcs);
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_G4_GDM_RDBL, retval, outbuf, sizeof(outbuf));
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Select, Authenticate, Read a MIFARE tag.
|
||||
// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)
|
||||
|
|
|
@ -59,6 +59,7 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overw
|
|||
void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
|
||||
|
||||
// MFC GEN4 GDM
|
||||
void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key);
|
||||
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain);
|
||||
|
||||
// MFC GEN4 GTU
|
||||
|
|
|
@ -230,13 +230,20 @@ int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t bloc
|
|||
}
|
||||
|
||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
|
||||
return mifare_classic_readblock_ex(pcs, uid, blockNo, blockData, false);
|
||||
}
|
||||
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm) {
|
||||
|
||||
int len;
|
||||
uint8_t bt[2] = {0x00, 0x00};
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
|
||||
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
uint16_t len;
|
||||
if (is_gdm) {
|
||||
len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
} else {
|
||||
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
}
|
||||
|
||||
if (len == 1) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]);
|
||||
return 1;
|
||||
|
@ -246,6 +253,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
|||
return 2;
|
||||
}
|
||||
|
||||
uint8_t bt[2] = {0x00, 0x00};
|
||||
memcpy(bt, receivedAnswer + 16, 2);
|
||||
AddCrc14A(receivedAnswer, 16);
|
||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||
|
@ -416,19 +424,14 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
|
|||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) {
|
||||
return mifare_classic_writeblock_ex(pcs, uid, blockNo, blockData, false);
|
||||
}
|
||||
|
||||
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm) {
|
||||
// variables
|
||||
uint16_t len = 0;
|
||||
uint32_t pos = 0;
|
||||
uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send
|
||||
uint8_t res = 0;
|
||||
|
||||
uint8_t d_block[18], d_block_enc[18];
|
||||
// variables
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
|
||||
// command MIFARE_MAGIC_GDM_WRITEBLOCK
|
||||
uint16_t len;
|
||||
if (is_gdm) {
|
||||
len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||
} else {
|
||||
|
@ -440,11 +443,14 @@ int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t
|
|||
return 1;
|
||||
}
|
||||
|
||||
uint8_t d_block[18], d_block_enc[18];
|
||||
memcpy(d_block, blockData, 16);
|
||||
AddCrc14A(d_block, 16);
|
||||
|
||||
// enough for 18 Bytes to send
|
||||
uint8_t par[3] = {0x00, 0x00, 0x00};
|
||||
// crypto
|
||||
for (pos = 0; pos < 18; pos++) {
|
||||
for (uint32_t pos = 0; pos < 18; pos++) {
|
||||
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
||||
par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
|
||||
}
|
||||
|
@ -452,9 +458,10 @@ int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t
|
|||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
||||
|
||||
// Receive the response
|
||||
|
||||
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||
|
||||
res = 0;
|
||||
uint8_t res = 0;
|
||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0;
|
||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1;
|
||||
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2;
|
||||
|
|
|
@ -73,7 +73,10 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
|
|||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
|
||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
|
||||
int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm);
|
||||
|
||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm);
|
||||
|
||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
|
||||
int mifare_classic_halt_ex(struct Crypto1State *pcs);
|
||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
|
|
|
@ -7674,6 +7674,78 @@ static int CmdHF14AGen4Save(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF14AGen4_GDM_GetBlk(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mf gdmgetblk",
|
||||
"Get block data from magic gen4 GDM card.",
|
||||
"hf mf gdmgetblk --blk 0 --> get block 0 (manufacturer)\n"
|
||||
"hf mf gdmgetblk --blk 3 -v --> get block 3, decode sector trailer\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_int1("b", "blk", "<dec>", "block number"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
arg_str0("k", "key", "<hex>", "key 6 bytes"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
int b = arg_get_int_def(ctx, 1, 0);
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
|
||||
int keylen = 0;
|
||||
uint8_t key[6] = {0};
|
||||
CLIGetHexWithReturn(ctx, 3, key, &keylen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// validate args
|
||||
if (b < 0 || b >= MIFARE_4K_MAXBLOCK) {
|
||||
PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (keylen != 6 && keylen != 0) {
|
||||
PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t blockno = (uint8_t)b;
|
||||
PrintAndLogEx(NORMAL, "Block: %x", blockno) ;
|
||||
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t keytype;
|
||||
uint8_t key[6];
|
||||
} PACKED payload;
|
||||
|
||||
payload.blockno = blockno;
|
||||
payload.keytype = 0;
|
||||
memcpy(payload.key, key, sizeof(payload.key));
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_G4_GDM_RDBL, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_GDM_RDBL, &resp, 1500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
uint8_t sector = mfSectorNum(blockno);
|
||||
mf_print_sector_hdr(sector);
|
||||
|
||||
uint8_t *d = resp.data.asBytes;
|
||||
mf_print_block_one(blockno, d, verbose);
|
||||
|
||||
if (verbose) {
|
||||
decode_print_st(blockno, d);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
}
|
||||
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
|
@ -7713,7 +7785,7 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
|
|||
CLIParserFree(ctx);
|
||||
|
||||
if (blen != MFBLOCK_SIZE) {
|
||||
PrintAndLogEx(WARNING, "expected 16 HEX bytes. got %i", blen);
|
||||
PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
|
@ -7722,6 +7794,11 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (keylen != 6 && keylen != 0) {
|
||||
PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t blockno = (uint8_t)b;
|
||||
|
||||
PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key)));
|
||||
|
@ -8022,6 +8099,7 @@ static command_t CommandTable[] = {
|
|||
{"gsetblk", CmdHF14AGen4SetBlk, IfPm3Iso14443a, "Write block to card"},
|
||||
{"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GDM") " --------------------------"},
|
||||
{"gdmgetblk", CmdHF14AGen4_GDM_GetBlk, IfPm3Iso14443a, "Read block from card"},
|
||||
{"gdmsetblk", CmdHF14AGen4_GDM_SetBlk, IfPm3Iso14443a, "Write block to card"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("ndef") " -----------------------"},
|
||||
// {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
|
||||
|
|
|
@ -20,6 +20,7 @@ Useful docs:
|
|||
* [MIFARE Classic DirectWrite, UFUID version](#mifare-classic-directwrite-ufuid-version)
|
||||
* [MIFARE Classic, other versions](#mifare-classic-other-versions)
|
||||
* [MIFARE Classic Gen3 aka APDU](#mifare-classic-gen3-aka-apdu)
|
||||
* [MIFARE Classic Gen4 aka GDM](#mifare-classic-gen4-aka-gdm)
|
||||
* [MIFARE Classic Super](#mifare-classic-super)
|
||||
- [MIFARE Ultralight](#mifare-ultralight)
|
||||
* [MIFARE Ultralight blocks 0..2](#mifare-ultralight-blocks-02)
|
||||
|
@ -68,6 +69,7 @@ To restore anticollision config of the Proxmark3:
|
|||
```
|
||||
hf 14a config --std
|
||||
```
|
||||
|
||||
# MIFARE Classic
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -89,7 +91,7 @@ UID 4b: (actually NUID as there are no more "unique" IDs on 4b)
|
|||
```
|
||||
|
||||
|
||||
Computing BCC on UID 11223344: `hf analyse lcr -d 11223344` = `44`
|
||||
Computing BCC on UID 11223344: `analyse lcr -d 11223344` = `44`
|
||||
|
||||
UID 7b:
|
||||
|
||||
|
@ -262,6 +264,8 @@ hf 14a info
|
|||
* Read: `40(7)`, `30xx`
|
||||
* Write: `40(7)`, `A0xx`+crc, `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`+crc
|
||||
|
||||
|
||||
|
||||
## MIFARE Classic DirectWrite aka Gen2 aka CUID
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -396,6 +400,7 @@ hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566184200626364656667 # for 4k
|
|||
hf 14a config --std
|
||||
hf 14a reader
|
||||
```
|
||||
|
||||
## MIFARE Classic DirectWrite, FUID version aka 1-write
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -436,14 +441,6 @@ hf 14a raw -k -c e100
|
|||
hf 14a raw -c 85000000000000000000000000000008
|
||||
```
|
||||
|
||||
## MIFARE Classic, other versions
|
||||
^[Top](#top)
|
||||
|
||||
**TODO**
|
||||
|
||||
* ZXUID, EUID, ICUID ?
|
||||
* Some cards exhibit a specific SAK=28 ??
|
||||
|
||||
## MIFARE Classic Gen3 aka APDU
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -517,6 +514,72 @@ hf 14a raw -s -c -t 2000 90F0CCCC10 041219c3219316984200e32000000000
|
|||
hf 14a raw -s -c 90FD111100
|
||||
```
|
||||
|
||||
## MIFARE Classic Gen4 aka GDM
|
||||
^[Top](#top)
|
||||
Tag has shadow mode enabled from start.
|
||||
Meaning every write or changes to normal MFC memory is restored back to a copy from persistent memory after about 3 seconds
|
||||
off rfid field.
|
||||
Tag also seems to support Gen2 style, direct write, to block 0 to the normal MFC memory.
|
||||
|
||||
The persistent memory is also writable. For that tag uses its own backdoor commands.
|
||||
for example to write, you must use a customer authentication byte, 0x80, to authenticate with an all zeros key, 0x0000000000.
|
||||
Then send the data to be written.
|
||||
|
||||
** OBS **
|
||||
When writing to persistent memory it is possible to write _bad_ ACL and perm-brick the tag.
|
||||
|
||||
|
||||
### Identify
|
||||
^[Top](#top)
|
||||
|
||||
```
|
||||
hf 14a info
|
||||
...
|
||||
[+] Magic capabilities : Gen 4 GDM
|
||||
```
|
||||
### Magic commands
|
||||
^[Top](#top)
|
||||
|
||||
* Auth: `80xx`+crc
|
||||
* Write: `A8xx`+crc, `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`+crc
|
||||
* Read : `E000`+crc (unidentified)
|
||||
|
||||
### Characteristics
|
||||
^[Top](#top)
|
||||
|
||||
* Have no knowledge in ATQA/SAK/BCC quirks or if there is a wipe, softbrick recover
|
||||
* Its magic part seem to be three identified custom command.
|
||||
* Auth command 0x80, with the key 0x0000000000, Write 0xA8 allows writing to persistent memory, Read 0xE0 which seems to return a configuration. This is unknown today what these bytes are.
|
||||
|
||||
It is unknown what kind of block 0 changes the tag supports
|
||||
* UID: 4b
|
||||
* ATQA/SAK: unknown
|
||||
* BCC: unknown
|
||||
* ATS: none
|
||||
|
||||
### Proxmark3 commands
|
||||
^[Top](#top)
|
||||
```
|
||||
# Write to persistent memory
|
||||
hf mf gdmsetblk
|
||||
|
||||
# Read 0xE0 configuration:
|
||||
hf mf gdmgetblk
|
||||
|
||||
```
|
||||
|
||||
### libnfc commands
|
||||
^[Top](#top)
|
||||
No implemented commands today
|
||||
|
||||
## MIFARE Classic, other versions
|
||||
^[Top](#top)
|
||||
|
||||
**TODO**
|
||||
|
||||
* ZXUID, EUID, ICUID ?
|
||||
* Some cards exhibit a specific SAK=28 ??
|
||||
|
||||
## MIFARE Classic Super
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -1019,7 +1082,6 @@ script run hf_15_magic -u E004013344556677
|
|||
|
||||
A.k.a ultimate magic card, most promenent feature is shadow mode (GTU) and optional password protected backdoor commands.
|
||||
|
||||
|
||||
Can emulate MIFARE Classic, Ultralight/NTAG families, 14b UID & App Data
|
||||
|
||||
- [Identify](#identify)
|
||||
|
@ -1057,6 +1119,7 @@ The card will be identified only if the password is the default one. One can ide
|
|||
hf 14a raw -s -c -t 1000 CF00000000C6
|
||||
```
|
||||
If the card is an Ultimate Magic Card, it returns 30 or 32 bytes.
|
||||
|
||||
### Magic commands
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
@ -1203,6 +1266,7 @@ OR (Note the script will correct the ATQA correctly)
|
|||
```
|
||||
script run hf_mf_ultimatecard -q 004428
|
||||
```
|
||||
|
||||
### Change ATS
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
@ -1240,6 +1304,7 @@ Example: set UID length to 7 bytes, default pwd
|
|||
```
|
||||
hf 14a raw -s -c -t 1000 CF000000006801
|
||||
```
|
||||
|
||||
### Set 14443A UID
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
@ -1353,6 +1418,7 @@ script run hf_mf_ultimatecard -m 02
|
|||
```
|
||||
|
||||
Now the card supports the 3DES UL-C authentication.
|
||||
|
||||
### Set Ultralight and M1 maximum read/write sectors
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
@ -1366,6 +1432,7 @@ Example: set maximum 63 blocks read/write for Mifare Classic 1K
|
|||
```
|
||||
hf 14a raw -s -c -t 1000 CF000000006B3F
|
||||
```
|
||||
|
||||
### Set shadow mode (GTU)
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
@ -1479,6 +1546,7 @@ Default configuration:
|
|||
^^ cf cmd 68: UID length
|
||||
^^ cf cmd 69: Ultralight protocol
|
||||
```
|
||||
|
||||
### Fast configuration
|
||||
^[Top](#top) ^^[Gen4](#g4top)
|
||||
|
||||
|
|
|
@ -193,6 +193,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define MIFARE_MAGIC_GDM_AUTH_KEYA 0x80
|
||||
#define MIFARE_MAGIC_GDM_AUTH_KEYB 0x81
|
||||
#define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8
|
||||
#define MIFARE_MAGIC_GDM_READBLOCK 0xE0
|
||||
|
||||
#define MIFARE_EV1_PERSONAL_UID 0x40
|
||||
#define MIFARE_EV1_SETMODE 0x43
|
||||
|
|
Loading…
Reference in a new issue