mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
added GDM read configuration block
This commit is contained in:
parent
22a193a7f2
commit
7b93de7a81
7 changed files with 154 additions and 2 deletions
|
@ -3,6 +3,7 @@ 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 `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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -7560,6 +7560,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;
|
||||
|
@ -7599,7 +7671,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;
|
||||
}
|
||||
|
||||
|
@ -7608,6 +7680,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)));
|
||||
|
@ -7908,6 +7985,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"},
|
||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue