1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-13 05:06:30 +04:00

bruteforce sfi 2-3 records 1-5

This commit is contained in:
Methodius
2024-02-12 14:34:11 +09:00
parent 809e1b3aff
commit 11cfbd1ec8
8 changed files with 56 additions and 36 deletions

View File

@@ -64,16 +64,6 @@ static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) {
furi_string_free(temp_str);
}
// static void nfc_scene_emulate_on_enter_emv(NfcApp* instance) {
// const Iso14443_4aData* iso14443_4a_data =
// nfc_device_get_data(instance->nfc_device, NfcProtocolIso14443_4a);
// instance->listener =
// nfc_listener_alloc(instance->nfc, NfcProtocolIso14443_4a, iso14443_4a_data);
// nfc_listener_start(
// instance->listener, nfc_scene_emulate_listener_callback_iso14443_4a, instance);
// }
const NfcProtocolSupportBase nfc_protocol_support_emv = {
.features = NfcProtocolFeatureMoreInfo,

View File

@@ -147,9 +147,8 @@ static bool emv_parse(const NfcDevice* device, FuriString* parsed_data) {
parsed = true;
}
if(app.pin_attempts_counter != 0xFF) {
furi_string_cat_printf(
parsed_data, "PIN attempts left: %d\n", app.pin_attempts_counter);
if(app.pin_try_counter != 0xFF) {
furi_string_cat_printf(parsed_data, "PIN attempts left: %d\n", app.pin_try_counter);
parsed = true;
}

View File

@@ -28,7 +28,7 @@ const NfcDeviceBase nfc_device_emv = {
EmvData* emv_alloc() {
EmvData* data = malloc(sizeof(EmvData));
data->iso14443_4a_data = iso14443_4a_alloc();
data->emv_application.pin_attempts_counter = 0xff;
data->emv_application.pin_try_counter = 0xff;
return data;
}
@@ -76,6 +76,9 @@ bool emv_load(EmvData* data, FlipperFormat* ff, uint32_t version) {
EmvApplication* app = &data->emv_application;
flipper_format_read_string(ff, "Cardholder name", temp_str);
strcpy(app->cardholder_name, furi_string_get_cstr(temp_str));
flipper_format_read_string(ff, "Application name", temp_str);
strcpy(app->application_name, furi_string_get_cstr(temp_str));
@@ -107,9 +110,9 @@ bool emv_load(EmvData* data, FlipperFormat* ff, uint32_t version) {
if(!flipper_format_read_hex(ff, "Effective month", &app->effective_month, 1)) break;
if(!flipper_format_read_hex(ff, "Effective day", &app->effective_day, 1)) break;
uint32_t pin_attempts_counter;
if(!flipper_format_read_uint32(ff, "PIN attempts left", &pin_attempts_counter, 1)) break;
app->pin_attempts_counter = pin_attempts_counter;
uint32_t pin_try_counter;
if(!flipper_format_read_uint32(ff, "PIN try counter", &pin_try_counter, 1)) break;
app->pin_try_counter = pin_try_counter;
parsed = true;
} while(false);
@@ -131,6 +134,8 @@ bool emv_save(const EmvData* data, FlipperFormat* ff) {
if(!flipper_format_write_comment_cstr(ff, "EMV specific data:\n")) break;
if(!flipper_format_write_string_cstr(ff, "Cardholder name", app.cardholder_name)) break;
if(!flipper_format_write_string_cstr(ff, "Application name", app.application_name)) break;
if(!flipper_format_write_string_cstr(ff, "Application label", app.application_label))
@@ -160,8 +165,7 @@ bool emv_save(const EmvData* data, FlipperFormat* ff) {
break;
if(!flipper_format_write_hex(ff, "Effective day", (uint8_t*)&app.effective_day, 1)) break;
if(!flipper_format_write_uint32(
ff, "PIN attempts left", (uint32_t*)&app.pin_attempts_counter, 1))
if(!flipper_format_write_uint32(ff, "PIN try counter", (uint32_t*)&app.pin_try_counter, 1))
break;
saved = true;

View File

@@ -16,7 +16,7 @@ extern "C" {
#define EMV_TAG_APPL_LABEL 0x50
#define EMV_TAG_APPL_NAME 0x9F12
#define EMV_TAG_APPL_EFFECTIVE 0x5F25
#define EMV_TAG_PIN_ATTEMPTS_COUNTER 0x9F17
#define EMV_TAG_PIN_TRY_COUNTER 0x9F17
#define EMV_TAG_LOG_ENTRY 0x9F4D
#define EMV_TAG_LOG_FMT 0x9F4F
@@ -36,6 +36,7 @@ extern "C" {
#define EMV_TAG_COUNTRY_CODE 0x5F28
#define EMV_TAG_CURRENCY_CODE 0x9F42
#define EMV_TAG_CARDHOLDER_NAME 0x5F20
#define EMV_TAG_CARDHOLDER_NAME_EXTENDED 0x9F0B
#define EMV_TAG_TRACK_2_DATA 0x9F6B
#define EMV_TAG_GPO_FMT1 0x80
@@ -91,7 +92,7 @@ typedef struct {
uint8_t effective_year;
uint16_t country_code;
uint16_t currency_code;
uint8_t pin_attempts_counter;
uint8_t pin_try_counter;
uint16_t transaction_counter;
uint16_t last_online_atc;
APDU pdol;

View File

@@ -108,7 +108,7 @@ static NfcCommand emv_poller_handler_read_files(EmvPoller* instance) {
static NfcCommand emv_poller_handler_read_extra_data(EmvPoller* instance) {
emv_poller_get_last_online_atc(instance);
emv_poller_get_pin_attempts_counter(instance);
emv_poller_get_pin_try_counter(instance);
instance->state = EmvPollerStateReadSuccess;
return NfcCommandContinue;

View File

@@ -50,7 +50,7 @@ EmvError emv_poller_read_afl(EmvPoller* instance);
EmvError emv_poller_read_log_entry(EmvPoller* instance);
EmvError emv_poller_get_pin_attempts_counter(EmvPoller* instance);
EmvError emv_poller_get_pin_try_counter(EmvPoller* instance);
EmvError emv_poller_get_last_online_atc(EmvPoller* instance);

View File

@@ -193,6 +193,14 @@ static bool
if(strlen(app->cardholder_name) > tlen) break;
memcpy(app->cardholder_name, &buff[i], tlen);
app->cardholder_name[tlen] = '\0';
// use space char as terminator
for(size_t i = 0; i < tlen; i++)
if(app->cardholder_name[i] == 0x20) {
app->cardholder_name[i] = '\0';
break;
}
success = true;
FURI_LOG_T(TAG, "found EMV_TAG_CARDHOLDER_NAME %x: %s", tag, app->cardholder_name);
break;
@@ -262,11 +270,10 @@ static bool
memcpy(&app->trans[app->active_tr].time, &buff[i], tlen);
success = true;
break;
case EMV_TAG_PIN_ATTEMPTS_COUNTER:
app->pin_attempts_counter = buff[i];
case EMV_TAG_PIN_TRY_COUNTER:
app->pin_try_counter = buff[i];
success = true;
FURI_LOG_T(
TAG, "found EMV_TAG_PIN_ATTEMPTS_COUNTER %x: %d", tag, app->pin_attempts_counter);
FURI_LOG_T(TAG, "found EMV_TAG_PIN_TRY_COUNTER %x: %d", tag, app->pin_try_counter);
break;
}
return success;
@@ -615,6 +622,8 @@ EmvError emv_poller_read_afl(EmvPoller* instance) {
FURI_LOG_D(TAG, "Search PAN in SFI");
bool pan_fetched = (instance->data->emv_application.pan_len);
// Iterate through all files
for(size_t i = 0; i < instance->data->emv_application.afl.size; i += 4) {
uint8_t sfi = afl->data[i] >> 3;
@@ -633,15 +642,32 @@ EmvError emv_poller_read_afl(EmvPoller* instance) {
FURI_LOG_T(TAG, "Failed to parse SFI 0x%X record %d", sfi, record);
}
// Some READ RECORD returns 1 byte response 0x12/0x13 (IDK WTF),
// then poller return Timeout to all subsequent requests.
// TODO: remove below lines when it was fixed
if(instance->data->emv_application.pan_len != 0)
return EmvErrorNone; // Card number fetched
if(instance->data->emv_application.pan_len) pan_fetched = true; // Card number fetched
}
}
return error;
// Bruteforse files 2-3
FURI_LOG_T(TAG, "Bruteforce files 2-3");
for(size_t sfi = 2; sfi <= 3; sfi++) {
// Iterate through records 1-5 in file
for(size_t record = 1; record <= 5; record++) {
if(strlen(instance->data->emv_application.cardholder_name)) return EmvErrorNone;
error = emv_poller_read_sfi_record(instance, sfi, record);
if(error != EmvErrorNone) break;
if(!emv_decode_response_tlv(
bit_buffer_get_data(instance->rx_buffer),
bit_buffer_get_size_bytes(instance->rx_buffer),
&instance->data->emv_application)) {
error = EmvErrorProtocol;
FURI_LOG_T(TAG, "Failed to parse SFI 0x%X record %d", sfi, record);
}
}
}
if(pan_fetched)
return EmvErrorNone;
else
return error;
}
static EmvError emv_poller_req_get_data(EmvPoller* instance, uint16_t tag) {
@@ -684,8 +710,8 @@ static EmvError emv_poller_req_get_data(EmvPoller* instance, uint16_t tag) {
return error;
}
EmvError emv_poller_get_pin_attempts_counter(EmvPoller* instance) {
return emv_poller_req_get_data(instance, EMV_TAG_PIN_ATTEMPTS_COUNTER);
EmvError emv_poller_get_pin_try_counter(EmvPoller* instance) {
return emv_poller_req_get_data(instance, EMV_TAG_PIN_TRY_COUNTER);
}
EmvError emv_poller_get_last_online_atc(EmvPoller* instance) {

View File

@@ -890,7 +890,7 @@ Function,+,emv_get_uid,const uint8_t*,"const EmvData*, size_t*"
Function,+,emv_is_equal,_Bool,"const EmvData*, const EmvData*"
Function,+,emv_load,_Bool,"EmvData*, FlipperFormat*, uint32_t"
Function,+,emv_poller_get_last_online_atc,EmvError,EmvPoller*
Function,+,emv_poller_get_pin_attempts_counter,EmvError,EmvPoller*
Function,+,emv_poller_get_pin_try_counter,EmvError,EmvPoller*
Function,+,emv_poller_get_processing_options,EmvError,EmvPoller*
Function,+,emv_poller_read_afl,EmvError,EmvPoller*
Function,+,emv_poller_read_log_entry,EmvError,EmvPoller*
1 entry status name type params
890 Function + emv_is_equal _Bool const EmvData*, const EmvData*
891 Function + emv_load _Bool EmvData*, FlipperFormat*, uint32_t
892 Function + emv_poller_get_last_online_atc EmvError EmvPoller*
893 Function + emv_poller_get_pin_attempts_counter emv_poller_get_pin_try_counter EmvError EmvPoller*
894 Function + emv_poller_get_processing_options EmvError EmvPoller*
895 Function + emv_poller_read_afl EmvError EmvPoller*
896 Function + emv_poller_read_log_entry EmvError EmvPoller*