Merge branch 'RfidResearchGroup:master' into master

This commit is contained in:
Davi Mikael 2023-05-05 16:22:31 -03:00 committed by GitHub
commit 2d72bbd751
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 432 additions and 115 deletions

View file

@ -3,6 +3,12 @@ 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]
- Changed `nfc decode -f` - now can detect and convert MFC dumpfiles to NDEF byte arrays (@iceman1001)
- Changed `nfc decode` - now handles EXTERNAL RECORDS better (@iceman1001)
- Fixed `nfc decode` - now handles NDEF Signature version1 records better (@iceman1001)
- Added new standalone mode `LF_MULTIHID` - HID26 (H1031) multi simulator (@flamebarke)
- Changed `hf 14b dump --ns` - now supports `no save` of card memory (@iceman1001)
- Changed `hf mfu dump --ns` - now supports `no save` of card memory (@iceman1001)
- Changed the PM3 client to honor the preferences dump/trace paths. experimental support (@iceman1001)
- Added the possibility to load `.MCT` dump files (@iceman1001)
- Changed `lf t55xx dump --ns` - now supports `no save` of memory (@iceman1001)
@ -53,6 +59,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Changed `hf legic view` - now also print the decoded info of the dump file (@0xdeb)
- Now `script run hf_mf_ultimatecard.lua -u` supports 10bytes UID (@alejandro12120)
- Update documentation for installation on macOS with MacPorts (@linuxgemini)
- Added possible Paxton id to hitag2 tag info output
- Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147)
## [Nitride.4.16191][2023-01-29]
- Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox)

View file

@ -50,6 +50,9 @@ define KNOWN_STANDALONE_DEFINITIONS
| LF_ICEHID | LF HID collector to flashmem |
| (RDV4 only) | |
+----------------------------------------------------------+
| LF_MULTIHID | LF HID 26 Bit (H1031) multi simulator |
| | - Shain Lakin |
+----------------------------------------------------------+
| LF_NEDAP_SIM | LF Nedap ID simple simulator |
| | |
+----------------------------------------------------------+
@ -126,7 +129,7 @@ endef
STANDALONE_MODES := LF_SKELETON
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
STANDALONE_MODES += LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE
STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_YOUNG
STANDALONE_MODES += DANKARMULTI
STANDALONE_MODES_REQ_BT := HF_REBLAY

View file

