diff --git a/chromeos_startup.sh b/chromeos_startup.sh index 823f6f8..091162e 100644 --- a/chromeos_startup.sh +++ b/chromeos_startup.sh @@ -33,11 +33,8 @@ fi # this is because ssh-keygen was introduced somewhere around R80, where many shims are still stuck on R73 # filesystem unfuck can only be done before stateful is mounted, which is perfectly fine in a shim but not if you run it while booted # because mkfs is mean and refuses to let us format - # note that this will lead to confusing behaviour, since it will appear as if it crashed as a result of fakemurk -# startup plugins are also launched here, for low-level control over - # funny boot messages echo "Oh fuck - ChromeOS is trying to kill itself." >/usr/share/chromeos-assets/text/boot_messages/en/block_devmode_virtual.txt echo "ChromeOS detected developer mode and is trying to disable it to" >>/usr/share/chromeos-assets/text/boot_messages/en/block_devmode_virtual.txt diff --git a/cr50-update.conf b/cr50-update.conf index 1105a42..5250a3e 100644 --- a/cr50-update.conf +++ b/cr50-update.conf @@ -1,35 +1,10 @@ -# Copyright 2016 The ChromiumOS Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# This script first determines if it needs to run at all: if the cr50 firmware -# image is not present in the local directory this must be happening on a -# board without a cr50 device, no need to do anything. -# -# If the firmware image is present, the script checks the number of previous -# runs saved in a state file. The file name is bound to the firmware image, if -# the firmware image changes, the name of the state file will also have to -# change. -# -# In most cases one firmware update run will be enough, but sometimes more -# than one step will be required (when updating from an old cr50 version or -# when rotating RW keys). The entire chromebook needs to be restarted between -# cr50 update runs, up to four update runs on a particular firmware image are -# allowed by this script. -# -# The gsctool utility exit status indicates if more runs are required. Exit -# status of 0 means update has succeeded. Other exit statuses are processed by -# the follow up startup script cr50-result.conf. -# +# Gutted so that there's zero chance of the cr50 accidentally getting updated description "Chromium OS startup file for cr50 firmware updater" author "chromium-os-dev@chromium.org" oom score -100 -# Starts on boot-services by exception, since it triggers a long chain of -# dependant tpm-related daemons that need to start early. Normally services -# should start on 'starting system-services'. start on started boot-services script diff --git a/docs/dev_reference.md b/docs/dev_reference.md index 991cf2b..0bba732 100644 --- a/docs/dev_reference.md +++ b/docs/dev_reference.md @@ -13,6 +13,8 @@ At the main menu, you have the option to enter a number corresponding to a menu - `112`: Purge extension processes - Kills all extension processes. - `113`: Prints a list of installed plugins and their individual metadata. - `114` and `115`: Legacy install/uninstall plugin - Readline-based plugin management for easier interface from the helper extension. +- `2**`: Interface for the JS plugin filesystem access API (see `class MurkmodFsAccess`) +- `30*`: Interface for the JS plugin stack API (see `class MurkmodStack`) The murkmod installation script (murkmod.sh, **not** the VT2 installer!) reads an environment variable called `MURKMOD_BRANCH` - it is normally set by option `26`, but it can be set by hand by using the following command: diff --git a/docs/js_plugins.md b/docs/js_plugins.md index 6b547d8..65661b3 100644 --- a/docs/js_plugins.md +++ b/docs/js_plugins.md @@ -75,3 +75,36 @@ Shit, that's a lot! Let's break it down a bit: - `finished`: If this string is present in the output from the terminal, the task is considered completed. 99% of the time this should be `> (1-`, but depending on your use case ift can differ. - `output_handler`: A function that takes a single string as a parameter, being the output from the terminal. Called every time output is received from the running task. - `once_done`: A callback that is executed once the task is completed. + +## Filesystem API + +In order to asynchronously access the filesystem from a JS plugin, you can use `MurkmodFsAccess`: + +```js +var fs = new MurkmodFsAccess(); +``` + +The methods available in `MurkmodFsAccess` are as follows: + +- `cd(string dir)`: Changes to a given directory. +- `ls()` or `ls(string dir)`: Lists contents of a directory as a string, delimited with spaces. +- `rm_dir(string dir)`: Deletes a directory recursively. +- `rm_file(string file)`: Deletes a single file. +- `mkdir(string dir)`: Creates a directory, recursively if neccesary. +- `touch(string file)`: Creates a file or updates its date last modified. +- `append(string file, string|array content)`: Appends a string or binary data to a given file. +- `write(string file, string|array content)`: Overwrites the contents of a file with the given string or binary data. +- `read(string file)`: Reads the contents of a given file. + +All of these functions return a `Promise` which resolves differently according to each function. + +For instance: + +```js +var fs = new MurkmodFsAccess(); +fs.cd("/").then(function(){ + fs.read("startup_log").then(log => { + console.log("Startup log:", log); + }); +}); +``` \ No newline at end of file diff --git a/docs/plugin_communication.md b/docs/plugin_communication.md new file mode 100644 index 0000000..3045664 --- /dev/null +++ b/docs/plugin_communication.md @@ -0,0 +1,49 @@ +# Plugin Communication + +Plugins sometimes need to communicate with each other - and to do so, there is a stack-based communication system that exists that allows developers to easily communicate between both JS and bash plugins. + +### In bash + +First, ensure your plugin sources from `plugin_common.sh`: + +```sh +. /usr/bin/murkmod_plugin_common.sh +``` + +Then, choose a name for your stack (for this guide, I'll go with `test_stack`): + +```sh +starts "test_stack" +``` + +And finally, push a message to the stack that the JS plugin will pick up later: + +```sh +pushs "Hello, world!" +``` + +### In JS + +Create a new `MurkmodStack` object and set it to the same stack name as before: + +```js +var stack = new MurkmodStack("test_stack"); +``` + +In order to log out the message saved to the stack earlier, we can call: + +```js +stack.pop().then(console.log); // Hello, world! +``` + +And we can push another message back: + +```js +stack.push("Hello, bash plugin!"); +``` + +And back in bash, we can read this again. + +```bash +pops # Hello, bash plugin! +``` \ No newline at end of file diff --git a/docs/plugin_dev.md b/docs/plugin_dev.md index 3f6a48f..54e6131 100644 --- a/docs/plugin_dev.md +++ b/docs/plugin_dev.md @@ -12,6 +12,7 @@ PLUGIN_FUNCTION="Print a hello world message" PLUGIN_DESCRIPTION="The friendliest murkmod plugin you'll ever see." PLUGIN_AUTHOR="rainestorme" PLUGIN_VERSION=1 +. /usr/bin/murkmod_plugin_common.sh echo "Hello, World!" ``` diff --git a/helper/html/index.html b/helper/html/index.html index 94909c1..ded954f 100644 --- a/helper/html/index.html +++ b/helper/html/index.html @@ -4,13 +4,13 @@ murkmod helper webui - - + + - +

murkmod helper

@@ -104,6 +104,10 @@

murkmod helper

xterm×

murkmod helper terminal×

- + + + + + diff --git a/helper/js/api/fs.js b/helper/js/api/fs.js new file mode 100644 index 0000000..5a450e6 --- /dev/null +++ b/helper/js/api/fs.js @@ -0,0 +1,159 @@ +class MurkmodFsAccess { + constructor() { + this.working_dir = "/"; + this.mush_id = null; + this.listeners = []; + this.read_buffer = ""; + this.read_start_tripped = false; + var self = this; + tp.openTerminalProcess("crosh", id => { + self.mush_id = id; + window.secondary_classes.push(self); + }); + } + + _generic_singlestep_promise(input, wait_for, response) { + var self = this; + return new Promise((resolve, reject) => { + tp.sendInput(self.mush_id, input); + self.listeners.push(function(decoded){ + if (decoded.includes(wait_for)) { + tp.sendInput(self.mush_id, response); + } else if (decoded.includes("> (1-")) { + const index = self.listeners.indexOf(this); + if (index > -1) { + array.splice(index, 1); + } + resolve(); + } + }); + }); + } + + _generic_doublestep_promise(input, wait_for1, response1, wait_for2, response2) { + var self = this; + return new Promise((resolve, reject) => { + tp.sendInput(self.mush_id, input); + self.listeners.push(function(decoded){ + if (decoded.includes(wait_for1)) { + tp.sendInput(self.mush_id, response1); + } else if (decoded.includes(wait_for2)) { + tp.sendInput(self.mush_id, response1); + } else if (decoded.includes("> (1-")) { + const index = self.listeners.indexOf(this); + if (index > -1) { + array.splice(index, 1); + } + resolve(); + } + }); + }); + } + + handle_output(decoded) { + for (var key in this.listeners) { + this.listeners[key](decoded); + } + } + + cd(new_dir) { + var self = this; + return new Promise((resolve, reject) => { + tp.sendInput(self.mush_id, "209\n"); + self.listeners.push(function(decoded){ + if (decoded.includes("dir?")) { + tp.sendInput(self.mush_id, new_dir + "\n"); + } else if (decoded.includes("> (1-")) { + self.working_dir = new_dir; + const index = self.listeners.indexOf(this); + if (index > -1) { + array.splice(index, 1); + } + resolve(); + } + }); + }); + } + + ls() { + return this._generic_singlestep_promise("208\n", + "dirname? (or . for current dir)", + ".\n"); + } + + ls(dir) { + return this._generic_singlestep_promise("208\n", + "dirname? (or . for current dir)", + dir + "\n"); + } + + rm_dir(dir) { + return this._generic_singlestep_promise("207\n", + "dirname?", + dir + "\n"); + } + + rm_file(file) { + return this._generic_singlestep_promise("206\n", + "filename?", + file + "\n"); + } + + mkdir(dir) { + return this._generic_singlestep_promise("205\n", + "dirname?", + dir + "\n"); + } + + touch(file) { + return this._generic_singlestep_promise("204\n", + "filename?", + file + "\n"); + } + + append(file, content){ + return this._generic_doublestep_promise("203\n", + "file to write to?", + file + "\n", + "base64 contents to append?", + btoa(content)); + } + + write(file, content) { + return this._generic_doublestep_promise("202\n", + "file to write to?", + file + "\n", + "base64 contents?", + btoa(content)); + } + + read(file) { + var self = this; + return new Promise((resolve, reject) => { + tp.sendInput(self.mush_id, input); + self.listeners.push(function(decoded){ + if (self.read_start_tripped) { + self.read_buffer = self.read_buffer + decoded; + } + if (decoded.includes("file to read?")) { + tp.sendInput(self.mush_id, file+"\n"); + } + if (decoded.includes("start content: ")) { + self.read_start_tripped = true; + } + if (self.read_buffer.includes("end content")) { + var startIndex = self.read_buffer.indexOf("start content: ") + "start content: ".length; + var endIndex = self.read_buffer.indexOf("end content"); + var content = atob(self.read_buffer.substring(startIndex, endIndex)); + self.read_buffer = ""; + self.read_start_tripped = false; + const index = self.listeners.indexOf(this); + if (index > -1) { + array.splice(index, 1); + } + resolve(content); + } + }); + }); + } +} \ No newline at end of file diff --git a/helper/js/api/murkmod.js b/helper/js/api/murkmod.js new file mode 100644 index 0000000..c128d9f --- /dev/null +++ b/helper/js/api/murkmod.js @@ -0,0 +1,307 @@ +// this file contains the main murkmod js api + +window.mush_ready = false; + +if (localStorage.getItem("plugins") === null) { + localStorage.setItem("plugins", JSON.stringify([])); +} + +document.addEventListener("DOMContentLoaded", function () { + window.tp = chrome.terminalPrivate; + window.enc = new TextDecoder("utf-8"); + window.once_done = function () { }; + window.finished = ""; + window.use_finished = false; + window.output_handler = function (output) { }; + window.exit_string = ""; + window.crouton_running = false; + window.crouton_id = ""; + window.soft_running = false; + window.soft_id = ""; + window.to_enable = []; + window.to_disable = []; + window.bash_id = ""; + window.send_fans = false; + window.plugins_propagated = false; + window.propagation_stage = 0; + window.legacy_plugins = []; + window.allow_autoclose = true; + window.secondary_classes = []; + window.no_ext_icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADA0lEQVQ4jX2TvW9bZRjFz/O8773+rBPHju2mbklCTQgIAVWiVpGQkEBsRexMHZgYkfgXYOcPgKFMDEhF6kgHUBCqCKiloq2bpAngOG6+ajvXvve+7/MwJK1g4WxHOsvROT/68savy7VGfYUBBQACyMPDGEMBB0jTVD0AA8ADeJYTgHrd3VVba9RXKuViHaKpqjAEMKHVKErccDjQSqVsjGEWETyXQsEUAFhhAArR1Il458XDsD887PvR3uPXq5nh+9sb9xtJ6px6kTR13qfinYiHaApAGQBEhQggJ5oKm9H6+iYvzDfeunzp1SVJxq2/u0dxKhQTs560BJgZAGABT9Za9PtDfdrdfKVYzBXyZhRH4zgaHI/dTnefZrPZpaNOLzv2Zr05u7AvPmFRIcCTBQTWWuzs9mjp4szKy60XZlPnYK2FF9WPr119OwgsRaMYX3/30/W5MOxRKuydI8CAAYCJNU1iG4Y2AwDWWjgnqiLEbFQUGidpurXV4d9/WysNBpEGYagA1Hz40SdX8rlMfhiNRdPRuT/af0WGiaYmi1kRqKiSKsCGMVMrTy/OT19+0H7Uz5WqT7x3MQOAcw61alVv33l496tvV2/+cnejzURETApARZSgQK1anr5wrj5FXs8fPu2zNQwLCMIg1PbDtrn67vI7H7x3RfP5XEEUGAwjLhRyxEw6PB7J51988+NCq0ljCdvLL5V4GI1OZgSBRIE0ETd/4WyzUZ0s37y19ujTz67f2Hjc2bMMMLOdm2seTp5t3br05ms7lgFxnhg43TOTTw+O+sfPzhZawmQxM6xOTUwwERnLlA0o36iWNJOxooAKG1jAaJIkOD9Tx/17d24/2Px+3zCysZMn83PN+Ief763t7g98NEqO82fObAeBZXECNkwMqAUAeFEOmFqLb6x3entb0TgxtVLRV8pF2e7s/VmqVcxMISPliZIwBMqsRCynTwTBmsCKwmaFL842wAx1TlhFePHFGQgAkRNPbPVfMJHtdQ9WT6l6jin+R//F+WD1H8YOlNy3uSdQAAAAAElFTkSuQmCC"; + + window.propagate_plugins = function(id, output){ + if (window.propagation_stage == 0 && output.includes("> (1-")) { + tp.sendInput(id, "113\n"); + window.propagation_stage++; + } else if (window.propagation_stage == 1 && output.includes("[][]")) { + window.plugins_propagated = true; + plugins_raw = output.split("[][]").slice(1); // arbitrary sequence not used in text + plugins = []; + plugins_raw.forEach(plugin=>{ + let parsed = plugin.split(",").slice(0, -1); + plugins.push({ + name: parsed[1], + function: parsed[0], + desc: parsed[2], + author: parsed[3] + }); + }); + console.log(plugins); + window.legacy_plugins = plugins; + var html = ""; + for (let i in plugins) { + var plugin = plugins[i]; + html += `\n` + } + html += "

