This commit is contained in:
Willy-JL
2023-12-29 21:09:05 +01:00
59 changed files with 1688 additions and 591 deletions

View File

@@ -164,6 +164,24 @@ App(
sources=["plugins/supported_cards/microel.c"],
)
App(
appid="zolotaya_korona_parser",
apptype=FlipperAppType.PLUGIN,
entry_point="zolotaya_korona_plugin_ep",
targets=["f7"],
requires=["nfc"],
sources=["plugins/supported_cards/zolotaya_korona.c"],
)
App(
appid="hid_parser",
apptype=FlipperAppType.PLUGIN,
entry_point="hid_plugin_ep",
targets=["f7"],
requires=["nfc"],
sources=["plugins/supported_cards/hid.c"],
)
App(
appid="nfc_start",
targets=["f7"],

View File

@@ -1,6 +1,6 @@
#include "mf_user_dict.h"
#include <nfc/helpers/nfc_dict.h>
#include <toolbox/keys_dict.h>
#include <nfc/protocols/mf_classic/mf_classic.h>
#include <furi/furi.h>
@@ -15,22 +15,22 @@ struct MfUserDict {
MfUserDict* mf_user_dict_alloc(size_t max_keys_to_load) {
MfUserDict* instance = malloc(sizeof(MfUserDict));
NfcDict* dict = nfc_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
KeysDict* dict = keys_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
furi_assert(dict);
size_t dict_keys_num = nfc_dict_get_total_keys(dict);
size_t dict_keys_num = keys_dict_get_total_keys(dict);
instance->keys_num = MIN(max_keys_to_load, dict_keys_num);
if(instance->keys_num > 0) {
instance->keys_arr = malloc(instance->keys_num * sizeof(MfClassicKey));
for(size_t i = 0; i < instance->keys_num; i++) {
bool key_loaded =
nfc_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey));
keys_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey));
furi_assert(key_loaded);
}
}
nfc_dict_free(dict);
keys_dict_free(dict);
return instance;
}
@@ -67,13 +67,13 @@ bool mf_user_dict_delete_key(MfUserDict* instance, uint32_t index) {
furi_assert(index < instance->keys_num);
furi_assert(instance->keys_arr);
NfcDict* dict = nfc_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
KeysDict* dict = keys_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
furi_assert(dict);
bool key_delete_success =
nfc_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey));
nfc_dict_free(dict);
keys_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey));
keys_dict_free(dict);
if(key_delete_success) {
instance->keys_num--;

View File

@@ -344,7 +344,7 @@ bool nfc_load_file(NfcApp* instance, FuriString* path, bool show_dialog) {
nfc_supported_cards_load_cache(instance->nfc_supported_cards);
FuriString* load_path = furi_string_alloc();
if(nfc_has_shadow_file_internal(instance, path)) {
if(nfc_has_shadow_file_internal(instance, path)) { //-V1051
nfc_set_shadow_file_path(path, load_path);
} else if(furi_string_end_with(path, NFC_APP_SHADOW_EXTENSION)) {
size_t path_len = furi_string_size(path);

View File

@@ -52,7 +52,7 @@
#include <nfc/nfc_device.h>
#include <nfc/helpers/nfc_data_generator.h>
#include <nfc/helpers/nfc_dict.h>
#include <toolbox/keys_dict.h>
#include <gui/modules/validators.h>
#include <toolbox/path.h>
@@ -80,7 +80,7 @@ typedef enum {
} NfcRpcState;
typedef struct {
NfcDict* dict;
KeysDict* dict;
uint8_t sectors_total;
uint8_t sectors_read;
uint8_t current_sector;

View File

@@ -0,0 +1,153 @@
#include "nfc_supported_card_plugin.h"
#include <flipper_application/flipper_application.h>
#include <nfc/nfc_device.h>
#include <nfc/helpers/nfc_util.h>
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
#define TAG "HID"
static const uint64_t hid_key = 0x484944204953;
bool hid_verify(Nfc* nfc) {
bool verified = false;
do {
const uint8_t verify_sector = 1;
uint8_t block_num = mf_classic_get_first_block_num_of_sector(verify_sector);
FURI_LOG_D(TAG, "Verifying sector %u", verify_sector);
MfClassicKey key = {};
nfc_util_num2bytes(hid_key, COUNT_OF(key.data), key.data);
MfClassicAuthContext auth_ctx = {};
MfClassicError error =
mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx);
if(error != MfClassicErrorNone) {
FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
break;
}
verified = true;
} while(false);
return verified;
}
static bool hid_read(Nfc* nfc, NfcDevice* device) {
furi_assert(nfc);
furi_assert(device);
bool is_read = false;
MfClassicData* data = mf_classic_alloc();
nfc_device_copy_data(device, NfcProtocolMfClassic, data);
do {
MfClassicType type = MfClassicType1k;
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
if(error != MfClassicErrorNone) break;
data->type = type;
MfClassicDeviceKeys keys = {};
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
nfc_util_num2bytes(hid_key, sizeof(MfClassicKey), keys.key_a[i].data);
FURI_BIT_SET(keys.key_a_mask, i);
nfc_util_num2bytes(hid_key, sizeof(MfClassicKey), keys.key_b[i].data);
FURI_BIT_SET(keys.key_b_mask, i);
}
error = mf_classic_poller_sync_read(nfc, &keys, data);
if(error != MfClassicErrorNone) {
FURI_LOG_W(TAG, "Failed to read data");
break;
}
nfc_device_set_data(device, NfcProtocolMfClassic, data);
is_read = true;
} while(false);
mf_classic_free(data);
return is_read;
}
static uint8_t get_bit_length(const uint8_t* half_block) {
uint8_t bitLength = 0;
uint32_t* halves = (uint32_t*)half_block;
if(halves[0] == 0) {
uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1]));
bitLength = 31 - leading0s;
} else {
uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[0]));
bitLength = 63 - leading0s;
}
return bitLength;
}
static uint64_t get_pacs_bits(const uint8_t* block, uint8_t bitLength) {
// Remove sentinel bit from credential. Byteswapping to handle array of bytes vs 64bit value
uint64_t sentinel = __builtin_bswap64(1ULL << bitLength);
uint64_t swapped = 0;
memcpy(&swapped, block, sizeof(uint64_t));
swapped = __builtin_bswap64(swapped ^ sentinel);
FURI_LOG_D(TAG, "PACS: (%d) %016llx", bitLength, swapped);
return swapped;
}
static bool hid_parse(const NfcDevice* device, FuriString* parsed_data) {
furi_assert(device);
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
bool parsed = false;
do {
// verify key
const uint8_t verify_sector = 1;
MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(data, verify_sector);
uint64_t key = nfc_util_bytes2num(sec_tr->key_a.data, 6);
if(key != hid_key) break;
// Currently doesn't support bit length > 63
const uint8_t* credential_block = data->block[5].data + 8;
uint8_t bitLength = get_bit_length(credential_block);
if(bitLength == 0) break;
uint64_t credential = get_pacs_bits(credential_block, bitLength);
if(credential == 0) break;
furi_string_printf(parsed_data, "\e#HID Card\n%dbit\n%llx", bitLength, credential);
parsed = true;
} while(false);
return parsed;
}
/* Actual implementation of app<>plugin interface */
static const NfcSupportedCardsPlugin hid_plugin = {
.protocol = NfcProtocolMfClassic,
.verify = hid_verify,
.read = hid_read,
.parse = hid_parse,
};
/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor hid_plugin_descriptor = {
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
.entry_point = &hid_plugin,
};
/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* hid_plugin_ep() {
return &hid_plugin_descriptor;
}

