Electra intercom

Also today I found out you cant write a blank key from Electra using the Flipper, they use a device sold by Electra. Also the RFID tag has 3 codes, one code that is the basic code, one installer code ( this is written on the box of the Electra cloning equipment when bought), and one private code which must be a security measure taken by Electra to stop cloning. So I saved the FF:FF:FF:FF:FF code to the flipper and visited the nearest key shop and told them to copy the Flipper code to the tag ( they also told me that they cant make a custom code like the one I’ve found and a key needs to be copied, also the code was displayed as a string of numbers like “2365916492” or something like this) so I gave them my Flipper which they scanned ( a prompt popped saying that it was a Chinese copy of the tag) and then they transferred this to the tag which when read with the Flipper displays FF:FF:FF:FF:FD instead of the code provided. (I’ve tried this twice). I know dev’s are busy but maybe someone from the dev team might shed some light on this matter. Also all help is welcome so don’t hold back. :grin:
Also this is the installation tutorial of the intercom and some photos from my flipper :


3 Likes

up up up :slight_smile: we needs to find a way

2 Likes

Bumping the thread, same issue :frowning:

2 Likes

Same here!

1 Like

Same issue ! Need to find the solution :frowning:

I guess it would help to have RAW read dumps from both the original card that works
and a cloned card (the blank ones written to by flipper) which is not detected by the reader

then dev team might be able to figure out how both tags are differing

Hi! at your recommendation, I upload the raw files. As the name suggests, in “original_electra.zip” are the raw files resulting from reading an original electra tag. In the “electra_clone.zip” you can find the raw files read from a tag with the T5577 chip on which the original electra tag was cloned. I hope it is helpful.
Electra_original.zip (12.3 KB)
Electra_clone.zip (12.0 KB)

Not only Romania, Moldova also depends on this solution =) Same problem for us!

Maybe worth taking a look to:

It’s for a different hw but at least the change log mentions: “Added support to demodulate Electra tags and column parity check for EM410x”. Seems to be useful information related to how Electra tags work.

2 Likes

I’ve successfully managed to emulate and Electra tag by re-playing the raw capture.

  1. Record raw data
    125 kHz RFID->Extra Actions->Read RAW RFID data

  2. Re-play raw data from rfid command line interface
    //you can run it from an Android phone through “Serial USB Terminal” app for example → https://play.google.com/store/apps/details?id=de.kai_morich.serial_usb_terminal&hl=en&gl=US
    //replace the default name of the raw capture file with your own

: rfid raw_emulate /ext/lfrfid/RfidRecord.ask.raw

Fixes:
a. short time workaround would be to add the “raw_emulate” option to the rfid UI
b. long time implementation would be to add an Electra EM4100 protocol option. They are probably messing up with one of the parity bits (see the EM4100 standard at EM4100 protocol description).

Hrm! My attempts with raw_emulate showed that while there is some modulation received by reader, it doesn’t decode into original tag. It is also officially unsupported. Either it got better since then, or I was doing something wrong.

Find bellow a patch that adds “Add Emulate RAW RFID data” to UI “125 kHz RFID->Extra Actions” and instructions on how to build and update your firmware.
Note: raw filename is hardcoded to default “RfidRecord.ask.raw”. Please let me know if it works for you and I can make filename user provided input.

#1. copy sources locally
$ git clone GitHub - flipperdevices/flipperzero-firmware: Flipper Zero firmware source code
$ cd flipperzero-firmware/
#2. apply changes from the patch
$ git apply 0001-Add-Emulate-RAW-RFID-data-to-125-kHz-RFID-Extra-Acti.patch
#3. build the updated sources
$ ./fbt
#4. connect usb cable to flipperzero and update using built firmware
$ ./fbt flash_usb

0001-Add-Emulate-RAW-RFID-data-to-125-kHz-RFID-Extra-Acti.patch

From 3ed4dc5ed0e0d9d6338c1a89ce6adb4c9c71e230 Mon Sep 17 00:00:00 2001
From: Dan Caprita <[email protected]>
Date: Mon, 17 Apr 2023 23:15:36 +0300
Subject: [PATCH] Add Emulate RAW RFID data to "125 kHz RFID->Extra Actions"

NOTES:
* works also with Electra raw dumps
  (use "125 kHz RFID->Extra Actions->Read RAW RFID data")
* need to activate Debug from "Settings->System" for RAW options

TODO: don't hardcode raw file name to default RfidRecord.ask.raw,
      allow user input

Signed-off-by: Dan Caprita <[email protected]>
---
 .../main/lfrfid/scenes/lfrfid_scene_config.h  |  1 +
 .../scenes/lfrfid_scene_extra_actions.c       | 13 +++
 .../lfrfid/scenes/lfrfid_scene_raw_emulate.c  | 85 +++++++++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c

diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_config.h b/applications/main/lfrfid/scenes/lfrfid_scene_config.h
index b77ade82..dede2a83 100644
--- a/applications/main/lfrfid/scenes/lfrfid_scene_config.h
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_config.h
@@ -22,3 +22,4 @@ ADD_SCENE(lfrfid, raw_name, RawName)
 ADD_SCENE(lfrfid, raw_read, RawRead)
 ADD_SCENE(lfrfid, raw_success, RawSuccess)
 ADD_SCENE(lfrfid, rpc, Rpc)
+ADD_SCENE(lfrfid, raw_emulate, RawEmulate)
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
index fac2ebce..1bec9c89 100644
--- a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
@@ -5,6 +5,7 @@ typedef enum {
     SubmenuIndexASK,
     SubmenuIndexPSK,
     SubmenuIndexRAW,
+    SubmenuIndexRAWEMULATE,
 } SubmenuIndex;
 
 static void lfrfid_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
@@ -39,6 +40,15 @@ void lfrfid_scene_extra_actions_on_enter(void* context) {
             app);
     }
 
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        submenu_add_item(
+            submenu,
+            "Emulate RAW RFID data",
+            SubmenuIndexRAWEMULATE,
+            lfrfid_scene_extra_actions_submenu_callback,
+            app);
+    }
+
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions));
 
@@ -68,6 +78,9 @@ bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event)
         } else if(event.event == SubmenuIndexRAW) {
             scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);
             consumed = true;
+        } else if(event.event == SubmenuIndexRAWEMULATE) {
+            scene_manager_next_scene(app->scene_manager, LfRfidSceneRawEmulate);
+            consumed = true;
         }
         scene_manager_set_scene_state(app->scene_manager, LfRfidSceneExtraActions, event.event);
     }
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
new file mode 100644
index 00000000..b3fef0c7
--- /dev/null
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
@@ -0,0 +1,85 @@
+#include "../lfrfid_i.h"
+
+typedef struct {
+    FuriString* string_file_name;
+    bool error;
+} LfRfidEmulateRawState;
+
+static void lfrfid_raw_emulate_callback(LFRFIDWorkerEmulateRawResult result, void* context) {
+    LfRfid* app = context;
+
+    if(result == LFRFIDWorkerEmulateRawFileError) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadError);
+    } else if(result == LFRFIDWorkerEmulateRawOverrun) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadOverrun);
+    }
+}
+
+void lfrfid_scene_raw_emulate_on_enter(void* context) {
+    LfRfid* app = context;
+    Popup* popup = app->popup;
+
+    LfRfidEmulateRawState* state = malloc(sizeof(LfRfidEmulateRawState));
+    scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawEmulate, (uint32_t)state);
+    state->string_file_name = furi_string_alloc();
+
+    popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
+    view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+    lfrfid_worker_start_thread(app->lfworker);
+    lfrfid_make_app_folder(app);
+
+    //TODO: don't hardcode it, allow user to input it
+    furi_string_set(app->raw_file_name,"RfidRecord");
+    furi_string_printf(
+        state->string_file_name,
+        "%s/%s%s",
+        LFRFID_SD_FOLDER,
+        furi_string_get_cstr(app->raw_file_name),
+        LFRFID_APP_RAW_ASK_EXTENSION);
+    popup_set_header(popup, "Emulating\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
+    lfrfid_worker_emulate_raw_start(
+        app->lfworker,
+        furi_string_get_cstr(state->string_file_name),
+        lfrfid_raw_emulate_callback,
+        app);
+
+    notification_message(app->notifications, &sequence_blink_start_cyan);
+
+    state->error = false;
+}
+
+bool lfrfid_scene_raw_emulate_on_event(void* context, SceneManagerEvent event) {
+    LfRfid* app = context;
+    Popup* popup = app->popup;
+    LfRfidEmulateRawState* state =
+        (LfRfidEmulateRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawEmulate);
+    bool consumed = false;
+
+    furi_assert(state);
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == LfRfidEventReadError) {
+            consumed = true;
+            state->error = true;
+            popup_set_header(
+                popup, "Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop);
+            notification_message(app->notifications, &sequence_blink_start_red);
+        }
+    }
+
+    return consumed;
+}
+
+void lfrfid_scene_raw_emulate_on_exit(void* context) {
+    LfRfid* app = context;
+    LfRfidEmulateRawState* state =
+        (LfRfidEmulateRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawEmulate);
+
+    notification_message(app->notifications, &sequence_blink_stop);
+    popup_reset(app->popup);
+    lfrfid_worker_stop(app->lfworker);
+    lfrfid_worker_stop_thread(app->lfworker);
+
+    furi_string_free(state->string_file_name);
+    free(state);
+}
-- 
2.34.1
2 Likes