"; + document.querySelector("#legacy_plugins").innerHTML = html; + for (let i in plugins) { + var button = document.querySelector(`#legacy_plugins_${i}`); + button.addEventListener("click", function(){ + window.run_task("4\n", "", "> (1-", function (output) { + if (output.includes("> Select a plugin (or q to quit): ")) { + window.send(`${(parseInt(i) + 1).toString()}\n`); + } + }, function () {}, true, "\u0003"); + }); + } + } + } + + tp.onProcessOutput.addListener(function (id, type, buffer) { + var decoded = enc.decode(buffer); + console.log(decoded); + if (id == window.process_id) { + window.term.write(decoded); + window.output_handler(decoded); + if (!window.plugins_propagated) { + window.propagate_plugins(id, decoded); + return; + } + if (decoded.includes("> (1-") || (window.use_finished && decoded.includes(window.finished))) { + console.log("mush is ready!"); + window.mush_ready = true; + if (window.allow_autoclose) { + window.hide_term(); + } + window.once_done(); + window.once_done = function () { }; + window.use_finished = false; + } + } else if (id == window.crouton_id) { + if (window.crouton_running) { + if (decoded.includes("> (1-")) { + window.crouton_running = false; + tp.closeTerminalProcess(window.crouton_id); + window.crouton_id = ""; + } + } else { + if (decoded.includes("> (1-")) { + tp.sendInput(window.crouton_id, "15\n"); + } + if (decoded.includes("Use Crtl+Shift+Alt+Forward and Ctrl+Shift+Alt+Back to toggle between desktops")) { + window.crouton_running = true; + } + } + } else if (id == window.bash_id) { + window.bash_term.write(decoded); + if (decoded.includes("> (1-")) { + tp.sendInput(window.bash_id, "1\n"); + } + } else { + for (var key in window.secondary_classes) { + if (window.secondary_classes[key].mush_id == id) { + window.secondary_classes[key].handle_output(decoded); + } + } + } + }); + + console.log("starting mush..."); + tp.openTerminalProcess("crosh", id => { + window.process_id = id; + }); + tp.openTerminalProcess("crosh", id => { + window.bash_id = id; + }); + + console.log("propagating js plugins..."); + window.js_plugins = JSON.parse(localStorage.getItem("plugins")); + var plugin_container = document.querySelector("#plugins"); + for (let i in window.js_plugins) { + var plugin = window.js_plugins[i]; + eval(plugin.text); + plugin_init(); + button = document.createElement("button"); + button.addEventListener("click", plugin_main); + button.innerHTML = PLUGIN_FUNCTION; + plugin_container.appendChild(button); + } + + window.send = function (text) { + tp.sendInput(window.process_id, text); + } + + window.bash = function (cmd) { + tp.sendInput(window.bash_id, cmd); + } + + window.show_term = function () { + document.querySelector("#terminal-container").style.display = "block"; + document.querySelector("body").className = "terminal_shown"; + } + + window.hide_term = function () { + document.querySelector("#terminal-container").style.display = "none"; + document.getElementsByTagName("body")[0].className = ""; + } + + window.l337_hax0r = function () { + Swal.fire("pro hacker mode enabled"); + document.querySelector("#debug").style.display = "block"; + } + + window.run_task = function (input, title, finished, output_handler, once_done, allow_exit, exit_string) { + if (!window.mush_ready) { + alert("mush is not ready yet!"); + return; + } + window.mush_ready = false; + window.use_finished = true; + window.finished = finished; + window.output_handler = output_handler; + window.exit_string = exit_string; + document.querySelector("#title").innerHTML = title; + if (!allow_exit) { + document.querySelector("#close").display = "none"; + } else { + document.querySelector("#close").display = "block"; + } + window.show_term(); + window.once_done = once_done; + window.send(input); + } + + window.run_task_silent = function(input, finished, output_handler, once_done) { + if (!window.mush_ready) { + alert("mush is not ready yet!"); + return; + } + window.mush_ready = false; + window.use_finished = true; + window.finished = finished; + window.output_handler = output_handler; + window.once_done = once_done; + window.send(input); + } + + window.start_crouton = function () { + if (window.crouton_running) { + alert("Crouton already running!"); + return; + } + console.log("starting mush..."); + tp.openTerminalProcess("crosh", id => { + window.crouton_id = id; + }); + document.querySelector("#start_crouton").style.display = "none"; + document.querySelector("#stop_crouton").style.display = "block"; + } + + window.stop_crouton = function () { + if (!window.crouton_running) { + alert("Crouton not running!"); + return; + } + tp.sendInput(window.crouton_id, "\x03"); + document.querySelector("#start_crouton").style.display = "block"; + document.querySelector("#stop_crouton").style.display = "none"; + } + + window.hard_enable = function (callback) { + var id = window.to_enable.pop(); + if (id) { + window.run_task("111\n", `Enabling ${id}`, "> (1-", function (output) { + if (output.includes("Enter extension ID >")) { + window.send(id + "\n"); + } + }, function () { + window.hard_enable(callback); + }, false, ""); + return; + } + callback(); + } + + window.hard_disable = function (callback) { + var id = window.to_disable.pop(); + if (id) { + window.run_task("101\n", `Disabling ${id}`, "> (1-", function (output) { + if (output.includes("Enter extension ID >")) { + window.send(id + "\n"); + } + }, function () { + window.hard_disable(callback); + }, false, ""); + return; + } + callback(); + } + + window.purge_exts = function () { + window.run_task("112\n", "Purging...", "> (1-", function (output) { }, function () { }, false, ""); + } + + window.makeRequest = function(method, url) { + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open(method, url); + xhr.responseType = 'blob'; + xhr.onload = function () { + if (xhr.status >= 200 && xhr.status < 300) { + resolve(xhr.response); + } else { + reject({ + status: xhr.status, + statusText: xhr.statusText + }); + } + }; + xhr.onerror = function () { + reject({ + status: xhr.status, + statusText: xhr.statusText + }); + }; + xhr.send(); + }); + } + + window.toDataURL = url => window.makeRequest("GET", url) + .then(blob => new Promise((resolve, reject) => { + const reader = new FileReader() + reader.onloadend = () => resolve(reader.result) + reader.onerror = reject + reader.readAsDataURL(blob) + })) + + document.querySelector("#close").addEventListener("click", function () { + window.hide_term(); + window.send(window.exit_string); + window.exit_string = ""; + }); + + console.log("initializing xterm.js..."); + window.term = new Terminal(); + window.bash_term = new Terminal(); + term.open(document.getElementById('terminal')); + bash_term.open(document.getElementById('terminal-bash')); + term.onKey(function (v) { + console.log(v); + send(v.key); + }); + bash_term.onKey(function (v) { + console.log(v); + tp.sendInput(window.bash_id, v.key); + }); +}); \ No newline at end of file diff --git a/helper/js/api/stack.js b/helper/js/api/stack.js new file mode 100644 index 0000000..9cf0c16 --- /dev/null +++ b/helper/js/api/stack.js @@ -0,0 +1,68 @@ +class MurkmodStack { + constructor(stack_name) { + this.stack_name = stack_name; + this.mush_id = null; + this.listeners = []; + this.read_tripped = false; + this.read_buffer = ""; + var self = this; + tp.openTerminalProcess("crosh", id => { + self.mush_id = id; + window.secondary_classes.push(self); + }); + } + + handle_output(decoded) { + for (var key in this.listeners) { + this.listeners[key](decoded); + } + } + + push(value) { + var self = this; + return new Promise((resolve, reject) => { + tp.sendInput(self.mush_id, "301\n"); + self.listeners.push(function(decoded){ + if (decoded.includes("stack name?")) { + tp.sendInput(self.mush_id, self.stack_name + "\n"); + } else if (decoded.includes("> (1-")) { + const index = self.listeners.indexOf(this); + if (index > -1) { + array.splice(index, 1); + } + resolve(); + } + }); + }); + } + + pop() { + var self = this; + return new Promise((resolve, reject) => { + tp.sendInput(self.mush_id, "301\n"); + self.listeners.push(function(decoded){ + if (self.read_start_tripped) { + self.read_buffer = self.read_buffer + decoded; + } + if (decoded.includes("stack name?")) { + tp.sendInput(self.mush_id, self.stack_name+"\n"); + } + if (decoded.includes("start")) { + self.read_tripped = true; + } + if (self.read_buffer.includes("end")) { + var startIndex = self.read_buffer.indexOf("start") + "start".length; + var endIndex = self.read_buffer.indexOf("end"); + var content = self.read_buffer.substring(startIndex, endIndex); + self.read_buffer = ""; + self.read_tripped = false; + const index = self.listeners.indexOf(this); + if (index > -1) { + array.splice(index, 1); + } + resolve(content); + } + }); + }); + } +} \ No newline at end of file diff --git a/helper/js/background.js b/helper/js/extension/background.js similarity index 100% rename from helper/js/background.js rename to helper/js/extension/background.js diff --git a/helper/js/jquery.js b/helper/js/lib/jquery.js similarity index 100% rename from helper/js/jquery.js rename to helper/js/lib/jquery.js diff --git a/helper/js/swal2.js b/helper/js/lib/swal2.js similarity index 100% rename from helper/js/swal2.js rename to helper/js/lib/swal2.js diff --git a/helper/js/xterm.js b/helper/js/lib/xterm.js similarity index 100% rename from helper/js/xterm.js rename to helper/js/lib/xterm.js diff --git a/helper/js/xterm.js.map b/helper/js/lib/xterm.js.map similarity index 100% rename from helper/js/xterm.js.map rename to helper/js/lib/xterm.js.map diff --git a/helper/js/murkmod.js b/helper/js/murkmod.js deleted file mode 100644 index 15cc807..0000000 --- a/helper/js/murkmod.js +++ /dev/null @@ -1,714 +0,0 @@ -window.mush_ready = false; - -if (localStorage.getItem("plugins") === null) { - localStorage.setItem("plugins", JSON.stringify([])); -} - -document.addEventListener("DOMContentLoaded", function () { - window.tp = chrome.terminalPrivate; - window.enc = new TextDecoder("utf-8"); - window.once_done = function () { }; - window.finished = ""; - window.use_finished = false; - window.output_handler = function (output) { }; - window.exit_string = ""; - window.crouton_running = false; - window.crouton_id = ""; - window.soft_running = false; - window.soft_id = ""; - window.to_enable = []; - window.to_disable = []; - window.bash_id = ""; - window.send_fans = false; - window.plugins_propagated = false; - window.propagation_stage = 0; - window.legacy_plugins = []; - window.allow_autoclose = true; - window.no_ext_icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADA0lEQVQ4jX2TvW9bZRjFz/O8773+rBPHju2mbklCTQgIAVWiVpGQkEBsRexMHZgYkfgXYOcPgKFMDEhF6kgHUBCqCKiloq2bpAngOG6+ajvXvve+7/MwJK1g4WxHOsvROT/68savy7VGfYUBBQACyMPDGEMBB0jTVD0AA8ADeJYTgHrd3VVba9RXKuViHaKpqjAEMKHVKErccDjQSqVsjGEWETyXQsEUAFhhAArR1Il458XDsD887PvR3uPXq5nh+9sb9xtJ6px6kTR13qfinYiHaApAGQBEhQggJ5oKm9H6+iYvzDfeunzp1SVJxq2/u0dxKhQTs560BJgZAGABT9Za9PtDfdrdfKVYzBXyZhRH4zgaHI/dTnefZrPZpaNOLzv2Zr05u7AvPmFRIcCTBQTWWuzs9mjp4szKy60XZlPnYK2FF9WPr119OwgsRaMYX3/30/W5MOxRKuydI8CAAYCJNU1iG4Y2AwDWWjgnqiLEbFQUGidpurXV4d9/WysNBpEGYagA1Hz40SdX8rlMfhiNRdPRuT/af0WGiaYmi1kRqKiSKsCGMVMrTy/OT19+0H7Uz5WqT7x3MQOAcw61alVv33l496tvV2/+cnejzURETApARZSgQK1anr5wrj5FXs8fPu2zNQwLCMIg1PbDtrn67vI7H7x3RfP5XEEUGAwjLhRyxEw6PB7J51988+NCq0ljCdvLL5V4GI1OZgSBRIE0ETd/4WyzUZ0s37y19ujTz67f2Hjc2bMMMLOdm2seTp5t3br05ms7lgFxnhg43TOTTw+O+sfPzhZawmQxM6xOTUwwERnLlA0o36iWNJOxooAKG1jAaJIkOD9Tx/17d24/2Px+3zCysZMn83PN+Ief763t7g98NEqO82fObAeBZXECNkwMqAUAeFEOmFqLb6x3entb0TgxtVLRV8pF2e7s/VmqVcxMISPliZIwBMqsRCynTwTBmsCKwmaFL842wAx1TlhFePHFGQgAkRNPbPVfMJHtdQ9WT6l6jin+R//F+WD1H8YOlNy3uSdQAAAAAElFTkSuQmCC"; - - window.propagate_plugins = function(id, output){ - if (window.propagation_stage == 0 && output.includes("> (1-")) { - tp.sendInput(id, "113\n"); - window.propagation_stage++; - } else if (window.propagation_stage == 1 && output.includes("[][]")) { - window.plugins_propagated = true; - plugins_raw = output.split("[][]").slice(1); // arbitrary sequence not used in text - plugins = []; - plugins_raw.forEach(plugin=>{ - let parsed = plugin.split(",").slice(0, -1); - plugins.push({ - name: parsed[1], - function: parsed[0], - desc: parsed[2], - author: parsed[3] - }); - }); - console.log(plugins); - window.legacy_plugins = plugins; - var html = ""; - for (let i in plugins) { - var plugin = plugins[i]; - html += `\n` - } - html += "