@ -49,6 +49,10 @@ endif
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icehid.c
endif
# WITH_STANDALONE_LF_MULTIHID
ifneq (,$(findstring WITH_STANDALONE_LF_MULTIHID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_multihid.c
endif
# WITH_STANDALONE_LF_NEDAP_SIM
ifneq (,$(findstring WITH_STANDALONE_LF_NEDAP_SIM,$(APP_CFLAGS)))
SRC_STANDALONE = lf_nedap_sim.c

View file

@ -0,0 +1,76 @@
//-----------------------------------------------------------------------------
// Copyright (C) Shain Lakin, 2023
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// LF HID 26 Bit (H10301) multi simulator:
// Simple LF HID26 (H10301) tag simulator
// Short click - select next slot and start simulation
// LEDS = LED ON for selected slot
// Add tags (raw) to the hid26_predefined_raw array
//-----------------------------------------------------------------------------
#include "standalone.h"
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "util.h"
#include "dbprint.h"
#include "ticks.h"
#include "lfops.h"
#define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
#define MAX_IND 4
void LED_Slot(int i);
static uint64_t hid26_predefined_raw[] = {0x2004ec2e87, 0x2004421807, 0x20064312d6, 0x2006ec0c86};
static uint8_t hid26_slots_count;
void ModInfo(void) {
DbpString("LF HID 26 Bit (H10301) multi simulator - aka MultiHID (Shain Lakin)");
}
void LED_Slot(int i) {
LEDsoff();
if (hid26_slots_count > 4) {
LED(i % MAX_IND, 0);
} else {
LED(1 << i, 0);
}
}
void RunMod(void) {
StandAloneMode();
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
Dbprintf(">> LF HID26 multi simulator started - aka MultiHID (Shain Lakin) <<");
int selected = 0; //selected slot after start
hid26_slots_count = ARRAYLEN(hid26_predefined_raw);
for (;;) {
WDT_HIT();
if (data_available()) {
LEDsoff();
break;
}
SpinDelay(100);
SpinUp(100);
LED_Slot(selected);
uint64_t raw_data = hid26_predefined_raw[selected];
CmdHIDsimTAG(0, raw_data >> 32, raw_data & 0xFFFFFFFF, 0, false);
selected = (selected + 1) % hid26_slots_count;
}
}

View file

@ -2097,8 +2097,8 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
if (timer == 0) {
timer = GetTickCount();
} else {
// 50ms no field --> card to idle state
if (GetTickCountDelta(timer) > 50) {
// 6ms no field --> card to idle state
if (GetTickCountDelta(timer) > 6) {
return 2;
}
}

View file

@ -2029,9 +2029,8 @@ D144BD193063
8627C10A7014
453857395635
#
# Data from "the more, the marriott" mifare project (colonel borkmundus)
#
# Isn't theirs Saflok ?
# Data from "the more the marriott" mifare project (colonelborkmundus)
# aka The Horde
#
# 20230125-01, Elite Member Marriott Rewards
43012BD9EB87
@ -2098,6 +2097,52 @@ C49DAE1C6049
6E029927600D
3E173F64C01C
C670A9AD6066
# 20230413-69, Westin
487339FA02E0
# 20230413-70, Marriott Bonvoy
DBD5CA4EE467
A0B1F234006C
180DE12B700E
# 20230413-71, Westin
1352C68F7A56
# 20230413-76, Ritz Carlton
318BD98C1CEF
# 20230413-77, Marriott
D23C1CB1216E
# 20230413-78, Caesars
A1D92F808CAF
# 20230413-79, The Cosmopolitan, Vegas
# 96A301BCE267
# 20230413-80, Aria
1153C319B4F8
# 20230413-81, Aria
110C819BBEF8
# 20230413-82, Aria
1332117E8756
# 20230413-83, Kimpton
500AE915F50A
5032E362B484
8B63AB712753
# 20230413-85, Kimpton
06106E187106
2E45C23DC541
D9FF8BEE7550
# 20230413-87, Marriott
42F7A186BF87
# 20230413-88, Meritage Resort
D213B093B79A
# 20230413-89, Meritage Resort
216024C49EDF
# 20230413-90, Gaylord Palms
D201DBB6AB6E
# 20230413-91, Residence Inn
9F4AD875BB30
# 20230413-92, Marriott
3352DB1E8777
# 20230413-94, Marriott
09074A146605
151F3E85EC46
#
#
# Food GEM
6686FADE5566

View file

@ -2243,8 +2243,8 @@
"AID": "A0000002480400",
"Vendor": "ISO/IEC JTC1/SC17",
"Country": "",
"Name": "Personal identification (mDL)",
"Description": "ISO/IEC 18013-5:2021 compliant Mobile driving licence (mDL) application.",
"Name": "Personal identification (mDL) data transfer",
"Description": "ISO/IEC 18013-5:2021 compliant Mobile driving licence (mDL) application data transfer.",
"Type": "identity"
},
{
@ -2259,10 +2259,26 @@
"AID": "A000000809434343444B467631",
"Vendor": "Car Connectivity Consortium (CCC)",
"Country": "",
"Name": "Digital Car Key Framework",
"Description": "Used during key provisioning and configuration",
"Type": "access"
},
{
"AID": "A000000809434343444B417631",
"Vendor": "Car Connectivity Consortium (CCC)",
"Country": "",
"Name": "Digital Car Key",
"Description": "",
"Type": "access"
},
{
"AID": "A0000008580102",
"Vendor": "Apple",
"Country": "",
"Name": "Apple Home Key Framework",
"Description": "Home Key configuration applet. Selected after a first transaction on a newely-invited device (allegedly for mailbox sync/attestation exchange)",
"Type": ""
},
{
"AID": "A0000008580101",
"Vendor": "Apple",
@ -2270,5 +2286,45 @@
"Name": "Apple Home Key",
"Description": "NFC Home Key for select HomeKit-compatible locks",
"Type": "access"
},
{
"AID": "A000000396564341",
"Vendor": "NXP",
"Country": "",
"Name": "MIFARE 2GO",
"Description": "AID prefix used by MIFARE 2GO-based cards",
"Type": ""
},
{
"AID": "A0000002164954534F2D31",
"Vendor": "ITSO",
"Country": "United Kingdom",
"Name": "ITSO CMD2",
"Description": "AID used by ITSO for smartcard/phone-based transit cards",
"Type": "transit"
},
{
"AID": "A000000632010105",
"Vendor": "CTTIC",
"Country": "China",
"Name": "China T-Union",
"Description": "Universal transit card used by many big public transit operators",
"Type": "transit"
},
{
"AID": "D2760000254D010200",
"Vendor": "Zentraler Kreditausschuss (ZKA)",
"Country": "Germany",
"Name": "Girocard Jugendschutz",
"Description": "Age verification",
"Type": ""
},
{
"AID": "A00000000491",
"Vendor": "MasterCard International",
"Country": "",
"Name": "Mastercard Private Label Transit",
"Description": "AID prefix used by transit cards that use private label mastercards (E.g. Ventra and HOP)",
"Type": "transit"
}
]

View file

@ -1359,6 +1359,7 @@ static int CmdHF14BDump(const char *Cmd) {
void *argtable[] = {
arg_param_begin,
arg_str0("f", "file", "<fn>", "(optional) filename, if no <name> UID will be used as filename"),
arg_lit0(NULL, "ns", "no save to file"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1366,6 +1367,7 @@ static int CmdHF14BDump(const char *Cmd) {
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
bool nosave = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
@ -1514,15 +1516,17 @@ static int CmdHF14BDump(const char *Cmd) {
print_sr_blocks(data, cardsize, card.uid);
// save to file
if (fnlen < 1) {
PrintAndLogEx(INFO, "using UID as filename");
char *fptr = filename + snprintf(filename, sizeof(filename), "hf-14b-");
FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen);
}
if (nosave == false) {
// save to file
if (fnlen < 1) {
PrintAndLogEx(INFO, "using UID as filename");
char *fptr = filename + snprintf(filename, sizeof(filename), "hf-14b-");
FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen);
}
size_t datalen = (lastblock + 2) * ST25TB_SR_BLOCK_SIZE;
pm3_save_dump(filename, data, datalen, jsf14b, ST25TB_SR_BLOCK_SIZE);
size_t datalen = (lastblock + 2) * ST25TB_SR_BLOCK_SIZE;
pm3_save_dump(filename, data, datalen, jsf14b, ST25TB_SR_BLOCK_SIZE);
}
}
return switch_off_field_14b();

View file

@ -3836,9 +3836,9 @@ static int CmdHFiClassEncode(const char *Cmd) {
CLIParserInit(&ctx, "hf iclass encode",
"Encode binary wiegand to block 7,8,9\n"
"Use either --bin or --wiegand/--fc/--cn",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337\n"
"hf iclass encode --fc 31 --cn 337 --ki 0 -> FC 31 CN 337\n"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337, writing w elite key"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)\n"
"hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)\n"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key"
);
void *argtable[] = {

View file

@ -2861,6 +2861,9 @@ tryNested:
}
case PM3_ESTATIC_NONCE:
PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;;
e_sector[current_sector_i].foundKey[current_key_type_i] = false;
// Show the results to the user
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
@ -2907,6 +2910,10 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
}
case PM3_ESTATIC_NONCE: {
PrintAndLogEx(ERR, "\nError: Static encrypted nonce detected. Aborted\n");
e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;;
e_sector[current_sector_i].foundKey[current_key_type_i] = false;
// Show the results to the user
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
@ -3899,57 +3906,48 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto
PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
PrintAndLogEx(SUCCESS, " Sec | Blk | key A |res| key B |res");
PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
bool extended_legend = false;
for (uint8_t i = 0; i < sectorscnt; i++) {
snprintf(strA, sizeof(strA), "------------");
snprintf(strB, sizeof(strB), "------------");
if (e_sector[i].foundKey[0])
snprintf(strA, sizeof(strA), "%012" PRIX64, e_sector[i].Key[0]);
if (e_sector[i].foundKey[1])
snprintf(strB, sizeof(strB), "%012" PRIX64, e_sector[i].Key[1]);
if (e_sector[i].foundKey[0] > 1) {
PrintAndLogEx(SUCCESS, " "_YELLOW_("%03d")" | %03d | " _GREEN_("%s")" | " _BRIGHT_GREEN_("%c")" | " _GREEN_("%s")" | " _BRIGHT_GREEN_("%c")
, i
, mfSectorTrailerOfSector(i)
, strA, e_sector[i].foundKey[0]
, strB, e_sector[i].foundKey[1]
);
} else {
// keep track if we use start_sector or i...
uint8_t s = start_sector;
if (start_sector == 0)
s = i;
if (e_sector[i].foundKey[0]) {
snprintf(strA, sizeof(strA), _GREEN_("%012" PRIX64), e_sector[i].Key[0]);
snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%d"), 1);
} else {
snprintf(strA, sizeof(strA), _RED_("%s"), "------------");
snprintf(resA, sizeof(resA), _RED_("%d"), 0);
}
if (e_sector[i].foundKey[1]) {
snprintf(strB, sizeof(strB), _GREEN_("%012" PRIX64), e_sector[i].Key[1]);
snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%d"), 1);
} else {
snprintf(strB, sizeof(strB), _RED_("%s"), "------------");
snprintf(resB, sizeof(resB), _RED_("%d"), 0);
}
PrintAndLogEx(SUCCESS, " " _YELLOW_("%03d") " | %03d | %s | %s | %s | %s"
, s
, mfSectorTrailerOfSector(s)
, strA, resA
, strB, resB
);
if ((e_sector[i].foundKey[0] > 1) || (e_sector[i].foundKey[1] > 1)) {
extended_legend = true;
}
if (e_sector[i].foundKey[0]) {
snprintf(strA, sizeof(strA), _GREEN_("%012" PRIX64), e_sector[i].Key[0]);
snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[0]);
} else {
snprintf(strA, sizeof(strA), _RED_("%s"), "------------");
snprintf(resA, sizeof(resA), _RED_("%d"), 0);
}
if (e_sector[i].foundKey[1]) {
snprintf(strB, sizeof(strB), _GREEN_("%012" PRIX64), e_sector[i].Key[1]);
snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[1]);
} else {
snprintf(strB, sizeof(strB), _RED_("%s"), "------------");
snprintf(resB, sizeof(resB), _RED_("%d"), 0);
}
// keep track if we use start_sector or i
// show one sector or all.
uint8_t s = start_sector;
if (start_sector == 0) {
s = i;
}
PrintAndLogEx(SUCCESS, " " _YELLOW_("%03d") " | %03d | %s | %s | %s | %s"
, s
, mfSectorTrailerOfSector(s)
, strA, resA
, strB, resB
);
}
PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
if (e_sector[0].foundKey[0] > 1) {
if (extended_legend) {
PrintAndLogEx(INFO, "( "
_YELLOW_("D") ":Dictionary / "
_YELLOW_("S") ":darkSide / "

View file

@ -2439,6 +2439,7 @@ static int CmdHF14AMfUDump(const char *Cmd) {
arg_lit0("l", NULL, "Swap entered key's endianness"),
arg_int0("p", "page", "<dec>", "Manually set start page number to start from"),
arg_int0("q", "qty", "<dec>", "Manually set number of pages to dump"),
arg_lit0(NULL, "ns", "no save to file"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -2454,6 +2455,7 @@ static int CmdHF14AMfUDump(const char *Cmd) {
bool swap_endian = arg_get_lit(ctx, 3);
int start_page = arg_get_int_def(ctx, 4, 0);
int pages = arg_get_int_def(ctx, 5, 16);
bool nosave = arg_get_lit(ctx, 6);
CLIParserFree(ctx);
bool has_auth_key = false;
@ -2649,21 +2651,24 @@ static int CmdHF14AMfUDump(const char *Cmd) {
printMFUdumpEx(&dump_file_data, pages, start_page);
// user supplied filename?
if (fnlen < 1) {
if (nosave == false) {
// user supplied filename?
if (fnlen < 1) {
PrintAndLogEx(INFO, "Using UID as filename");
uint8_t uid[7] = {0};
memcpy(uid, (uint8_t *)&dump_file_data.data, 3);
memcpy(uid + 3, (uint8_t *)&dump_file_data.data + 4, 4);
strcat(filename, "hf-mfu-");
FillFileNameByUID(filename, uid, "-dump", sizeof(uid));
}
PrintAndLogEx(INFO, "Using UID as filename");
uint8_t uid[7] = {0};
memcpy(uid, (uint8_t *)&dump_file_data.data, 3);
memcpy(uid + 3, (uint8_t *)&dump_file_data.data + 4, 4);
strcat(filename, "hf-mfu-");
FillFileNameByUID(filename, uid, "-dump", sizeof(uid));
uint16_t datalen = pages * MFU_BLOCK_SIZE + MFU_DUMP_PREFIX_LENGTH;
pm3_save_dump(filename, (uint8_t *)&dump_file_data, datalen, jsfMfuMemory, MFU_BLOCK_SIZE);
if (is_partial) {
PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size);
}
}
uint16_t datalen = pages * MFU_BLOCK_SIZE + MFU_DUMP_PREFIX_LENGTH;
pm3_save_dump(filename, (uint8_t *)&dump_file_data, datalen, jsfMfuMemory, MFU_BLOCK_SIZE);
if (is_partial)
PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size);
return PM3_SUCCESS;
}

View file

@ -324,6 +324,37 @@ static int CmdLFHitagSim(const char *Cmd) {
return PM3_SUCCESS;
}
static void printHitag2PaxtonDowngrade(const uint8_t *data) {
uint64_t bytes = 0;
uint64_t num = 0;
uint64_t paxton_id = 0;
uint16_t skip = 48;
uint16_t digit = 0;
uint64_t mask = 0xF80000000000;
for (int i = 16; i < 22; i++) {
bytes = (bytes * 0x100) + data[i];
}
for (int j = 0; j< 8; j++) {
num = bytes & mask;
skip -= 5;
mask = mask >> 5;
digit = (num >> skip & 15);
paxton_id = (paxton_id * 10) + digit;
if (j == 5) {
skip -= 2;
mask = mask >> 2;
}
}
PrintAndLogEx(INFO, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
PrintAndLogEx(SUCCESS, "Paxton id: %lu | 0x%lx", paxton_id, paxton_id);
}
static void printHitag2Configuration(uint8_t config) {
char msg[100];
@ -630,6 +661,8 @@ static int CmdLFHitagReader(const char *Cmd) {
// print data
print_hex_break(data, 48, 4);
printHitag2PaxtonDowngrade(data);
}
return PM3_SUCCESS;
}

View file

@ -30,6 +30,8 @@
#include "cmdhftopaz.h"
#include "cmdnfc.h"
#include "fileutils.h"
#include "mifare/mifaredefault.h"
#include "mifare/mad.h"
void print_type4_cc_info(uint8_t *d, uint8_t n) {
if (n < 0x0F) {
@ -111,6 +113,17 @@ static int CmdNfcDecode(const char *Cmd) {
return res;
}
// convert from MFC dump file to a pure NDEF byte array
if (HasMADKey(dump)) {
PrintAndLogEx(SUCCESS, "MFC dump file detected. Converting...");
uint8_t ndef[4096] = {0};
uint16_t ndeflen = 0;
uint8_t skip = (4 * MFBLOCK_SIZE);
convert_mfc_2_arr(dump + skip, bytes_read - skip, ndef, &ndeflen);
memcpy(dump, ndef, ndeflen);
bytes_read = ndeflen;
}
res = NDEFDecodeAndPrint(dump, bytes_read, verbose);
if (res != PM3_SUCCESS) {
PrintAndLogEx(INFO, "Trying to parse NDEF records w/o NDEF header");

View file

@ -1467,12 +1467,12 @@ int convert_mfc_2_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen)
if (mfIsSectorTrailer(blockno) == false) {
memcpy(out, in, MFBLOCK_SIZE);
out += MFBLOCK_SIZE;
*olen += MFBLOCK_SIZE;
}
blockno++;
out += MFBLOCK_SIZE;
in += MFBLOCK_SIZE;
ilen -= MFBLOCK_SIZE;
*olen += MFBLOCK_SIZE;
}
return PM3_SUCCESS;
}

View file

@ -39,8 +39,6 @@
#define NDEF_VCARDTEXT "text/vcard"
#define NDEF_XVCARDTEXT "text/x-vcard"
static const char *TypeNameFormat_s[] = {
"Empty Record",
"Well Known Record",
@ -289,22 +287,35 @@ static int ndef_print_signature(uint8_t *data, uint8_t data_len, uint8_t *signat
}
static int ndefDecodeSig1(uint8_t *sig, size_t siglen) {
size_t indx = 1;
size_t indx = 1;
uint8_t sigType = sig[indx] & 0x7f;
bool sigURI = sig[indx] & 0x80;
indx++;
PrintAndLogEx(SUCCESS, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA]));
PrintAndLogEx(SUCCESS, "\tsignature uri: %s", (sigURI ? "present" : "not present"));
PrintAndLogEx(SUCCESS, "\tType...... " _YELLOW_("%s"), ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA]));
PrintAndLogEx(SUCCESS, "\tURI....... " _YELLOW_("%s"), (sigURI ? "present" : "not present"));
if (sigType == 0 && sigURI == false) {
PrintAndLogEx(INFO, "\tRecord should be considered a start marker");
}
if (sigType == 0 && sigURI) {
PrintAndLogEx(INFO, _RED_("\tSignature record is invalid"));
}
uint16_t intsiglen = MemBeToUint2byte(sig + indx);
indx += 2;
size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2];
// ecdsa 0x04
if (sigType == stECDSA_P192 || sigType == stECDSA_P256) {
indx += 3;
int slen = 24;
if (sigType == stECDSA_P256)
if (sigType == stECDSA_P256) {
slen = 32;
PrintAndLogEx(SUCCESS, "\tsignature [%zu]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen));
}
PrintAndLogEx(SUCCESS, "\tSignature [%u]...", intsiglen);
print_hex_noascii_break(&sig[indx], intsiglen, 32);
uint8_t rval[300] = {0};
uint8_t sval[300] = {0};
@ -313,38 +324,53 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) {
PrintAndLogEx(SUCCESS, "\t\tr: %s", sprint_hex(rval + 32 - slen, slen));
PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(sval + 32 - slen, slen));
}
} else {
PrintAndLogEx(SUCCESS, "\tData [%u]...", intsiglen);
print_hex_noascii_break(&sig[indx], intsiglen, 32);
}
indx += intsiglen;
if (sigURI) {
size_t intsigurilen = (sig[indx] << 8) + sig[indx + 1];
uint16_t intsigurilen = MemBeToUint2byte(sig + indx);
indx += 2;
PrintAndLogEx(SUCCESS, "\tsignature uri [%zu]: %.*s", intsigurilen, (int)intsigurilen, &sig[indx]);
PrintAndLogEx(SUCCESS, "\tSignature URI... " _YELLOW_("%.*s"), (int)intsigurilen, &sig[indx]);
indx += intsigurilen;
}
// CERTIFICATE SECTION
PrintAndLogEx(INFO, "");
PrintAndLogEx(INFO, _CYAN_("Certificate"));
uint8_t certFormat = (sig[indx] >> 4) & 0x07;
uint8_t certCount = sig[indx] & 0x0f;
bool certURI = sig[indx] & 0x80;
indx++;
PrintAndLogEx(SUCCESS, "\tcertificate format: %s", ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA]));
PrintAndLogEx(SUCCESS, "\tcertificates count: %d", certCount);
PrintAndLogEx(SUCCESS, "\tFormat............ " _YELLOW_("%s"), ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA]));
if (certCount) {
PrintAndLogEx(SUCCESS, "\tNum of certs#..... " _YELLOW_("%d"), certCount);
}
// print certificates
indx++;
for (int i = 0; i < certCount; i++) {
size_t intcertlen = (sig[indx + 1] << 8) + sig[indx + 2];
for (uint8_t i = 0; i < certCount; i++) {
uint16_t intcertlen = MemBeToUint2byte(sig + indx);
indx += 2;
PrintAndLogEx(SUCCESS, "\tcertificate %d [%zu]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen));
PrintAndLogEx(INFO, "");
PrintAndLogEx(SUCCESS, "\tCertificate %u [%u]...", i + 1, intcertlen);
print_hex_noascii_break(&sig[indx], intcertlen, 32);
indx += intcertlen;
}
// have certificate uri
// print certificate uri
if ((indx <= siglen) && certURI) {
size_t inturilen = (sig[indx] << 8) + sig[indx + 1];
uint16_t inturilen = MemBeToUint2byte(sig + indx);
indx += 2;
PrintAndLogEx(SUCCESS, "\tcertificate uri [%zu]: %.*s", inturilen, (int)inturilen, &sig[indx]);
PrintAndLogEx(SUCCESS, "\tCertificate URI... " _YELLOW_("%.*s"), (int)inturilen, &sig[indx]);
}
return PM3_SUCCESS;
@ -417,9 +443,9 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) {
}
static int ndefDecodeSig(uint8_t *sig, size_t siglen) {
PrintAndLogEx(SUCCESS, "\tsignature version : \t" _GREEN_("0x%02x"), sig[0]);
PrintAndLogEx(SUCCESS, "\tVersion... " _GREEN_("0x%02x"), sig[0]);
if (sig[0] != 0x01 && sig[0] != 0x20) {
PrintAndLogEx(ERR, "signature version unknown.");
PrintAndLogEx(ERR, _RED_("Version unknown"));
return PM3_ESOFT;
}
@ -789,7 +815,7 @@ static int ndefDecodeMime_bt(NDEFHeader_t *ndef) {
return PM3_SUCCESS;
}
PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type);
uint16_t ooblen = (ndef->Payload[1] << 8 | ndef->Payload[0]);
uint16_t ooblen = MemBeToUint2byte(ndef->Payload);
PrintAndLogEx(INFO, "OOB data len.... %u", ooblen);
PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(ndef->Payload + 2, 6));
// Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit
@ -828,6 +854,38 @@ static int ndefDecodeMime_bt(NDEFHeader_t *ndef) {
return PM3_SUCCESS;
}
// https://raw.githubusercontent.com/haldean/ndef/master/docs/NFCForum-TS-RTD_1.0.pdf
static int ndefDecodeExternal_record(NDEFHeader_t *ndef) {
if (ndef->TypeLen == 0) {
PrintAndLogEx(INFO, "no type");
return PM3_SUCCESS;
}
if (ndef->PayloadLen == 0) {
PrintAndLogEx(INFO, "no payload");
return PM3_SUCCESS;
}
PrintAndLogEx(INFO
, " URN... " _GREEN_("urn:nfc:ext:%.*s")
, (int)ndef->TypeLen
, ndef->Type
);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Payload [%u]...", ndef->PayloadLen);
print_hex_noascii_break(ndef->Payload, ndef->PayloadLen, 32);
// do a character check?
if (!strncmp((char *)ndef->Type, "pilet.ee:ekaart:2", ndef->TypeLen)) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _GREEN_("Ekaart detected") " - Trying ASN1 decode...");
asn1_print(ndef->Payload, ndef->PayloadLen, " ");
}
return PM3_SUCCESS;
}
static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) {
PrintAndLogEx(INFO, "");
@ -835,7 +893,7 @@ static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) {
case tnfEmptyRecord:
PrintAndLogEx(INFO, "Empty Record");
if (ndef->TypeLen != 0 || ndef->IDLen != 0 || ndef->PayloadLen != 0) {
PrintAndLogEx(FAILED, "unexpected data in TNF_EMPTY record");
PrintAndLogEx(FAILED, "unexpected data in empty record");
break;
}
break;
@ -931,20 +989,33 @@ static int ndefDecodePayload(NDEFHeader_t *ndef, bool verbose) {
}
case tnfAbsoluteURIRecord:
PrintAndLogEx(INFO, "Absolute URI Record");
PrintAndLogEx(INFO, " payload : %.*s", (int)ndef->PayloadLen, ndef->Payload);
PrintAndLogEx(INFO, " payload : " _YELLOW_("%.*s"), (int)ndef->PayloadLen, ndef->Payload);
break;
case tnfExternalRecord:
PrintAndLogEx(INFO, "External Record");
PrintAndLogEx(INFO, "- decoder to be impl -");
ndefDecodeExternal_record(ndef);
break;
case tnfUnknownRecord:
PrintAndLogEx(INFO, "Unknown Record");
PrintAndLogEx(INFO, "- decoder to be impl -");
if (ndef->TypeLen != 0) {
PrintAndLogEx(FAILED, "unexpected type field");
break;
}
break;
case tnfUnchangedRecord:
PrintAndLogEx(INFO, "Unchanged Record");
PrintAndLogEx(INFO, "- decoder to be impl -");
break;
case tnfReservedRecord:
PrintAndLogEx(INFO, "Reserved Record");
if (ndef->TypeLen != 0) {
PrintAndLogEx(FAILED, "unexpected type field");
break;
}
break;
default:
PrintAndLogEx(FAILED, "unexpected tnf value... 0x%02x", ndef->TypeNameFormat);
break;
}
PrintAndLogEx(INFO, "");
return PM3_SUCCESS;

View file

@ -31,7 +31,8 @@ typedef enum {
tnfAbsoluteURIRecord = 0x03,
tnfExternalRecord = 0x04,
tnfUnknownRecord = 0x05,
tnfUnchangedRecord = 0x06
tnfUnchangedRecord = 0x06,
tnfReservedRecord = 0x07,
} TypeNameFormat_t;
typedef enum {

View file

@ -3100,9 +3100,9 @@
"command": "hf iclass encode",
"description": "Encode binary wiegand to block 7,8,9 Use either --bin or --wiegand/--fc/--cn",
"notes": [
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337",
"hf iclass encode --fc 31 --cn 337 --ki 0 -> FC 31 CN 337",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337, writing w elite key"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)",
"hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key"
],
"offline": true,
"options": [
@ -11991,4 +11991,4 @@
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2023-03-26T15:04:49"
}
}
}

View file

@ -108,6 +108,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo
| LF_HIDBRUTE | HID corporate 1000 bruteforce - Federico dotta & Maurizio Agazzini
| LF_HIDFCBRUTE | LF HID facility code bruteforce - ss23
| LF_ICEHID | LF HID collector to flashmem - Iceman1001
| LF_MULTIHID | LF HID 26 Bit (H1031) multi simulator - Shain Lakin
| LF_NEDAP_SIM | LF Nedap ID simulator
| LF_NEXID | Nexwatch credentials detection mode - jrjgjk & Zolorah
| LF_PROXBRUTE | HID ProxII bruteforce - Brad Antoniewicz

