Merge pull request #2327 from henrygab/autorecover

lf em 4x70 autorecover
This commit is contained in:
Iceman 2024-03-12 08:44:36 +01:00 committed by GitHub
commit 2cac75d8bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 1027 additions and 402 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 `lf em 4x70 autorecover` - writable ID48 tags now have automatic key recovery (@henrygab)
- Set max write blocks to 251 in hf_mf_ultimatecard before writing version/signature in NTAG 21X (@antgamdia)
- Changed HF_UNISNIFF standalone mode, output and also sniffs iclass too (@iceman1001)
- Changed `hw standalone` - added `-b` param to control HF_UNISNIFF from client (@iceman1001)

View file

@ -581,6 +581,11 @@ static bool send_command_and_read(uint8_t command, uint8_t *bytes, size_t length
Dbprintf("Invalid data received length: %d, expected %d", len, out_length_bits);
return false;
}
// TODO: Figure out why getting an extra bit (quite often) here
// e.g., write block and info commands both reach here and output:
// [#] Should have a multiple of 8 bits, was sent 33
// [#] Should have a multiple of 8 bits, was sent 65
// Extra bits are currently just dropped, with no ill effect noticed.
bits2bytes(bits, len, bytes);
return true;
}
@ -903,10 +908,12 @@ void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol) {
break;
}
}
// TODO: Ideally here we would perform a test authentication
// to ensure the new key was written correctly. This is
// what the datasheet suggests. We can't do that until
// we have the crypto algorithm implemented.
// The client now has support for test authentication after
// writing a new key, thus allowing to verify that the new
// key was written correctly. This is what the datasheet
// suggests. Not currently implemented in the firmware,
// although ID48LIB has no dependencies that would prevent
// use within the firmware layer.
}
}

File diff suppressed because it is too large Load diff

View file