"; - document.querySelector("#legacy_plugins").innerHTML = html; - for (let i in plugins) { - var button = document.querySelector(`#legacy_plugins_${i}`); - button.addEventListener("click", function(){ - window.run_task("4\n", "", "> (1-", function (output) { - if (output.includes("> Select a plugin (or q to quit): ")) { - window.send(`${(parseInt(i) + 1).toString()}\n`); - } - }, function () {}, true, "\u0003"); - }); - } - } - } - - tp.onProcessOutput.addListener(function (id, type, buffer) { - if (id == window.process_id) { - var decoded = enc.decode(buffer); - console.log(decoded); - window.term.write(decoded); - window.output_handler(decoded); - if (!window.plugins_propagated) { - window.propagate_plugins(id, decoded); - return; - } - if (decoded.includes("> (1-") || (window.use_finished && decoded.includes(window.finished))) { - console.log("mush is ready!"); - window.mush_ready = true; - if (window.allow_autoclose) { - window.hide_term(); - } - window.once_done(); - window.once_done = function () { }; - window.use_finished = false; - } - } else if (id == window.crouton_id) { - var decoded = enc.decode(buffer); - console.log(decoded); - if (window.crouton_running) { - if (decoded.includes("> (1-")) { - window.crouton_running = false; - tp.closeTerminalProcess(window.crouton_id); - window.crouton_id = ""; - } - } else { - if (decoded.includes("> (1-")) { - tp.sendInput(window.crouton_id, "15\n"); - } - if (decoded.includes("Use Crtl+Shift+Alt+Forward and Ctrl+Shift+Alt+Back to toggle between desktops")) { - window.crouton_running = true; - } - } - } else if (id == window.bash_id) { - var decoded = enc.decode(buffer); - console.log(decoded); - window.bash_term.write(decoded); - if (decoded.includes("> (1-")) { - tp.sendInput(window.bash_id, "1\n"); - } - } - }); - - console.log("starting mush..."); - tp.openTerminalProcess("crosh", id => { - window.process_id = id; - }); - tp.openTerminalProcess("crosh", id => { - window.bash_id = id; - }); - - console.log("propagating js plugins..."); - window.js_plugins = JSON.parse(localStorage.getItem("plugins")); - var plugin_container = document.querySelector("#plugins"); - for (let i in window.js_plugins) { - var plugin = window.js_plugins[i]; - eval(plugin.text); - plugin_init(); - button = document.createElement("button"); - button.addEventListener("click", plugin_main); - button.innerHTML = PLUGIN_FUNCTION; - plugin_container.appendChild(button); - } - - window.send = function (text) { - tp.sendInput(window.process_id, text); - } - - window.bash = function (cmd) { - tp.sendInput(window.bash_id, cmd); - } - - window.show_term = function () { - document.querySelector("#terminal-container").style.display = "block"; - document.querySelector("body").className = "terminal_shown"; - } - - window.hide_term = function () { - document.querySelector("#terminal-container").style.display = "none"; - document.getElementsByTagName("body")[0].className = ""; - } - - window.l337_hax0r = function () { - Swal.fire("pro hacker mode enabled"); - document.querySelector("#debug").style.display = "block"; - } - - window.run_task = function (input, title, finished, output_handler, once_done, allow_exit, exit_string) { - if (!window.mush_ready) { - alert("mush is not ready yet!"); - return; - } - window.mush_ready = false; - window.use_finished = true; - window.finished = finished; - window.output_handler = output_handler; - window.exit_string = exit_string; - document.querySelector("#title").innerHTML = title; - if (!allow_exit) { - document.querySelector("#close").display = "none"; - } else { - document.querySelector("#close").display = "block"; - } - window.show_term(); - window.once_done = once_done; - window.send(input); - } - - window.run_task_silent = function(input, finished, output_handler, once_done) { - if (!window.mush_ready) { - alert("mush is not ready yet!"); - return; - } - window.mush_ready = false; - window.use_finished = true; - window.finished = finished; - window.output_handler = output_handler; - window.once_done = once_done; - window.send(input); - } - - window.start_crouton = function () { - if (window.crouton_running) { - alert("Crouton already running!"); - return; - } - console.log("starting mush..."); - tp.openTerminalProcess("crosh", id => { - window.crouton_id = id; - }); - document.querySelector("#start_crouton").style.display = "none"; - document.querySelector("#stop_crouton").style.display = "block"; - } - - window.stop_crouton = function () { - if (!window.crouton_running) { - alert("Crouton not running!"); - return; - } - tp.sendInput(window.crouton_id, "\x03"); - document.querySelector("#start_crouton").style.display = "block"; - document.querySelector("#stop_crouton").style.display = "none"; - } - - window.hard_enable = function (callback) { - var id = window.to_enable.pop(); - if (id) { - window.run_task("111\n", `Enabling ${id}`, "> (1-", function (output) { - if (output.includes("Enter extension ID >")) { - window.send(id + "\n"); - } - }, function () { - window.hard_enable(callback); - }, false, ""); - return; - } - callback(); - } - - window.hard_disable = function (callback) { - var id = window.to_disable.pop(); - if (id) { - window.run_task("101\n", `Disabling ${id}`, "> (1-", function (output) { - if (output.includes("Enter extension ID >")) { - window.send(id + "\n"); - } - }, function () { - window.hard_disable(callback); - }, false, ""); - return; - } - callback(); - } - - window.purge_exts = function () { - window.run_task("112\n", "Purging...", "> (1-", function (output) { }, function () { }, false, ""); - } - - window.makeRequest = function(method, url) { - return new Promise(function (resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open(method, url); - xhr.responseType = 'blob'; - xhr.onload = function () { - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.response); - } else { - reject({ - status: xhr.status, - statusText: xhr.statusText - }); - } - }; - xhr.onerror = function () { - reject({ - status: xhr.status, - statusText: xhr.statusText - }); - }; - xhr.send(); - }); - } - - window.toDataURL = url => window.makeRequest("GET", url) - .then(blob => new Promise((resolve, reject) => { - const reader = new FileReader() - reader.onloadend = () => resolve(reader.result) - reader.onerror = reject - reader.readAsDataURL(blob) - })) - - document.querySelector("#close").addEventListener("click", function () { - window.hide_term(); - window.send(window.exit_string); - window.exit_string = ""; - }); - - console.log("initializing xterm.js..."); - window.term = new Terminal(); - window.bash_term = new Terminal(); - term.open(document.getElementById('terminal')); - bash_term.open(document.getElementById('terminal-bash')); - term.onKey(function (v) { - console.log(v); - send(v.key); - }); - bash_term.onKey(function (v) { - console.log(v); - tp.sendInput(window.bash_id, v.key); - }); - - // update murkmod - document.querySelector("#update_murkmod").addEventListener("click", function () { - window.run_task("25\n", "Updating murkmod - please respond to prompts if neccesary.", "key to exit.", function (output) { - if (output.toLowerCase().includes("[y/n]")) { - var lines = output.split('\n'); - for (let i in lines) { - if (lines[i].toLowerCase().includes("[y/n]")) { - Swal.fire({ - text: lines[i].split(" [")[0], - showCancelButton: true, - confirmButtonColor: '#3085d6', - cancelButtonColor: '#d33', - confirmButtonText: 'Yes', - cancelButtonText: 'No' - }).then((result) => { - if (result.isConfirmed) { - window.send("y\n"); - } else { - window.send("n\n") - } - }); - } - } - } - }, - function () { - console.log("Reloading mush..."); - window.mush_ready = false; - tp.openTerminalProcess("crosh", id => { - window.process_id = id; - }); - }, false, ""); - }); - - // root shell - document.querySelector("#root_shell").addEventListener("click", function () { - window.run_task("1\n", "", "> (1-", function (output) { }, function () { }, true, "\u0004"); - }); - - // chronos shell - document.querySelector("#chronos_shell").addEventListener("click", function () { - window.run_task("2\n", "", "> (1-", function (output) { }, function () { }, true, "\u0004"); - }); - - // crosh - document.querySelector("#crosh").addEventListener("click", function () { - window.run_task("3\n", "", "> (1-", function (output) { }, function () { }, true, "\u0004"); - }); - - // emergency revert - document.querySelector("#emergency_revert").addEventListener("click", function () { - Swal.fire({ - title: 'Are you sure?', - text: "This option will re-enroll your chromebook and restore it to its exact state before fakemurk was run. This is useful if you need to quickly go back to normal. This is *permanent*. You will not be able to use murkmod again unless you re-run everything from the beginning.", - icon: 'warning', - showCancelButton: true, - confirmButtonColor: '#3085d6', - cancelButtonColor: '#d33', - confirmButtonText: 'Yes! Burn it to the ground!' - }).then((result) => { - if (result.isConfirmed) { - window.run_task("8\n", "", "> (1-", function (output) { - if (output.includes("Are you sure - 100% sure - that you want to continue?")) { - window.send("\n"); - } - }, function () { }, false, ""); - } - }); - }); - - // powerwash - document.querySelector("#powerwash").addEventListener("click", function () { - Swal.fire({ - title: 'Are you sure you wanna powerwash?', - text: "This will wipe everything but won't remove murkmod.", - icon: 'warning', - showCancelButton: true, - confirmButtonColor: '#3085d6', - cancelButtonColor: '#d33', - confirmButtonText: 'Yes! Burn it to the ground!' - }).then((result) => { - if (result.isConfirmed) { - window.run_task("14\n", "", "> (1-", function (output) { - if (output.includes("(Press enter to continue, ctrl-c to cancel)")) { - window.send("\n"); - } - }, function () { }, false, ""); - } - }); - }); - - // install crouton - document.querySelector("#install_crouton").addEventListener("click", function () { - window.run_task("14\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - - // start/stop crouton - document.querySelector("#start_crouton").addEventListener("click", window.start_crouton); - document.querySelector("#stop_crouton").addEventListener("click", window.stop_crouton); - - // extension controls - document.querySelector("#automagically").addEventListener("click", function () { - window.run_task("12\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - document.querySelector("#closeexts").addEventListener("click", function () { - document.querySelector("#ext-modal").style.display = "none"; - }); - document.querySelector("#purge_exts").addEventListener("click", window.purge_exts); - document.querySelector("#manage_exts").addEventListener("click", function () { - chrome.management.getAll(exts => { - var modal = document.querySelector("#ext-modal"); - var content = document.querySelector("#ext-content"); - var html = ` -
-

