فهرست منبع

Add files via upload

Charles The Great 8 ماه پیش
والد
کامیت
1f21b74da0
3فایلهای تغییر یافته به همراه275 افزوده شده و 0 حذف شده
  1. 13 0
      application.fam
  2. BIN
      assets/app.png
  3. 262 0
      combo_cracker.c

+ 13 - 0
application.fam

@@ -0,0 +1,13 @@
+App(
+    appid="combo_cracker",
+    name="Combo Cracker",
+    apptype=FlipperAppType.EXTERNAL,
+    entry_point="combo_cracker_app",
+    stack_size=4 * 1024,
+    requires=["gui", "input"],
+    order=10,
+    fap_icon="assets/app.png",
+    fap_category="Tools",
+    fap_icon_assets="assets",
+    fap_description="Crack Combo Locks by feeling the gates and resistance, then calculating the value to pop.",
+)

BIN
assets/app.png


+ 262 - 0
combo_cracker.c

@@ -0,0 +1,262 @@
+#include <furi.h>
+#include <gui/gui.h>
+#include <input/input.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define SCREEN_HEIGHT 64
+#define MAX_VALUES    10
+
+typedef enum {
+    SCREEN_COMBO_ENTRY,
+    SCREEN_RESULTS,
+    SCREEN_ABOUT
+} ScreenState;
+
+typedef struct {
+    int first_lock;
+    int second_lock;
+    float resistance;
+    bool exit;
+    int selected;
+    char result[256];
+    ViewPort* view_port;
+    Gui* gui;
+    ScreenState screen_state;
+} ComboCrackerState;
+
+char* float_to_char(float num) {
+    static char buffer[8];
+    snprintf(buffer, sizeof(buffer), "%.1f", (double)num);
+    return buffer;
+}
+
+// calculate the value for the combo lock
+// Samy is my hero ;) -> https://www.youtube.com/watch?v=qkolWO6pAL8
+void calculate_combo(ComboCrackerState* app) {
+    float sticky_number = app->resistance;
+    int sticky_as_int = (int)sticky_number;
+
+    int first_digit;
+    if((sticky_number - sticky_as_int) == 0.0f) {
+        // first digit easy, resistance + 5... crazy world we live in
+        first_digit = sticky_as_int + 5;
+    } else {
+        first_digit = (int)(sticky_number + 5) + 1; // ceiling that biih... prob. a better way
+    }
+
+    first_digit = first_digit % 40;
+    int remainder = first_digit % 4;
+
+    int a = app->first_lock;
+    int b = app->second_lock;
+
+    // third digit isn't too bad
+    int third_position_values[MAX_VALUES];
+    int third_count = 0;
+
+    for(int i = 0; i < 3; i++) {
+        if(a % 4 == remainder) third_position_values[third_count++] = a;
+        if(b % 4 == remainder) third_position_values[third_count++] = b;
+        a = (a + 10) % 40;
+        b = (b + 10) % 40;
+    }
+
+    int row_1 = (remainder + 2) % 40;
+    int row_2 = (row_1 + 4) % 40;
+
+    int second_position_values[MAX_VALUES];
+    int second_count = 0;
+    second_position_values[second_count++] = row_1;
+    second_position_values[second_count++] = row_2;
+
+    for(int i = 0; i < 4; i++) {
+        row_1 = (row_1 + 8) % 40;
+        row_2 = (row_2 + 8) % 40;
+        second_position_values[second_count++] = row_1;
+        second_position_values[second_count++] = row_2;
+    }
+
+    // sort that biih
+    for(int i = 0; i < second_count - 1; i++) {
+        for(int j = i + 1; j < second_count; j++) {
+            if(second_position_values[i] > second_position_values[j]) {
+                int temp = second_position_values[i];
+                second_position_values[i] = second_position_values[j];
+                second_position_values[j] = temp;
+            }
+        }
+    }
+
+    // result to push to result_callback
+    snprintf(app->result, sizeof(app->result), "First Pin: %d\nSecond Pin(s): ", first_digit);
+    for(int i = 0; i < second_count; i++) {
+        char buf[6];
+        snprintf(buf, sizeof(buf), "%d", second_position_values[i]);
+        strcat(app->result, buf);
+        if(i < second_count - 1) strcat(app->result, ", ");
+        if(i == 3) strcat(app->result, "\n -> ");
+    }
+
+    strcat(app->result, "\nThird Pin(s): ");
+    for(int i = 0; i < third_count; i++) {
+        char buf[5];
+        snprintf(buf, sizeof(buf), "%d", third_position_values[i]);
+        strcat(app->result, buf);
+        if(i < third_count - 1) strcat(app->result, ", "); // may be more than one sometimes
+        // deduce to 8 attempts by popping -> (third_digit +/- 2)
+    }
+}
+
+// main screen to push the first, second, and resistance positions
+void draw_callback(Canvas* canvas, void* ctx) {
+    ComboCrackerState* app = ctx;
+
+    canvas_clear(canvas);
+    canvas_set_font(canvas, FontPrimary);
+
+    char buf[16];
+
+    canvas_draw_str(canvas, 2, 12, "First Lock:");
+    snprintf(buf, sizeof(buf), "%s%d", app->selected == 0 ? ">" : " ", app->first_lock);
+    canvas_draw_str(canvas, 100, 12, buf);
+
+    canvas_draw_str(canvas, 2, 24, "Second Lock:");
+    snprintf(buf, sizeof(buf), "%s%d", app->selected == 1 ? ">" : " ", app->second_lock);
+    canvas_draw_str(canvas, 100, 24, buf);
+
+    canvas_draw_str(canvas, 2, 36, "Resistance:");
+    snprintf(
+        buf, sizeof(buf), "%s%s", app->selected == 2 ? ">" : " ", float_to_char(app->resistance));
+    canvas_draw_str(canvas, 100, 36, buf);
+
+    snprintf(
+        buf, sizeof(buf), "%sAbout", app->selected == 3 ? ">" : " "); // ugly but we rollin wit it
+    canvas_draw_str(canvas, 2, 48, buf);
+
+    canvas_draw_str(canvas, 2, 62, "OK to calculate"); // is there an OK icon??
+}
+
+// push the calc to screen
+void result_draw_callback(Canvas* canvas, void* ctx) {
+    ComboCrackerState* app = ctx;
+    canvas_clear(canvas);
+    canvas_set_font(canvas, FontSecondary);
+
+    int y = 12;
+    char result_copy[256];
+    strncpy(result_copy, app->result, sizeof(result_copy));
+    char* line = strtok(result_copy, "\n");
+
+    while(line && y < SCREEN_HEIGHT - 10) {
+        canvas_draw_str(canvas, 2, y, line);
+        y += 10;
+        line = strtok(NULL, "\n");
+    }
+
+    canvas_draw_str(canvas, 2, SCREEN_HEIGHT - 2, "Back to edit");
+}
+
+void about_draw_callback(Canvas* canvas, void* ctx) {
+    UNUSED(ctx);
+    canvas_clear(canvas);
+    canvas_set_font(canvas, FontSecondary);
+
+    int y = 12;
+    canvas_draw_str(canvas, 2, y, "Combo Lock Cracker");
+    y += 10;
+    canvas_draw_str(canvas, 2, y, "Based on Samy Kamkar's");
+    y += 10;
+    canvas_draw_str(canvas, 2, y, "Master Lock research.");
+    y += 10;
+    canvas_draw_str(canvas, 2, y, "Crack Combo Locks in 8 tries");
+    y += 10;
+    canvas_draw_str(canvas, 2, y, "https://samy.pl/master/");
+    y += 18;
+    canvas_draw_str(canvas, 2, SCREEN_HEIGHT - 2, "Back to main menu");
+}
+
+void input_callback(InputEvent* event, void* ctx);
+void result_input_callback(InputEvent* event, void* ctx) {
+    ComboCrackerState* app = ctx;
+    if(event->type == InputTypeShort && event->key == InputKeyBack) {
+        app->screen_state = SCREEN_COMBO_ENTRY;
+        view_port_draw_callback_set(app->view_port, draw_callback, app);
+        view_port_input_callback_set(app->view_port, input_callback, app);
+    }
+    view_port_update(app->view_port);
+}
+
+void input_callback(InputEvent* event, void* ctx) {
+    ComboCrackerState* app = ctx;
+    if(event->type == InputTypeShort) {
+        switch(event->key) {
+        case InputKeyUp:
+            app->selected = (app->selected + 3) % 4;
+            break;
+        case InputKeyDown:
+            app->selected = (app->selected + 1) % 4;
+            break;
+        case InputKeyLeft:
+            if(app->selected == 0 && app->first_lock > 0) app->first_lock--;
+            if(app->selected == 1 && app->second_lock > 0) app->second_lock--;
+            if(app->selected == 2 && app->resistance > 0) app->resistance -= 0.5;
+            break;
+        case InputKeyRight: // can't figure out how to accomodate for long presses for fast incrementation??
+            if(app->selected == 0 && app->first_lock < 10) app->first_lock++;
+            if(app->selected == 1 && app->second_lock < 10) app->second_lock++;
+            if(app->selected == 2 && app->resistance < 39.5) app->resistance += 0.5;
+            if(app->selected == 3) { // about description
+                app->screen_state = SCREEN_ABOUT;
+                view_port_draw_callback_set(app->view_port, about_draw_callback, app);
+                view_port_input_callback_set(app->view_port, result_input_callback, app);
+            }
+            break;
+        case InputKeyOk:
+            calculate_combo(app);
+            app->screen_state = SCREEN_RESULTS;
+            view_port_draw_callback_set(app->view_port, result_draw_callback, app);
+            view_port_input_callback_set(app->view_port, result_input_callback, app);
+            break;
+        case InputKeyBack:
+            app->exit = true;
+            break;
+        default:
+            break;
+        }
+    }
+    view_port_update(app->view_port);
+}
+
+int32_t combo_cracker_app(void* p) {
+    UNUSED(p);
+
+    ComboCrackerState* app = malloc(sizeof(ComboCrackerState));
+    app->first_lock = 0;
+    app->second_lock = 0;
+    app->resistance = 0.0f;
+    app->selected = 0;
+    app->exit = false;
+    app->screen_state = SCREEN_COMBO_ENTRY;
+    app->result[0] = '\0';
+
+    app->view_port = view_port_alloc();
+    view_port_draw_callback_set(app->view_port, draw_callback, app);
+    view_port_input_callback_set(app->view_port, input_callback, app);
+
+    app->gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
+
+    while(!app->exit) {
+        furi_delay_ms(50);
+    }
+
+    view_port_enabled_set(app->view_port, false);
+    gui_remove_view_port(app->gui, app->view_port);
+    view_port_free(app->view_port);
+    furi_record_close(RECORD_GUI);
+    free(app);
+
+    return 0;
+}