From 0fd0077befc5ac71c7491ac4a1decab11a551c0a Mon Sep 17 00:00:00 2001 From: Manti <67705577+mantikafasi@users.noreply.github.com> Date: Tue, 13 Jun 2023 00:33:07 +0300 Subject: [PATCH] Add WebServer Support --- Common/Config.cs | 3 + MLock/App.xaml.cs | 18 +++++- MLock/LockWindow.xaml.cs | 18 +++--- MLock/MLock.csproj | 4 +- MLock/{ => Modules}/USB.cs | 0 MLock/Modules/WebServer.cs | 60 ++++++++++++++++++++ MLock/Utils.cs | 6 +- MLockConfigurator/App.xaml.cs | 16 +++++- MLockConfigurator/ConfiguratorWindow.xaml | 15 ++++- MLockConfigurator/ConfiguratorWindow.xaml.cs | 17 +++++- MLockConfigurator/Utils.cs | 14 ++--- README.md | 10 +++- 12 files changed, 153 insertions(+), 28 deletions(-) rename MLock/{ => Modules}/USB.cs (100%) create mode 100644 MLock/Modules/WebServer.cs diff --git a/Common/Config.cs b/Common/Config.cs index 6d43954..12ae3bb 100644 --- a/Common/Config.cs +++ b/Common/Config.cs @@ -18,5 +18,8 @@ public class Config [DataMember(Name = "startLocked")] public bool StartLocked { get; set; } [DataMember(Name = "enableBlur")] public bool BlurBackground { get; set; } + [DataMember(Name="enableWebServer")] public bool EnableWebServer { get; set;} + [DataMember (Name="webServerPassword")] public string WebServerPassword { get; set; } + [DataMember (Name="debug")] public bool Debug { get; set; } // this is only used to disable keyhook for testing } } \ No newline at end of file diff --git a/MLock/App.xaml.cs b/MLock/App.xaml.cs index f20040b..0de212a 100644 --- a/MLock/App.xaml.cs +++ b/MLock/App.xaml.cs @@ -2,8 +2,11 @@ using System.Drawing; using System.IO; using System.Reflection; +using System.Security.Principal; +using System.Windows; using System.Windows.Forms; using Common; +using MessageBox = System.Windows.MessageBox; namespace MLock { @@ -14,6 +17,14 @@ public partial class App public App() { + var isAdmin = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); + if (!isAdmin) + { + MessageBox.Show("Please run MLock as administrator", "Admin Privileges Required", MessageBoxButton.OK, + MessageBoxImage.Warning); + Environment.Exit(0); + } + if (!ParseConfig()) Environment.Exit(0); InitializeComponent(); @@ -54,7 +65,7 @@ public bool ParseConfig() { if (!File.Exists(MLOCK_DIR + "\\publicKey.xml")) { - System.Windows.MessageBox.Show( + MessageBox.Show( "Public Key for USB Locking not found, please run the USB key generator and config installer first"); return false; } @@ -65,11 +76,12 @@ public bool ParseConfig() if (Config.INSTANCE.EnablePasswordUnlocking && (Config.INSTANCE.Password == null || Config.INSTANCE.Password.Trim() == "")) { - System.Windows.MessageBox.Show("Password not set, please run the config installer first"); + MessageBox.Show("Password not set, please run the config installer first"); return false; } - if (!Config.INSTANCE.EnablePasswordUnlocking && !Config.INSTANCE.EnableUSBUnlocking) + if (!Config.INSTANCE.EnablePasswordUnlocking && !Config.INSTANCE.EnableUSBUnlocking && + !Config.INSTANCE.EnableWebServer) { MessageBox.Show("No unlocking methods enabled, please run the config installer first"); return false; diff --git a/MLock/LockWindow.xaml.cs b/MLock/LockWindow.xaml.cs index a151b2a..d02d683 100644 --- a/MLock/LockWindow.xaml.cs +++ b/MLock/LockWindow.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using System.Windows; using System.Windows.Interop; using System.Windows.Media; @@ -8,6 +9,7 @@ using System.Windows.Media.Effects; using System.Windows.Media.Imaging; using Common; +using MLock.Modules; namespace MLock { @@ -43,11 +45,10 @@ public MainWindow() Events.LockApp += () => { - var screenshot = Utils.Screenshot(); - - Dispatcher.Invoke(() => { + var screenshot = Utils.Screenshot(); + var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( screenshot.GetHbitmap(), IntPtr.Zero, @@ -62,17 +63,19 @@ public MainWindow() Events.UnlockApp += () => { SetBlur(true); }; } - Native.SetKHookConfig(config); - if (Config.INSTANCE.StartLocked) Events.Lock(); + if (Config.INSTANCE.StartLocked && !Config.INSTANCE.EnableUSBUnlocking) // CheckUSBs method automaticly locks if no USBs are found + Events.Lock(); if (Config.INSTANCE.EnableUSBUnlocking) { USB.Initialize(); - USB.CheckUSBs(); } + + if (Config.INSTANCE.EnableWebServer) + Task.Run(() => new WebServer().Initialize()); } private void SetPasswordText(string text) @@ -132,7 +135,8 @@ public void OnLock() return; } - Native.InstallKHook(); + if (!Config.INSTANCE.Debug) + Native.InstallKHook(); Visibility = Visibility.Visible; }); } diff --git a/MLock/MLock.csproj b/MLock/MLock.csproj index b701463..3bfc7de 100644 --- a/MLock/MLock.csproj +++ b/MLock/MLock.csproj @@ -78,7 +78,8 @@ Designer - + + MSBuild:Compile @@ -123,5 +124,6 @@ Common + \ No newline at end of file diff --git a/MLock/USB.cs b/MLock/Modules/USB.cs similarity index 100% rename from MLock/USB.cs rename to MLock/Modules/USB.cs diff --git a/MLock/Modules/WebServer.cs b/MLock/Modules/WebServer.cs new file mode 100644 index 0000000..dbe0dc8 --- /dev/null +++ b/MLock/Modules/WebServer.cs @@ -0,0 +1,60 @@ +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using Common; + +namespace MLock.Modules +{ + internal class WebServer + { + private CancellationTokenSource cts; + private HttpListener listener; + + public async Task Initialize() + { + listener = new HttpListener(); + listener.Prefixes.Add("http://+:4444/"); + + listener.Start(); + + while (listener.IsListening) + { + var context = await listener.GetContextAsync(); + ProcessRequest(context); + } + + listener.Stop(); + } + + private void ProcessRequest(HttpListenerContext context) + { + var password = context.Request.QueryString.Get("password"); + if (password == null || password != Config.INSTANCE.WebServerPassword) + { + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + context.Response.Close(); + return; + } + + switch (context.Request.Url.AbsolutePath) + { + case "/lock": + Events.Lock(); + break; + case "/unlock": + Events.Unlock(); + break; + } + + context.Response.StatusCode = (int)HttpStatusCode.OK; + + context.Response.Close(); + } + + private void StopServer(object sender, RoutedEventArgs e) // I am guessing server gets closed automatically when the program closes + { + cts?.Cancel(); + } + } +} \ No newline at end of file diff --git a/MLock/Utils.cs b/MLock/Utils.cs index b1a6e79..231f78b 100644 --- a/MLock/Utils.cs +++ b/MLock/Utils.cs @@ -39,8 +39,10 @@ public static Bitmap Screenshot() var captureRectangle = Screen.PrimaryScreen.Bounds; var captureBitmap = new Bitmap(captureRectangle.Width, captureRectangle.Height); - var captureGraphics = Graphics.FromImage(captureBitmap); - captureGraphics.CopyFromScreen(captureRectangle.Left, captureRectangle.Top, 0, 0, captureRectangle.Size); + using (var graphics = Graphics.FromImage(captureBitmap)) + { + graphics.CopyFromScreen(captureRectangle.Left, captureRectangle.Top, 0, 0, captureRectangle.Size); + } return captureBitmap; } diff --git a/MLockConfigurator/App.xaml.cs b/MLockConfigurator/App.xaml.cs index d231b3c..6b7a16a 100644 --- a/MLockConfigurator/App.xaml.cs +++ b/MLockConfigurator/App.xaml.cs @@ -1,9 +1,23 @@ -namespace MLockUSBKeyGenerator +using System.Windows; +using System; + +namespace MLockUSBKeyGenerator { /// /// Interaction logic for App.xaml /// public partial class App { + public App() + { + if (!Utils.IsAdmin()) + { + MessageBox.Show("Configurator requires administrative privileges to properly save the config file. Please run the program as an administrator.", "Admin Privileges Required", MessageBoxButton.OK, MessageBoxImage.Warning); + Environment.Exit(0); + return; + } + + InitializeComponent(); + } } } \ No newline at end of file diff --git a/MLockConfigurator/ConfiguratorWindow.xaml b/MLockConfigurator/ConfiguratorWindow.xaml index 08a5b54..84af9ee 100644 --- a/MLockConfigurator/ConfiguratorWindow.xaml +++ b/MLockConfigurator/ConfiguratorWindow.xaml @@ -4,7 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" - Title="MLock Config Generator" Height="400" Width="525"> + Title="MLock Config Generator" Height="500" Width="525"> @@ -22,6 +22,19 @@ IsEnabled="{Binding EnablePasswordUnlocking}" /> + + + + + + + + + + diff --git a/MLockConfigurator/ConfiguratorWindow.xaml.cs b/MLockConfigurator/ConfiguratorWindow.xaml.cs index 5d4e8ec..748e257 100644 --- a/MLockConfigurator/ConfiguratorWindow.xaml.cs +++ b/MLockConfigurator/ConfiguratorWindow.xaml.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Security.AccessControl; using System.Windows; using Common; using Microsoft.Win32; @@ -106,6 +107,14 @@ public void InstallConfigButton_Click(object sender, RoutedEventArgs e) if (config.EnableUSBUnlocking && config.privateKey != null) File.WriteAllText(MLOCK_DIR + "\\publicKey.xml", RSAUtils.GetPublicKey(config.privateKey)); + + // Make Config file only readable by admins + FileSecurity fileSecurity = File.GetAccessControl(MLOCK_DIR); + fileSecurity.SetAccessRuleProtection(true, false); + FileSystemAccessRule rule = new FileSystemAccessRule("Administrators", FileSystemRights.FullControl, AccessControlType.Allow); + fileSecurity.AddAccessRule(rule); + File.SetAccessControl(MLOCK_DIR, fileSecurity); + MessageBox.Show("Config installed successfully"); } } @@ -142,7 +151,13 @@ public bool ValidateConfig() return false; } - if (!config.EnablePasswordUnlocking && !config.EnableUSBUnlocking) + if (Config.INSTANCE.EnableWebServer && Config.INSTANCE.WebServerPassword.Trim() == "") + { + MessageBox.Show("WebServer password not set"); + return false; + } + + if (!config.EnablePasswordUnlocking && !config.EnableUSBUnlocking && !config.EnableWebServer) { MessageBox.Show("No unlocking methods enabled, select one first"); return false; diff --git a/MLockConfigurator/Utils.cs b/MLockConfigurator/Utils.cs index 61c7a9c..92090a4 100644 --- a/MLockConfigurator/Utils.cs +++ b/MLockConfigurator/Utils.cs @@ -39,17 +39,13 @@ public static bool IsTaskInstalled() return TaskService.Instance.RootFolder.Tasks.Any(task => task.Name == "MLockTask"); } - public static void InstallTask() + public static bool IsAdmin() { - var isAdmin = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); - - if (!isAdmin) - { - MessageBox.Show("To Install task, please run Configurator as admin"); - // Instead of this I can make it start a CMD process as admin and copy file but better do in code i think - return; - } + return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); + } + public static void InstallTask() + { var td = TaskService.Instance.NewTask(); td.RegistrationInfo.Description = "Starts MLock"; td.Principal.RunLevel = TaskRunLevel.Highest; diff --git a/README.md b/README.md index 7a394e3..e8527de 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,14 @@ https://github.com/mantikafasi/MLock/assets/67705577/7440eb07-5159-47ea-a202-524 Incase you get locked out, from different account with admin permissions you can delete config.json inside C:/Users/YourUser/AppData/Roaming/MLock +## Notes +- Currently passwords are stored as plaintext in config.json, so any user with admin permissions can see your password. +- WebServer doesnt use https, so if someone is sniffing your network they can see your password. + ## TODO -- [ ] Add more unlock methods (Like from mobile app) -- [ ] Design a better UI (current one is terrible) -- [ ] Add option to configurator to run program at startup +- [x] Add more unlock methods (Like from mobile app) +- [x] Design a better UI (current one is terrible) +- [x] Add option to configurator to run program at startup - [ ] Add github actions to create releases automatically - [ ] Maybe add option to remove sound when locked - [ ] Log Failures to file