Add identification of known AID names for DESFire

This commit is contained in:
kormax
2026-04-29 21:31:02 +03:00
parent d0661c4ce2
commit bf6458171a
3 changed files with 103 additions and 54 deletions
+2 -35
View File
@@ -203,30 +203,6 @@ typedef struct aidhdr {
uint8_t name[16];
} PACKED aidhdr_t;
typedef struct {
const uint32_t aidnum;
const char *aid;
const char *comment;
} mfdesCommonAID_t;
/*
PACS application id(s) - HID Factory, CP1000 Standard, Mobile, Custom and Elite
We have HID Factory, Field Encoder == CP1000 (?)
No mobile, Custom or Elite
*/
static const mfdesCommonAID_t commonAids[] = {
{ 0x53494F, "\x53\x49\x4F", "SIO DESFire EV1 - HID Factory" },
{ 0xD3494F, "\xD3\x49\x4F", "SIO DESFire EV1 - Field Encoder" },
{ 0xD9494F, "\xD9\x49\x4F", "SIO DESFire EV1 - Field Encoder" },
{ 0xF484E3, "\xF4\x84\xE3", "SE Enhanced" },
{ 0xF484E4, "\xF4\x84\xE4", "SE Enhanced" },
{ 0xF4812F, "\xf4\x81\x2f", "Gallagher card data application" },
{ 0xF48120, "\xf4\x81\x20", "Gallagher card application directory" }, // Can be 0xF48120 - 0xF4812B, but I've only ever seen 0xF48120
{ 0xF47300, "\xf4\x73\x00", "Inner Range card application" },
{ 0xF51CD6, "\xF5\x1C\xD6", "LEAF Verified Open Application" },
};
typedef enum {
MFDES_BRUTEAID_PRESET_FULL = 0,
MFDES_BRUTEAID_PRESET_ASCII = 1,
@@ -269,15 +245,6 @@ static int CLIGetUint32Hex(CLIParserContext *ctx, uint8_t paramnum, uint32_t def
return PM3_SUCCESS;
}
static const char *getAidCommentStr(uint32_t aid) {
for (int i = 0; i < ARRAYLEN(commonAids); i++) {
if (aid == commonAids[i].aidnum) {
return commonAids[i].comment;
}
}
return "";
}
nxp_cardtype_t getCardType(uint8_t type, uint8_t major, uint8_t minor) {
// DESFire MF3ICD40
@@ -1010,7 +977,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
j = 0;
for (int i = 0; i < aidbuflen; i += 3, j++) {
uint32_t aid = DesfireAIDByteToUint(&aidbuf[i]);
PrintAndLogEx(SUCCESS, _YELLOW_("%06X") ", %s", aid, getAidCommentStr(aid));
PrintAndLogEx(SUCCESS, _YELLOW_("%06X") ", %s", aid, AIDDFGetCommentStr(aid));
}
PrintAndLogEx(NORMAL, "");
}
@@ -4956,7 +4923,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) {
PrintAndLogEx(SUCCESS, "--- " _CYAN_("AID list") " ( " _YELLOW_("%u") " found )", j);
for (int i = 0; i < buflen; i += 3) {
uint32_t aid = DesfireAIDByteToUint(&buf[i]);
PrintAndLogEx(SUCCESS, _YELLOW_("%06X") " %s", aid, getAidCommentStr(aid));
PrintAndLogEx(SUCCESS, _YELLOW_("%06X") " %s", aid, AIDDFGetCommentStr(aid));
}
PrintAndLogEx(NORMAL, "");
} else {
+100 -19
View File
@@ -17,6 +17,10 @@
//-----------------------------------------------------------------------------
#include "aiddesfire.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pm3_cmd.h"
#include "fileutils.h"
#include "jansson.h"
@@ -218,6 +222,7 @@ const char *nxp_cluster_to_text(uint8_t cluster) {
}
static json_t *df_known_aids = NULL;
static bool df_known_aids_load_tried = false;
static int open_aiddf_file(json_t **root, bool verbose) {
@@ -230,6 +235,7 @@ static int open_aiddf_file(json_t **root, bool verbose) {
int retval = PM3_SUCCESS;
json_error_t error;
*root = NULL;
*root = json_load_file(path, 0, &error);
if (!*root) {
PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text);
@@ -239,6 +245,8 @@ static int open_aiddf_file(json_t **root, bool verbose) {
if (!json_is_array(*root)) {
PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", path);
json_decref(*root);
*root = NULL;
retval = PM3_ESOFT;
goto out;
}
@@ -255,19 +263,28 @@ out:
return retval;
}
static int close_aiddf_file(json_t *root) {
json_decref(root);
return PM3_SUCCESS;
static int ensure_aiddf_file_loaded(void) {
if (df_known_aids != NULL) {
return PM3_SUCCESS;
}
if (df_known_aids_load_tried) {
return PM3_EFILE;
}
df_known_aids_load_tried = true;
return open_aiddf_file(&df_known_aids, false);
}
static const char *aiddf_json_get_str(json_t *data, const char *name) {
static const char *aiddf_json_get_str_ex(json_t *data, const char *name, bool verbose) {
json_t *jstr = json_object_get(data, name);
if (jstr == NULL)
return NULL;
if (!json_is_string(jstr)) {
PrintAndLogEx(WARNING, _YELLOW_("`%s`") " is not a string", name);
if (verbose)
PrintAndLogEx(WARNING, _YELLOW_("`%s`") " is not a string", name);
return NULL;
}
@@ -278,28 +295,63 @@ static const char *aiddf_json_get_str(json_t *data, const char *name) {
return cstr;
}
static int print_aiddf_description(json_t *root, uint8_t aid[3], char *fmt, bool verbose) {
char laid[7] = {0};
snprintf(laid, sizeof(laid), "%02x%02x%02x", aid[2], aid[1], aid[0]); // must be lowercase
static const char *aiddf_json_get_str(json_t *data, const char *name) {
return aiddf_json_get_str_ex(data, name, true);
}
json_t *elm = NULL;
static const char *aiddf_json_get_str_quiet(json_t *data, const char *name) {
return aiddf_json_get_str_ex(data, name, false);
}
static bool aiddf_parse_aid_str(const char *aid_str, uint32_t *aid) {
if (aid_str == NULL || aid == NULL || strlen(aid_str) != 6) {
return false;
}
for (int c = 0; c < 6; c++) {
if (isxdigit((uint8_t)aid_str[c]) == 0) {
return false;
}
}
char *end = NULL;
unsigned long parsed_aid = strtoul(aid_str, &end, 16);
if (end == NULL || *end != '\0' || parsed_aid > 0xFFFFFFUL) {
return false;
}
*aid = (uint32_t)parsed_aid;
return true;
}
static json_t *find_aiddf_entry(json_t *root, uint32_t aid) {
if (json_is_array(root) == false) {
return NULL;
}
for (uint32_t idx = 0; idx < json_array_size(root); idx++) {
json_t *data = json_array_get(root, idx);
if (!json_is_object(data)) {
PrintAndLogEx(ERR, "data [%d] is not an object\n", idx);
continue;
}
const char *faid = aiddf_json_get_str(data, "AID");
char lfaid[strlen(faid) + 1];
strcpy(lfaid, faid);
str_lower(lfaid);
if (strcmp(laid, lfaid) == 0) {
elm = data;
break;
uint32_t db_aid = 0;
if (aiddf_parse_aid_str(aiddf_json_get_str_quiet(data, "AID"), &db_aid) == false) {
continue;
}
if (db_aid == aid) {
return data;
}
}
return NULL;
}
static int print_aiddf_description(json_t *root, uint8_t aid[3], char *fmt, bool verbose) {
uint32_t aid_num = aid[0] | ((uint32_t)aid[1] << 8) | ((uint32_t)aid[2] << 16);
json_t *elm = find_aiddf_entry(root, aid_num);
if (elm == NULL) {
PrintAndLogEx(INFO, fmt, " (unknown)");
return PM3_ENODATA;
@@ -334,12 +386,41 @@ static int print_aiddf_description(json_t *root, uint8_t aid[3], char *fmt, bool
return PM3_SUCCESS;
}
const char *AIDDFGetCommentStr(uint32_t aid) {
static char result[256] = {0};
result[0] = '\0';
if (ensure_aiddf_file_loaded() != PM3_SUCCESS) {
return "";
}
json_t *elm = find_aiddf_entry(df_known_aids, aid);
if (elm == NULL) {
return "";
}
const char *name = aiddf_json_get_str_quiet(elm, "Name");
const char *vendor = aiddf_json_get_str_quiet(elm, "Vendor");
const char *description = aiddf_json_get_str_quiet(elm, "Description");
if (name && vendor) {
snprintf(result, sizeof(result), "%s [%s]", name, vendor);
} else if (name) {
snprintf(result, sizeof(result), "%s", name);
} else if (description) {
snprintf(result, sizeof(result), "%s", description);
}
return result;
}
int AIDDFDecodeAndPrint(uint8_t aid[3]) {
open_aiddf_file(&df_known_aids, false);
if (ensure_aiddf_file_loaded() != PM3_SUCCESS) {
return PM3_EFILE;
}
char fmt[80];
snprintf(fmt, sizeof(fmt), " DF AID Function... %02X%02X%02X :" _YELLOW_("%s"), aid[2], aid[1], aid[0], "%s");
print_aiddf_description(df_known_aids, aid, fmt, false);
close_aiddf_file(df_known_aids);
return PM3_SUCCESS;
}
+1
View File
@@ -22,6 +22,7 @@
#include "common.h"
const char *nxp_cluster_to_text(uint8_t cluster);
const char *AIDDFGetCommentStr(uint32_t aid);
int AIDDFDecodeAndPrint(uint8_t aid[3]);
#endif // _AIDDESFIRE_H_