Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 11 additions & 66 deletions DwmLutGUI/DwmLutGUI/Injector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace DwmLutGUI
{
Expand Down Expand Up @@ -36,7 +35,7 @@ static Injector()
}
catch (Exception)
{
#if !DEBUG
#if RELEASE
MessageBox.Show("Failed to enter debug mode – will not be able to apply LUTs.");
#endif
NoDebug = true;
Expand Down Expand Up @@ -116,41 +115,8 @@ private static void CopyOrConvertLut(string source, string dest)
}
}

private static void ElevatePrivilege()
{
var pid = Process.GetProcessesByName("lsass")[0].Id;
var processHandle = OpenProcess(DesiredAccess.ProcessQueryLimitedInformation, true, (uint)pid);
var openProcessResult = OpenProcessToken(processHandle, DesiredAccess.MaximumAllowed, out var impersonatedTokenHandle);
if (!openProcessResult)
{
throw new Exception("Failed to open process token");
}
var impersonateResult = ImpersonateLoggedOnUser(impersonatedTokenHandle);
if (!impersonateResult)
{
throw new Exception("Failed to impersonate logged on user");
}

// Get username of the current process
StringBuilder userName = new StringBuilder(1024);
uint userNameSize = (uint)userName.Capacity;
var userNameResult = GetUserName(userName, ref userNameSize);
if (!userNameResult)
{
throw new Exception("Failed to get username");
}

// Check if the username is SYSTEM
if (userName.ToString() != "SYSTEM")
{
throw new Exception("Not running as SYSTEM");
}
}

public static void Inject(IEnumerable<MonitorData> monitors)
{
ElevatePrivilege();

File.Copy(AppDomain.CurrentDomain.BaseDirectory + DllName, DllPath, true);
ClearPermissions(DllPath);

Expand Down Expand Up @@ -180,8 +146,11 @@ public static void Inject(IEnumerable<MonitorData> monitors)
var failed = false;
var bytes = Encoding.ASCII.GetBytes(DllPath);
var dwmInstances = Process.GetProcessesByName("dwm");
var currentSessionId = Process.GetCurrentProcess().SessionId;
foreach (var dwm in dwmInstances)
{
// Check if dwm instance has the same session id as the current process
if (dwm.SessionId != currentSessionId) continue;
var address = VirtualAllocEx(dwm.Handle, IntPtr.Zero, (UIntPtr)bytes.Length,
AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
WriteProcessMemory(dwm.Handle, address, bytes, (UIntPtr)bytes.Length, out _);
Expand All @@ -201,35 +170,30 @@ public static void Inject(IEnumerable<MonitorData> monitors)
}

Directory.Delete(LutsPath, true);


if (!failed)
{
RevertToSelf();
return;
}
if (!failed) return;

File.Delete(DllPath);

RevertToSelf();

throw new Exception(
"Failed to load or initialize DLL. This probably means that a LUT file is malformed or that DWM got updated.");
}

public static void Uninject()
{
var currentSessionId = Process.GetCurrentProcess().SessionId;
var dwmInstances = Process.GetProcessesByName("dwm");
foreach (var dwm in dwmInstances)
{
// Check if dwm instance has the same session id as the current process
if (dwm.SessionId != currentSessionId) continue;
var modules = dwm.Modules;
foreach (ProcessModule module in modules)
{
if (module.ModuleName == DllName)
{
var thread = CreateRemoteThread(dwm.Handle, IntPtr.Zero, 0, FreeLibrary, module.BaseAddress,
0, out _);
WaitForSingleObject(thread, uint.MaxValue);
WaitForSingleObject(thread, 3000);
CloseHandle(thread);
}

Expand All @@ -239,7 +203,7 @@ public static void Uninject()
dwm.Dispose();
}

File.Delete(DllPath);
//File.Delete(DllPath);
}

private static void ClearPermissions(string path)
Expand Down Expand Up @@ -284,23 +248,6 @@ private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThread
[DllImport("kernel32.dll")]
private static extern IntPtr CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll")]
private static extern IntPtr OpenProcess(DesiredAccess dwDesiredAccess, bool bInheritHandle,
uint dwProcessId);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr processHandle, DesiredAccess desiredAccess, out IntPtr tokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool ImpersonateLoggedOnUser(IntPtr hToken);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool GetUserName(StringBuilder lpBuffer, ref uint nSize);


[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool RevertToSelf();

[DllImport("kernel32.dll")]
private static extern IntPtr CreateFile(string lpFileName, DesiredAccess dwDesiredAccess, uint dwShareMode,
IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
Expand Down Expand Up @@ -334,9 +281,7 @@ private enum MemoryProtection
private enum DesiredAccess
{
ReadControl = 0x20000,
WriteDac = 0x40000,
ProcessQueryLimitedInformation = 0x1000,
MaximumAllowed = 0x02000000
WriteDac = 0x40000
}

private enum CreationDisposition
Expand Down
50 changes: 50 additions & 0 deletions DwmLutGUI/DwmLutGUI/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using Microsoft.Win32;
using ContextMenu = System.Windows.Forms.ContextMenu;
using MenuItem = System.Windows.Forms.MenuItem;
Expand All @@ -21,6 +24,17 @@ public partial class MainWindow
{
private readonly MainViewModel _viewModel;
private bool _applyOnCooldown;
private static Window _antiDfOverlay;

[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hwnd, int index);

[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

private const int GWL_EXSTYLE = -20;
private const int WS_EX_TRANSPARENT = 0x20;
private const int WS_EX_TOOLWINDOW = 0x80;

private readonly MenuItem _statusItem;
private readonly MenuItem _applyItem;
Expand Down Expand Up @@ -199,6 +213,7 @@ private void Disable_Click(object sender, RoutedEventArgs e)
{
try
{
HideAntiDirectFlipOverlay();
_viewModel.Uninject();
RedrawScreens();
}
Expand All @@ -217,6 +232,7 @@ private void Apply_Click(object sender, RoutedEventArgs e)
{
_viewModel.ReInject();
RedrawScreens();
ShowAntiDirectFlipOverlay();
}
catch (Exception x)
{
Expand All @@ -230,6 +246,40 @@ private void Apply_Click(object sender, RoutedEventArgs e)
});
}

private static void ShowAntiDirectFlipOverlay()
{
if (_antiDfOverlay != null) return;

var rect = Screen.AllScreens.Select(x => x.Bounds).Aggregate(Rectangle.Union);
_antiDfOverlay = new Window
{
WindowStyle = WindowStyle.None,
AllowsTransparency = true,
Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(1, 0, 0, 0)),
Topmost = true,
ShowInTaskbar = false,
ShowActivated = false,
WindowStartupLocation = WindowStartupLocation.Manual,
Left = rect.Left,
Top = rect.Top,
Width = rect.Width,
Height = rect.Height,
};

_antiDfOverlay.Show();

// Make click-through so it doesn't block mouse input
var hwnd = new WindowInteropHelper(_antiDfOverlay).Handle;
var extStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extStyle | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW);
}

private static void HideAntiDirectFlipOverlay()
{
_antiDfOverlay?.Close();
_antiDfOverlay = null;
}

private static void RedrawScreens()
{
var rect = Screen.AllScreens.Select(x => x.Bounds).Aggregate(Rectangle.Union);
Expand Down
Loading