Merge pull request #1821 from DidierA/gen4_ident

Add Magic Gen4 GTU detection
This commit is contained in:
Iceman 2022-11-25 17:23:19 +01:00 committed by GitHub
commit f9aa183382
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 149 additions and 76 deletions

View file

@ -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... 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 detection of magic Gen4 GTU (@DidierA)
- Added luascript `hf_i2c_plus_2k_utils` - Script for dumping/modifying user memory of sectors 0 and 1 (@flamebarke) - Added luascript `hf_i2c_plus_2k_utils` - Script for dumping/modifying user memory of sectors 0 and 1 (@flamebarke)
- Added `hf mfu esave` - saves emulator memory to mfu dump file (@DidierA) - Added `hf mfu esave` - saves emulator memory to mfu dump file (@DidierA)
- Added luascript `hf_mfu_ntag` - Script for configuring NTAG216 configuration pages (@flamebarke) - Added luascript `hf_mfu_ntag` - Script for configuring NTAG216 configuration pages (@flamebarke)

View file

@ -2356,6 +2356,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 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);
uint8_t *uid = BigBuf_malloc(10); uint8_t *uid = BigBuf_malloc(10);
@ -2388,6 +2389,26 @@ void MifareCIdent(bool is_mfc) {
int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res == 2) { if (res == 2) {
// Check for Magic Gen4 GTU with default password :
// Get config should return 30 bytes.
AddCrc14A(gen4GetConf, sizeof(gen4GetConf) - 2);
ReaderTransmit(gen4GetConf, sizeof(gen4GetConf), NULL);
res = ReaderReceive(buf, par);
if (res == 32) {
isGen = MAGIC_GEN_4GTU;
goto OUT;
}
}
// reset card
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(40);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res == 2) {
if (cuid == 0xAA55C396) { if (cuid == 0xAA55C396) {
isGen = MAGIC_GEN_UNFUSED; isGen = MAGIC_GEN_UNFUSED;
goto OUT; goto OUT;
@ -2746,7 +2767,7 @@ void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags) {
iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout
} }
uint8_t cmd[] = { 0xCF, 0x00, 0x00, 0x00, 0x00, 0xCE, blockno, uint8_t cmd[] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_READ, blockno,
0x00, 0x00 0x00, 0x00
}; };
@ -2822,7 +2843,7 @@ void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t work
iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout
} }
uint8_t cmd[] = { 0xCF, 0x00, 0x00, 0x00, 0x00, 0xCD, blockno, uint8_t cmd[] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_WRITE, blockno,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 0x00, 0x00

View file

@ -228,7 +228,6 @@ local function read_config()
if ulmode == '03' then versionstr = 'Ultralight' if ulmode == '03' then versionstr = 'Ultralight'
elseif ulmode == '02' then versionstr = 'Ultralight-C' elseif ulmode == '02' then versionstr = 'Ultralight-C'
elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b' elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b'
elseif cversion == '0004030101000B03' then versionstr = 'UL EV1 48b'
elseif cversion == '0004030101000E03' then versionstr = 'UL EV1 128b' elseif cversion == '0004030101000E03' then versionstr = 'UL EV1 128b'
elseif cversion == '0004040101000B03' then versionstr = 'NTAG 210' elseif cversion == '0004040101000B03' then versionstr = 'NTAG 210'
elseif cversion == '0004040101000E03' then versionstr = 'NTAG 212' elseif cversion == '0004040101000E03' then versionstr = 'NTAG 212'
@ -845,86 +844,101 @@ local function set_type(tagtype)
end end
end end
--- ---
-- returns true if b is the index of a sector trailer
local function mfIsSectorTrailer(b)
n=b+1
if (n < 32*4 ) then
if (n % 4 == 0) then return true
else return false
end
end
if (n % 16 == 0) then return true
end
return false
end
---
-- wipe tag -- wipe tag
local function wipe(wtype) local function wipe(wtype)
local info = connect() local info = connect()
if not info then return false, "Can't select card" end if not info then return false, "Can't select card" end
if wtype == '0' then if wtype == '0' then
print('Starting Mifare Wipe') print('Starting Mifare Wipe')
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800") send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800")
send("CF".._key.."CD000102030404080400000000000000BEAF") send("CF".._key.."CD000102030404080400000000000000BEAF")
local err, msg, resp local err, msg, resp
local cmd_empty = 'CF'.._key..'CD%02X00000000000000000000000000000000' local cmd_empty = 'CF'.._key..'CD%02X00000000000000000000000000000000'
local cmd_cfg1 = 'CF'.._key..'CD%02XFFFFFFFFFFFFFF078069FFFFFFFFFFFF' local cmd_trail = 'CF'.._key..'CD%02XFFFFFFFFFFFFFF078069FFFFFFFFFFFF'
for b = 1, 0xFB do for b = 1, 0xFF do
if b == 0x03 or b == 0x07 or b == 0x0B or b == 0x0F or b == 0x13 or b == 0x17 or b == 0x1B or b == 0x1F or b == 0x23 or b == 0x27 or b == 0x2B or b == 0x2F or b == 0x33 or b == 0x37 or b == 0x3B or b == 0x3F then if mfIsSectorTrailer(b) then
local cmd = (cmd_cfg1):format(b) local cmd = (cmd_trail):format(b)
resp = send(cmd) resp = send(cmd)
else else
local cmd = (cmd_empty):format(b) local cmd = (cmd_empty):format(b)
resp = send(cmd) resp = send(cmd)
end end
if resp == nil then if resp == nil then
io.write('\nwrote block '..b, ' failed\n') io.write('\nwrote block '..b, ' failed\n')
err = true err = true
else else
io.write('.') io.write('.')
end end
io.flush() io.flush()
end end
print('\n') print('\n')
err, msg = set_type(3) err, msg = set_type(3)
if err == nil then return err, msg end if err == nil then return err, msg end
lib14a.disconnect() lib14a.disconnect()
return true, 'Ok' return true, 'Ok'
elseif wtype == '1' then elseif wtype == '1' then
print('Starting Ultralight Wipe') print('Starting Ultralight Wipe')
local err, msg, resp local err, msg, resp
local cmd_empty = 'A2%02X00000000' local cmd_empty = 'A2%02X00000000'
local cmd_cfg1 = 'A2%02X000000FF' local cmd_cfg1 = 'A2%02X000000FF'
local cmd_cfg2 = 'A2%02X00050000' local cmd_cfg2 = 'A2%02X00050000'
print('Wiping tag') print('Wiping tag')
local info = connect() local info = connect()
if not info then return false, "Can't select card" end if not info then return false, "Can't select card" end
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001") send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
for b = 3, 0xFB do for b = 3, 0xFB do
--configuration block 0 --configuration block 0
if b == 0x29 or b == 0x83 or b == 0xe3 then if b == 0x29 or b == 0x83 or b == 0xe3 then
local cmd = (cmd_cfg1):format(b) local cmd = (cmd_cfg1):format(b)
resp = send(cmd) resp = send(cmd)
--configuration block 1 --configuration block 1
elseif b == 0x2a or b == 0x84 or b == 0xe4 then elseif b == 0x2a or b == 0x84 or b == 0xe4 then
local cmd = (cmd_cfg2):format(b) local cmd = (cmd_cfg2):format(b)
resp = send(cmd) resp = send(cmd)
else else
resp = send(cmd_empty:format(b)) resp = send(cmd_empty:format(b))
end end
if resp == '04' or #resp == 0 then if resp == '04' or #resp == 0 then
io.write('\nwrote block '..b, ' failed\n') io.write('\nwrote block '..b, ' failed\n')
err = true err = true
else else
io.write('.') io.write('.')
end end
io.flush() io.flush()
end end
io.write('\r\n') io.write('\r\n')
lib14a.disconnect() lib14a.disconnect()
print('\n') print('\n')
if err then return nil, "Tag locked down, "..err_lock end if err then return nil, "Tag locked down, "..err_lock end
-- set NTAG213 default values -- set NTAG213 default values
err, msg = set_type(14) err, msg = set_type(14)
if err == nil then return err, msg end if err == nil then return err, msg end
--set UID --set UID
err, msg = write_uid('04112233445566') err, msg = write_uid('04112233445566')
if err == nil then return err, msg end if err == nil then return err, msg end
--set NTAG pwd --set NTAG pwd
err, msg = write_ntagpwd('FFFFFFFF') err, msg = write_ntagpwd('FFFFFFFF')
if err == nil then return err, msg end if err == nil then return err, msg end
--set pack --set pack
err, msg = write_pack('0000') err, msg = write_pack('0000')
if err == nil then return err, msg end if err == nil then return err, msg end
lib14a.disconnect() lib14a.disconnect()
return true, 'Ok' return true, 'Ok'
else oops('Use 0 for Mifare wipe or 1 for Ultralight wipe') else oops('Use 0 for Mifare wipe or 1 for Ultralight wipe')
end end
end end