There shouldn’t be any decoding-encoding involved, it’s just replaying what was dumped (raw data). It was just a PoC (proof of concept) to see if there are any hardware limitations of the flipperzero.
See also the 0001-Add-Emulate-RAW-RFID-data-to-125-kHz-RFID-Extra-Acti.patch for the RFID UI app, so that you don’t need an additional device (phone, laptop) to trigger the raw emulation from CLI.

To check your raw dump, you can run from CLI: rfid raw_analyze /ext/lfrfid/RfidRecord.ask.raw

I do have a Proxmark3 easy but didn’t manage to clone the Electra EM410x tag… I also tried it to clone it on a t55xx chip + password for write protection…but didn’t help … the cloned fobs don’t work…

I meant decoding on reader side. It gets something, but not the key data. I’ll recheck now, thanks for reporting your success.

Updated the patch to allow user selection of the tag dump from the available *.ask.raw files.

Note: I’ve tried 2 different keys and 9/10 dumps worked ok. Interesting that some of the dumps, event if not correctly recognized as valid EM4100 (using CLI rfid raw_analyze), were replayed ok and recognized by the Electra reader.

From 7748f70e2ae02185af752714139e80b3a6771bef Mon Sep 17 00:00:00 2001
From: Dan Caprita <[email protected]>
Date: Tue, 18 Apr 2023 23:32:41 +0300
Subject: [PATCH] Add Emulate RAW RFID data to "125 kHz RFID->Extra Actions"

NOTES:
* works also with Electra raw dumps
  (use "125 kHz RFID->Extra Actions->Read RAW RFID data")
* need to activate Debug from "Settings->System" for RAW options

Signed-off-by: Dan Caprita <[email protected]>
---
 applications/main/lfrfid/lfrfid.c             | 20 +++++
 applications/main/lfrfid/lfrfid_i.h           |  2 +
 .../main/lfrfid/scenes/lfrfid_scene_config.h  |  2 +
 .../scenes/lfrfid_scene_extra_actions.c       | 13 +++
 .../lfrfid/scenes/lfrfid_scene_raw_emulate.c  | 86 +++++++++++++++++++
 .../scenes/lfrfid_scene_select_raw_key.c      | 23 +++++
 6 files changed, 146 insertions(+)
 create mode 100644 applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
 create mode 100644 applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c

diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c
index 85a00eea..f78393d6 100644
--- a/applications/main/lfrfid/lfrfid.c
+++ b/applications/main/lfrfid/lfrfid.c
@@ -243,6 +243,26 @@ bool lfrfid_load_key_from_file_select(LfRfid* app) {
     return result;
 }
 
