Fix PN532 transport and NFC tag handling.
Tighten PN532 framing and NFC access locking so scan, read, write, and raw operations behave reliably on hardware, and correct Classic versus Type 2 tag classification so common cards hit the right code paths. Refresh the embedded web assets and launcher files to match the corrected firmware behavior. Made-with: Cursor
This commit is contained in:
@@ -36,6 +36,27 @@ static const uint8_t k_builtin[][6] = {
|
||||
#define MAX_VARIANTS_PER_KEY 14
|
||||
#define MAX_TRIES_BEFORE_WDT 48
|
||||
|
||||
static bool add_sector_hit(cJSON *hits, uint8_t sector, const uint8_t key[6], const char *key_type)
|
||||
{
|
||||
if (!hits || !key || !key_type) {
|
||||
return false;
|
||||
}
|
||||
char hx[16];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
snprintf(hx + i * 2, 3, "%02X", key[i]);
|
||||
}
|
||||
hx[12] = 0;
|
||||
cJSON *h = cJSON_CreateObject();
|
||||
if (!h) {
|
||||
return false;
|
||||
}
|
||||
cJSON_AddNumberToObject(h, "sector", sector);
|
||||
cJSON_AddStringToObject(h, "keyHex", hx);
|
||||
cJSON_AddStringToObject(h, "keyType", key_type);
|
||||
cJSON_AddItemToArray(hits, h);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int push_variant(const uint8_t base[6], int idx, uint8_t out[6])
|
||||
{
|
||||
memcpy(out, base, 6);
|
||||
@@ -76,7 +97,7 @@ static bool try_key_on_trailer(nfc_tag_info_t *tag, uint8_t trailer, const uint8
|
||||
/** Trailer block for MIFARE Classic sector index (0..15 for 1K, 0..39 for 4K). */
|
||||
static uint8_t classic_trailer_for_sector(const nfc_tag_info_t *tag, uint8_t sec)
|
||||
{
|
||||
if (tag->sak == 0x19) {
|
||||
if (nfc_tag_is_mifare_classic_4k(tag)) {
|
||||
if (sec <= 31) {
|
||||
return (uint8_t)(sec * 4 + 3);
|
||||
}
|
||||
@@ -102,7 +123,13 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (tag->type_hint != 1) {
|
||||
if (!tag) {
|
||||
cJSON_Delete(root);
|
||||
cJSON_Delete(hits);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!nfc_tag_is_mifare_classic(tag)) {
|
||||
cJSON_AddStringToObject(root, "error", "not_classic_sak_hint");
|
||||
cJSON_AddItemToObject(root, "sectorHits", hits);
|
||||
if (attempts_out) {
|
||||
@@ -111,13 +138,22 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u
|
||||
return root;
|
||||
}
|
||||
|
||||
uint8_t sector_max = nfc_tag_is_mifare_classic_4k(tag) ? 39 : 15;
|
||||
|
||||
if (sector_first > sector_last) {
|
||||
uint8_t t = sector_first;
|
||||
sector_first = sector_last;
|
||||
sector_last = t;
|
||||
}
|
||||
if (sector_first > sector_max) {
|
||||
sector_first = sector_max;
|
||||
}
|
||||
if (sector_last > sector_max) {
|
||||
sector_last = sector_max;
|
||||
}
|
||||
|
||||
for (uint8_t sec = sector_first; sec <= sector_last; sec++) {
|
||||
for (int sec_i = sector_first; sec_i <= sector_last; sec_i++) {
|
||||
uint8_t sec = (uint8_t)sec_i;
|
||||
uint8_t trailer = classic_trailer_for_sector(tag, sec);
|
||||
if (trailer == 0xFF) {
|
||||
continue;
|
||||
@@ -133,30 +169,18 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u
|
||||
}
|
||||
attempts++;
|
||||
if (try_key_on_trailer(tag, trailer, trial, false)) {
|
||||
char hx[16];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
snprintf(hx + i * 2, 3, "%02X", trial[i]);
|
||||
if (!add_sector_hit(hits, sec, trial, "A")) {
|
||||
cJSON_Delete(root);
|
||||
return NULL;
|
||||
}
|
||||
hx[12] = 0;
|
||||
cJSON *h = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(h, "sector", sec);
|
||||
cJSON_AddStringToObject(h, "keyHex", hx);
|
||||
cJSON_AddStringToObject(h, "keyType", "A");
|
||||
cJSON_AddItemToArray(hits, h);
|
||||
got = true;
|
||||
break;
|
||||
}
|
||||
if (try_key_on_trailer(tag, trailer, trial, true)) {
|
||||
char hx[16];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
snprintf(hx + i * 2, 3, "%02X", trial[i]);
|
||||
if (!add_sector_hit(hits, sec, trial, "B")) {
|
||||
cJSON_Delete(root);
|
||||
return NULL;
|
||||
}
|
||||
hx[12] = 0;
|
||||
cJSON *h = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(h, "sector", sec);
|
||||
cJSON_AddStringToObject(h, "keyHex", hx);
|
||||
cJSON_AddStringToObject(h, "keyType", "B");
|
||||
cJSON_AddItemToArray(hits, h);
|
||||
got = true;
|
||||
break;
|
||||
}
|
||||
@@ -177,30 +201,18 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u
|
||||
}
|
||||
attempts++;
|
||||
if (try_key_on_trailer(tag, trailer, trial, false)) {
|
||||
char hx[16];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
snprintf(hx + i * 2, 3, "%02X", trial[i]);
|
||||
if (!add_sector_hit(hits, sec, trial, "A")) {
|
||||
cJSON_Delete(root);
|
||||
return NULL;
|
||||
}
|
||||
hx[12] = 0;
|
||||
cJSON *h = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(h, "sector", sec);
|
||||
cJSON_AddStringToObject(h, "keyHex", hx);
|
||||
cJSON_AddStringToObject(h, "keyType", "A");
|
||||
cJSON_AddItemToArray(hits, h);
|
||||
got = true;
|
||||
break;
|
||||
}
|
||||
if (try_key_on_trailer(tag, trailer, trial, true)) {
|
||||
char hx[16];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
snprintf(hx + i * 2, 3, "%02X", trial[i]);
|
||||
if (!add_sector_hit(hits, sec, trial, "B")) {
|
||||
cJSON_Delete(root);
|
||||
return NULL;
|
||||
}
|
||||
hx[12] = 0;
|
||||
cJSON *h = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(h, "sector", sec);
|
||||
cJSON_AddStringToObject(h, "keyHex", hx);
|
||||
cJSON_AddStringToObject(h, "keyType", "B");
|
||||
cJSON_AddItemToArray(hits, h);
|
||||
got = true;
|
||||
break;
|
||||
}
|
||||
@@ -213,6 +225,10 @@ cJSON *nfc_mifare_dictionary_attack(nfc_tag_info_t *tag, uint8_t sector_first, u
|
||||
|
||||
if (!got) {
|
||||
cJSON *h = cJSON_CreateObject();
|
||||
if (!h) {
|
||||
cJSON_Delete(root);
|
||||
return NULL;
|
||||
}
|
||||
cJSON_AddNumberToObject(h, "sector", sec);
|
||||
cJSON_AddBoolToObject(h, "miss", true);
|
||||
cJSON_AddItemToArray(hits, h);
|
||||
|
||||
Reference in New Issue
Block a user