View File

@@ -250,19 +250,18 @@ static bool kazan_parse(const NfcDevice* device, FuriString* parsed_data) {
last_trip.day = block_start_ptr[2];
last_trip.hour = block_start_ptr[3];
last_trip.minute = block_start_ptr[4];
bool is_last_trip_valid = (block_start_ptr[0] | block_start_ptr[1] | block_start_ptr[0]) &&
bool is_last_trip_valid = (block_start_ptr[0] | block_start_ptr[1] | block_start_ptr[2]) &&
(last_trip.day < 32 && last_trip.month < 12 &&
last_trip.hour < 24 && last_trip.minute < 60);
start_block_num = mf_classic_get_first_block_num_of_sector(balance_sector_number);
block_start_ptr = &data->block[start_block_num].data[0];
const uint32_t trip_counter = (block_start_ptr[3] << 24) | (block_start_ptr[2] << 16) |
(block_start_ptr[1] << 8) | (block_start_ptr[0]);
const uint32_t trip_counter = nfc_util_bytes2num_little_endian(block_start_ptr, 4);
size_t uid_len = 0;
const uint8_t* uid = mf_classic_get_uid(data, &uid_len);
const uint32_t card_number = (uid[3] << 24) | (uid[2] << 16) | (uid[1] << 8) | (uid[0]);
const uint32_t card_number = nfc_util_bytes2num_little_endian(uid, 4);
furi_string_cat_printf(
parsed_data, "\e#Kazan transport card\nCard number: %lu\n", card_number);

View File

@@ -148,15 +148,14 @@ static bool metromoney_parse(const NfcDevice* device, FuriString* parsed_data) {
const uint8_t* block_start_ptr =
&data->block[start_block_num + ticket_block_number].data[0];
uint32_t balance = (block_start_ptr[3] << 24) | (block_start_ptr[2] << 16) |
(block_start_ptr[1] << 8) | (block_start_ptr[0]);
uint32_t balance = nfc_util_bytes2num_little_endian(block_start_ptr, 4);
uint32_t balance_lari = balance / 100;
uint8_t balance_tetri = balance % 100;
size_t uid_len = 0;
const uint8_t* uid = mf_classic_get_uid(data, &uid_len);
uint32_t card_number = (uid[3] << 24) | (uid[2] << 16) | (uid[1] << 8) | (uid[0]);
uint32_t card_number = nfc_util_bytes2num_little_endian(uid, 4);
furi_string_printf(
parsed_data,

View File

@@ -0,0 +1,254 @@
/*
* Parser for Zolotaya Korona card (Russia).
*
* Copyright 2023 Leptoptilos <leptoptilos@icloud.com>
*
* More info about Zolotaya Korona cards: https://github.com/metrodroid/metrodroid/wiki/Zolotaya-Korona
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "core/core_defines.h"
#include "core/string.h"
#include "furi_hal_rtc.h"
#include "nfc_supported_card_plugin.h"
#include "protocols/mf_classic/mf_classic.h"
#include <flipper_application/flipper_application.h>
#include <nfc/nfc_device.h>
#include <nfc/helpers/nfc_util.h>
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
#include <stdbool.h>
#include <stdint.h>
#define TAG "Zolotaya Korona"
#define TRIP_SECTOR_NUM (4)
#define PURSE_SECTOR_NUM (6)
#define INFO_SECTOR_NUM (15)
typedef struct {
uint64_t a;
uint64_t b;
} MfClassicKeyPair;
// Sector 15 data. Byte [11] contains the mistake. If byte [11] was 0xEF, bytes [1-18] means "ЗАО Золотая Корона"
static const uint8_t info_sector_signature[] = {0xE2, 0x87, 0x80, 0x8E, 0x20, 0x87, 0xAE,
0xAB, 0xAE, 0xF2, 0xA0, 0xEF, 0x20, 0x8A,
0xAE, 0xE0, 0xAE, 0xAD, 0xA0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60
#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60)
#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24)
#define FURI_HAL_RTC_EPOCH_START_YEAR 1970
void timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime) {
uint32_t days = timestamp / FURI_HAL_RTC_SECONDS_PER_DAY;
uint32_t seconds_in_day = timestamp % FURI_HAL_RTC_SECONDS_PER_DAY;
datetime->year = FURI_HAL_RTC_EPOCH_START_YEAR;
while(days >= furi_hal_rtc_get_days_per_year(datetime->year)) {
days -= furi_hal_rtc_get_days_per_year(datetime->year);
(datetime->year)++;
}
datetime->month = 1;
while(days >= furi_hal_rtc_get_days_per_month(
furi_hal_rtc_is_leap_year(datetime->year), datetime->month)) {
days -= furi_hal_rtc_get_days_per_month(
furi_hal_rtc_is_leap_year(datetime->year), datetime->month);
(datetime->month)++;
}
datetime->day = days + 1;
datetime->hour = seconds_in_day / FURI_HAL_RTC_SECONDS_PER_HOUR;
datetime->minute =
(seconds_in_day % FURI_HAL_RTC_SECONDS_PER_HOUR) / FURI_HAL_RTC_SECONDS_PER_MINUTE;
datetime->second = seconds_in_day % FURI_HAL_RTC_SECONDS_PER_MINUTE;
}
uint64_t bytes2num_bcd(const uint8_t* src, uint8_t len_bytes) {
furi_assert(src);
uint64_t res = 0;
for(uint8_t i = 0; i < len_bytes; i++) {
res *= 10;
res += src[i] / 16;
res *= 10;
res += src[i] % 16;
}
return res;
}
static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_data) {
furi_assert(device);
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
bool parsed = false;
do {
// Verify info sector data
const uint8_t start_info_block_number =
mf_classic_get_first_block_num_of_sector(INFO_SECTOR_NUM);
const uint8_t* block_start_ptr = &data->block[start_info_block_number].data[0];
bool verified = true;
for(uint8_t i = 0; i < sizeof(info_sector_signature); i++) {
if(i == 16) {
block_start_ptr = &data->block[start_info_block_number + 1].data[0];
}
if(block_start_ptr[i % 16] != info_sector_signature[i]) {
verified = false;
break;
}
}
if(!verified) break;
// Parse data
// INFO SECTOR
// block 1
const uint8_t region_number = bytes2num_bcd(block_start_ptr + 10, 1);
// block 2
block_start_ptr = &data->block[start_info_block_number + 2].data[4];
const uint64_t card_number =
bytes2num_bcd(block_start_ptr, 9) * 10 + bytes2num_bcd(block_start_ptr + 9, 1) / 10;
// TRIP SECTOR
const uint8_t start_trip_block_number =
mf_classic_get_first_block_num_of_sector(TRIP_SECTOR_NUM);
// block 0
block_start_ptr = &data->block[start_trip_block_number].data[7];
const uint8_t status = block_start_ptr[0] % 16;
const uint16_t sequence_number = nfc_util_bytes2num(block_start_ptr + 1, 2);
const uint8_t discount_code = nfc_util_bytes2num(block_start_ptr + 3, 1);
// block 1: refill block
block_start_ptr = &data->block[start_trip_block_number + 1].data[1];
const uint16_t refill_machine_id = nfc_util_bytes2num_little_endian(block_start_ptr, 2);
const uint32_t last_refill_timestamp =
nfc_util_bytes2num_little_endian(block_start_ptr + 2, 4);
const uint32_t last_refill_amount =
nfc_util_bytes2num_little_endian(block_start_ptr + 6, 4);
const uint32_t last_refill_amount_rub = last_refill_amount / 100;
const uint8_t last_refill_amount_kop = last_refill_amount % 100;
const uint16_t refill_counter = nfc_util_bytes2num_little_endian(block_start_ptr + 10, 2);
FuriHalRtcDateTime last_refill_datetime = {0};
timestamp_to_datetime(last_refill_timestamp, &last_refill_datetime);
// block 2: trip block
block_start_ptr = &data->block[start_trip_block_number + 2].data[0];
const char validator_first_letter =
nfc_util_bytes2num_little_endian(block_start_ptr + 1, 1);
const uint32_t validator_id = bytes2num_bcd(block_start_ptr + 2, 3);
const uint32_t last_trip_timestamp =
nfc_util_bytes2num_little_endian(block_start_ptr + 6, 4);
const uint8_t track_number = nfc_util_bytes2num_little_endian(block_start_ptr + 10, 1);
const uint32_t prev_balance = nfc_util_bytes2num_little_endian(block_start_ptr + 11, 4);
const uint32_t prev_balance_rub = prev_balance / 100;
const uint8_t prev_balance_kop = prev_balance % 100;
FuriHalRtcDateTime last_trip_datetime = {0};
timestamp_to_datetime(last_trip_timestamp, &last_trip_datetime);
// PARSE DATA FROM PURSE SECTOR
const uint8_t start_purse_block_number =
mf_classic_get_first_block_num_of_sector(PURSE_SECTOR_NUM);
block_start_ptr = &data->block[start_purse_block_number].data[0];
// block 0
uint32_t balance = nfc_util_bytes2num_little_endian(block_start_ptr, 4);
uint32_t balance_rub = balance / 100;
uint8_t balance_kop = balance % 100;
furi_string_cat_printf(
parsed_data,
"\e#Zolotaya korona\nCard number: %llu\nRegion: %u\nBalance: %lu.%02u RUR\nPrev. balance: %lu.%02u RUR",
card_number,
region_number,
balance_rub,
balance_kop,
prev_balance_rub,
prev_balance_kop);
furi_string_cat_printf(
parsed_data,
"\nLast refill amount: %lu.%02u RUR\nRefill counter: %u\nLast refill: %u.%02u.%02u %02u:%02u\nRefill machine id: %u",
last_refill_amount_rub,
last_refill_amount_kop,
refill_counter,
last_refill_datetime.day,
last_refill_datetime.month,
last_refill_datetime.year,
last_refill_datetime.hour,
last_refill_datetime.minute,
refill_machine_id);
furi_string_cat_printf(
parsed_data,
"\nLast trip: %u.%02u.%02u %02u:%02u\nTrack number: %u\nValidator: %c%06lu",
last_trip_datetime.day,
last_trip_datetime.month,
last_trip_datetime.year,
last_trip_datetime.hour,
last_trip_datetime.minute,
track_number,
validator_first_letter,
validator_id);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
furi_string_cat_printf(
parsed_data,
"\nStatus: %u\nSequence num: %u\nDiscount code: %u",
status,
sequence_number,
discount_code);
}
parsed = true;
} while(false);
return parsed;
}
/* Actual implementation of app<>plugin interface */
static const NfcSupportedCardsPlugin zolotaya_korona_plugin = {
.protocol = NfcProtocolMfClassic,
.verify = NULL,
.read = NULL,
.parse = zolotaya_korona_parse,
};
/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor zolotaya_korona_plugin_descriptor = {
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
.entry_point = &zolotaya_korona_plugin,
};
/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* zolotaya_korona_plugin_ep() {
return &zolotaya_korona_plugin_descriptor;
}

View File

@@ -4363,4 +4363,39 @@ EB9D9C1B03F6
5A4920FD6F87
544954CBB2C4
4752533E1965
17C06D19E92F
17C06D19E92F
# Bandai Namco Passport [fka Banapassport] / Sega Aime Card
6090D00632F5
019761AA8082
574343467632
A99164400748
62742819AD7C
CC5075E42BA1
B9DF35A0814C
8AF9C718F23D
58CD5C3673CB
FC80E88EB88C
7A3CDAD7C023
30424C029001
024E4E44001F
ECBBFA57C6AD
4757698143BD
1D30972E6485
F8526D1A8D6D
1300EC8C7E80
F80A65A87FFA
DEB06ED4AF8E
4AD96BF28190
000390014D41
0800F9917CB0
730050555253
4146D4A956C4
131157FBB126
E69DD9015A43
337237F254D5
9A8389F32FBF
7B8FB4A7100B
C8382A233993
7B304F2A12A6
FC9418BF788B

View File

@@ -41,7 +41,8 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context)
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate);
} else if(mfc_event->type == MfClassicPollerEventTypeRequestKey) {
MfClassicKey key = {};
if(nfc_dict_get_next_key(instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) {
if(keys_dict_get_next_key(
instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) {
mfc_event->data->key_request_data.key = key;
mfc_event->data->key_request_data.key_provided = true;
instance->nfc_dict_context.dict_keys_current++;
@@ -60,7 +61,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context)
view_dispatcher_send_custom_event(
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate);
} else if(mfc_event->type == MfClassicPollerEventTypeNextSector) {
nfc_dict_rewind(instance->nfc_dict_context.dict);
keys_dict_rewind(instance->nfc_dict_context.dict);
instance->nfc_dict_context.dict_keys_current = 0;
instance->nfc_dict_context.current_sector =
mfc_event->data->next_sector_data.current_sector;
@@ -79,7 +80,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context)
view_dispatcher_send_custom_event(
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate);
} else if(mfc_event->type == MfClassicPollerEventTypeKeyAttackStop) {
nfc_dict_rewind(instance->nfc_dict_context.dict);
keys_dict_rewind(instance->nfc_dict_context.dict);
instance->nfc_dict_context.is_key_attack = false;
instance->nfc_dict_context.dict_keys_current = 0;
view_dispatcher_send_custom_event(
@@ -124,15 +125,15 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) {
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicDictAttack);
if(state == DictAttackStateUserDictInProgress) {
do {
if(!nfc_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) {
if(!keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) {
state = DictAttackStateSystemDictInProgress;
break;
}
instance->nfc_dict_context.dict = nfc_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
if(nfc_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) {
nfc_dict_free(instance->nfc_dict_context.dict);
instance->nfc_dict_context.dict = keys_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
if(keys_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) {
keys_dict_free(instance->nfc_dict_context.dict);
state = DictAttackStateSystemDictInProgress;
break;
}
@@ -141,13 +142,13 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) {
} while(false);
}
if(state == DictAttackStateSystemDictInProgress) {
instance->nfc_dict_context.dict = nfc_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey));
instance->nfc_dict_context.dict = keys_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey));
dict_attack_set_header(instance->dict_attack, "MF Classic System Dictionary");
}
instance->nfc_dict_context.dict_keys_total =
nfc_dict_get_total_keys(instance->nfc_dict_context.dict);
keys_dict_get_total_keys(instance->nfc_dict_context.dict);
dict_attack_set_total_dict_keys(
instance->dict_attack, instance->nfc_dict_context.dict_keys_total);
instance->nfc_dict_context.dict_keys_current = 0;
@@ -185,7 +186,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
if(state == DictAttackStateUserDictInProgress) {
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
nfc_dict_free(instance->nfc_dict_context.dict);
keys_dict_free(instance->nfc_dict_context.dict);
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfClassicDictAttack,
@@ -215,7 +216,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
if(instance->nfc_dict_context.is_card_present) {
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
nfc_dict_free(instance->nfc_dict_context.dict);
keys_dict_free(instance->nfc_dict_context.dict);
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfClassicDictAttack,
@@ -253,7 +254,7 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) {
scene_manager_set_scene_state(
instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateUserDictInProgress);
nfc_dict_free(instance->nfc_dict_context.dict);
keys_dict_free(instance->nfc_dict_context.dict);
instance->nfc_dict_context.current_sector = 0;
instance->nfc_dict_context.sectors_total = 0;

View File

@@ -14,20 +14,20 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
// Load flipper dict keys total
uint32_t flipper_dict_keys_total = 0;
NfcDict* dict = nfc_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey));
KeysDict* dict = keys_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey));
if(dict) {
flipper_dict_keys_total = nfc_dict_get_total_keys(dict);
nfc_dict_free(dict);
flipper_dict_keys_total = keys_dict_get_total_keys(dict);
keys_dict_free(dict);
}
// Load user dict keys total
uint32_t user_dict_keys_total = 0;
dict = nfc_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
dict = keys_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
if(dict) {
user_dict_keys_total = nfc_dict_get_total_keys(dict);
nfc_dict_free(dict);
user_dict_keys_total = keys_dict_get_total_keys(dict);
keys_dict_free(dict);
}
FuriString* temp_str = furi_string_alloc();

View File

@@ -29,23 +29,23 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
// Add key to dict
NfcDict* dict = nfc_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
KeysDict* dict = keys_dict_alloc(
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
furi_assert(dict);
MfClassicKey key = {};
memcpy(key.data, instance->byte_input_store, sizeof(MfClassicKey));
if(nfc_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) {
if(keys_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) {
scene_manager_next_scene(
instance->scene_manager, NfcSceneMfClassicKeysWarnDuplicate);
} else if(nfc_dict_add_key(dict, key.data, sizeof(MfClassicKey))) {
} else if(keys_dict_add_key(dict, key.data, sizeof(MfClassicKey))) {
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveSuccess);
dolphin_deed(DolphinDeedNfcMfcAdd);
} else {
scene_manager_previous_scene(instance->scene_manager);
}
nfc_dict_free(dict);
keys_dict_free(dict);
consumed = true;
}
}