+bool lfrfid_load_raw_key_from_file_select(LfRfid* app) {
+    furi_assert(app);
+
+    DialogsFileBrowserOptions browser_options;
+    dialog_file_browser_set_basic_options(&browser_options, LFRFID_APP_RAW_ASK_EXTENSION, &I_125_10px);
+    browser_options.base_path = LFRFID_APP_FOLDER;
+
+    // Input events and views are managed by file_browser
+    bool result =
+        dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options);
+
+    if(result) {
+        // Extract .raw and then .ask
+        path_extract_filename(app->file_path, app->file_name, true);
+        path_extract_filename(app->file_name, app->file_name, true);
+    }
+
+    return result;
+}
+
 bool lfrfid_delete_key(LfRfid* app) {
     furi_assert(app);
 
diff --git a/applications/main/lfrfid/lfrfid_i.h b/applications/main/lfrfid/lfrfid_i.h
index 72b06193..86929a14 100644
--- a/applications/main/lfrfid/lfrfid_i.h
+++ b/applications/main/lfrfid/lfrfid_i.h
@@ -125,6 +125,8 @@ bool lfrfid_save_key(LfRfid* app);
 
 bool lfrfid_load_key_from_file_select(LfRfid* app);
 
+bool lfrfid_load_raw_key_from_file_select(LfRfid* app);
+
 bool lfrfid_delete_key(LfRfid* app);
 
 bool lfrfid_load_key_data(LfRfid* app, FuriString* path, bool show_dialog);
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_config.h b/applications/main/lfrfid/scenes/lfrfid_scene_config.h
index b77ade82..4ca78d7e 100644
--- a/applications/main/lfrfid/scenes/lfrfid_scene_config.h
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_config.h
@@ -22,3 +22,5 @@ ADD_SCENE(lfrfid, raw_name, RawName)
 ADD_SCENE(lfrfid, raw_read, RawRead)
 ADD_SCENE(lfrfid, raw_success, RawSuccess)
 ADD_SCENE(lfrfid, rpc, Rpc)
+ADD_SCENE(lfrfid, raw_emulate, RawEmulate)
+ADD_SCENE(lfrfid, select_raw_key, SelectRawKey)
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
index fac2ebce..2af12466 100644
--- a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
@@ -5,6 +5,7 @@ typedef enum {
     SubmenuIndexASK,
     SubmenuIndexPSK,
     SubmenuIndexRAW,
+    SubmenuIndexRAWEMULATE,
 } SubmenuIndex;
 
 static void lfrfid_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
@@ -39,6 +40,15 @@ void lfrfid_scene_extra_actions_on_enter(void* context) {
             app);
     }
 
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        submenu_add_item(
+            submenu,
+            "Emulate RAW RFID data",
+            SubmenuIndexRAWEMULATE,
+            lfrfid_scene_extra_actions_submenu_callback,
+            app);
+    }
+
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions));
 
@@ -68,6 +78,9 @@ bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event)
         } else if(event.event == SubmenuIndexRAW) {
             scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);
             consumed = true;
