-
Notifications
You must be signed in to change notification settings - Fork 3.1k
MIFARE Classic Key Recovery Improvements #3822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 78 commits
cf6d6bb
b154603
ef16770
d3bf372
213ec1d
9ba78bf
6d66638
e61b543
09f8a73
7d2cab5
8dd3daf
4b44288
5feeae8
3acba77
6332ec7
01b1948
8d1a220
cc8cae7
79bc887
0af28fb
08ca794
b7e63bf
bbc10cd
75a0e4b
c1f01ce
26845cb
5235592
0b33c85
c0331ba
4c14594
144424e
90d0c3d
2abeb07
ccc4326
9c7120e
2cb2f05
6e9fe1e
2e0cd32
3cb3eab
92122b2
7bb3349
b09d5a0
9ea7a46
9558a5f
cba58ed
ab8bc3e
d7484ee
c43806b
ab0debb
8d26636
13411da
8edafa3
18f8cfb
4836a54
3ab752b
8eae5c0
d8864a4
c1cdd49
96606dc
6eccdc8
c21b359
6a77ab7
901bdf9
4eb0f2a
6ae9506
cd76926
0ba8ac4
61e24fc
099bb40
ba672e7
232560f
00f3564
4f722a0
a905c14
f346412
a1590fc
bcc8d3e
56febb1
b843856
3976f12
a7c0819
5404788
889b19b
f530eee
02f7c6b
2bc02c0
4be9e79
1101748
2be0cfb
897817a
db26c85
92aa70b
4763762
bf7b91f
6dbb46a
2282587
eb1aabb
c240077
907019c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
#include "../nfc_app_i.h" | ||
|
||
#include <bit_lib/bit_lib.h> | ||
#include <dolphin/dolphin.h> | ||
#include <lib/nfc/protocols/mf_classic/mf_classic_poller.h> | ||
|
||
#define TAG "NfcMfClassicDictAttack" | ||
|
||
// TODO: Fix lag when leaving the dictionary attack view after Hardnested | ||
// TODO: Re-enters backdoor detection between user and system dictionary if no backdoor is found | ||
|
||
noproto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
typedef enum { | ||
DictAttackStateCUIDDictInProgress, | ||
DictAttackStateUserDictInProgress, | ||
DictAttackStateSystemDictInProgress, | ||
} DictAttackState; | ||
|
@@ -29,7 +34,9 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) | |
} else if(mfc_event->type == MfClassicPollerEventTypeRequestMode) { | ||
const MfClassicData* mfc_data = | ||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic); | ||
mfc_event->data->poller_mode.mode = MfClassicPollerModeDictAttack; | ||
mfc_event->data->poller_mode.mode = (instance->nfc_dict_context.enhanced_dict) ? | ||
skotopes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
MfClassicPollerModeDictAttackEnhanced : | ||
MfClassicPollerModeDictAttackStandard; | ||
mfc_event->data->poller_mode.data = mfc_data; | ||
instance->nfc_dict_context.sectors_total = | ||
mf_classic_get_total_sectors_num(mfc_data->type); | ||
|
@@ -58,6 +65,11 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) | |
instance->nfc_dict_context.sectors_read = data_update->sectors_read; | ||
instance->nfc_dict_context.keys_found = data_update->keys_found; | ||
instance->nfc_dict_context.current_sector = data_update->current_sector; | ||
instance->nfc_dict_context.nested_phase = data_update->nested_phase; | ||
instance->nfc_dict_context.prng_type = data_update->prng_type; | ||
instance->nfc_dict_context.backdoor = data_update->backdoor; | ||
instance->nfc_dict_context.nested_target_key = data_update->nested_target_key; | ||
instance->nfc_dict_context.msb_count = data_update->msb_count; | ||
view_dispatcher_send_custom_event( | ||
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate); | ||
} else if(mfc_event->type == MfClassicPollerEventTypeNextSector) { | ||
|
@@ -117,19 +129,75 @@ static void nfc_scene_mf_classic_dict_attack_update_view(NfcApp* instance) { | |
dict_attack_set_keys_found(instance->dict_attack, mfc_dict->keys_found); | ||
dict_attack_set_current_dict_key(instance->dict_attack, mfc_dict->dict_keys_current); | ||
dict_attack_set_current_sector(instance->dict_attack, mfc_dict->current_sector); | ||
dict_attack_set_nested_phase(instance->dict_attack, mfc_dict->nested_phase); | ||
dict_attack_set_prng_type(instance->dict_attack, mfc_dict->prng_type); | ||
dict_attack_set_backdoor(instance->dict_attack, mfc_dict->backdoor); | ||
dict_attack_set_nested_target_key(instance->dict_attack, mfc_dict->nested_target_key); | ||
dict_attack_set_msb_count(instance->dict_attack, mfc_dict->msb_count); | ||
} | ||
} | ||
|
||
static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { | ||
uint32_t state = | ||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicDictAttack); | ||
if(state == DictAttackStateCUIDDictInProgress) { | ||
do { | ||
size_t cuid_len = 0; | ||
const uint8_t* cuid = nfc_device_get_uid(instance->nfc_device, &cuid_len); | ||
FuriString* cuid_dict_path = furi_string_alloc_printf( | ||
noproto marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
"%s/mf_classic_dict_%08lx.nfc", | ||
|
||
EXT_PATH("nfc/assets"), | ||
(uint32_t)bit_lib_bytes_to_num_be(cuid + (cuid_len - 4), 4)); | ||
|
||
if(!keys_dict_check_presence(furi_string_get_cstr(cuid_dict_path))) { | ||
state = DictAttackStateUserDictInProgress; | ||
noproto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
break; | ||
} | ||
|
||
instance->nfc_dict_context.dict = keys_dict_alloc( | ||
furi_string_get_cstr(cuid_dict_path), | ||
KeysDictModeOpenExisting, | ||
sizeof(MfClassicKey)); | ||
|
||
furi_string_free(cuid_dict_path); | ||
|
||
if(keys_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) { | ||
keys_dict_free(instance->nfc_dict_context.dict); | ||
state = DictAttackStateUserDictInProgress; | ||
break; | ||
} | ||
|
||
dict_attack_set_header(instance->dict_attack, "MF Classic CUID Dictionary"); | ||
} while(false); | ||
} | ||
if(state == DictAttackStateUserDictInProgress) { | ||
do { | ||
instance->nfc_dict_context.enhanced_dict = true; | ||
|
||
if(keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_SYSTEM_NESTED_PATH)) { | ||
storage_common_remove( | ||
instance->storage, NFC_APP_MF_CLASSIC_DICT_SYSTEM_NESTED_PATH); | ||
} | ||
if(keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH)) { | ||
storage_common_copy( | ||
instance->storage, | ||
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, | ||
NFC_APP_MF_CLASSIC_DICT_SYSTEM_NESTED_PATH); | ||
} | ||
|
||
if(!keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) { | ||
state = DictAttackStateSystemDictInProgress; | ||
break; | ||
} | ||
|
||
if(keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_NESTED_PATH)) { | ||
storage_common_remove(instance->storage, NFC_APP_MF_CLASSIC_DICT_USER_NESTED_PATH); | ||
} | ||
storage_common_copy( | ||
instance->storage, | ||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, | ||
NFC_APP_MF_CLASSIC_DICT_USER_NESTED_PATH); | ||
|
||
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) { | ||
|
@@ -164,7 +232,7 @@ void nfc_scene_mf_classic_dict_attack_on_enter(void* context) { | |
NfcApp* instance = context; | ||
|
||
scene_manager_set_scene_state( | ||
instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateUserDictInProgress); | ||
instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateCUIDDictInProgress); | ||
nfc_scene_mf_classic_dict_attack_prepare_view(instance); | ||
dict_attack_set_card_state(instance->dict_attack, true); | ||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewDictAttack); | ||
|
@@ -193,7 +261,21 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent | |
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicDictAttack); | ||
if(event.type == SceneManagerEventTypeCustom) { | ||
if(event.event == NfcCustomEventDictAttackComplete) { | ||
if(state == DictAttackStateUserDictInProgress) { | ||
bool ran_nested_dict = instance->nfc_dict_context.nested_phase != | ||
MfClassicNestedPhaseNone; | ||
if(state == DictAttackStateCUIDDictInProgress) { | ||
nfc_poller_stop(instance->poller); | ||
nfc_poller_free(instance->poller); | ||
keys_dict_free(instance->nfc_dict_context.dict); | ||
scene_manager_set_scene_state( | ||
instance->scene_manager, | ||
NfcSceneMfClassicDictAttack, | ||
DictAttackStateUserDictInProgress); | ||
nfc_scene_mf_classic_dict_attack_prepare_view(instance); | ||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic); | ||
nfc_poller_start(instance->poller, nfc_dict_attack_worker_callback, instance); | ||
consumed = true; | ||
} else if(state == DictAttackStateUserDictInProgress && !(ran_nested_dict)) { | ||
nfc_poller_stop(instance->poller); | ||
nfc_poller_free(instance->poller); | ||
keys_dict_free(instance->nfc_dict_context.dict); | ||
|
@@ -222,7 +304,27 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent | |
} else if(event.event == NfcCustomEventDictAttackSkip) { | ||
const MfClassicData* mfc_data = nfc_poller_get_data(instance->poller); | ||
nfc_device_set_data(instance->nfc_device, NfcProtocolMfClassic, mfc_data); | ||
if(state == DictAttackStateUserDictInProgress) { | ||
bool ran_nested_dict = instance->nfc_dict_context.nested_phase != | ||
skotopes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
MfClassicNestedPhaseNone; | ||
if(state == DictAttackStateCUIDDictInProgress) { | ||
if(instance->nfc_dict_context.is_card_present) { | ||
nfc_poller_stop(instance->poller); | ||
nfc_poller_free(instance->poller); | ||
keys_dict_free(instance->nfc_dict_context.dict); | ||
scene_manager_set_scene_state( | ||
instance->scene_manager, | ||
NfcSceneMfClassicDictAttack, | ||
DictAttackStateUserDictInProgress); | ||
nfc_scene_mf_classic_dict_attack_prepare_view(instance); | ||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic); | ||
nfc_poller_start(instance->poller, nfc_dict_attack_worker_callback, instance); | ||
} else { | ||
nfc_scene_mf_classic_dict_attack_notify_read(instance); | ||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess); | ||
dolphin_deed(DolphinDeedNfcReadSuccess); | ||
} | ||
consumed = true; | ||
} else if(state == DictAttackStateUserDictInProgress && !(ran_nested_dict)) { | ||
if(instance->nfc_dict_context.is_card_present) { | ||
nfc_poller_stop(instance->poller); | ||
nfc_poller_free(instance->poller); | ||
|
@@ -240,7 +342,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent | |
dolphin_deed(DolphinDeedNfcReadSuccess); | ||
} | ||
consumed = true; | ||
} else if(state == DictAttackStateSystemDictInProgress) { | ||
} else { | ||
nfc_scene_mf_classic_dict_attack_notify_read(instance); | ||
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess); | ||
dolphin_deed(DolphinDeedNfcReadSuccess); | ||
|
@@ -262,7 +364,7 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { | |
|
||
dict_attack_reset(instance->dict_attack); | ||
scene_manager_set_scene_state( | ||
instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateUserDictInProgress); | ||
instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateCUIDDictInProgress); | ||
|
||
keys_dict_free(instance->nfc_dict_context.dict); | ||
|
||
|
@@ -275,6 +377,20 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { | |
instance->nfc_dict_context.is_key_attack = false; | ||
instance->nfc_dict_context.key_attack_current_sector = 0; | ||
instance->nfc_dict_context.is_card_present = false; | ||
instance->nfc_dict_context.nested_phase = MfClassicNestedPhaseNone; | ||
instance->nfc_dict_context.prng_type = MfClassicPrngTypeUnknown; | ||
instance->nfc_dict_context.backdoor = MfClassicBackdoorUnknown; | ||
instance->nfc_dict_context.nested_target_key = 0; | ||
instance->nfc_dict_context.msb_count = 0; | ||
instance->nfc_dict_context.enhanced_dict = false; | ||
|
||
// Clean up temporary files used for nested dictionary attack | ||
if(keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_NESTED_PATH)) { | ||
storage_common_remove(instance->storage, NFC_APP_MF_CLASSIC_DICT_USER_NESTED_PATH); | ||
} | ||
if(keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_SYSTEM_NESTED_PATH)) { | ||
storage_common_remove(instance->storage, NFC_APP_MF_CLASSIC_DICT_SYSTEM_NESTED_PATH); | ||
} | ||
|
||
nfc_blink_stop(instance); | ||
notification_message(instance->notifications, &sequence_display_backlight_enforce_auto); | ||
|
Uh oh!
There was an error while loading. Please reload this page.