mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
added support for the magic card called GDM.
This commit is contained in:
parent
390720144a
commit
07f6162780
10 changed files with 205 additions and 11 deletions
|
@ -3,6 +3,8 @@ 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...
|
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]
|
## [unreleased][unreleased]
|
||||||
|
- 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)
|
- Changed CLI max string argument length limit from 512 to 4096 (@iceman1001)
|
||||||
- Fixed `data asn1` - now handles bad input better (@iceman1001)
|
- Fixed `data asn1` - now handles bad input better (@iceman1001)
|
||||||
- Added new public key for signature MIFARE Plus Troika (@iceman100)
|
- Added new public key for signature MIFARE Plus Troika (@iceman100)
|
||||||
|
|
|
@ -1686,7 +1686,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
MifareECardLoadExt(payload->sectorcnt, payload->keytype);
|
MifareECardLoadExt(payload->sectorcnt, payload->keytype);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Work with "magic Chinese" card
|
// Gen1a / 1b - "magic Chinese" card
|
||||||
case CMD_HF_MIFARE_CSETBL: {
|
case CMD_HF_MIFARE_CSETBL: {
|
||||||
MifareCSetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
MifareCSetBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||||
break;
|
break;
|
||||||
|
@ -1713,6 +1713,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
MifareGen3Freez();
|
MifareGen3Freez();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Gen 4 GTU magic cards
|
||||||
case CMD_HF_MIFARE_G4_RDBL: {
|
case CMD_HF_MIFARE_G4_RDBL: {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t blockno;
|
uint8_t blockno;
|
||||||
|
@ -1723,7 +1724,6 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
MifareG4ReadBlk(payload->blockno, payload->pwd, payload->workFlags);
|
MifareG4ReadBlk(payload->blockno, payload->pwd, payload->workFlags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Gen 4 GTU magic cards
|
|
||||||
case CMD_HF_MIFARE_G4_WRBL: {
|
case CMD_HF_MIFARE_G4_WRBL: {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t blockno;
|
uint8_t blockno;
|
||||||
|
@ -1735,6 +1735,18 @@ 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_WRBL: {
|
||||||
|
struct p {
|
||||||
|
uint8_t blockno;
|
||||||
|
uint8_t keytype;
|
||||||
|
uint8_t key[6];
|
||||||
|
uint8_t data[16]; // data to be written
|
||||||
|
} PACKED;
|
||||||
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
|
MifareWriteBlockGDM(payload->blockno, payload->keytype, payload->key, payload->data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
case CMD_HF_MIFARE_PERSONALIZE_UID: {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t keytype;
|
uint8_t keytype;
|
||||||
|
|
|
@ -446,6 +446,73 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
set_tracing(false);
|
set_tracing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain) {
|
||||||
|
|
||||||
|
int retval = PM3_SUCCESS;
|
||||||
|
|
||||||
|
// check args
|
||||||
|
if (datain == NULL) {
|
||||||
|
retval = PM3_EINVARG;
|
||||||
|
goto OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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_writeblock_ex(pcs, cuid, blockno, datain, true)) {
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mifare_classic_halt(pcs, cuid)) {
|
||||||
|
retval = PM3_ESOFT;
|
||||||
|
goto OUT;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (g_dbglevel >= 2) DbpString("WRITE BLOCK FINISHED");
|
||||||
|
|
||||||
|
OUT:
|
||||||
|
crypto1_deinit(pcs);
|
||||||
|
|
||||||
|
reply_ng(CMD_HF_MIFARE_G4_GDM_WRBL, retval, NULL, 0);
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LEDsoff();
|
||||||
|
set_tracing(false);
|
||||||
|
BigBuf_free();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
|
||||||
// params
|
// params
|
||||||
uint8_t blockNo = arg0;
|
uint8_t blockNo = arg0;
|
||||||
|
@ -2356,7 +2423,7 @@ void MifareCIdent(bool is_mfc) {
|
||||||
uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 };
|
uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 };
|
||||||
uint8_t rdblf0[4] = { ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
uint8_t rdblf0[4] = { ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
||||||
uint8_t rdbl00[4] = { ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
uint8_t rdbl00[4] = { ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
||||||
uint8_t gen3gmd[4] = { MIFARE_MAGIC_GDM_AUTH_KEYA, 0x00, 0x6C, 0x92};
|
uint8_t gen4gmd[4] = { MIFARE_MAGIC_GDM_AUTH_KEYA, 0x00, 0x6C, 0x92};
|
||||||
uint8_t gen4GetConf[8] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0};
|
uint8_t gen4GetConf[8] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0};
|
||||||
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||||
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
|
||||||
|
@ -2493,17 +2560,17 @@ void MifareCIdent(bool is_mfc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// magic MFC Gen3 test 2
|
// magic MFC Gen4 GDM test
|
||||||
if (isGen != MAGIC_GEN_3) {
|
if (isGen != MAGIC_GEN_3) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
SpinDelay(40);
|
SpinDelay(40);
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||||
if (res == 2) {
|
if (res == 2) {
|
||||||
ReaderTransmit(gen3gmd, sizeof(gen3gmd), NULL);
|
ReaderTransmit(gen4gmd, sizeof(gen4gmd), NULL);
|
||||||
res = ReaderReceive(buf, par);
|
res = ReaderReceive(buf, par);
|
||||||
if (res == 4) {
|
if (res == 4) {
|
||||||
isGen = MAGIC_GEN_3;
|
isGen = MAGIC_GEN_4GDM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,16 +46,21 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
||||||
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype);
|
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype);
|
||||||
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype);
|
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype);
|
||||||
|
|
||||||
|
// MFC GEN1a /1b
|
||||||
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
|
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
|
||||||
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
|
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
|
||||||
void MifareCIdent(bool is_mfc); // is "magic chinese" card?
|
void MifareCIdent(bool is_mfc); // is "magic chinese" card?
|
||||||
void MifareHasStaticNonce(void); // Has the tag a static nonce?
|
void MifareHasStaticNonce(void); // Has the tag a static nonce?
|
||||||
|
|
||||||
|
// MFC GEN3
|
||||||
int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len);
|
int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len);
|
||||||
void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID without manufacturer block
|
void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID without manufacturer block
|
||||||
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block
|
||||||
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
|
||||||
|
void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain);
|
||||||
|
|
||||||
// MFC GEN4 GTU
|
// MFC GEN4 GTU
|
||||||
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags);
|
void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags);
|
||||||
void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t workFlags);
|
void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t workFlags);
|
||||||
|
|
|
@ -137,8 +137,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_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) {
|
||||||
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
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(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) {
|
||||||
|
return mifare_classic_authex_2(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL, false);
|
||||||
|
}
|
||||||
|
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 len;
|
int len;
|
||||||
uint32_t pos, nt, ntpp; // Supplied tag nonce
|
uint32_t pos, nt, ntpp; // Supplied tag nonce
|
||||||
uint8_t par[1] = {0x00};
|
uint8_t par[1] = {0x00};
|
||||||
|
@ -150,8 +152,9 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
||||||
// "random" reader nonce:
|
// "random" reader nonce:
|
||||||
num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
|
num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
|
||||||
|
|
||||||
// Transmit MIFARE_CLASSIC_AUTH
|
// Transmit MIFARE_CLASSIC_AUTH 0x60, 0x61 or GDM 0x80
|
||||||
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
|
uint8_t cmdbyte = (is_gdm) ? MIFARE_MAGIC_GDM_AUTH_KEYA : MIFARE_AUTH_KEYA + (keyType & 0x01);
|
||||||
|
len = mifare_sendcmd_short(pcs, isNested, cmdbyte, blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||||
if (len != 4) return 1;
|
if (len != 4) return 1;
|
||||||
|
|
||||||
// Save the tag nonce (nt)
|
// Save the tag nonce (nt)
|
||||||
|
@ -411,6 +414,10 @@ 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) {
|
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
|
// variables
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
uint32_t pos = 0;
|
uint32_t pos = 0;
|
||||||
|
@ -421,8 +428,12 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
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};
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
// command MIFARE_MAGIC_GDM_WRITEBLOCK
|
||||||
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
if (is_gdm) {
|
||||||
|
len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
} else {
|
||||||
|
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
|
@ -456,6 +467,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action) {
|
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action) {
|
||||||
// variables
|
// variables
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
|
|
|
@ -72,10 +72,12 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t
|
||||||
// mifare classic
|
// mifare classic
|
||||||
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_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(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(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||||
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);
|
||||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||||
|
int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm);
|
||||||
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action);
|
int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action);
|
||||||
|
|
||||||
// Ultralight/NTAG...
|
// Ultralight/NTAG...
|
||||||
|
|
|
@ -7560,6 +7560,88 @@ static int CmdHF14AGen4Save(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf mf gdmsetblk",
|
||||||
|
"Set block data on a magic gen4 GDM card",
|
||||||
|
"hf mf gdmsetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_int1(NULL, "blk", "<dec>", "block number"),
|
||||||
|
arg_lit0("a", NULL, "input key type is key A (def)"),
|
||||||
|
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_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
int b = arg_get_int_def(ctx, 1, 1);
|
||||||
|
|
||||||
|
uint8_t keytype = MF_KEY_A;
|
||||||
|
if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "Input key type must be A or B");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else if (arg_get_lit(ctx, 3)) {
|
||||||
|
keytype = MF_KEY_B;;
|
||||||
|
}
|
||||||
|
|
||||||
|
int keylen = 0;
|
||||||
|
uint8_t key[6] = {0};
|
||||||
|
CLIGetHexWithReturn(ctx, 4, key, &keylen);
|
||||||
|
|
||||||
|
uint8_t block[MFBLOCK_SIZE] = {0x00};
|
||||||
|
int blen = 0;
|
||||||
|
CLIGetHexWithReturn(ctx, 5, block, &blen);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (blen != MFBLOCK_SIZE) {
|
||||||
|
PrintAndLogEx(WARNING, "expected 16 HEX bytes. got %i", blen);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b < 0 || b >= MIFARE_4K_MAXBLOCK) {
|
||||||
|
PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
|
||||||
|
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)));
|
||||||
|
PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block)));
|
||||||
|
|
||||||
|
struct p {
|
||||||
|
uint8_t blockno;
|
||||||
|
uint8_t keytype;
|
||||||
|
uint8_t key[6];
|
||||||
|
uint8_t data[MFBLOCK_SIZE]; // data to be written
|
||||||
|
} PACKED payload;
|
||||||
|
|
||||||
|
payload.blockno = blockno;
|
||||||
|
payload.keytype = keytype;
|
||||||
|
memcpy(payload.key, key, sizeof(payload.key));
|
||||||
|
memcpy(payload.data, block, sizeof(payload.data));
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_MIFARE_G4_GDM_WRBL, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_GDM_WRBL, &resp, 1500) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "command execute timeout");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.status == PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
|
||||||
|
PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf rdbl") "` to verify");
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
|
||||||
|
PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype `" _YELLOW_("hf mf gdmsetblk -%c ...") "` instead", (keytype == MF_KEY_A) ? 'b' : 'a');
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHF14AMfValue(const char *Cmd) {
|
static int CmdHF14AMfValue(const char *Cmd) {
|
||||||
|
|
||||||
|
@ -7825,6 +7907,8 @@ static command_t CommandTable[] = {
|
||||||
{"gsave", CmdHF14AGen4Save, IfPm3Iso14443a, "Save dump from card into file or emulator"},
|
{"gsave", CmdHF14AGen4Save, IfPm3Iso14443a, "Save dump from card into file or emulator"},
|
||||||
{"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") " --------------------------"},
|
||||||
|
{"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"},
|
||||||
{"ndefformat", CmdHFMFNDEFFormat, IfPm3Iso14443a, "Format MIFARE Classic Tag as NFC Tag"},
|
{"ndefformat", CmdHFMFNDEFFormat, IfPm3Iso14443a, "Format MIFARE Classic Tag as NFC Tag"},
|
||||||
|
|
|
@ -1214,6 +1214,7 @@ int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
uint32_t cuid = 0; // uid part used for crypto1.
|
uint32_t cuid = 0; // uid part used for crypto1.
|
||||||
|
|
||||||
|
@ -1414,6 +1415,9 @@ int detect_mf_magic(bool is_mfc) {
|
||||||
case MAGIC_GEN_4GTU:
|
case MAGIC_GEN_4GTU:
|
||||||
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 4 GTU"));
|
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 4 GTU"));
|
||||||
break;
|
break;
|
||||||
|
case MAGIC_GEN_4GDM:
|
||||||
|
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 4 GDM"));
|
||||||
|
break;
|
||||||
case MAGIC_GEN_UNFUSED:
|
case MAGIC_GEN_UNFUSED:
|
||||||
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Write Once / FUID"));
|
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Write Once / FUID"));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -686,6 +686,10 @@ typedef struct {
|
||||||
#define CMD_HF_MIFARE_G4_RDBL 0x0860
|
#define CMD_HF_MIFARE_G4_RDBL 0x0860
|
||||||
#define CMD_HF_MIFARE_G4_WRBL 0x0861
|
#define CMD_HF_MIFARE_G4_WRBL 0x0861
|
||||||
|
|
||||||
|
// Gen 4 GDM magic cards
|
||||||
|
#define CMD_HF_MIFARE_G4_GDM_RDBL 0x0870
|
||||||
|
#define CMD_HF_MIFARE_G4_GDM_WRBL 0x0871
|
||||||
|
|
||||||
#define CMD_UNKNOWN 0xFFFF
|
#define CMD_UNKNOWN 0xFFFF
|
||||||
|
|
||||||
//Mifare simulation flags
|
//Mifare simulation flags
|
||||||
|
|
|
@ -192,6 +192,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||||
|
|
||||||
#define MIFARE_MAGIC_GDM_AUTH_KEYA 0x80
|
#define MIFARE_MAGIC_GDM_AUTH_KEYA 0x80
|
||||||
#define MIFARE_MAGIC_GDM_AUTH_KEYB 0x81
|
#define MIFARE_MAGIC_GDM_AUTH_KEYB 0x81
|
||||||
|
#define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8
|
||||||
|
|
||||||
#define MIFARE_EV1_PERSONAL_UID 0x40
|
#define MIFARE_EV1_PERSONAL_UID 0x40
|
||||||
#define MIFARE_EV1_SETMODE 0x43
|
#define MIFARE_EV1_SETMODE 0x43
|
||||||
|
@ -259,6 +260,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||||
#define MAGIC_NTAG21X 7
|
#define MAGIC_NTAG21X 7
|
||||||
#define MAGIC_GEN_3 8
|
#define MAGIC_GEN_3 8
|
||||||
#define MAGIC_GEN_4GTU 9
|
#define MAGIC_GEN_4GTU 9
|
||||||
|
#define MAGIC_GEN_4GDM 10
|
||||||
|
|
||||||
// Commands for configuration of Gen4 GTU cards.
|
// Commands for configuration of Gen4 GTU cards.
|
||||||
// see https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md
|
// see https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue