mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-03 22:23:35 -07:00
Merge branch 'UNLEASHED' into 420
This commit is contained in:
@@ -81,7 +81,7 @@ static bool protocol_awid_can_be_decoded(uint8_t* data) {
|
||||
|
||||
// Avoid detection for invalid formats
|
||||
uint8_t len = bit_lib_get_bits(data, 8, 8);
|
||||
if(len != 26 && len != 50 && len != 37 && len != 34) break;
|
||||
if(len != 26 && len != 50 && len != 37 && len != 34 && len != 36) break;
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
@@ -207,7 +207,7 @@ bool protocol_awid_write_data(ProtocolAwid* protocol, void* data) {
|
||||
|
||||
// Fix incorrect length byte
|
||||
if(protocol->data[0] != 26 && protocol->data[0] != 50 && protocol->data[0] != 37 &&
|
||||
protocol->data[0] != 34) {
|
||||
protocol->data[0] != 34 && protocol->data[0] != 36) {
|
||||
protocol->data[0] = 26;
|
||||
}
|
||||
|
||||
|
||||
+62
-28
@@ -494,6 +494,9 @@ static void nfc_worker_mf_classic_key_attack(
|
||||
uint16_t start_sector) {
|
||||
furi_assert(nfc_worker);
|
||||
|
||||
bool card_found_notified = true;
|
||||
bool card_removed_notified = false;
|
||||
|
||||
MfClassicData* data = &nfc_worker->dev_data->mf_classic_data;
|
||||
uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type);
|
||||
|
||||
@@ -501,36 +504,52 @@ static void nfc_worker_mf_classic_key_attack(
|
||||
|
||||
// Check every sector's A and B keys with the given key
|
||||
for(size_t i = start_sector; i < total_sectors; i++) {
|
||||
uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i);
|
||||
if(mf_classic_is_sector_read(data, i)) continue;
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Trying A key for sector %d, key: %04lx%08lx",
|
||||
i,
|
||||
(uint32_t)(key >> 32),
|
||||
(uint32_t)key);
|
||||
if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) {
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyA, key);
|
||||
FURI_LOG_D(TAG, "Key found");
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
|
||||
furi_hal_nfc_sleep();
|
||||
if(furi_hal_nfc_activate_nfca(200, NULL)) {
|
||||
furi_hal_nfc_sleep();
|
||||
if(!card_found_notified) {
|
||||
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
|
||||
card_found_notified = true;
|
||||
card_removed_notified = false;
|
||||
}
|
||||
uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i);
|
||||
if(mf_classic_is_sector_read(data, i)) continue;
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Trying A key for sector %d, key: %04lx%08lx",
|
||||
i,
|
||||
(uint32_t)(key >> 32),
|
||||
(uint32_t)key);
|
||||
if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) {
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyA, key);
|
||||
FURI_LOG_D(TAG, "Key found");
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
|
||||
}
|
||||
}
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Trying B key for sector %d, key: %04lx%08lx",
|
||||
i,
|
||||
(uint32_t)(key >> 32),
|
||||
(uint32_t)key);
|
||||
if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) {
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyB, key);
|
||||
FURI_LOG_D(TAG, "Key found");
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
|
||||
}
|
||||
}
|
||||
|
||||
if(mf_classic_is_sector_read(data, i)) continue;
|
||||
mf_classic_read_sector(tx_rx, data, i);
|
||||
} else {
|
||||
if(!card_removed_notified) {
|
||||
nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
|
||||
card_removed_notified = true;
|
||||
card_found_notified = false;
|
||||
}
|
||||
}
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Trying B key for sector %d, key: %04lx%08lx",
|
||||
i,
|
||||
(uint32_t)(key >> 32),
|
||||
(uint32_t)key);
|
||||
if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) {
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyB, key);
|
||||
FURI_LOG_D(TAG, "Key found");
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
|
||||
}
|
||||
}
|
||||
if(mf_classic_is_sector_read(data, i)) continue;
|
||||
mf_classic_read_sector(tx_rx, data, i);
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
|
||||
}
|
||||
}
|
||||
@@ -544,6 +563,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
&nfc_worker->dev_data->mf_classic_dict_attack_data;
|
||||
uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type);
|
||||
uint64_t key = 0;
|
||||
uint64_t prev_key = 0;
|
||||
FuriHalNfcTxRxContext tx_rx = {};
|
||||
bool card_found_notified = true;
|
||||
bool card_removed_notified = false;
|
||||
@@ -556,6 +576,18 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear found keys if the key cache is incorrect (key set as found but sector not read)
|
||||
for(uint16_t sector = 0; sector < total_sectors; sector++) {
|
||||
if(mf_classic_is_key_found(data, sector, MfClassicKeyA) &&
|
||||
!mf_classic_is_sector_read(data, sector)) {
|
||||
mf_classic_set_key_not_found(data, sector, MfClassicKeyA);
|
||||
}
|
||||
if(mf_classic_is_key_found(data, sector, MfClassicKeyB) &&
|
||||
!mf_classic_is_sector_read(data, sector)) {
|
||||
mf_classic_set_key_not_found(data, sector, MfClassicKeyB);
|
||||
}
|
||||
}
|
||||
|
||||
FURI_LOG_D(
|
||||
TAG, "Start Dictionary attack, Key Count %ld", mf_classic_dict_get_total_keys(dict));
|
||||
for(size_t i = 0; i < total_sectors; i++) {
|
||||
@@ -578,6 +610,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
|
||||
card_found_notified = true;
|
||||
card_removed_notified = false;
|
||||
nfc_worker_mf_classic_key_attack(nfc_worker, prev_key, &tx_rx, i);
|
||||
}
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
@@ -614,6 +647,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
|
||||
}
|
||||
memcpy(&prev_key, &key, sizeof(key));
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
|
||||
mf_classic_read_sector(&tx_rx, data, i);
|
||||
|
||||
@@ -155,6 +155,16 @@ void mf_classic_set_key_found(
|
||||
}
|
||||
}
|
||||
|
||||
void mf_classic_set_key_not_found(MfClassicData* data, uint8_t sector_num, MfClassicKey key_type) {
|
||||
furi_assert(data);
|
||||
|
||||
if(key_type == MfClassicKeyA) {
|
||||
FURI_BIT_CLEAR(data->key_a_mask, sector_num);
|
||||
} else if(key_type == MfClassicKeyB) {
|
||||
FURI_BIT_CLEAR(data->key_b_mask, sector_num);
|
||||
}
|
||||
}
|
||||
|
||||
bool mf_classic_is_sector_read(MfClassicData* data, uint8_t sector_num) {
|
||||
furi_assert(data);
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ void mf_classic_set_key_found(
|
||||
MfClassicKey key_type,
|
||||
uint64_t key);
|
||||
|
||||
void mf_classic_set_key_not_found(MfClassicData* data, uint8_t sector_num, MfClassicKey key_type);
|
||||
|
||||
bool mf_classic_is_block_read(MfClassicData* data, uint8_t block_num);
|
||||
|
||||
void mf_classic_set_block_read(MfClassicData* data, uint8_t block_num, MfClassicBlock* block_data);
|
||||
|
||||
@@ -28,6 +28,8 @@ struct SubGhzProtocolDecoderKeeloq {
|
||||
uint16_t header_count;
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
|
||||
FuriString* manufacture_from_file;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolEncoderKeeloq {
|
||||
@@ -38,6 +40,8 @@ struct SubGhzProtocolEncoderKeeloq {
|
||||
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
|
||||
FuriString* manufacture_from_file;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -113,12 +117,16 @@ void* subghz_protocol_encoder_keeloq_alloc(SubGhzEnvironment* environment) {
|
||||
instance->encoder.size_upload = 256;
|
||||
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
|
||||
instance->encoder.is_running = false;
|
||||
|
||||
instance->manufacture_from_file = furi_string_alloc();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_keeloq_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolEncoderKeeloq* instance = context;
|
||||
furi_string_free(instance->manufacture_from_file);
|
||||
free(instance->encoder.upload);
|
||||
free(instance);
|
||||
}
|
||||
@@ -143,6 +151,13 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc
|
||||
instance->manufacture_name = "";
|
||||
}
|
||||
|
||||
// Nice Smilo, MHouse, JCM has 8bit serial - simple learning
|
||||
if((strcmp(instance->manufacture_name, "NICE_Smilo") == 0) ||
|
||||
(strcmp(instance->manufacture_name, "NICE_MHOUSE") == 0) ||
|
||||
(strcmp(instance->manufacture_name, "JCM_Tech") == 0)) {
|
||||
decrypt = btn << 28 | (instance->generic.serial & 0xFF) << 16 | instance->generic.cnt;
|
||||
}
|
||||
|
||||
if(strcmp(instance->manufacture_name, "Unknown") == 0) {
|
||||
code_found_reverse = subghz_protocol_blocks_reverse_key(
|
||||
instance->generic.data, instance->generic.data_count_bit);
|
||||
@@ -347,6 +362,16 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "ENCODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
uint8_t seed_data[sizeof(uint32_t)] = {0};
|
||||
for(size_t i = 0; i < sizeof(uint32_t); i++) {
|
||||
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
|
||||
@@ -415,6 +440,7 @@ void* subghz_protocol_decoder_keeloq_alloc(SubGhzEnvironment* environment) {
|
||||
instance->base.protocol = &subghz_protocol_keeloq;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
instance->keystore = subghz_environment_get_keystore(environment);
|
||||
instance->manufacture_from_file = furi_string_alloc();
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -422,6 +448,7 @@ void* subghz_protocol_decoder_keeloq_alloc(SubGhzEnvironment* environment) {
|
||||
void subghz_protocol_decoder_keeloq_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderKeeloq* instance = context;
|
||||
furi_string_free(instance->manufacture_from_file);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
@@ -950,6 +977,16 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "DECODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
uint8_t seed_data[sizeof(uint32_t)] = {0};
|
||||
for(size_t i = 0; i < sizeof(uint32_t); i++) {
|
||||
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
|
||||
|
||||
@@ -28,6 +28,8 @@ struct SubGhzProtocolDecoderStarLine {
|
||||
uint16_t header_count;
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
|
||||
FuriString* manufacture_from_file;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolEncoderStarLine {
|
||||
@@ -38,6 +40,8 @@ struct SubGhzProtocolEncoderStarLine {
|
||||
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
|
||||
FuriString* manufacture_from_file;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -109,16 +113,20 @@ void* subghz_protocol_encoder_star_line_alloc(SubGhzEnvironment* environment) {
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
instance->keystore = subghz_environment_get_keystore(environment);
|
||||
|
||||
instance->manufacture_from_file = furi_string_alloc();
|
||||
|
||||
instance->encoder.repeat = 10;
|
||||
instance->encoder.size_upload = 256;
|
||||
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
|
||||
instance->encoder.is_running = false;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_star_line_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolEncoderStarLine* instance = context;
|
||||
furi_string_free(instance->manufacture_from_file);
|
||||
free(instance->encoder.upload);
|
||||
free(instance);
|
||||
}
|
||||
@@ -274,6 +282,15 @@ bool subghz_protocol_encoder_star_line_deserialize(void* context, FlipperFormat*
|
||||
break;
|
||||
}
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "ENCODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
subghz_protocol_star_line_check_remote_controller(
|
||||
&instance->generic, instance->keystore, &instance->manufacture_name);
|
||||
|
||||
@@ -331,6 +348,9 @@ void* subghz_protocol_decoder_star_line_alloc(SubGhzEnvironment* environment) {
|
||||
SubGhzProtocolDecoderStarLine* instance = malloc(sizeof(SubGhzProtocolDecoderStarLine));
|
||||
instance->base.protocol = &subghz_protocol_star_line;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
|
||||
instance->manufacture_from_file = furi_string_alloc();
|
||||
|
||||
instance->keystore = subghz_environment_get_keystore(environment);
|
||||
|
||||
return instance;
|
||||
@@ -339,6 +359,7 @@ void* subghz_protocol_decoder_star_line_alloc(SubGhzEnvironment* environment) {
|
||||
void subghz_protocol_decoder_star_line_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderStarLine* instance = context;
|
||||
furi_string_free(instance->manufacture_from_file);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
@@ -705,6 +726,16 @@ bool subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat*
|
||||
FURI_LOG_E(TAG, "Deserialize error");
|
||||
break;
|
||||
}
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "DECODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
res = true;
|
||||
} while(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user