@ -415,19 +415,19 @@ const static vocabulary_t vocabulary[] = {
{ 1, "hf mfu pwdgen" },
{ 0, "hf mfu otptear" },
{ 0, "hf mfu cauth" },
{ 0, "hf mfu setpwd" },
{ 0, "hf mfu dump" },
{ 0, "hf mfu info" },
{ 0, "hf mfu ndefread" },
{ 0, "hf mfu rdbl" },
{ 0, "hf mfu restore" },
{ 0, "hf mfu tamper" },
{ 1, "hf mfu view" },
{ 0, "hf mfu wrbl" },
{ 0, "hf mfu tamper" },
{ 0, "hf mfu eload" },
{ 0, "hf mfu esave" },
{ 0, "hf mfu eview" },
{ 0, "hf mfu sim" },
{ 0, "hf mfu setpwd" },
{ 0, "hf mfu setuid" },
{ 0, "hf mfu amiibo" },
{ 1, "hf mfdes help" },
@ -512,8 +512,6 @@ const static vocabulary_t vocabulary[] = {
{ 1, "hf vas help" },
{ 0, "hf vas reader" },
{ 1, "hf vas decrypt" },
{ 1, "hf waveshare help" },
{ 1, "hf waveshare load" },
{ 1, "hf xerox help" },
{ 1, "hf xerox list" },
{ 0, "hf xerox info" },
@ -617,6 +615,8 @@ const static vocabulary_t vocabulary[] = {
{ 0, "lf em 4x70 auth" },
{ 0, "lf em 4x70 writepin" },
{ 0, "lf em 4x70 writekey" },
{ 0, "lf em 4x70 recover" },
{ 0, "lf em 4x70 autorecover" },
{ 1, "lf fdxb help" },
{ 1, "lf fdxb demod" },
{ 0, "lf fdxb reader" },

View file

@ -3061,7 +3061,7 @@
},
"hf help": {
"command": "hf help",
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service } waveshare { Waveshare NFC ePaper... } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
"notes": [
"hf list --frame -> show frame delay times",
"hf list -1 -> use trace buffer"
@ -4411,9 +4411,10 @@
"--1k MIFARE Classic 1k / S50 (def)",
"--2k MIFARE Classic/Plus 2k",
"--4k MIFARE Classic 4k / S70",
"--ns no save to file"
"--ns no save to file",
"-v, --verbose verbose output"
],
"usage": "hf mf dump [-h] [-f <fn>] [-k <fn>] [--mini] [--1k] [--2k] [--4k] [--ns]"
"usage": "hf mf dump [-hv] [-f <fn>] [-k <fn>] [--mini] [--1k] [--2k] [--4k] [--ns]"
},
"hf mf ecfill": {
"command": "hf mf ecfill",
@ -7721,28 +7722,6 @@
],
"usage": "hf vas reader [-h@v] [--pid <str>] [-f <fn>] [--url <str>]"
},
"hf waveshare help": {
"command": "hf waveshare help",
"description": "help This help load Load image file to Waveshare NFC ePaper --------------------------------------------------------------------------------------- hf waveshare load available offline: yes Load image file to Waveshare NFC ePaper",
"notes": [
"hf waveshare load -f myfile -m 0 -> 2.13 inch e-paper ( 122, 250 )",
"hf waveshare load -f myfile -m 1 -> 2.9 inch e-paper ( 296, 128 )",
"hf waveshare load -f myfile -m 2 -> 4.2 inch e-paper ( 400, 300 )",
"hf waveshare load -f myfile -m 3 -> 7.5 inch e-paper ( 800, 480 )",
"hf waveshare load -f myfile -m 4 -> 2.7 inch e-paper ( 176, 276 )",
"hf waveshare load -f myfile -m 5 -> 2.13 inch e-paper B (with red) ( 104, 212 )",
"hf waveshare load -f myfile -m 6 -> 1.54 inch e-paper B (with red) ( 200, 200 )",
"hf waveshare load -f myfile -m 7 -> 7.5 inch e-paper HD ( 880, 528 )"
],
"offline": true,
"options": [
"-h, --help This help",
"-m <nr> model number [0 - 7] of your tag",
"-f, --file <fn> specify image to upload to tag",
"-s, --save <fn> save paletized version in file"
],
"usage": "hf waveshare load [-h] -m <nr> -f <fn> [-s <fn>]"
},
"hf xerox dump": {
"command": "hf xerox dump",
"description": "Dump all memory from a Fuji/Xerox tag ISO/IEC 14443 type B based communications",
@ -8877,9 +8856,10 @@
},
"lf em 4x70 auth": {
"command": "lf em 4x70 auth",
"description": "Authenticate against an EM4x70 by sending random number (RN) and F(RN) If F(RN) is incorrect based on the tag crypt key, the tag will not respond",
"description": "Authenticate against an EM4x70 by sending random number (RN) and F(RN) If F(RN) is incorrect based on the tag key, the tag will not respond If F(RN) is correct based on the tag key, the tag will give a 20-bit response",
"notes": [
"lf em 4x70 auth --rnd 45F54ADA252AAC --frn 4866BB70 -> Test authentication, tag will respond if successful"
"lf em 4x70 auth --rnd 45F54ADA252AAC --frn 4866BB70 -> (using pm3 test key)",
"lf em 4x70 auth --rnd 3FFE1FB6CC513F --frn F355F1A0 -> (using research paper key)"
],
"offline": false,
"options": [
@ -8890,6 +8870,23 @@
],
"usage": "lf em 4x70 auth [-h] [--par] --rnd <hex> --frn <hex>"
},
"lf em 4x70 autorecover": {
"command": "lf em 4x70 autorecover",
"description": "This command will perform automatic recovery of the key from a writable tag. All steps are possible to do manually. The corresponding sequence, if done manually, is as follows: 1. Verify passed parameters authenticate with the tag (safety check) lf em 4x70 auth --rnd <rnd_1> --frn <frn_1> 2. Brute force the key bits in block 9 lf em 4x70 write -b 9 -d 0000 lf em 4x70 recover -b 9 --rnd <rnd_1> --frn <frn_1> lf em 4x70 write -b 9 -d <key_block_9> 3. Brute force the key bits in block 8 lf em 4x70 write -b 8 -d 0000 lf em 4x70 recover -b 8 --rnd <rnd_1> --frn <frn_1> lf em 4x70 write -b 8 -d <key_block_8> 4. Brute force the key bits in block 7 lf em 4x70 write -b 7 -d 0000) lf em 4x70 recover -b 7 --rnd <rnd_1> --frn <frn_1> lf em 4x70 write -b 7 -d <key_block_7> 5. Recover potential values of the lower 48 bits of the key lf em 4x70 recover --key <key_block_9><key_block_8><key_block_7> --rnd <rnd_1> --frn <frn_1> 6. Verify which potential key is actually on the tag (using a different rnd/frn combination) lf em 4x70 auth --rnd <rnd_2> --frn <frn_N> 7. Print the validated key This command simply requires the rnd/frn/grn from a single known-good authentication.",
"notes": [
"lf em 4x70 autorecover --rnd 45F54ADA252AAC --frn 4866BB70 --grn 9BD180 (pm3 test key)",
"lf em 4x70 autorecover --rnd 3FFE1FB6CC513F --frn F355F1A0 --grn 609D60 (research paper key)"
],
"offline": false,
"options": [
"-h, --help This help",
"--par Add parity bit when sending commands",
"--rnd <hex> Random 56-bit from known-good authentication",
"--frn <hex> F(RN) 28-bit as 4 hex bytes from known-good authentication",
"--grn <hex> G(RN) 20-bit as 3 hex bytes from known-good authentication"
],
"usage": "lf em 4x70 autorecover [-h] [--par] --rnd <hex> --frn <hex> --grn <hex>"
},
"lf em 4x70 help": {
"command": "lf em 4x70 help",
"description": "help This help --------------------------------------------------------------------------------------- lf em 4x70 brute available offline: no Optimized partial key-update attack of 16-bit key block 7, 8 or 9 of an EM4x70 This attack does NOT write anything to the tag. Before starting this attack, 0000 must be written to the 16-bit key block: 'lf em 4x70 write -b 9 -d 0000'. After success, the 16-bit key block have to be restored with the key found: 'lf em 4x70 write -b 9 -d c0de'",
@ -8921,6 +8918,24 @@
],
"usage": "lf em 4x70 info [-h] [--par]"
},
"lf em 4x70 recover": {
"command": "lf em 4x70 recover",
"description": "After obtaining key bits 95..48 (such as via 'lf em 4x70 brute'), this command will recover key bits 47..00. By default, this process does NOT require a tag to be present. By default, the potential keys are shown (typically 1-6) along with a corresponding 'lf em 4x70 auth' command that will authenticate, if that potential key is correct. The user can copy/paste these commands when the tag is present to manually check which of the potential keys is correct.",
"notes": [
"lf em 4x70 recover --key F32AA98CF5BE --rnd 45F54ADA252AAC --frn 4866BB70 --grn 9BD180 (pm3 test key)",
"lf em 4x70 recover --key A090A0A02080 --rnd 3FFE1FB6CC513F --frn F355F1A0 --grn 609D60 (research paper key)"
],
"offline": false,
"options": [
"-h, --help This help",
"--par Add parity bit when sending commands",
"-k, --key <hex> Key as 6 hex bytes",
"--rnd <hex> Random 56-bit",
"--frn <hex> F(RN) 28-bit as 4 hex bytes",
"--grn <hex> G(RN) 20-bit as 3 hex bytes"
],
"usage": "lf em 4x70 recover [-h] [--par] -k <hex> --rnd <hex> --frn <hex> --grn <hex>"
},
"lf em 4x70 unlock": {
"command": "lf em 4x70 unlock",
"description": "Unlock EM4x70 by sending PIN Default pin may be: AAAAAAAA 00000000",
@ -8956,13 +8971,14 @@
"command": "lf em 4x70 writekey",
"description": "Write new 96-bit key to tag",
"notes": [
"lf em 4x70 writekey -k F32AA98CF5BE4ADFA6D3480B"
"lf em 4x70 writekey -k F32AA98CF5BE4ADFA6D3480B (pm3 test key)",
"lf em 4x70 writekey -k A090A0A02080000000000000 (research paper key)"
],
"offline": false,
"options": [
"-h, --help This help",
"--par Add parity bit when sending commands",
"-k, --key <hex> Crypt Key as 12 hex bytes"
"-k, --key <hex> Key as 12 hex bytes"
],
"usage": "lf em 4x70 writekey [-h] [--par] -k <hex>"
},
@ -12513,8 +12529,8 @@
}
},
"metadata": {
"commands_extracted": 722,
"commands_extracted": 723,
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2024-02-21T21:49:16"
"extracted_on": "2024-03-12T00:21:47"
}
}