View file

@ -1408,6 +1408,9 @@ int detect_mf_magic(bool is_mfc) {
case MAGIC_GEN_3: case MAGIC_GEN_3:
PrintAndLogEx(SUCCESS, "Magic capabilities : possibly " _GREEN_("Gen 3 / APDU")); PrintAndLogEx(SUCCESS, "Magic capabilities : possibly " _GREEN_("Gen 3 / APDU"));
break; break;
case MAGIC_GEN_4GTU:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 4 GTU"));
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;

View file

@ -998,9 +998,14 @@ Can emulate MIFARE Classic, Ultralight/NTAG families, 14b UID & App Data
### Identify ### Identify
^[Top](#top) ^^[Gen4](#g4top) ^[Top](#top) ^^[Gen4](#g4top)
👉 **TODO** Tag doesn't get identified correctly by latest Proxmark3 client (it might get mislabeled as MFC Gen2/CUID, Gen3/APDU or NTAG21x Modifiable, depending on configured UID/ATQA/SAK/ATS) 👉 **TODO** If the password is not default, Tag doesn't get identified correctly by latest Proxmark3 client (it might get mislabeled as MFC Gen2/CUID, Gen3/APDU or NTAG21x Modifiable, depending on configured UID/ATQA/SAK/ATS)
One can identify manually such card if the password is still the default one, with the command to get the current configuration: ```
hf 14a info
[+] Magic capabilities : Gen 4 GTU
```
The card will be identified only if the password is the default one. One can identify manually such card if the password is still the default one, with the command to get the current configuration:
``` ```
hf 14a raw -s -c -t 1000 CF00000000C6 hf 14a raw -s -c -t 1000 CF00000000C6
``` ```
@ -1108,6 +1113,14 @@ Default `<passwd>`: `00000000`
``` ```
# view contents of tag memory: # view contents of tag memory:
hf mf gview hf mf gview
# Read a specific block via backdoor command:
hf mf ggetblk
# Write a specific block via backdoor command:
hf mf gsetblk
# Load dump to tag:
hf mf gload
# Save dump from tag:
hf mf gsave
``` ```
👉 **TODO** `hf mf gview` is currently missing Ultralight memory maps 👉 **TODO** `hf mf gview` is currently missing Ultralight memory maps
@ -1120,6 +1133,8 @@ hf 14a raw -s -c -t 1000 CF00000000CE02
... ...
``` ```
👉 **TODO** In Mifare Ultralight / NTAG mode, the special writes (option -s, -e, -r) do not apply. Use `script run hf_mf_ultimatecard` for UID and signature, and `hf mfu wrbl` for PWD and PACK.
### Change ATQA / SAK ### Change ATQA / SAK
^[Top](#top) ^^[Gen4](#g4top) ^[Top](#top) ^^[Gen4](#g4top)

View file

@ -252,6 +252,25 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MAGIC_SUPER 6 #define MAGIC_SUPER 6
#define MAGIC_NTAG21X 7 #define MAGIC_NTAG21X 7
#define MAGIC_GEN_3 8 #define MAGIC_GEN_3 8
#define MAGIC_GEN_4GTU 9
// Commands for configuration of Gen4 GTU cards.
// see https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md
#define GEN_4GTU_CMD 0xCF // Prefix for all commands, followed by pasword (4b)
#define GEN_4GTU_SHADOW 0x32 // Configure GTU shadow mode
#define GEN_4GTU_ATS 0x34 // Configure ATS
#define GEN_4GTU_ATQA 0x35 // Configure ATQA/SAK (swap ATQA bytes)
#define GEN_4GTU_UIDLEN 0x68 // Configure UID length
#define GEN_4GTU_ULEN 0x69 // (De)Activate Ultralight mode
#define GEN_4GTU_ULMODE 0x6A // Select Ultralight mode
#define GEN_4GTU_GETCNF 0xC6 // Dump configuration
#define GEN_4GTU_TEST 0xCC // Factory test, returns 6666
#define GEN_4GTU_WRITE 0xCD // Backdoor write 16b block
#define GEN_4GTU_READ 0xCE // Backdoor read 16b block
#define GEN_4GTU_SETCNF 0xF0 // Configure all params in one cmd
#define GEN_4GTU_FUSCNF 0xF1 // Configure all params in one cmd and fuse the configuration permanently
#define GEN_4GTU_CHPWD 0xFE // change password
/** /**
06 00 = INITIATE 06 00 = INITIATE
0E xx = SELECT ID (xx = Chip-ID) 0E xx = SELECT ID (xx = Chip-ID)