From 2a747334bd926d79537b9e8d4f38c79a815752e5 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 7 Mar 2017 14:56:48 -0500 Subject: [PATCH] WHOA HACKING --- .../Applications/TutorialBox.Designer.cs | 57 +++ ShiftOS.WinForms/Applications/TutorialBox.cs | 73 +++ .../Applications/TutorialBox.resx | 120 +++++ ShiftOS.WinForms/Controls/TerminalBox.cs | 2 + ShiftOS.WinForms/HackerCommands.cs | 484 +++++++++++++++++- ShiftOS.WinForms/ShiftOS.WinForms.csproj | 9 + ShiftOS_TheReturn/Command.cs | 6 + ShiftOS_TheReturn/Commands.cs | 28 + ShiftOS_TheReturn/KernelWatchdog.cs | 70 +++ ShiftOS_TheReturn/SaveSystem.cs | 4 +- ShiftOS_TheReturn/ServerManager.cs | 7 + ShiftOS_TheReturn/ShiftOS.Engine.csproj | 1 + ShiftOS_TheReturn/Shiftorium.cs | 7 +- ShiftOS_TheReturn/TerminalBackend.cs | 156 +++--- 14 files changed, 939 insertions(+), 85 deletions(-) create mode 100644 ShiftOS.WinForms/Applications/TutorialBox.Designer.cs create mode 100644 ShiftOS.WinForms/Applications/TutorialBox.cs create mode 100644 ShiftOS.WinForms/Applications/TutorialBox.resx create mode 100644 ShiftOS_TheReturn/KernelWatchdog.cs diff --git a/ShiftOS.WinForms/Applications/TutorialBox.Designer.cs b/ShiftOS.WinForms/Applications/TutorialBox.Designer.cs new file mode 100644 index 0000000..6e74023 --- /dev/null +++ b/ShiftOS.WinForms/Applications/TutorialBox.Designer.cs @@ -0,0 +1,57 @@ +namespace ShiftOS.WinForms.Applications +{ + partial class TutorialBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.lbltuttext = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // lbltuttext + // + this.lbltuttext.Dock = System.Windows.Forms.DockStyle.Fill; + this.lbltuttext.Location = new System.Drawing.Point(0, 0); + this.lbltuttext.Name = "lbltuttext"; + this.lbltuttext.Size = new System.Drawing.Size(401, 134); + this.lbltuttext.TabIndex = 0; + // + // TutorialBox + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.lbltuttext); + this.Name = "TutorialBox"; + this.Size = new System.Drawing.Size(401, 134); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label lbltuttext; + } +} diff --git a/ShiftOS.WinForms/Applications/TutorialBox.cs b/ShiftOS.WinForms/Applications/TutorialBox.cs new file mode 100644 index 0000000..25921e1 --- /dev/null +++ b/ShiftOS.WinForms/Applications/TutorialBox.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using ShiftOS.Engine; +using System.Threading; + +namespace ShiftOS.WinForms.Applications +{ + + [DefaultTitle("Tutorial objective")] + public partial class TutorialBox : UserControl, IShiftOSWindow + { + public TutorialBox() + { + InitializeComponent(); + IsComplete = false; + lbltuttext.Text = ""; + } + + bool stillTyping = false; + + public void SetObjective(string text) + { + while (stillTyping == true) + { + + } + + new Thread(() => + { + stillTyping = true; + this.Invoke(new Action(() => + { + lbltuttext.Text = ""; + })); + foreach(var c in text.ToCharArray()) + { + this.Invoke(new Action(() => + { + lbltuttext.Text += c; + })); + Thread.Sleep(75); + } + stillTyping = false; + }).Start(); + } + + public void OnLoad() + { + } + + public void OnSkinLoad() + { + } + + public bool IsComplete { get; set; } + + public bool OnUnload() + { + return IsComplete; + } + + public void OnUpgrade() + { + } + } +} diff --git a/ShiftOS.WinForms/Applications/TutorialBox.resx b/ShiftOS.WinForms/Applications/TutorialBox.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/ShiftOS.WinForms/Applications/TutorialBox.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ShiftOS.WinForms/Controls/TerminalBox.cs b/ShiftOS.WinForms/Controls/TerminalBox.cs index 200c1d7..4fcb429 100644 --- a/ShiftOS.WinForms/Controls/TerminalBox.cs +++ b/ShiftOS.WinForms/Controls/TerminalBox.cs @@ -52,7 +52,9 @@ namespace ShiftOS.WinForms.Controls public void Write(string text) { + this.HideSelection = true; this.AppendText(Localization.Parse(text)); + this.HideSelection = false; } public void WriteLine(string text) diff --git a/ShiftOS.WinForms/HackerCommands.cs b/ShiftOS.WinForms/HackerCommands.cs index ebe25a2..7938fd0 100644 --- a/ShiftOS.WinForms/HackerCommands.cs +++ b/ShiftOS.WinForms/HackerCommands.cs @@ -1,27 +1,67 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Newtonsoft.Json; using ShiftOS.Engine; +using ShiftOS.Objects; using ShiftOS.WinForms.Applications; +using static ShiftOS.Objects.ShiftFS.Utils; namespace ShiftOS.WinForms { - [Namespace("l337")] + [Namespace("puppy")] + [RequiresUpgrade("hacker101_deadaccts")] + [KernelMode] + public static class KernelPuppyCommands + { + [Command("clear", true)] + public static bool ClearLogs() + { + WriteAllText("0:/system/data/kernel.log", ""); + Console.WriteLine(" logs cleared successfully."); + return true; + } + } + + [Namespace("krnl")] + public static class KernelCommands + { + [Command("control", true)] + [RequiresArgument("pass")] + public static bool Control(Dictionary args) + { + if(args["pass"].ToString() == ServerManager.thisGuid.ToString()) + { + KernelWatchdog.Log("warn", "User has breached the kernel."); + KernelWatchdog.EnterKernelMode(); + } + return true; + } + + [Command("lock_session")] + [KernelMode] + public static bool LeaveControl() + { + KernelWatchdog.Log("inf", "User has left the kernel-mode session."); + KernelWatchdog.LeaveKernelMode(); + KernelWatchdog.MudConnected = true; + return true; + } + } + + [Namespace("hacker101")] [RequiresUpgrade("hacker101_deadaccts")] public static class HackerCommands { private static void writeSlow(string text) { Console.Write("[hacker101@undisclosed]: "); - foreach(var c in text.ToCharArray()) - { - Console.Write(c); - Thread.Sleep(125); - } - Console.WriteLine(); + Thread.Sleep(200); + Console.WriteLine(text); Thread.Sleep(1000); } @@ -88,9 +128,217 @@ namespace ShiftOS.WinForms internal static void StartHackerTutorial() { - //nyi + Desktop.InvokeOnWorkerThread(() => + { + var tut = new TutorialBox(); + AppearanceManager.SetupWindow(tut); + + new Thread(() => + { + + + int tutPos = 0; + Action ondec = () => + { + if (tutPos == 2) + tutPos++; + }; + TerminalBackend.CommandProcessed += (o, a) => + { + switch (tutPos) + { + + case 0: + case 10: + if (o.ToLower().StartsWith("mud.disconnect")) + { + tutPos++; + } + break; + case 11: + if (o.ToLower().StartsWith("krnl.lock_session")) + tutPos++; + break; + case 1: + if (o.ToLower().StartsWith("hacker101.brute_decrypt")) + { + if (a.Contains("0:/system/data/kernel.log")) + { + tutPos++; + } + } + break; + case 3: + if (o.ToLower().StartsWith("krnl.control")) + { + tutPos++; + } + break; + case 4: + if (o.ToLower().StartsWith("puppy.clear")) + tutPos++; + break; + case 5: + if (o.ToLower().StartsWith("mud.reconnect")) + tutPos++; + break; + case 6: + if (o.ToLower().StartsWith("mud.sendmsg")) + { + var msg = JsonConvert.DeserializeObject(a); + try + { + if (msg.header == "getusers" && msg.body == "dead") + tutPos++; + } + catch + { + + } + } + break; + case 7: + if (o.ToLower().StartsWith("hacker101.breach_user_password")) + tutPos++; + break; + case 8: + if (o.ToLower().StartsWith("hacker101.print_user_info")) + tutPos++; + break; + case 9: + if (o.ToLower().StartsWith("hacker101.steal_codepoints")) + tutPos++; + break; + } + }; + tut.SetObjective("Welcome to the dead account exploitation tutorial. In this tutorial you will learn the basics of hacking within the multi-user domain."); + Thread.Sleep(1000); + tut.SetObjective("We will start with a simple system exploit - gaining kernel-level access to ShiftOS. This can help you perform actions not ever possible in the user level."); + Thread.Sleep(1000); + tut.SetObjective("To gain root access, you will first need to breach the system watchdog to keep it from dialing home to DevX."); + Thread.Sleep(1000); + tut.SetObjective("The watchdog can only function when it has a successful connection to the multi-user domain. You will need to use the MUD Control Centre to disconnect yourself from the MUD. This will lock you out of most features. To disconnect from the multi-user domain, simply run the 'mud.disconnect' command."); + while(tutPos == 0) + { + + } + tut.SetObjective("As you can see, the kernel watchdog has shut down temporarily, however before the disconnect it was able to tell DevX that it has gone offline."); + Thread.Sleep(1000); + tut.SetObjective("You'll also notice that commands like the shiftorium, MUD control centre and various applications that utilize these system components no longer function."); + Thread.Sleep(1000); + tut.SetObjective("The watchdog, however, is still watching. DevX was smart and programmed the kernel to log all events to a local file in 0:/system/data/kernel.log."); + Thread.Sleep(1000); + tut.SetObjective("You will need to empty out this file before you can connect to the multi-user domain, as the watchdog will send the contents of this file straight to DevX."); + Thread.Sleep(1000); + tut.SetObjective("Or, you can do what we're about to do and attempt to decrypt the log and sniff out the kernel-mode access password."); + Thread.Sleep(1000); + tut.SetObjective("This will allow us to gain kernel-level access to our system using the krnl.control{pass:} command."); + Thread.Sleep(1000); + tut.SetObjective("Let's start decrypting the log file using the hacker101.brute_decrypt{file:} script. The file: argument is a string and should point to a .log file. When the script succeeds, you will see a TextPad open with the decrypted contents."); + while(tutPos == 1) + { + + } + onCompleteDecrypt += ondec; + tut.SetObjective("This script isn't the most agile script ever, but it'll get the job done."); + while(tutPos == 2) + { + + } + onCompleteDecrypt -= ondec; + tut.SetObjective("Alright - it's done. Here's how it's laid out. In each log entry, you have the timestamp, then the event name, then the event description."); + Thread.Sleep(1000); + tut.SetObjective("Look for the most recent 'mudhandshake' event. This contains the kernel access code."); + Thread.Sleep(1000); + tut.SetObjective("Once you have it, run 'krnl.control{pass:\"the-kernel-code-here\"}. This will allow you to gain access to the kernel."); + while(tutPos == 3) + { + + } + tut.SetObjective("You are now in kernel mode. Every command you enter will run on the kernel. Now, let's clear the watchdog's logfile and reconnect to the multi-user domain."); + Thread.Sleep(1000); + tut.SetObjective("To clear the log, simply run 'puppy.clear'."); + while(tutPos == 4) + { + + } + tut.SetObjective("Who's a good dog... You are, ShiftOS. Now, we can connect back to the MUD using 'mud.reconnect'."); + Thread.Sleep(1000); + while(tutPos == 5) + { + + } + tut.SetObjective("We have now snuck by the watchdog and DevX has no idea. With kernel-level access, everything you do is not logged, however if you perform too much in one shot, you'll get kicked off and locked out of the multi-user domain temporarily."); + Thread.Sleep(1000); + tut.SetObjective("So, let's focus on the job. You want to get into one of those fancy dead accounts, don't ya? Well, first, we need to talk with the MUD to get a list of these accounts."); + Thread.Sleep(1000); + tut.SetObjective("Simply run the `mud.sendmsg` command, specifying a 'header' of \"getusers\", and a body of \"dead\"."); + while(tutPos == 6) + { + + } + tut.SetObjective("Great. We now have the usernames and sysnames of all dead accounts on the MUD. Now let's use the hacker101.breach_user_password{user:,sys:} command to breach one of these accounts' passwords."); + while(tutPos == 7) + { + + } + tut.SetObjective("There - you now have access to that account. Use its password, username and sysname and run the hacker101.print_user_info{user:,pass:,sys:} command to print the entirety of this user's information."); + while(tutPos == 8) + { + + } + tut.SetObjective("Now you can see a list of the user's Codepoints among other things. Now you can steal their codepoints by using the hacker101.steal_codepoints{user:,pass:,sys;,amount:} command. Be careful. This may alert DevX."); + while(tutPos == 9) + { + + } + if(devx_alerted == true) + { + tut.SetObjective("Alright... enough fun and games. DevX just found out we were doing this."); + Thread.Sleep(500); + tut.SetObjective("Quick! Disconnect from the MUD!!"); + while(tutPos == 10) + { + + } + tut.SetObjective("Now, get out of kernel mode! To do that, run krnl.lock_session."); + while(tutPos == 11) + { + + } + + } + else + { + tut.SetObjective("OK, that was risky, but we pulled it off. Treat yourself! But first, let's get you out of kernel mode."); + Thread.Sleep(500); + tut.SetObjective("First we need to get you off the MUD. Simply run mud.disconnect again."); + while (tutPos == 10) + { + + } + tut.SetObjective("Now, let's run krnl.lock_session. This will lock you back into the user mode, and reconnect you to the MUD."); + while (tutPos == 11) + { + + } + tut.SetObjective("If, for some reason, DevX DOES find out, you have to be QUICK to get off of kernel mode. You don't want to make him mad."); + } + + Thread.Sleep(1000); + tut.SetObjective("So that's all for now. Whenever you're in kernel mode again, and you have access to a user account, try breaching their filesystem next time. You can use sos.help{ns:} to show commands from a specific namespace to help you find more commands easily."); + Thread.Sleep(1000); + tut.SetObjective("You can now close this window."); + tut.IsComplete = true; + + }).Start(); + }); } + private static bool devx_alerted = false; + + private static event Action onCompleteDecrypt; + private static bool terminalIsOpen() { foreach(var win in AppearanceManager.OpenForms) @@ -100,6 +348,226 @@ namespace ShiftOS.WinForms } return false; } + + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_"; + + [Command("breach_user_password")] + [KernelMode] + [RequiresArgument("user")] + [RequiresArgument("sys")] + [RequiresUpgrade("hacker101_deadaccts")] + public static bool BreachUserPassword(Dictionary args) + { + string usr = args["user"].ToString(); + string sys = args["sys"].ToString(); + + ServerMessageReceived msgReceived = null; + + Console.WriteLine("--hooking system thread..."); + + msgReceived = (msg) => + { + if(msg.Name == "user_data") + { + var sve = JsonConvert.DeserializeObject(msg.Contents); + var rnd = new Random(); + var sw = new Stopwatch(); + sw.Start(); + string pass = ""; + for(int i = 0; i < sve.Password.Length; i++) + { + char c = '\0'; + while (c != sve.Password[i]) + c = chars[rnd.Next(0, chars.Length)]; + pass += c; + Thread.Sleep(rnd.Next(25,75)); + } + sw.Stop(); + Console.WriteLine(pass); + Console.WriteLine(); + Console.WriteLine("--password breached. Operation took " + sw.ElapsedMilliseconds + " milliseconds."); + } + else if(msg.Name == "user_data_not_found") + { + Console.WriteLine("--access denied."); + } + ServerManager.MessageReceived -= msgReceived; + }; + + Console.WriteLine("--beginning brute-force attack on " + usr + "@" + sys + "..."); + Thread.Sleep(500); + ServerManager.MessageReceived += msgReceived; + + ServerManager.SendMessage("get_user_data", JsonConvert.SerializeObject(new + { + user = usr, + sysname = sys + })); + return true; + } + + [Command("print_user_info")] + [KernelMode] + [RequiresArgument("pass")] + [RequiresArgument("user")] + [RequiresArgument("sys")] + [RequiresUpgrade("hacker101_deadaccts")] + public static bool PrintUserInfo(Dictionary args) + { + string usr = args["user"].ToString(); + string sys = args["sys"].ToString(); + string pass = args["pass"].ToString(); + + ServerMessageReceived msgReceived = null; + + Console.WriteLine("--hooking multi-user domain response call..."); + + msgReceived = (msg) => + { + if (msg.Name == "user_data") + { + var sve = JsonConvert.DeserializeObject(msg.Contents); + if(sve.Password == pass) + { + Console.WriteLine("Username: " + sve.Username); + Console.WriteLine("Password: " + sve.Password); + Console.WriteLine("System name: " + sve.SystemName); + Console.WriteLine(); + Console.WriteLine("Codepoints: " + sve.Codepoints.ToString()); + + } + else + { + Console.WriteLine("--access denied."); + } + + } + else if (msg.Name == "user_data_not_found") + { + Console.WriteLine("--access denied."); + } + ServerManager.MessageReceived -= msgReceived; + }; + + Console.WriteLine("--contacting multi-user domain..."); + Thread.Sleep(500); + ServerManager.MessageReceived += msgReceived; + + ServerManager.SendMessage("get_user_data", JsonConvert.SerializeObject(new + { + user = usr, + sysname = sys + })); + return true; + } + + [Command("steal_codepoints")] + [KernelMode] + [RequiresArgument("amount")] + [RequiresArgument("pass")] + [RequiresArgument("user")] + [RequiresArgument("sys")] + [RequiresUpgrade("hacker101_deadaccts")] + public static bool StealCodepoints(Dictionary args) + { + string usr = args["user"].ToString(); + string sys = args["sys"].ToString(); + string pass = args["pass"].ToString(); + long amount = (long)args["amount"]; + + if(amount < 0) + { + Console.WriteLine("--invalid codepoint amount - halting..."); + return true; + } + + ServerMessageReceived msgReceived = null; + + Console.WriteLine("--hooking multi-user domain response call..."); + + msgReceived = (msg) => + { + if (msg.Name == "user_data") + { + var sve = JsonConvert.DeserializeObject(msg.Contents); + if (sve.Password == pass) + { + if(amount > sve.Codepoints) + { + Console.WriteLine("--can't steal this many codepoints from user."); + return; + } + + sve.Codepoints -= amount; + SaveSystem.TransferCodepointsFrom(sve.Username, amount); + ServerManager.SendMessage("mud_save_allow_dead", JsonConvert.SerializeObject(sve)); + SaveSystem.SaveGame(); + } + else + { + Console.WriteLine("--access denied."); + } + + } + else if (msg.Name == "user_data_not_found") + { + Console.WriteLine("--access denied."); + } + ServerManager.MessageReceived -= msgReceived; + }; + + Console.WriteLine("--contacting multi-user domain..."); + Thread.Sleep(500); + ServerManager.MessageReceived += msgReceived; + + ServerManager.SendMessage("get_user_data", JsonConvert.SerializeObject(new + { + user = usr, + sysname = sys + })); + return true; + } + + + + [Command("brute_decrypt", true)] + [RequiresArgument("file")] + public static bool BruteDecrypt(Dictionary args) + { + if (FileExists(args["file"].ToString())) + { + string pass = new Random().Next(1000, 10000).ToString(); + string fake = ""; + Console.WriteLine("Beginning brute-force attack on password."); + var s = new Stopwatch(); + s.Start(); + for(int i = 0; i < pass.Length; i++) + { + for(int num = 0; num < 10; num++) + { + if(pass[i].ToString() == num.ToString()) + { + fake += num.ToString(); + Console.Write(num); + } + } + } + s.Stop(); + + Console.WriteLine("...password cracked - operation took " + s.ElapsedMilliseconds + " milliseconds."); + var tp = new TextPad(); + AppearanceManager.SetupWindow(tp); + WriteAllText("0:/temp.txt", ReadAllText(args["file"].ToString())); + tp.LoadFile("0:/temp.txt"); + Delete("0:/temp.txt"); + onCompleteDecrypt?.Invoke(); + } + else + { + Console.WriteLine("brute_decrypt: file not found"); + } + return true; + } } [Namespace("storydev")] diff --git a/ShiftOS.WinForms/ShiftOS.WinForms.csproj b/ShiftOS.WinForms/ShiftOS.WinForms.csproj index 4bc79a0..7f728d5 100644 --- a/ShiftOS.WinForms/ShiftOS.WinForms.csproj +++ b/ShiftOS.WinForms/ShiftOS.WinForms.csproj @@ -208,6 +208,12 @@ Terminal.cs + + UserControl + + + TutorialBox.cs + @@ -350,6 +356,9 @@ Terminal.cs + + TutorialBox.cs + DownloadControl.cs diff --git a/ShiftOS_TheReturn/Command.cs b/ShiftOS_TheReturn/Command.cs index 85da6ca..a5924ed 100644 --- a/ShiftOS_TheReturn/Command.cs +++ b/ShiftOS_TheReturn/Command.cs @@ -30,6 +30,12 @@ using System.Threading.Tasks; namespace ShiftOS.Engine { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] + public class KernelModeAttribute : Attribute + { + + } + public class Command : Attribute { public string name; diff --git a/ShiftOS_TheReturn/Commands.cs b/ShiftOS_TheReturn/Commands.cs index 76aa42f..0ea00e5 100644 --- a/ShiftOS_TheReturn/Commands.cs +++ b/ShiftOS_TheReturn/Commands.cs @@ -164,7 +164,35 @@ namespace ShiftOS.Engine } } + [Command("reconnect")] + [RequiresUpgrade("hacker101_deadaccts")] + public static bool Reconnect() + { + Console.WriteLine("--reconnecting to multi-user domain..."); + KernelWatchdog.MudConnected = true; + Console.WriteLine("--done."); + return true; + } + [Command("disconnect")] + [RequiresUpgrade("hacker101_deadaccts")] + public static bool Disconnect() + { + Console.WriteLine("--connection to multi-user domain severed..."); + KernelWatchdog.MudConnected = false; + return true; + } + + [Command("sendmsg")] + [KernelMode] + [RequiresUpgrade("hacker101_deadaccts")] + [RequiresArgument("header")] + [RequiresArgument("body")] + public static bool SendMessage(Dictionary args) + { + ServerManager.SendMessage(args["header"].ToString(), args["body"].ToString()); + return true; + } } [RequiresUpgrade("mud_fundamentals")] diff --git a/ShiftOS_TheReturn/KernelWatchdog.cs b/ShiftOS_TheReturn/KernelWatchdog.cs new file mode 100644 index 0000000..1b59b25 --- /dev/null +++ b/ShiftOS_TheReturn/KernelWatchdog.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using static ShiftOS.Objects.ShiftFS.Utils; + +namespace ShiftOS.Engine +{ + public static class KernelWatchdog + { + public static void Log(string e, string desc) + { + string line = $"[{DateTime.Now}] <{e}> {desc}"; + if (FileExists("0:/system/data/kernel.log")) + { + string contents = ReadAllText("0:/system/data/kernel.log"); + contents += Environment.NewLine + line; + WriteAllText("0:/system/data/kernel.log", contents); + } + else + { + WriteAllText("0:/system/data/kernel.log", line); + } + } + + public static bool InKernelMode { get; private set; } + public static bool MudConnected { get; set; } + + public static bool IsSafe(Type type) + { + if (InKernelMode == true) + return true; + + foreach (var attrib in type.GetCustomAttributes(false)) + { + if (attrib is KernelModeAttribute) + return false; + } + return true; + } + + public static bool IsSafe(MethodInfo type) + { + if (InKernelMode == true) + return true; + + foreach (var attrib in type.GetCustomAttributes(false)) + { + if (attrib is KernelModeAttribute) + return false; + } + return true; + } + + + public static void EnterKernelMode() + { + InKernelMode = true; + Console.WriteLine(" Watchdog deactivated, system-level access granted."); + } + + public static void LeaveKernelMode() + { + InKernelMode = false; + Console.WriteLine(" Kernel mode disabled."); + } + } +} diff --git a/ShiftOS_TheReturn/SaveSystem.cs b/ShiftOS_TheReturn/SaveSystem.cs index b9633e5..df4c6d6 100644 --- a/ShiftOS_TheReturn/SaveSystem.cs +++ b/ShiftOS_TheReturn/SaveSystem.cs @@ -155,6 +155,8 @@ namespace ShiftOS.Engine public static void FinishBootstrap() { + KernelWatchdog.Log("mud_handshake", "handshake successful: kernel watchdog access code is \"" + ServerManager.thisGuid.ToString() + "\""); + ServerManager.MessageReceived += (msg) => { if (msg.Name == "mud_savefile") @@ -313,7 +315,7 @@ namespace ShiftOS.Engine System.IO.File.WriteAllText(Paths.SaveFile, Utils.ExportMount(0)); } - public static void TransferCodepointsFrom(string who, int amount) + public static void TransferCodepointsFrom(string who, long amount) { NotificationDaemon.AddNotification(NotificationType.CodepointsReceived, amount); CurrentSave.Codepoints += amount; diff --git a/ShiftOS_TheReturn/ServerManager.cs b/ShiftOS_TheReturn/ServerManager.cs index 3059391..a121ab6 100644 --- a/ShiftOS_TheReturn/ServerManager.cs +++ b/ShiftOS_TheReturn/ServerManager.cs @@ -126,6 +126,13 @@ namespace ShiftOS.Engine thisGuid = new Guid(msg.Contents); GUIDReceived?.Invoke(msg.Contents); } + else if(msg.Name == "allusers") + { + foreach(var acc in JsonConvert.DeserializeObject(msg.Contents)) + { + Console.WriteLine(acc); + } + } else if(msg.Name == "update_your_cp") { var args = JsonConvert.DeserializeObject>(msg.Contents); diff --git a/ShiftOS_TheReturn/ShiftOS.Engine.csproj b/ShiftOS_TheReturn/ShiftOS.Engine.csproj index 3702b18..20ca879 100644 --- a/ShiftOS_TheReturn/ShiftOS.Engine.csproj +++ b/ShiftOS_TheReturn/ShiftOS.Engine.csproj @@ -107,6 +107,7 @@ + diff --git a/ShiftOS_TheReturn/Shiftorium.cs b/ShiftOS_TheReturn/Shiftorium.cs index 198dcc7..0bdd9f4 100644 --- a/ShiftOS_TheReturn/Shiftorium.cs +++ b/ShiftOS_TheReturn/Shiftorium.cs @@ -210,9 +210,12 @@ namespace ShiftOS.Engine if (SaveSystem.CurrentSave.StoriesExperienced == null) SaveSystem.CurrentSave.StoriesExperienced = new List(); - if (!SaveSystem.CurrentSave.StoriesExperienced.Contains(id)) - return SaveSystem.CurrentSave.Upgrades[id]; + bool upgInstalled = false; + if(SaveSystem.CurrentSave.Upgrades.ContainsKey(id)) + upgInstalled = SaveSystem.CurrentSave.Upgrades[id]; + if(upgInstalled == false) + return SaveSystem.CurrentSave.StoriesExperienced.Contains(id); return true; } catch diff --git a/ShiftOS_TheReturn/TerminalBackend.cs b/ShiftOS_TheReturn/TerminalBackend.cs index 3c8e62a..8be54d0 100644 --- a/ShiftOS_TheReturn/TerminalBackend.cs +++ b/ShiftOS_TheReturn/TerminalBackend.cs @@ -139,121 +139,129 @@ namespace ShiftOS.Engine { if (Shiftorium.UpgradeAttributesUnlocked(type)) { - foreach (var a in type.GetCustomAttributes(false)) + if (KernelWatchdog.IsSafe(type)) { - if (a is Namespace) + foreach (var a in type.GetCustomAttributes(false)) { - var ns = a as Namespace; - if (text.Split('.')[0] == ns.name) + if (a is Namespace) { - foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) + var ns = a as Namespace; + if (text.Split('.')[0] == ns.name) { - if (Shiftorium.UpgradeAttributesUnlocked(method)) + foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) { - if (CanRunRemotely(method, isRemote)) + if (Shiftorium.UpgradeAttributesUnlocked(method)) { - foreach (var ma in method.GetCustomAttributes(false)) + if (KernelWatchdog.IsSafe(method)) { - if (ma is Command) + if (CanRunRemotely(method, isRemote)) { - var cmd = ma as Command; - if (text.Split('.')[1] == cmd.name) + foreach (var ma in method.GetCustomAttributes(false)) { - - var attr = method.GetCustomAttribute(); - - if (attr != null) + if (ma is Command) { - string newcommand = attr.newcommand; - if (attr.warn) + var cmd = ma as Command; + if (text.Split('.')[1] == cmd.name) { - Console.WriteLine(Localization.Parse((newcommand == "" ? "{ERROR}" : "{WARN}") + attr.reason, new Dictionary() { + + var attr = method.GetCustomAttribute(); + + if (attr != null) + { + string newcommand = attr.newcommand; + if (attr.warn) + { + Console.WriteLine(Localization.Parse((newcommand == "" ? "{ERROR}" : "{WARN}") + attr.reason, new Dictionary() { {"%newcommand", newcommand} })); - } - if (newcommand != "") - { - // redo the entire process running newcommand + } + if (newcommand != "") + { + // redo the entire process running newcommand - return RunClient(newcommand, args); - } - } + return RunClient(newcommand, args); + } + } - var requiresArgs = method.GetCustomAttributes(); + var requiresArgs = method.GetCustomAttributes(); - bool error = false; - bool providedusage = false; + bool error = false; + bool providedusage = false; - foreach (RequiresArgument argument in requiresArgs) - { - if (!args.ContainsKey(argument.argument)) - { - - if (!providedusage) + foreach (RequiresArgument argument in requiresArgs) { - string usageparse = "{COMMAND_" + ns.name.ToUpper() + "_" + cmd.name.ToUpper() + "_USAGE}"; - if (usageparse == Localization.Parse(usageparse)) - usageparse = ""; - else - usageparse = Shiftorium.UpgradeInstalled("help_usage") ? Localization.Parse("{ERROR}{USAGE}" + usageparse, new Dictionary() { + if (!args.ContainsKey(argument.argument)) + { + + if (!providedusage) + { + string usageparse = "{COMMAND_" + ns.name.ToUpper() + "_" + cmd.name.ToUpper() + "_USAGE}"; + if (usageparse == Localization.Parse(usageparse)) + usageparse = ""; + else + usageparse = Shiftorium.UpgradeInstalled("help_usage") ? Localization.Parse("{ERROR}{USAGE}" + usageparse, new Dictionary() { {"%ns", ns.name}, {"%cmd", cmd.name} }) : ""; - Console.WriteLine(usageparse); + Console.WriteLine(usageparse); - providedusage = true; - } + providedusage = true; + } - if (Shiftorium.UpgradeInstalled("help_usage")) - { - Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED}", new Dictionary() { + if (Shiftorium.UpgradeInstalled("help_usage")) + { + Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED}", new Dictionary() { {"%argument", argument.argument} })); + } + else + { + Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED_NO_USAGE}")); + } + + error = true; + } } - else + + if (error) { - Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED_NO_USAGE}")); + throw new Exception("{ERROR_COMMAND_WRONG}"); } - error = true; + try + { + return (bool)method.Invoke(null, new[] { args }); + } + catch (TargetInvocationException e) + { + Console.WriteLine(Localization.Parse("{ERROR_EXCEPTION_THROWN_IN_METHOD}")); + Console.WriteLine(e.InnerException.Message); + Console.WriteLine(e.InnerException.StackTrace); + return true; + } + catch + { + return (bool)method.Invoke(null, new object[] { }); + } } } - - if (error) - { - throw new Exception("{ERROR_COMMAND_WRONG}"); - } - - try - { - return (bool)method.Invoke(null, new[] { args }); - } - catch (TargetInvocationException e) - { - Console.WriteLine(Localization.Parse("{ERROR_EXCEPTION_THROWN_IN_METHOD}")); - Console.WriteLine(e.InnerException.Message); - Console.WriteLine(e.InnerException.StackTrace); - return true; - } - catch - { - return (bool)method.Invoke(null, new object[] { }); - } } } + else + { + Console.WriteLine(text + " cannot be ran in a remote session"); + return true; + } } - } - else - { - Console.WriteLine(text + " cannot be ran in a remote session"); - return true; + } } } } } } + } } }