renamed gdm getblk to config since that is what it does

This commit is contained in:
iceman1001 2023-03-26 03:41:12 +02:00
parent 932e345c43
commit 97e16ba764
9 changed files with 88 additions and 97 deletions

View file

@ -1735,14 +1735,12 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareG4WriteBlk(payload->blockno, payload->pwd, payload->data, payload->workFlags); MifareG4WriteBlk(payload->blockno, payload->pwd, payload->data, payload->workFlags);
break; break;
} }
case CMD_HF_MIFARE_G4_GDM_RDBL: { case CMD_HF_MIFARE_G4_GDM_CONFIG: {
struct p { struct p {
uint8_t blockno;
uint8_t keytype;
uint8_t key[6]; uint8_t key[6];
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
MifareReadBlockGDM(payload->blockno, payload->keytype, payload->key); MifareReadConfigBlockGDM(payload->key);
break; break;
} }
case CMD_HF_MIFARE_G4_GDM_WRBL: { case CMD_HF_MIFARE_G4_GDM_WRBL: {

View file

@ -214,7 +214,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
LEDsoff(); LEDsoff();
} }
void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key) { void MifareReadConfigBlockGDM(uint8_t *key) {
int retval = PM3_SUCCESS; int retval = PM3_SUCCESS;
@ -248,12 +248,12 @@ void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key) {
goto OUT; goto OUT;
} }
if (mifare_classic_authex_2(pcs, cuid, blockno, keytype, ui64key, AUTH_FIRST, NULL, NULL, true)) { if (mifare_classic_authex_2(pcs, cuid, 0, 0, ui64key, AUTH_FIRST, NULL, NULL, true)) {
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
}; };
if (mifare_classic_readblock_ex(pcs, cuid, blockno, outbuf, true)) { if (mifare_classic_readblock_ex(pcs, cuid, 0, outbuf, MIFARE_MAGIC_GDM_READBLOCK)) {
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
}; };
@ -266,7 +266,7 @@ void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key) {
OUT: OUT:
crypto1_deinit(pcs); crypto1_deinit(pcs);
reply_ng(CMD_HF_MIFARE_G4_GDM_RDBL, retval, outbuf, sizeof(outbuf)); reply_ng(CMD_HF_MIFARE_G4_GDM_CONFIG, retval, outbuf, sizeof(outbuf));
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
set_tracing(false); set_tracing(false);

View file

@ -59,7 +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 void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes
// MFC GEN4 GDM // MFC GEN4 GDM
void MifareReadBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key); void MifareReadConfigBlockGDM(uint8_t *key);
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain); void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain);
// MFC GEN4 GTU // MFC GEN4 GTU

View file

@ -153,7 +153,7 @@ int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t bloc
num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr); num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
// Transmit MIFARE_CLASSIC_AUTH 0x60, 0x61 or GDM 0x80 // Transmit MIFARE_CLASSIC_AUTH 0x60, 0x61 or GDM 0x80
uint8_t cmdbyte = (is_gdm) ? MIFARE_MAGIC_GDM_AUTH_KEYA : MIFARE_AUTH_KEYA + (keyType & 0x01); uint8_t cmdbyte = (is_gdm) ? MIFARE_MAGIC_GDM_AUTH_KEYA + (keyType & 0x01) : MIFARE_AUTH_KEYA + (keyType & 0x01);
len = mifare_sendcmd_short(pcs, isNested, cmdbyte, blockNo, receivedAnswer, receivedAnswerPar, timing); len = mifare_sendcmd_short(pcs, isNested, cmdbyte, blockNo, receivedAnswer, receivedAnswerPar, timing);
if (len != 4) return 1; if (len != 4) return 1;
@ -230,20 +230,14 @@ 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) { 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); return mifare_classic_readblock_ex(pcs, uid, blockNo, blockData, ISO14443A_CMD_READBLOCK);
} }
int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm) { int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte) {
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
uint16_t len; uint16_t len = mifare_sendcmd_short(pcs, 1, iso_byte, blockNo, receivedAnswer, receivedAnswerPar, NULL);
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 (len == 1) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]); if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]);
return 1; return 1;
@ -458,7 +452,6 @@ int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
// Receive the response // Receive the response
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
uint8_t res = 0; uint8_t res = 0;

View file

@ -75,7 +75,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
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_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(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_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte);
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_classic_halt_ex(struct Crypto1State *pcs); int mifare_classic_halt_ex(struct Crypto1State *pcs);

View file