View file

@ -601,20 +601,20 @@ Check column "offline" for their availability.
|`hf mfu keygen `|Y |`Generate DES/3DES/AES MIFARE diversified keys`
|`hf mfu pwdgen `|Y |`Generate pwd from known algos`
|`hf mfu otptear `|N |`Tear-off test on OTP bits`
|`hf mfu cauth `|N |`Authentication - Ultralight-C`
|`hf mfu cauth `|N |`Ultralight-C - Authentication`
|`hf mfu setpwd `|N |`Ultralight-C - Set 3DES key`
|`hf mfu dump `|N |`Dump MIFARE Ultralight family tag to binary file`
|`hf mfu info `|N |`Tag information`
|`hf mfu ndefread `|N |`Prints NDEF records from card`
|`hf mfu rdbl `|N |`Read block`
|`hf mfu restore `|N |`Restore a dump onto a MFU MAGIC tag`
|`hf mfu restore `|N |`Restore a dump file onto a tag`
|`hf mfu tamper `|N |`NTAG 213TT - Configure the tamper feature`
|`hf mfu view `|Y |`Display content from tag dump file`
|`hf mfu wrbl `|N |`Write block`
|`hf mfu tamper `|N |`Configure the tamper feature on an NTAG 213TT`
|`hf mfu eload `|N |`Upload file into emulator memory`
|`hf mfu esave `|N |`Save emulator memory to file`
|`hf mfu eview `|N |`View emulator memory`
|`hf mfu sim `|N |`Simulate MIFARE Ultralight from emulator memory`
|`hf mfu setpwd `|N |`Set 3DES key - Ultralight-C`
|`hf mfu setuid `|N |`Set UID - MAGIC tags only`
|`hf mfu amiibo `|N |`Amiibo tag operations`
@ -773,16 +773,6 @@ Check column "offline" for their availability.
|`hf vas decrypt `|Y |`Decrypt a previously captured VAS cryptogram`
### hf waveshare
{ Waveshare NFC ePaper... }
|command |offline |description
|------- |------- |-----------
|`hf waveshare help `|Y |`This help`
|`hf waveshare load `|Y |`Load image file to Waveshare NFC ePaper`
### hf xerox
{ Fuji/Xerox cartridge RFIDs... }
@ -965,13 +955,15 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`lf em 4x70 help `|Y |`This help`
|`lf em 4x70 brute `|N |`Bruteforce EM4X70 to find partial Crypt Key`
|`lf em 4x70 brute `|N |`Bruteforce EM4X70 to find partial key`
|`lf em 4x70 info `|N |`Tag information EM4x70`
|`lf em 4x70 write `|N |`Write EM4x70`
|`lf em 4x70 unlock `|N |`Unlock EM4x70 for writing`
|`lf em 4x70 auth `|N |`Authenticate EM4x70`
|`lf em 4x70 writepin `|N |`Write PIN`
|`lf em 4x70 writekey `|N |`Write Crypt Key`
|`lf em 4x70 writekey `|N |`Write key`
|`lf em 4x70 recover `|N |`Recover remaining key from partial key`
|`lf em 4x70 autorecover `|N |`Recover entire key from writable tag`
### lf fdxb