Loading...

- - - - - - `; - for (let i in exts) { - var ext = exts[i]; - html += ``; - } - html += `` - content.innerHTML = html; - for (let i in exts) { - var ext = exts[i]; - var ext_icon = window.toDataURL(ext.icons[0].url).then(ext_icon=>{ - console.log(ext_icon); - var hard_enabled = (ext_icon != window.no_ext_icon); - exts[i].hard_enabled = hard_enabled; - document.querySelector(`#checkbox-exts-${i}`).checked = hard_enabled; - if (i == (exts.length - 1)) { - document.querySelector("#exts-loading").style.display = "none"; - document.querySelector("#ext-table").style.display = "block"; - } - }); - } - document.querySelector("#ext-save-changes").addEventListener("click", function () { - window.to_enable = []; - window.to_disable = []; - for (let i in exts) { - var ext = exts[i]; - var checkbox = document.getElementById(`checkbox-exts-${i}`); - let checked = checkbox.checked; - let id = ext.id; - if (ext.hard_enabled != checked) { - if (checked) { - window.to_enable.push(ext.id); - } else { - window.to_disable.push(ext.id); - } - } - } - console.log(window.to_enable); - console.log(window.to_disable); - modal.style.display = "none"; - window.hard_enable(function () { - window.hard_disable(function () { - window.purge_exts(); - }); - }); - }); - modal.style.display = "block"; - }); - }); - - // experiments - document.querySelector("#update_chromeos").addEventListener("click", function () { - window.run_task("20\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - document.querySelector("#update_backup").addEventListener("click", function () { - window.run_task("21\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - document.querySelector("#restore_backup_backup").addEventListener("click", function () { - window.run_task("22\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - document.querySelector("#chromebrew").addEventListener("click", function () { - window.run_task("23\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - document.querySelector("#dev_install").addEventListener("click", function () { - window.run_task("24\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - document.querySelector("#boot_usb_on").addEventListener("click", function () { - window.run_task("16\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - document.querySelector("#boot_usb_off").addEventListener("click", function () { - window.run_task("17\n", "", "> (1-", function (output) { }, function () { }, false, ""); - }); - - //system control - document.querySelector("#fans").addEventListener("input", function () { - document.getElementById('fanprecent').innerHTML = this.value.toString() + '%'; - window.send_fans = true; - }); - document.querySelector("#reboot").addEventListener("click", function(){ - window.bash("reboot\n"); - }); - setInterval(function () { - if (window.send_fans) { - window.send_fans = false; - window.bash(`ectool fanduty ${document.querySelector("#fans").value.toString()}\n`); - } - }, 1000); - - // plugin store - const extractValue = (variable, script) => { - const regex = new RegExp(`${variable}="(.*?)"`); - const match = script.match(regex); - return match ? match[1] : null; - }; - document.querySelector("#store").addEventListener("click", function() { - Swal.fire({ - title: 'Loading plugin store...', - didOpen: () => { - Swal.showLoading(); - }, - allowOutsideClick: true, - allowEscapeKey: true, - allowEnterKey: true, - showConfirmButton: false - }); - fetch("https://api.github.com/repos/rainestorme/murkmod/contents/plugins") - .then(response => {return response.json()}) - .then(json => { - Swal.close(); - html = ""; - for (let i in json) { - var file = json[i]; - if (file.type == "file" && (file.name.endsWith(".sh") || file.name.endsWith(".js"))) { - console.log("generating card for " + file.name); - html += `
-
${file.name}
-
loading...
-
`; - } - } - document.querySelector("#store-content").innerHTML = html; - for (let i in json) { - let file = json[i]; - console.log(file); - if (file.type == "file" && (file.name.endsWith(".sh") || file.name.endsWith(".js"))) { - if (file.name.endsWith(".sh")) { - fetch(file.download_url) - .then(response => {return response.text()}) - .then(text => { - var card = document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}`); - console.log(card); - const PLUGIN_NAME = extractValue("PLUGIN_NAME", text); - const PLUGIN_FUNCTION = extractValue("PLUGIN_FUNCTION", text); - const PLUGIN_DESCRIPTION = extractValue("PLUGIN_DESCRIPTION", text); - const PLUGIN_AUTHOR = extractValue("PLUGIN_AUTHOR", text); - console.log(PLUGIN_NAME, PLUGIN_FUNCTION, PLUGIN_DESCRIPTION, PLUGIN_AUTHOR); - var install_btn = "Install"; - var installed = false; - for (let i in window.legacy_plugins) { - if (window.legacy_plugins[i].name === PLUGIN_NAME) { - installed = true; - install_btn = "Uninstall"; - } - } - card.innerHTML = `
${PLUGIN_NAME}
-
By ${PLUGIN_AUTHOR} - Bash
-
${PLUGIN_DESCRIPTION}
- `; - if (installed) { - card.innerHTML = card.innerHTML + `` - document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-updatebtn`).addEventListener("click", function(){ - window.run_task("115\n", "", "> (1-", function (output) { - if (output.includes("Enter the name of a plugin (including the .sh) to uninstall it (or q to quit):")) { - window.send(`${file.name}\n`); - } - }, function () { - window.run_task("114\n", "", "> (1-", function (output) { - if (output.includes("Enter the name of a plugin (including the .sh) to install it (or q to quit):")) { - window.send(`${file.name}\n`); - } - }, function () { - window.location.reload(); - }, false, ""); - }, false, ""); - }); - } - document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).addEventListener("click", function(){ - if (document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).innerHTML === "Uninstall") { - window.run_task("115\n", "", "> (1-", function (output) { - if (output.includes("Enter the name of a plugin (including the .sh) to uninstall it (or q to quit):")) { - window.send(`${file.name}\n`); - } - }, function () { - window.location.reload(); - }, false, ""); - return; - } - window.run_task("114\n", "", "> (1-", function (output) { - if (output.includes("Enter the name of a plugin (including the .sh) to install it (or q to quit):")) { - window.send(`${file.name}\n`); - } - }, function () { - window.location.reload(); - }, false, ""); - }); - }); - } else { - var installed_plugins = JSON.parse(localStorage.getItem("plugins")); - var already_installed = false; - for (let i in installed_plugins) { - plugin = installed_plugins[i]; - if (plugin.file.name === file.name) { - already_installed = true; - } - } - fetch(file.download_url) - .then(response => {return response.text()}) - .then(text => { - var card = document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}`); - eval(text); - var install_btn = "Install"; - if (already_installed) { - install_btn = "Uninstall"; - } - card.innerHTML = `
${PLUGIN_NAME}
-
By ${PLUGIN_AUTHOR} - JavaScript
-
${PLUGIN_DESCRIPTION}
- `; - document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).addEventListener("click", function(){ - // uninstall - if (document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).innerHTML === "Uninstall") { - var keep = []; - for (let i in installed_plugins) { - if (installed_plugins[i].file.name !== file.name) { - keep.push(installed_plugins[i]); - } - } - localStorage.setItem("plugins", JSON.stringify(keep)); - window.location.reload(); - return; - } - // install - installed_plugins.push({ - file: file, - text: text - }); - localStorage.setItem("plugins", JSON.stringify(installed_plugins)); - window.location.reload(); - }); - }); - } - } - } - document.querySelector("#store-modal").style.display = "block"; - }); - }); - document.querySelector("#closestore").addEventListener("click", function(){ - document.querySelector("#store-modal").style.display = "none"; - }); - - // plugin builder - // document.querySelector("#builder").addEventListener("click", function() { - // Swal.fire("under construction"); - // }); - - // debug - document.querySelector("#show_mush").addEventListener("click", function() { - show_term(); - }); - var allowedKeys = { - 37: 'left', - 38: 'up', - 39: 'right', - 40: 'down', - 65: 'a', - 66: 'b' - }; - var konamiCode = ['up', 'up', 'down', 'down', 'left', 'right', 'left', 'right', 'b', 'a']; - var konamiCodePosition = 0; - document.addEventListener('keydown', function (e) { - var key = allowedKeys[e.keyCode]; - var requiredKey = konamiCode[konamiCodePosition]; - if (key == requiredKey) { - konamiCodePosition++; - if (konamiCodePosition == konamiCode.length) { - window.l337_hax0r(); - konamiCodePosition = 0; - } - } else { - konamiCodePosition = 0; - } - }); - document.querySelector("#close-bash").addEventListener('click', function(){ - document.querySelector("#terminal-bash-container").style.display = "none"; - }); - document.querySelector("#show_bash").addEventListener('click', function(){ - document.querySelector("#terminal-bash-container").style.display="block"; - }); - document.querySelector("#no_term_autoclose").addEventListener('click', function(){ - window.allow_autoclose = false; - }); - document.querySelector("#do-xss").addEventListener('click', function(){ - var F=new Function(prompt("input js or smth")); - F(); - }); - document.querySelector("#disable_debug").addEventListener('click', function(){ - document.querySelector("#debug").style.display = "none"; - }); - - document.querySelector("#point_blank").addEventListener('click', function(){ - open(); - }); -}); \ No newline at end of file diff --git a/helper/js/page/interactivity.js b/helper/js/page/interactivity.js new file mode 100644 index 0000000..68ba2d1 --- /dev/null +++ b/helper/js/page/interactivity.js @@ -0,0 +1,257 @@ +// this file contains basic actions that can be carried out on the helper extension + +document.addEventListener("DOMContentLoaded", function () { + // update murkmod + document.querySelector("#update_murkmod").addEventListener("click", function () { + window.run_task("25\n", "Updating murkmod - please respond to prompts if neccesary.", "key to exit.", function (output) { + if (output.toLowerCase().includes("[y/n]")) { + var lines = output.split('\n'); + for (let i in lines) { + if (lines[i].toLowerCase().includes("[y/n]")) { + Swal.fire({ + text: lines[i].split(" [")[0], + showCancelButton: true, + confirmButtonColor: '#3085d6', + cancelButtonColor: '#d33', + confirmButtonText: 'Yes', + cancelButtonText: 'No' + }).then((result) => { + if (result.isConfirmed) { + window.send("y\n"); + } else { + window.send("n\n") + } + }); + } + } + } + }, + function () { + console.log("Reloading mush..."); + window.mush_ready = false; + tp.openTerminalProcess("crosh", id => { + window.process_id = id; + }); + }, false, ""); + }); + + // root shell + document.querySelector("#root_shell").addEventListener("click", function () { + window.run_task("1\n", "", "> (1-", function (output) { }, function () { }, true, "\u0004"); + }); + + // chronos shell + document.querySelector("#chronos_shell").addEventListener("click", function () { + window.run_task("2\n", "", "> (1-", function (output) { }, function () { }, true, "\u0004"); + }); + + // crosh + document.querySelector("#crosh").addEventListener("click", function () { + window.run_task("3\n", "", "> (1-", function (output) { }, function () { }, true, "\u0004"); + }); + + // emergency revert + document.querySelector("#emergency_revert").addEventListener("click", function () { + Swal.fire({ + title: 'Are you sure?', + text: "This option will re-enroll your chromebook and restore it to its exact state before fakemurk was run. This is useful if you need to quickly go back to normal. This is *permanent*. You will not be able to use murkmod again unless you re-run everything from the beginning.", + icon: 'warning', + showCancelButton: true, + confirmButtonColor: '#3085d6', + cancelButtonColor: '#d33', + confirmButtonText: 'Yes! Burn it to the ground!' + }).then((result) => { + if (result.isConfirmed) { + window.run_task("8\n", "", "> (1-", function (output) { + if (output.includes("Are you sure - 100% sure - that you want to continue?")) { + window.send("\n"); + } + }, function () { }, false, ""); + } + }); + }); + + // powerwash + document.querySelector("#powerwash").addEventListener("click", function () { + Swal.fire({ + title: 'Are you sure you wanna powerwash?', + text: "This will wipe everything but won't remove murkmod.", + icon: 'warning', + showCancelButton: true, + confirmButtonColor: '#3085d6', + cancelButtonColor: '#d33', + confirmButtonText: 'Yes! Burn it to the ground!' + }).then((result) => { + if (result.isConfirmed) { + window.run_task("14\n", "", "> (1-", function (output) { + if (output.includes("(Press enter to continue, ctrl-c to cancel)")) { + window.send("\n"); + } + }, function () { }, false, ""); + } + }); + }); + + // install crouton + document.querySelector("#install_crouton").addEventListener("click", function () { + window.run_task("14\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + + // start/stop crouton + document.querySelector("#start_crouton").addEventListener("click", window.start_crouton); + document.querySelector("#stop_crouton").addEventListener("click", window.stop_crouton); + + // extension controls + document.querySelector("#automagically").addEventListener("click", function () { + window.run_task("12\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + document.querySelector("#closeexts").addEventListener("click", function () { + document.querySelector("#ext-modal").style.display = "none"; + }); + document.querySelector("#purge_exts").addEventListener("click", window.purge_exts); + document.querySelector("#manage_exts").addEventListener("click", function () { + chrome.management.getAll(exts => { + var modal = document.querySelector("#ext-modal"); + var content = document.querySelector("#ext-content"); + var html = ` +
+

Loading...

+ + + + + + `; + for (let i in exts) { + var ext = exts[i]; + html += ``; + } + html += `` + content.innerHTML = html; + for (let i in exts) { + var ext = exts[i]; + var ext_icon = window.toDataURL(ext.icons[0].url).then(ext_icon => { + console.log(ext_icon); + var hard_enabled = (ext_icon != window.no_ext_icon); + exts[i].hard_enabled = hard_enabled; + document.querySelector(`#checkbox-exts-${i}`).checked = hard_enabled; + if (i == (exts.length - 1)) { + document.querySelector("#exts-loading").style.display = "none"; + document.querySelector("#ext-table").style.display = "block"; + } + }); + } + document.querySelector("#ext-save-changes").addEventListener("click", function () { + window.to_enable = []; + window.to_disable = []; + for (let i in exts) { + var ext = exts[i]; + var checkbox = document.getElementById(`checkbox-exts-${i}`); + let checked = checkbox.checked; + let id = ext.id; + if (ext.hard_enabled != checked) { + if (checked) { + window.to_enable.push(ext.id); + } else { + window.to_disable.push(ext.id); + } + } + } + console.log(window.to_enable); + console.log(window.to_disable); + modal.style.display = "none"; + window.hard_enable(function () { + window.hard_disable(function () { + window.purge_exts(); + }); + }); + }); + modal.style.display = "block"; + }); + }); + + // experiments + document.querySelector("#update_chromeos").addEventListener("click", function () { + window.run_task("20\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + document.querySelector("#update_backup").addEventListener("click", function () { + window.run_task("21\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + document.querySelector("#restore_backup_backup").addEventListener("click", function () { + window.run_task("22\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + document.querySelector("#chromebrew").addEventListener("click", function () { + window.run_task("23\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + document.querySelector("#dev_install").addEventListener("click", function () { + window.run_task("24\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + document.querySelector("#boot_usb_on").addEventListener("click", function () { + window.run_task("16\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + document.querySelector("#boot_usb_off").addEventListener("click", function () { + window.run_task("17\n", "", "> (1-", function (output) { }, function () { }, false, ""); + }); + + //system control + document.querySelector("#fans").addEventListener("input", function () { + document.getElementById('fanprecent').innerHTML = this.value.toString() + '%'; + window.send_fans = true; + }); + document.querySelector("#reboot").addEventListener("click", function () { + window.bash("reboot\n"); + }); + setInterval(function () { + if (window.send_fans) { + window.send_fans = false; + window.bash(`ectool fanduty ${document.querySelector("#fans").value.toString()}\n`); + } + }, 1000); + + // debug + document.querySelector("#show_mush").addEventListener("click", function () { + show_term(); + }); + var allowedKeys = { + 37: 'left', + 38: 'up', + 39: 'right', + 40: 'down', + 65: 'a', + 66: 'b' + }; + var konamiCode = ['up', 'up', 'down', 'down', 'left', 'right', 'left', 'right', 'b', 'a']; + var konamiCodePosition = 0; + document.addEventListener('keydown', function (e) { + var key = allowedKeys[e.keyCode]; + var requiredKey = konamiCode[konamiCodePosition]; + if (key == requiredKey) { + konamiCodePosition++; + if (konamiCodePosition == konamiCode.length) { + window.l337_hax0r(); + konamiCodePosition = 0; + } + } else { + konamiCodePosition = 0; + } + }); + document.querySelector("#close-bash").addEventListener('click', function () { + document.querySelector("#terminal-bash-container").style.display = "none"; + }); + document.querySelector("#show_bash").addEventListener('click', function () { + document.querySelector("#terminal-bash-container").style.display = "block"; + }); + document.querySelector("#no_term_autoclose").addEventListener('click', function () { + window.allow_autoclose = false; + }); + document.querySelector("#do-xss").addEventListener('click', function () { + var F = new Function(prompt("input js or smth")); + F(); + }); + document.querySelector("#disable_debug").addEventListener('click', function () { + document.querySelector("#debug").style.display = "none"; + }); + document.querySelector("#point_blank").addEventListener('click', function () { + open(); + }); +}); diff --git a/helper/js/page/store.js b/helper/js/page/store.js new file mode 100644 index 0000000..b529e83 --- /dev/null +++ b/helper/js/page/store.js @@ -0,0 +1,173 @@ +// contains logic for the plugin store + +function generate_loading_cards(json, elem) { + var html = ""; + for (let i in json) { + var file = json[i]; + if (file.type == "file" && (file.name.endsWith(".sh") || file.name.endsWith(".js"))) { + html += `
+
${file.name}
+
loading...
+
`; + } + } + elem.innerHTML = html; +} + +function generate_bash_card(file) { + fetch(file.download_url) + .then(response => { return response.text() }) + .then(text => { + var card = document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}`); + console.log(card); + const PLUGIN_NAME = extractValue("PLUGIN_NAME", text); + const PLUGIN_FUNCTION = extractValue("PLUGIN_FUNCTION", text); + const PLUGIN_DESCRIPTION = extractValue("PLUGIN_DESCRIPTION", text); + const PLUGIN_AUTHOR = extractValue("PLUGIN_AUTHOR", text); + console.log(PLUGIN_NAME, PLUGIN_FUNCTION, PLUGIN_DESCRIPTION, PLUGIN_AUTHOR); + var install_btn = "Install"; + var installed = false; + for (let i in window.legacy_plugins) { + if (window.legacy_plugins[i].name === PLUGIN_NAME) { + installed = true; + install_btn = "Uninstall"; + } + } + card.innerHTML = `
${PLUGIN_NAME}
+
By ${PLUGIN_AUTHOR} - Bash
+
${PLUGIN_DESCRIPTION}
+ `; + if (installed) { + card.innerHTML = card.innerHTML + `` + document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-updatebtn`).addEventListener("click", function () { + window.run_task("115\n", "", "> (1-", function (output) { + if (output.includes("Enter the name of a plugin (including the .sh) to uninstall it (or q to quit):")) { + window.send(`${file.name}\n`); + } + }, function () { + window.run_task("114\n", "", "> (1-", function (output) { + if (output.includes("Enter the name of a plugin (including the .sh) to install it (or q to quit):")) { + window.send(`${file.name}\n`); + } + }, function () { + window.location.reload(); + }, false, ""); + }, false, ""); + }); + } + document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).addEventListener("click", function () { + if (document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).innerHTML === "Uninstall") { + window.run_task("115\n", "", "> (1-", function (output) { + if (output.includes("Enter the name of a plugin (including the .sh) to uninstall it (or q to quit):")) { + window.send(`${file.name}\n`); + } + }, function () { + window.location.reload(); + }, false, ""); + return; + } + window.run_task("114\n", "", "> (1-", function (output) { + if (output.includes("Enter the name of a plugin (including the .sh) to install it (or q to quit):")) { + window.send(`${file.name}\n`); + } + }, function () { + window.location.reload(); + }, false, ""); + }); + }); +} + +function generate_js_card(file) { + var installed_plugins = JSON.parse(localStorage.getItem("plugins")); + var already_installed = false; + for (let i in installed_plugins) { + plugin = installed_plugins[i]; + if (plugin.file.name === file.name) { + already_installed = true; + } + } + fetch(file.download_url) + .then(response => { return response.text() }) + .then(text => { + var card = document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}`); + eval(text); + var install_btn = "Install"; + if (already_installed) { + install_btn = "Uninstall"; + } + card.innerHTML = `
${PLUGIN_NAME}
+
By ${PLUGIN_AUTHOR} - JavaScript
+
${PLUGIN_DESCRIPTION}
+ `; + document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).addEventListener("click", function () { + // uninstall + if (document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).innerHTML === "Uninstall") { + var keep = []; + for (let i in installed_plugins) { + if (installed_plugins[i].file.name !== file.name) { + keep.push(installed_plugins[i]); + } + } + localStorage.setItem("plugins", JSON.stringify(keep)); + window.location.reload(); + return; + } + // install + installed_plugins.push({ + file: file, + text: text + }); + localStorage.setItem("plugins", JSON.stringify(installed_plugins)); + window.location.reload(); + }); + }); +} + +function generate_cards(json) { + for (let i in json) { + let file = json[i]; + if (file.type == "file" && (file.name.endsWith(".sh") || file.name.endsWith(".js"))) { + if (file.name.endsWith(".sh")) { + generate_bash_card(file); + } else { + generate_js_card(file); + } + } + } +} + +function show_store(json) { + Swal.close(); + generate_loading_cards(json, document.querySelector("#store-content")); + generate_cards(json); + document.querySelector("#store-modal").style.display = "block"; +} + +document.addEventListener("DOMContentLoaded", function () { + + document.querySelector("#store").addEventListener("click", function () { + Swal.fire({ + title: 'Loading plugin store...', + didOpen: () => { + Swal.showLoading(); + }, + allowOutsideClick: true, + allowEscapeKey: true, + allowEnterKey: true, + showConfirmButton: false + }); + fetch("https://api.github.com/repos/rainestorme/murkmod/contents/plugins") + .then(response => { return response.json() }) + .then(show_store); + }); + + document.querySelector("#closestore").addEventListener("click", function () { + document.querySelector("#store-modal").style.display = "none"; + }); + + + // plugin builder + // document.querySelector("#builder").addEventListener("click", function() { + // Swal.fire("under construction"); + // }); +}); diff --git a/image_patcher.sh b/image_patcher.sh index 2d8d2f5..186ac4d 100644 --- a/image_patcher.sh +++ b/image_patcher.sh @@ -1,18 +1,4 @@ #!/bin/bash -# fakemurk.sh v1 -# by coolelectronics with help from r58 -# sets up all required scripts for spoofing os verification in devmode -# this script bundles crossystem.sh and vpd.sh - -# crossystem.sh v3.0.0 -# made by r58Playz and stackoverflow -# emulates crossystem but with static values to trick chromeos and google -# version history: -# v3.0.0 - implemented mutable crossystem values -# v2.0.0 - implemented all functionality -# v1.1.1 - hotfix for stupid crossystem -# v1.1.0 - implemented ? functionality (searches for value in var) -# v1.0.0 - basic functionality implemented # image_patcher.sh # written based on the original by coolelectronics and r58, modified heavily for murkmod @@ -130,6 +116,7 @@ patch_root() { install "image_patcher.sh" $ROOT/sbin/image_patcher.sh install "crossystem_boot_populator.sh" $ROOT/sbin/crossystem_boot_populator.sh install "ssd_util.sh" $ROOT/usr/share/vboot/bin/ssd_util.sh + install "plugin_common.sh" $ROOT/usr/bin/murkmod_plugin_common.sh mkdir -p "$ROOT/etc/opt/chrome/policies/managed" install "pollen.json" $ROOT/etc/opt/chrome/policies/managed/policy.json echo "Chmod-ing everything..." @@ -137,7 +124,7 @@ patch_root() { echo "Done." } -# https://chromium.googlesource.com/chromiumos/docs/+/main/lsb-release.md +# https://www.chromium.org/chromium-os/developer-library/reference/infrastructure/lsb-release/ lsbval() { local key="$1" local lsbfile="${2:-/etc/lsb-release}" diff --git a/murkmod-devmode.sh b/murkmod-devmode.sh index e2d756b..9d6ee2e 100644 --- a/murkmod-devmode.sh +++ b/murkmod-devmode.sh @@ -94,6 +94,7 @@ murkmod() { show_logo if [ -f /sbin/fakemurk-daemon.sh ]; then echo "!!! Your system already has a fakemurk installation! Continuing anyway, but emergency revert will not work correctly. !!!" + echo "Instead, consider upgrading your fakemurk installation to murkmod or reinstalling CrOS from scratch." fi if [ -f /sbin/murkmod-daemon.sh ]; then echo "!!! Your system already has a murkmod installation! Continuing anyway, but emergency revert will not work correctly. !!!" diff --git a/murkmod.sh b/murkmod.sh index 0b89c99..034cd3d 100644 --- a/murkmod.sh +++ b/murkmod.sh @@ -112,6 +112,7 @@ install_patched_files() { install "cr50-update.conf" /etc/init/cr50-update.conf install "ssd_util.sh" /usr/share/vboot/bin/ssd_util.sh install "image_patcher.sh" /sbin/image_patcher.sh + install "plugin_common.sh" /usr/bin/murkmod_plugin_common.sh chmod 777 /sbin/murkmod-daemon.sh /sbin/chromeos_startup.sh /sbin/chromeos_startup /usr/bin/crosh /usr/share/vboot/bin/ssd_util.sh /sbin/image_patcher.sh } @@ -225,7 +226,7 @@ set_cros_debug() { check_legacy_daemon() { if [ -f /sbin/fakemurk-daemon.sh ]; then echo "Found legacy fakemurk daemon, removing..." - kill $(pgrep fakemurk) + kill -9 $(pgrep fakemurk) rm -f /sbin/fakemurk-daemon.sh mkdir -p /var/murkmod echo "Restarting daemon..." diff --git a/mush.sh b/mush.sh index 9017bfc..5b38fd4 100644 --- a/mush.sh +++ b/mush.sh @@ -172,12 +172,99 @@ EOF 113) runjob list_plugins ;; 114) runjob install_plugin_legacy ;; 115) runjob uninstall_plugin_legacy ;; + 201) runjob api_read_file ;; + 202) runjob api_write_file ;; + 203) runjob api_append_file ;; + 204) runjob api_touch_file ;; + 205) runjob api_create_dir ;; + 206) runjob api_rm_file ;; + 207) runjob api_rm_dir ;; + 208) runjob api_ls_dir ;; + 209) runjob api_cd ;; + 301) runjob stack_push ;; + 302) runjob stack_pop ;; *) echo && echo "Invalid option, dipshit." && echo ;; esac done } +stack_push() { + echo "stack name?" + read -r name + echo "text to push?" + read -r text + echo "$text" >> "/mnt/stateful_partition/murkmod/stacks/$name" +} + +stack_pop() { + echo "stack name?" + read -r name + echo "start" + echo $(head -n 1 "/mnt/stateful_partition/murkmod/stacks/$STACK_NAME") + echo "end" + sed -i 1d "/mnt/stateful_partition/murkmod/stacks/$STACK_NAME" # delete first line +} + +api_read_file() { + echo "file to read?" + read -r filename + local contents=$( base64 $filename ) + echo "start content: $contents end content" +} + +api_write_file() { + echo "file to write to?" + read -r filename + echo "base64 contents?" + read -r contents + base64 -d <<< "$contents" > $filename +} + +api_append_file() { + echo "file to write to?" + read -r filename + echo "base64 contents to append?" + read -r contents + base64 -d <<< "$contents" >> $filename +} + +api_touch_file() { + echo "filename?" + read -r filename + touch $filename +} + +api_create_dir() { + echo "dirname?" + read -r dirname + mkdir -p $dirname +} + +api_rm_file() { + echo "filename?" + read -r filename + rm -f $filename +} + +api_rm_dir() { + echo "dirname?" + read -r dirname + rm -Rf $dirname +} + +api_ls_dir() { + echo "dirname? (or . for current dir)" + read -r dirname + ls $dirname +} + +api_cd() { + echo "dir?" + read -r dirname + cd $dirname +} + install_plugin_legacy() { local raw_url="https://raw.githubusercontent.com/rainestorme/murkmod/main/plugins" diff --git a/plugin_common.sh b/plugin_common.sh new file mode 100644 index 0000000..4a1e729 --- /dev/null +++ b/plugin_common.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +STACK_ENABLED="0" +STACK_NAME="" + +mkdir -p /mnt/stateful_partition/murkmod/stacks + +starts() { + touch /mnt/stateful_partition/murkmod/stacks/$1 + STACK_NAME="$1" + STACK_ENABLED="1" +} + +pushs() { + if [ "$STACK_ENABLED" != "0" ]; then + echo "$1" >> "/mnt/stateful_partition/murkmod/stacks/$STACK_NAME" + else + >&2 echo "The stack is not enabled for this plugin! To enable it, choose a name and run 'starts ' at the beginning of your plugin's script." + fi +} + +pops() { + if [ "$STACK_ENABLED" != "0" ]; then + echo $(head -n 1 "/mnt/stateful_partition/murkmod/stacks/$STACK_NAME") + sed -i 1d "/mnt/stateful_partition/murkmod/stacks/$STACK_NAME" # delete first line + else + >&2 echo "The stack is not enabled for this plugin! To enable it, choose a name and run 'starts ' at the beginning of your plugin's script." + fi +} \ No newline at end of file