@ -400,6 +400,47 @@ static void mf_analyse_acl(uint16_t n, uint8_t *d) {
} }
} }
/*
Sector trailer sanity checks.
Warn if ACL is strict read-only, or invalid ACL.
*/
static int mf_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) {
PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing with default values");
memcpy(block + 6, "\xFF\x07\x80\x69", 4);
}
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 passed checks, continuing...");
}
return PM3_SUCCESS;
}
static int CmdHF14AMfAcl(const char *Cmd) { static int CmdHF14AMfAcl(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf acl", CLIParserInit(&ctx, "hf mf acl",
@ -521,7 +562,6 @@ static int CmdHF14AMfWrBl(const char *Cmd) {
arg_lit0(NULL, "force", "override warnings"), arg_lit0(NULL, "force", "override warnings"),
arg_str0("k", "key", "<hex>", "key, 6 hex bytes"), arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"), arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -569,36 +609,8 @@ static int CmdHF14AMfWrBl(const char *Cmd) {
uint8_t blockno = (uint8_t)b; uint8_t blockno = (uint8_t)b;
// Sector trailer sanity checks. if (mf_analyse_st_block(blockno, block, force) != PM3_SUCCESS) {
// Warn if ACL is strict read-only, or invalid ACL. return PM3_EINVARG;
if (mfIsSectorTrailer(blockno)) {
PrintAndLogEx(INFO, "Sector trailer (ST) write detected");
// ensure access right isn't messed up.
if (mfValidateAccessConditions(&block[6]) == false) {
PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing with default values");
memcpy(block + 6, "\xFF\x07\x80\x69", 4);
}
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 passed checks, continuing...");
}
} }
PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key))); PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key)));
@ -7560,73 +7572,47 @@ static int CmdHF14AGen4Save(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHF14AGen4_GDM_GetBlk(const char *Cmd) { static int CmdHF14AGen4_GDM_ConfigBlk(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf gdmgetblk", CLIParserInit(&ctx, "hf mf gdmconfig",
"Get block data from magic gen4 GDM card.", "Get configuration data from magic gen4 GDM card.",
"hf mf gdmgetblk --blk 0 --> get block 0 (manufacturer)\n" "hf mf gdmconfig\n"
"hf mf gdmgetblk --blk 3 -v --> get block 3, decode sector trailer\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, 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_str0("k", "key", "<hex>", "key 6 bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, true);
int b = arg_get_int_def(ctx, 1, 0);
bool verbose = arg_get_lit(ctx, 2);
int keylen = 0; int keylen = 0;
uint8_t key[6] = {0}; uint8_t key[6] = {0};
CLIGetHexWithReturn(ctx, 3, key, &keylen); CLIGetHexWithReturn(ctx, 1, key, &keylen);
CLIParserFree(ctx); CLIParserFree(ctx);
// validate args // 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) { if (keylen != 6 && keylen != 0) {
PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen); PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t blockno = (uint8_t)b;
PrintAndLogEx(NORMAL, "Block: %x", blockno) ;
struct p { struct p {
uint8_t blockno;
uint8_t keytype;
uint8_t key[6]; uint8_t key[6];
} PACKED payload; } PACKED payload;
payload.blockno = blockno;
payload.keytype = 0;
memcpy(payload.key, key, sizeof(payload.key)); memcpy(payload.key, key, sizeof(payload.key));
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_G4_GDM_RDBL, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_HF_MIFARE_G4_GDM_CONFIG, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_GDM_RDBL, &resp, 1500) == false) { if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_GDM_CONFIG, &resp, 1500) == false) {
PrintAndLogEx(WARNING, "command execute timeout"); PrintAndLogEx(WARNING, "command execute timeout");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (resp.status == PM3_SUCCESS) { if (resp.status == PM3_SUCCESS) {
uint8_t sector = mfSectorNum(blockno);
mf_print_sector_hdr(sector);
uint8_t *d = resp.data.asBytes; uint8_t *d = resp.data.asBytes;
mf_print_block_one(blockno, d, verbose); PrintAndLogEx(SUCCESS, "config... %s", sprint_hex(d, resp.length));
PrintAndLogEx(NORMAL, "");
if (verbose) {
decode_print_st(blockno, d);
} else {
PrintAndLogEx(NORMAL, "");
}
} }
return resp.status; return resp.status;
@ -7636,7 +7622,9 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf gdmsetblk", CLIParserInit(&ctx, "hf mf gdmsetblk",
"Set block data on a magic gen4 GDM card", "Set block data on a magic gen4 GDM card\n"
"`--force` param is used to override warnings like bad ACL writes.\n"
" if not specified, it will exit if detected",
"hf mf gdmsetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f" "hf mf gdmsetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
); );
void *argtable[] = { void *argtable[] = {
@ -7644,8 +7632,9 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
arg_int1(NULL, "blk", "<dec>", "block number"), arg_int1(NULL, "blk", "<dec>", "block number"),
arg_lit0("a", NULL, "input key type is key A (def)"), arg_lit0("a", NULL, "input key type is key A (def)"),
arg_lit0("b", NULL, "input key type is key B"), arg_lit0("b", NULL, "input key type is key B"),
arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"), arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
arg_lit0(NULL, "force", "override warnings"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -7661,13 +7650,15 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
keytype = MF_KEY_B;; keytype = MF_KEY_B;;
} }
int keylen = 0;
uint8_t key[6] = {0};
CLIGetHexWithReturn(ctx, 4, key, &keylen);
uint8_t block[MFBLOCK_SIZE] = {0x00}; uint8_t block[MFBLOCK_SIZE] = {0x00};
int blen = 0; int blen = 0;
CLIGetHexWithReturn(ctx, 5, block, &blen); CLIGetHexWithReturn(ctx, 4, block, &blen);
int keylen = 0;
uint8_t key[6] = {0};
CLIGetHexWithReturn(ctx, 5, key, &keylen);
bool force = arg_get_lit(ctx, 6);
CLIParserFree(ctx); CLIParserFree(ctx);
if (blen != MFBLOCK_SIZE) { if (blen != MFBLOCK_SIZE) {
@ -7687,6 +7678,10 @@ static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
uint8_t blockno = (uint8_t)b; uint8_t blockno = (uint8_t)b;
if (mf_analyse_st_block(blockno, block, force) != PM3_SUCCESS) {
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key))); PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key)));
PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block))); PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block)));
@ -7985,7 +7980,7 @@ static command_t CommandTable[] = {
{"gsetblk", CmdHF14AGen4SetBlk, IfPm3Iso14443a, "Write block to card"}, {"gsetblk", CmdHF14AGen4SetBlk, IfPm3Iso14443a, "Write block to card"},
{"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"}, {"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"},
{"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GDM") " --------------------------"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GDM") " --------------------------"},
{"gdmgetblk", CmdHF14AGen4_GDM_GetBlk, IfPm3Iso14443a, "Read block from card"}, {"gdmconfig", CmdHF14AGen4_GDM_ConfigBlk, IfPm3Iso14443a, "Read config block from card"},
{"gdmsetblk", CmdHF14AGen4_GDM_SetBlk, IfPm3Iso14443a, "Write block to card"}, {"gdmsetblk", CmdHF14AGen4_GDM_SetBlk, IfPm3Iso14443a, "Write block to card"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("ndef") " -----------------------"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("ndef") " -----------------------"},
// {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, // {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},

View file

@ -540,9 +540,11 @@ This tag has simular commands to the [UFUID](#mifare-classic-directwrite-ufuid-v
It seems to be developed by the same person. It seems to be developed by the same person.
**OBS** **OBS**
When writing to persistent memory it is possible to write _bad_ ACL and perm-brick the tag. When writing to persistent memory it is possible to write _bad_ ACL and perm-brick the tag.
**OBS** **OBS**
It is possible to write a configuration that perma locks the tag, ie no more magic It is possible to write a configuration that perma locks the tag, ie no more magic
### Identify ### Identify
@ -579,6 +581,7 @@ Write config:
3. send 16 bytes 3. send 16 bytes
**Warning** **Warning**
Example of configuration to Perma lock tag: Example of configuration to Perma lock tag:
`85000000000000000000000000000008` `85000000000000000000000000000008`
@ -596,7 +599,7 @@ It is unknown what kind of block 0 changes the tag supports
hf mf gdmsetblk hf mf gdmsetblk
# Read 0xE0 configuration: # Read 0xE0 configuration:
hf mf gdmgetblk hf mf gdmconfig
``` ```

View file

@ -689,6 +689,7 @@ typedef struct {
// Gen 4 GDM magic cards // Gen 4 GDM magic cards
#define CMD_HF_MIFARE_G4_GDM_RDBL 0x0870 #define CMD_HF_MIFARE_G4_GDM_RDBL 0x0870
#define CMD_HF_MIFARE_G4_GDM_WRBL 0x0871 #define CMD_HF_MIFARE_G4_GDM_WRBL 0x0871
#define CMD_HF_MIFARE_G4_GDM_CONFIG 0x0872
#define CMD_UNKNOWN 0xFFFF #define CMD_UNKNOWN 0xFFFF

View file

@ -194,6 +194,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MIFARE_MAGIC_GDM_AUTH_KEYB 0x81 #define MIFARE_MAGIC_GDM_AUTH_KEYB 0x81
#define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8 #define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8
#define MIFARE_MAGIC_GDM_READBLOCK 0xE0 #define MIFARE_MAGIC_GDM_READBLOCK 0xE0
#define MIFARE_MAGIC_GDM_READBLOCK_1 0xE1
#define MIFARE_EV1_PERSONAL_UID 0x40 #define MIFARE_EV1_PERSONAL_UID 0x40
#define MIFARE_EV1_SETMODE 0x43 #define MIFARE_EV1_SETMODE 0x43