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...
## [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 `hf mfu esave` - saves emulator memory to mfu dump file (@DidierA)
- 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 rdblf0[4] = { ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
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 *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE);
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);
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) {
isGen = MAGIC_GEN_UNFUSED;
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
}
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
};
@ -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
}
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

View file

@ -228,7 +228,6 @@ local function read_config()
if ulmode == '03' then versionstr = 'Ultralight'
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 == '0004030101000E03' then versionstr = 'UL EV1 128b'
elseif cversion == '0004040101000B03' then versionstr = 'NTAG 210'
elseif cversion == '0004040101000E03' then versionstr = 'NTAG 212'
@ -845,86 +844,101 @@ local function set_type(tagtype)
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
local function wipe(wtype)
local info = connect()
if not info then return false, "Can't select card" end
if wtype == '0' then
print('Starting Mifare Wipe')
print('Starting Mifare Wipe')
send("CF".._key.."F000000000000002000978009102DABC19101011121314151604000800")
send("CF".._key.."CD000102030404080400000000000000BEAF")
local err, msg, resp
local cmd_empty = 'CF'.._key..'CD%02X00000000000000000000000000000000'
local cmd_cfg1 = 'CF'.._key..'CD%02XFFFFFFFFFFFFFF078069FFFFFFFFFFFF'
for b = 1, 0xFB 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
local cmd = (cmd_cfg1):format(b)
resp = send(cmd)
else
local cmd = (cmd_empty):format(b)
resp = send(cmd)
end
if resp == nil then
io.write('\nwrote block '..b, ' failed\n')
err = true
else
io.write('.')
end
io.flush()
end
print('\n')
err, msg = set_type(3)
if err == nil then return err, msg end
lib14a.disconnect()
return true, 'Ok'
local err, msg, resp
local cmd_empty = 'CF'.._key..'CD%02X00000000000000000000000000000000'
local cmd_trail = 'CF'.._key..'CD%02XFFFFFFFFFFFFFF078069FFFFFFFFFFFF'
for b = 1, 0xFF do
if mfIsSectorTrailer(b) then
local cmd = (cmd_trail):format(b)
resp = send(cmd)
else
local cmd = (cmd_empty):format(b)
resp = send(cmd)
end
if resp == nil then
io.write('\nwrote block '..b, ' failed\n')
err = true
else
io.write('.')
end
io.flush()
end
print('\n')
err, msg = set_type(3)
if err == nil then return err, msg end
lib14a.disconnect()
return true, 'Ok'
elseif wtype == '1' then
print('Starting Ultralight Wipe')
local err, msg, resp
local cmd_empty = 'A2%02X00000000'
local cmd_cfg1 = 'A2%02X000000FF'
local cmd_cfg2 = 'A2%02X00050000'
print('Wiping tag')
local info = connect()
if not info then return false, "Can't select card" end
print('Starting Ultralight Wipe')
local err, msg, resp
local cmd_empty = 'A2%02X00000000'
local cmd_cfg1 = 'A2%02X000000FF'
local cmd_cfg2 = 'A2%02X00050000'
print('Wiping tag')
local info = connect()
if not info then return false, "Can't select card" end
send("CF".._key.."F001010000000003000978009102DABC19101011121314151644000001")
for b = 3, 0xFB do
--configuration block 0
if b == 0x29 or b == 0x83 or b == 0xe3 then
local cmd = (cmd_cfg1):format(b)
resp = send(cmd)
--configuration block 1
elseif b == 0x2a or b == 0x84 or b == 0xe4 then
local cmd = (cmd_cfg2):format(b)
resp = send(cmd)
else
resp = send(cmd_empty:format(b))
end
if resp == '04' or #resp == 0 then
io.write('\nwrote block '..b, ' failed\n')
err = true
else
io.write('.')
end
io.flush()
end
io.write('\r\n')
lib14a.disconnect()
print('\n')
if err then return nil, "Tag locked down, "..err_lock end
-- set NTAG213 default values
err, msg = set_type(14)
if err == nil then return err, msg end
--set UID
err, msg = write_uid('04112233445566')
if err == nil then return err, msg end
--set NTAG pwd
err, msg = write_ntagpwd('FFFFFFFF')
if err == nil then return err, msg end
--set pack
err, msg = write_pack('0000')
if err == nil then return err, msg end
lib14a.disconnect()
return true, 'Ok'
for b = 3, 0xFB do
--configuration block 0
if b == 0x29 or b == 0x83 or b == 0xe3 then
local cmd = (cmd_cfg1):format(b)
resp = send(cmd)
--configuration block 1
elseif b == 0x2a or b == 0x84 or b == 0xe4 then
local cmd = (cmd_cfg2):format(b)
resp = send(cmd)
else
resp = send(cmd_empty:format(b))
end
if resp == '04' or #resp == 0 then
io.write('\nwrote block '..b, ' failed\n')
err = true
else
io.write('.')
end
io.flush()
end
io.write('\r\n')
lib14a.disconnect()
print('\n')
if err then return nil, "Tag locked down, "..err_lock end
-- set NTAG213 default values
err, msg = set_type(14)
if err == nil then return err, msg end
--set UID
err, msg = write_uid('04112233445566')
if err == nil then return err, msg end
--set NTAG pwd
err, msg = write_ntagpwd('FFFFFFFF')
if err == nil then return err, msg end
--set pack
err, msg = write_pack('0000')
if err == nil then return err, msg end
lib14a.disconnect()
return true, 'Ok'
else oops('Use 0 for Mifare wipe or 1 for Ultralight wipe')
end
end

View file

@ -1408,6 +1408,9 @@ int detect_mf_magic(bool is_mfc) {
case MAGIC_GEN_3:
PrintAndLogEx(SUCCESS, "Magic capabilities : possibly " _GREEN_("Gen 3 / APDU"));
break;
case MAGIC_GEN_4GTU:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 4 GTU"));
break;
case MAGIC_GEN_UNFUSED:
PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Write Once / FUID"));
break;

View file

@ -998,9 +998,14 @@ Can emulate MIFARE Classic, Ultralight/NTAG families, 14b UID & App Data
### Identify
^[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
```
@ -1108,6 +1113,14 @@ Default `<passwd>`: `00000000`
```
# view contents of tag memory:
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
@ -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
^[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_NTAG21X 7
#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
0E xx = SELECT ID (xx = Chip-ID)