View file

@ -148,16 +148,16 @@ extern bool g_tearoff_enabled;
// convert 2 bytes to U16 in little endian
#ifndef BYTES2UINT16
# define BYTES2UINT16(x) ((x[1] << 8) | (x[0]))
# define BYTES2UINT16(x) (((x)[1] << 8) | ((x)[0]))
#endif
// convert 4 bytes to U32 in little endian
#ifndef BYTES2UINT32
# define BYTES2UINT32(x) ((x[3] << 24) | (x[2] << 16) | (x[1] << 8) | (x[0]))
# define BYTES2UINT32(x) (((x)[3] << 24) | ((x)[2] << 16) | ((x)[1] << 8) | ((x)[0]))
#endif
// convert 4 bytes to U32 in big endian
#ifndef BYTES2UINT32_BE
# define BYTES2UINT32_BE(x) ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | (x[3]))
# define BYTES2UINT32_BE(x) (((x)[0] << 24) | ((x)[1] << 16) | ((x)[2] << 8) | ((x)[3]))
#endif
@ -174,7 +174,7 @@ extern bool g_tearoff_enabled;
#endif
#ifndef CRUMB
# define CRUMB(b,p) (((b & (0x3 << p) ) >> p ) & 0xF)
# define CRUMB(b,p) ((((b) & (0x3 << (p)) ) >> (p) ) & 0xF)
#endif
#ifndef SWAP_NIBBLE
@ -183,18 +183,18 @@ extern bool g_tearoff_enabled;
// Binary Encoded Digit
#ifndef BCD2DEC
# define BCD2DEC(bcd) HornerScheme(bcd, 0x10, 10)
# define BCD2DEC(bcd) HornerScheme((bcd), 0x10, 10)
#endif
#ifndef DEC2BCD
# define DEC2BCD(dec) HornerScheme(dec, 10, 0x10)
# define DEC2BCD(dec) HornerScheme((dec), 10, 0x10)
#endif
// bit stream operations
#define TEST_BIT(data, i) (*(data + (i / 8)) >> (7 - (i % 8))) & 1
#define SET_BIT(data, i) *(data + (i / 8)) |= (1 << (7 - (i % 8)))
#define CLEAR_BIT(data, i) *(data + (i / 8)) &= ~(1 << (7 - (i % 8)))
#define FLIP_BIT(data, i) *(data + (i / 8)) ^= (1 << (7 - (i % 8)))
#define TEST_BIT(data, i) (*((data) + ((i) / 8)) >> (7 - ((i) % 8))) & 1
#define SET_BIT(data, i) *((data) + ((i) / 8)) |= (1 << (7 - ((i) % 8)))
#define CLEAR_BIT(data, i) *((data) + ((i) / 8)) &= ~(1 << (7 - ((i) % 8)))
#define FLIP_BIT(data, i) *((data) + ((i) / 8)) ^= (1 << (7 - ((i) % 8)))
// time for decompressing and loading the image to the FPGA
#define FPGA_LOAD_WAIT_TIME (1500)

View file

@ -30,7 +30,7 @@
typedef struct {
// ISSUE: `bool` type does not have a standard-defined size.
// therefore, compatibility between architectures /
// therefore, compatibility between architectures /
// compilers is not guaranteed.
// ISSUE: C99 has no _Static_assert() ... was added in C11
// TODO: add _Static_assert(sizeof(bool)==1);
@ -39,6 +39,7 @@ typedef struct {
// Used for writing address
uint8_t address;
// ISSUE: Presumes target is little-endian
uint16_t word;
// PIN to unlock
@ -53,6 +54,7 @@ typedef struct {
uint8_t crypt_key[12];
// used for bruteforce the partial key
// ISSUE: Presumes target is little-endian
uint16_t start_key;
} em4x70_data_t;