+        } else if(event.event == SubmenuIndexRAWEMULATE) {
+            scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectRawKey);
+            consumed = true;
         }
         scene_manager_set_scene_state(app->scene_manager, LfRfidSceneExtraActions, event.event);
     }
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
new file mode 100644
index 00000000..a9c441a1
--- /dev/null
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_emulate.c
@@ -0,0 +1,86 @@
+#include "../lfrfid_i.h"
+
+#define TAG "ADC"
+
+typedef struct {
+    FuriString* string_file_name;
+    bool error;
+} LfRfidEmulateRawState;
+
+static void lfrfid_raw_emulate_callback(LFRFIDWorkerEmulateRawResult result, void* context) {
+    LfRfid* app = context;
+
+    if(result == LFRFIDWorkerEmulateRawFileError) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadError);
+    } else if(result == LFRFIDWorkerEmulateRawOverrun) {
+        view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadOverrun);
+    }
+}
+
+void lfrfid_scene_raw_emulate_on_enter(void* context) {
+    LfRfid* app = context;
+    Popup* popup = app->popup;
+
+    LfRfidEmulateRawState* state = malloc(sizeof(LfRfidEmulateRawState));
+    scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawEmulate, (uint32_t)state);
+    state->string_file_name = furi_string_alloc();
+
+    popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
+    view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+    lfrfid_worker_start_thread(app->lfworker);
+    lfrfid_make_app_folder(app);
+
+    furi_string_printf(
+        state->string_file_name,
+        "%s/%s%s",
+        LFRFID_SD_FOLDER,
+        furi_string_get_cstr(app->file_name),
+        LFRFID_APP_RAW_ASK_EXTENSION);
+    FURI_LOG_D(TAG, "raw_emulate->file_name=%s", furi_string_get_cstr(state->string_file_name));
+    popup_set_header(popup, "Emulating\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
+    lfrfid_worker_emulate_raw_start(
+        app->lfworker,
+        furi_string_get_cstr(state->string_file_name),
+        lfrfid_raw_emulate_callback,
+        app);
+
+    notification_message(app->notifications, &sequence_blink_start_cyan);
+
+    state->error = false;
+}
+
+bool lfrfid_scene_raw_emulate_on_event(void* context, SceneManagerEvent event) {
+    LfRfid* app = context;
+    Popup* popup = app->popup;
+    LfRfidEmulateRawState* state =
+        (LfRfidEmulateRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawEmulate);
+    bool consumed = false;
+
+    furi_assert(state);
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == LfRfidEventReadError) {
+            consumed = true;
+            state->error = true;
+            popup_set_header(
+                popup, "Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop);
+            notification_message(app->notifications, &sequence_blink_start_red);
+        }
+    }
+
+    return consumed;
+}
+
+void lfrfid_scene_raw_emulate_on_exit(void* context) {
+    LfRfid* app = context;
+    LfRfidEmulateRawState* state =
+        (LfRfidEmulateRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawEmulate);
+
+    notification_message(app->notifications, &sequence_blink_stop);
+    popup_reset(app->popup);
+    lfrfid_worker_stop(app->lfworker);
+    lfrfid_worker_stop_thread(app->lfworker);
+
+    furi_string_free(state->string_file_name);
+    free(state);
+}
diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c b/applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c
new file mode 100644
index 00000000..f12d280a
--- /dev/null
+++ b/applications/main/lfrfid/scenes/lfrfid_scene_select_raw_key.c
@@ -0,0 +1,23 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_select_raw_key_on_enter(void* context) {
+    LfRfid* app = context;
+
+    if(lfrfid_load_raw_key_from_file_select(app)) {
+        scene_manager_next_scene(app->scene_manager, LfRfidSceneRawEmulate);
+
+    } else {
+        scene_manager_previous_scene(app->scene_manager);
+    }
+}
+
+bool lfrfid_scene_select_raw_key_on_event(void* context, SceneManagerEvent event) {
+    UNUSED(context);
+    UNUSED(event);
+    bool consumed = false;
+    return consumed;
+}
+
+void lfrfid_scene_select_raw_key_on_exit(void* context) {
+    UNUSED(context);
+}
-- 
2.34.1
1 Like
  1. Is the reading using Proxmark3 (having the Electra commit mentioned above) the same as flipper zero?
  2. Can you dump the whole 64bits (including the 9 ones from the header, row and column parity bits and stop bit 0), not just the 40bits data payload

How exactly is it possible to dump the header with the Proxmark?

EM4100 protocol description

So on my proxmark i can detect 7 blocks. Where should the 9 header pairity bits be dumped? Or am I doing this corectly?

I don’t know Proxmark but I guess it has some debug options.

For flipperzero, you can for example update the display info showed in 125 kHz RFID->Saved->“your_key”->Info

lib/lfrfid/protocols/protocol_em4100.c
@@ -274,6 +280,8 @@ void protocol_em4100_render_data(ProtocolEM4100* protocol, FuriString* result) {
     uint8_t* data = protocol->data;
     furi_string_printf(
         result, "FC: %03u, Card: %05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
+    furi_string_printf(
+        result, "ed: %llX", protocol->encoded_data);
 };

I have tried to raw emulate an Electra tag, but the reader is not responding… How did you manage to emulate that?
Thanks!