View file

@ -22,8 +22,7 @@ echo "Destination: ${DEST:=firmware}"
echo "Produce stats?: ${STATS:=false}"
# Which parts to skip for the 256kb version?
SKIPS256="SKIP_HITAG=1 SKIP_LEGICRF=1 SKIP_FELICA=1 SKIP_EM4x50=1 SKIP_ISO14443b=1 SKIP_NFCBARCODE=1 SKIP_ZX8211=1"
SKIPS256="SKIP_HITAG=1 SKIP_LEGICRF=1 SKIP_FELICA=1 SKIP_EM4x50=1 SKIP_ISO14443b=1 SKIP_NFCBARCODE=1 SKIP_ZX8211=1 SKIP_LF=1"
make $MKFLAGS bootrom || exit 1
chmod 644 bootrom/obj/bootrom.elf
@ -32,7 +31,7 @@ mv bootrom/obj/bootrom.elf "$DEST/PM3BOOTROM.elf"
# cf armsrc/Standalone/Makefile.hal
STANDALONE_MODES=(LF_SKELETON)
STANDALONE_MODES+=(LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE)
STANDALONE_MODES+=(LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_MULTIHID LF_NEDAP_SIM LF_NEXID LF_PROXBRUTE LF_PROX2BRUTE LF_SAMYRUN LF_THAREXDE)
STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_REBLAY HF_TCPRST HF_TMUDFORD HF_YOUNG)
STANDALONE_MODES+=(DANKARMULTI)
STANDALONE_MODES_REQ_BT=(HF_REBLAY)