VMProtect/runtime/VMProtect.Runtime/Loader.cs

703 lines
23 KiB
C#

using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
using System.Reflection.Emit;
// ReSharper disable once CheckNamespace
namespace VMProtect
{
[VMProtect.DeleteOnCompilation]
enum MessageType
{
InitializationError,
ProcNotFound,
OrdinalNotFound,
FileCorrupted,
DebuggerFound,
UnregisteredVersion,
VirtualMachineFound
}
[VMProtect.DeleteOnCompilation]
enum ErrorType
{
VIRTUAL_PROTECT_ERROR = 1,
UNPACKER_ERROR = 2
}
[VMProtect.DeleteOnCompilation]
enum LoaderOption
{
CHECK_PATCH = 0x1,
CHECK_DEBUGGER = 0x2,
CHECK_KERNEL_DEBUGGER = 0x4,
EXIT_PROCESS = 0x8,
CHECK_VIRTUAL_MACHINE = 0x10
}
[VMProtect.DeleteOnCompilation]
enum FixupType
{
Absolute = 0,
High = 1,
Low = 2,
HighLow = 3,
Dir64 = 10
}
public static class Loader
{
public static object[] IAT;
internal static bool FindFirmwareVendor(byte[] data)
{
for (var i = 0; i < data.Length; i++)
{
if (i + 3 < data.Length && data[i + 0] == 'Q' && data[i + 1] == 'E' && data[i + 2] == 'M' && data[i + 3] == 'U')
return true;
if (i + 8 < data.Length && data[i + 0] == 'M' && data[i + 1] == 'i' && data[i + 2] == 'c' && data[i + 3] == 'r' && data[i + 4] == 'o' && data[i + 5] == 's' && data[i + 6] == 'o' && data[i + 7] == 'f' && data[i + 8] == 't')
return true;
if (i + 6 < data.Length && data[i + 0] == 'i' && data[i + 1] == 'n' && data[i + 2] == 'n' && data[i + 3] == 'o' && data[i + 4] == 't' && data[i + 5] == 'e' && data[i + 6] == 'k')
return true;
if (i + 9 < data.Length && data[i + 0] == 'V' && data[i + 1] == 'i' && data[i + 2] == 'r' && data[i + 3] == 't' && data[i + 4] == 'u' && data[i + 5] == 'a' && data[i + 6] == 'l' && data[i + 7] == 'B' && data[i + 8] == 'o' && data[i + 9] == 'x')
return true;
if (i + 5 < data.Length && data[i + 0] == 'V' && data[i + 1] == 'M' && data[i + 2] == 'w' && data[i + 3] == 'a' && data[i + 4] == 'r' && data[i + 5] == 'e')
return true;
if (i + 8 < data.Length && data[i + 0] == 'P' && data[i + 1] == 'a' && data[i + 2] == 'r' && data[i + 3] == 'a' && data[i + 4] == 'l' && data[i + 5] == 'l' && data[i + 6] == 'e' && data[i + 7] == 'l' && data[i + 8] == 's')
return true;
}
return false;
}
private static void ShowMessage(uint type, uint param = 0)
{
uint position;
switch (type)
{
case (uint)MessageType.DebuggerFound:
position = (uint)Faces.DEBUGGER_FOUND;
break;
case (uint)MessageType.VirtualMachineFound:
position = (uint)Faces.VIRTUAL_MACHINE_FOUND;
break;
case (uint)MessageType.FileCorrupted:
position = (uint)Faces.FILE_CORRUPTED;
break;
case (uint)MessageType.UnregisteredVersion:
position = (uint)Faces.UNREGISTERED_VERSION;
break;
case (uint)MessageType.InitializationError:
position = (uint)Faces.INITIALIZATION_ERROR;
break;
default:
return;
}
long instance = Marshal.GetHINSTANCE(typeof(Loader).Module).ToInt64();
String message = null;
var buffer = new byte[1024];
for (var pos = 0; pos < 512; pos++)
{
var c = (ushort)(Marshal.ReadInt16(new IntPtr(instance + position + pos * 2)) ^ (BitRotate.Left((uint)Faces.STRING_DECRYPT_KEY, pos) + pos));
if (c == 0)
{
if (pos > 0)
message = Encoding.Unicode.GetString(buffer, 0, pos * 2);
break;
}
buffer[pos * 2] = (byte)c;
buffer[pos * 2 + 1] = (byte)(c >> 8);
}
if (message != null)
{
if (type == (uint)MessageType.InitializationError)
message = String.Format(message, param);
Win32.ShowMessage(message, Assembly.GetExecutingAssembly().GetName().Name, MessageBoxButtons.OK, type == (uint)MessageType.UnregisteredVersion ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
}
}
internal static bool LzmaDecode(IntPtr dst, IntPtr src, byte[] properties, ref uint dstSize, out uint srcSize)
{
srcSize = 0;
unsafe
{
using (
var srcStream = new UnmanagedMemoryStream((byte*)src.ToPointer(), int.MaxValue, int.MaxValue, FileAccess.Read)
)
{
using (
var dstStream = new UnmanagedMemoryStream((byte*) dst.ToPointer(), dstSize, dstSize,
FileAccess.Write))
{
try
{
var coder = new SevenZip.Compression.LZMA.Decoder();
coder.SetDecoderProperties(properties);
coder.Code(srcStream, dstStream, dstSize);
dstStream.Flush();
srcSize = (uint)srcStream.Position;
dstSize = (uint)dstStream.Position;
}
catch (Exception)
{
return false;
}
return true;
}
}
}
}
public static void Main()
{
if (GlobalData.LoaderStatus() != 0)
return;
var module = typeof(Loader).Module;
long instance = Marshal.GetHINSTANCE(module).ToInt64();
var options = (uint)Faces.LOADER_OPTIONS;
GlobalData.SetIsPatchDetected(false);
GlobalData.SetIsDebuggerDetected(false);
GlobalData.SetLoaderCrcInfo((uint)Faces.LOADER_CRC_INFO);
GlobalData.SetLoaderCrcSize((uint)Faces.LOADER_CRC_INFO_SIZE);
GlobalData.SetLoaderCrcHash((uint)Faces.LOADER_CRC_INFO_HASH);
GlobalData.SetServerDate(0);
// detect a debugger
if ((options & (uint)LoaderOption.CHECK_DEBUGGER) != 0)
{
if (Debugger.IsAttached || Debugger.IsLogging())
{
ShowMessage((uint)MessageType.DebuggerFound);
Environment.Exit(1);
return;
}
if (Win32.IsDebuggerPresent() || Win32.CheckRemoteDebuggerPresent())
{
ShowMessage((uint)MessageType.DebuggerFound);
Environment.Exit(1);
return;
}
Win32.NtSetInformationThread(Win32.CurrentThread, Win32.THREADINFOCLASS.ThreadHideFromDebugger, IntPtr.Zero, 0);
}
// check header and loader CRC
var crcSize = (uint)Faces.LOADER_CRC_INFO_SIZE;
if (crcSize != 0)
{
crcSize = (uint)Marshal.ReadInt32(new IntPtr(instance + crcSize));
var crcPosition = (uint)Faces.LOADER_CRC_INFO;
var crcCryptor = new CRCValueCryptor();
bool isValid = true;
var crcInfo = new byte[12];
var crc32 = new CRC32();
var crcHash = (uint)Marshal.ReadInt32(new IntPtr(instance + (uint)Faces.LOADER_CRC_INFO_HASH));
if (crcHash != crc32.Hash(new IntPtr(instance + crcPosition), crcSize))
isValid = false;
for (var i = 0; i < crcSize; i += crcInfo.Length)
{
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
if (crc32.Hash(new IntPtr(instance + address), size) != hash)
isValid = false;
}
if (!isValid)
{
if ((options & (uint)LoaderOption.CHECK_PATCH) != 0)
{
ShowMessage((uint)MessageType.FileCorrupted);
Environment.Exit(1);
return;
}
GlobalData.SetIsPatchDetected(true);
}
}
// check file CRC
crcSize = (uint)Faces.FILE_CRC_INFO_SIZE;
if (crcSize != 0) //-V3022
{
crcSize = (uint)Marshal.ReadInt32(new IntPtr(instance + crcSize));
var crcPosition = (uint)Faces.FILE_CRC_INFO;
bool isValid = true;
var file = Win32.OpenFile(Assembly.GetExecutingAssembly().Location, (uint)Win32.Values.GENERIC_READ, (uint)Win32.Values.FILE_SHARE_READ | (uint)Win32.Values.FILE_SHARE_WRITE);
if (file != Win32.InvalidHandleValue)
{
var fileSize = Win32.GetFileSize(file, IntPtr.Zero);
if (fileSize < (uint)Marshal.ReadInt32(new IntPtr(instance + crcPosition)))
isValid = false;
else
{
var map = Win32.CreateFileMapping(file, IntPtr.Zero, Win32.MemoryProtection.ReadOnly, 0, 0, null);
if (map != Win32.NullHandle)
{
IntPtr baseAddress = Win32.MapViewOfFile(map, Win32.MapAccess.Read, 0, 0, IntPtr.Zero);
if (baseAddress != IntPtr.Zero)
{
var crcInfo = new byte[12];
var crc32 = new CRC32();
var crcCryptor = new CRCValueCryptor();
for (var i = 4; i < crcSize; i += crcInfo.Length)
{
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
if (crc32.Hash(new IntPtr(baseAddress.ToInt64() + address), size) != hash)
isValid = false;
}
Win32.UnmapViewOfFile(baseAddress);
}
Win32.CloseHandle(map);
}
}
Win32.CloseHandle(file);
}
if (!isValid)
{
if ((options & (uint)LoaderOption.CHECK_PATCH) != 0)
{
ShowMessage((uint)MessageType.FileCorrupted);
Environment.Exit(1);
return;
}
GlobalData.SetIsPatchDetected(true);
}
}
// setup WRITABLE flag for memory pages
var sectionSize = (uint)Faces.SECTION_INFO_SIZE;
if (sectionSize != 0)
{
var sectionPos = (uint)Faces.SECTION_INFO;
var sectionInfo = new byte[12];
for (var i = 0; i < sectionSize; i += sectionInfo.Length) //-V3022
{
Marshal.Copy(new IntPtr(instance + sectionPos + i), sectionInfo, 0, sectionInfo.Length);
uint address = BitConverter.ToUInt32(sectionInfo, 0);
uint size = BitConverter.ToUInt32(sectionInfo, 4);
uint type = BitConverter.ToUInt32(sectionInfo, 8);
Win32.MemoryProtection protect, old_protect;
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.ExecuteReadWrite : Win32.MemoryProtection.ReadWrite;
if (!Win32.VirtualProtect(new IntPtr(instance + address), new UIntPtr(size), protect, out old_protect))
{
ShowMessage((uint)MessageType.InitializationError, (uint)ErrorType.VIRTUAL_PROTECT_ERROR);
Environment.Exit(1);
return;
}
if (((uint)old_protect & ((uint)Win32.MemoryProtection.NoAccess | (uint)Win32.MemoryProtection.Guard)) != 0)
{
if ((options & (uint)LoaderOption.CHECK_DEBUGGER) != 0)
{
ShowMessage((uint)MessageType.DebuggerFound);
Environment.Exit(1);
return;
}
GlobalData.SetIsDebuggerDetected(true);
}
}
}
// unpack regions
var packerSize = (uint)Faces.PACKER_INFO_SIZE;
if (packerSize != 0)
{
int tlsIndex = 0;
var tlsIndexPos = (uint)Faces.TLS_INDEX_INFO;
if (tlsIndexPos != 0)
tlsIndex = Marshal.ReadInt32(new IntPtr(instance + tlsIndexPos));
var packerPos = (uint)Faces.PACKER_INFO;
var packerInfo = new byte[8];
Marshal.Copy(new IntPtr(instance + packerPos), packerInfo, 0, packerInfo.Length);
uint src = BitConverter.ToUInt32(packerInfo, 0);
uint dst = BitConverter.ToUInt32(packerInfo, 4);
var properties = new byte[dst];
Marshal.Copy(new IntPtr(instance + src), properties, 0, properties.Length);
for (var i = packerInfo.Length; i < packerSize; i += packerInfo.Length) //-V3022
{
Marshal.Copy(new IntPtr(instance + packerPos + i), packerInfo, 0, packerInfo.Length);
src = BitConverter.ToUInt32(packerInfo, 0);
dst = BitConverter.ToUInt32(packerInfo, 4);
uint dstSize = int.MaxValue, srcSize;
if (!LzmaDecode(new IntPtr(instance + dst), new IntPtr(instance + src), properties, ref dstSize, out srcSize))
{
ShowMessage((uint)MessageType.InitializationError, (uint)ErrorType.UNPACKER_ERROR);
Environment.Exit(1);
return;
}
}
if (tlsIndexPos != 0)
Marshal.WriteInt32(new IntPtr(instance + tlsIndexPos), tlsIndex);
}
// setup fixups
long fileBase = (uint)Faces.FILE_BASE;
long deltaBase = instance - fileBase;
if (deltaBase != 0)
{
var fixupSize = (uint)Faces.FIXUP_INFO_SIZE;
if (fixupSize != 0)
{
var fixupPos = (uint)Faces.FIXUP_INFO;
var fixupInfo = new byte[8];
uint blockSize = 0;
for (uint i = 0; i < fixupSize; i += blockSize)
{
Marshal.Copy(new IntPtr(instance + fixupPos + i), fixupInfo, 0, fixupInfo.Length);
uint address = BitConverter.ToUInt32(fixupInfo, 0);
blockSize = BitConverter.ToUInt32(fixupInfo, 4);
if (blockSize < fixupInfo.Length)
break;
var c = blockSize - fixupInfo.Length;
var block = new byte[c];
Marshal.Copy(new IntPtr(instance + fixupPos + i + fixupInfo.Length), block, 0, block.Length);
for (var j = 0; j < c; j += 2)
{
ushort typeOffset = BitConverter.ToUInt16(block, j);
var type = (typeOffset & 0xf);
var ptr = new IntPtr(instance + address + (typeOffset >> 4));
if (type == (uint)FixupType.HighLow)
{
int value = Marshal.ReadInt32(ptr);
value += (int)deltaBase;
Marshal.WriteInt32(ptr, value);
}
else if (type == (uint)FixupType.Dir64)
{
long value = Marshal.ReadInt64(ptr);
value += deltaBase;
Marshal.WriteInt64(ptr, value);
}
else if (type == (uint)FixupType.High)
{
short value = Marshal.ReadInt16(ptr);
value += (short)(deltaBase >> 16);
Marshal.WriteInt16(ptr, value);
}
else if (type == (uint)FixupType.Low)
{
short value = Marshal.ReadInt16(ptr);
value += (short)deltaBase;
Marshal.WriteInt16(ptr, value);
}
}
}
}
}
// setup IAT
var iatSize = (uint)Faces.IAT_INFO_SIZE;
if (iatSize != 0)
{
var iatPos = (uint)Faces.IAT_INFO;
var iatInfo = new byte[12];
for (var i = 0; i < iatSize; i += iatInfo.Length) //-V3022
{
Marshal.Copy(new IntPtr(instance + iatPos + i), iatInfo, 0, iatInfo.Length);
uint src = BitConverter.ToUInt32(iatInfo, 0);
uint dst = BitConverter.ToUInt32(iatInfo, 4);
uint size = BitConverter.ToUInt32(iatInfo, 8);
var data = new byte[size];
Marshal.Copy(new IntPtr(instance + src), data, 0, data.Length);
Marshal.Copy(data, 0, new IntPtr(instance + dst), data.Length);
}
}
// reset WRITABLE flag for memory pages
if (sectionSize != 0) //-V3022
{
var sectionPos = (uint)Faces.SECTION_INFO;
var sectionInfo = new byte[12];
for (var i = 0; i < sectionSize; i += sectionInfo.Length) //-V3022
{
Marshal.Copy(new IntPtr(instance + sectionPos + i), sectionInfo, 0, sectionInfo.Length);
uint address = BitConverter.ToUInt32(sectionInfo, 0);
uint size = BitConverter.ToUInt32(sectionInfo, 4);
uint type = BitConverter.ToUInt32(sectionInfo, 8);
Win32.MemoryProtection protect, old_protect;
if ((type & (uint)Win32.SectionType.Read) != 0)
{
if ((type & (uint)Win32.SectionType.Write) != 0)
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.ExecuteReadWrite : Win32.MemoryProtection.ReadWrite;
else
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.ExecuteRead : Win32.MemoryProtection.ReadOnly;
}
else
{
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.Execute : Win32.MemoryProtection.NoAccess;
}
if (!Win32.VirtualProtect(new IntPtr(instance + address), new UIntPtr(size), protect, out old_protect))
{
ShowMessage((uint)MessageType.InitializationError, (uint)ErrorType.VIRTUAL_PROTECT_ERROR);
Environment.Exit(1);
}
if (((uint)old_protect & ((uint)Win32.MemoryProtection.NoAccess | (uint)Win32.MemoryProtection.Guard)) != 0)
{
if ((options & (uint)LoaderOption.CHECK_DEBUGGER) != 0)
{
ShowMessage((uint)MessageType.DebuggerFound);
Environment.Exit(1);
return;
}
GlobalData.SetIsDebuggerDetected(true);
}
}
}
// detect a virtual machine
if ((options & (uint)LoaderOption.CHECK_VIRTUAL_MACHINE) != 0)
{
var info = CpuId.Invoke(1);
if (((info[2] >> 31) & 1) != 0)
{
// hypervisor found
bool isFound = true;
// check Hyper-V root partition
info = CpuId.Invoke(0x40000000);
if (info[1] == 0x7263694d && info[2] == 0x666f736f && info[3] == 0x76482074) // "Microsoft Hv"
{
info = CpuId.Invoke(0x40000003);
if ((info[1] & 1) != 0)
isFound = false;
}
if (isFound)
{
ShowMessage((uint)MessageType.VirtualMachineFound);
Environment.Exit(1);
return;
}
}
else
{
int size;
uint tableSignature = (byte)'R' << 24 | (byte)'S' << 16 | (byte)'M' << 8 | (byte)'B';
try
{
size = (int)Win32.EnumSystemFirmwareTables(tableSignature, IntPtr.Zero, 0);
}
catch (EntryPointNotFoundException) { size = 0; }
if (size > 0)
{
IntPtr nativeBuffer = Marshal.AllocHGlobal(size);
Win32.EnumSystemFirmwareTables(tableSignature, nativeBuffer, (uint)size);
byte[] buffer = new byte[size];
Marshal.Copy(nativeBuffer, buffer, 0, size);
Marshal.FreeHGlobal(nativeBuffer);
for (var i = 0; i < size / sizeof(uint); i += sizeof(uint))
{
uint tableId = BitConverter.ToUInt32(buffer, i);
int dataSize = (int)Win32.GetSystemFirmwareTable(tableSignature, tableId, IntPtr.Zero, 0);
if (dataSize > 0)
{
nativeBuffer = Marshal.AllocHGlobal(dataSize);
Win32.GetSystemFirmwareTable(tableSignature, tableId, nativeBuffer, (uint)dataSize);
byte[] data = new byte[dataSize];
Marshal.Copy(nativeBuffer, data, 0, dataSize);
Marshal.FreeHGlobal(nativeBuffer);
if (FindFirmwareVendor(data))
{
ShowMessage((uint)MessageType.VirtualMachineFound);
Environment.Exit(1);
return;
}
}
}
}
}
}
// check memory CRC
crcSize = (uint)Faces.MEMORY_CRC_INFO_SIZE;
if (crcSize != 0) //-V3022
{
var crcPosition = (uint)Faces.MEMORY_CRC_INFO;
var crcCryptor = new CRCValueCryptor();
bool isValid = true;
var crcInfo = new byte[12];
var crc32 = new CRC32();
var crcHash = (uint)Faces.MEMORY_CRC_INFO_HASH;
if (crcHash != crc32.Hash(new IntPtr(instance + crcPosition), crcSize))
isValid = false;
for (var i = 0; i < crcSize; i += crcInfo.Length) //-V3022
{
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
if (crc32.Hash(new IntPtr(instance + address), size) != hash)
isValid = false;
}
if (!isValid)
{
if ((options & (uint)LoaderOption.CHECK_PATCH) != 0)
{
ShowMessage((uint)MessageType.FileCorrupted);
Environment.Exit(1);
return;
}
GlobalData.SetIsPatchDetected(true);
}
}
GlobalData.SetSessionKey((uint)new Random().Next());
if (!Core.Instance.Init(instance))
{
Environment.Exit(1);
return;
}
// setup Import
var importSize = (uint)Faces.IMPORT_INFO_SIZE;
if (importSize != 0)
{
var importPos = (uint)Faces.IMPORT_INFO;
var key = (uint)Faces.STRING_DECRYPT_KEY;
var importInfo = new byte[12];
object[] iat = new object[importSize / importInfo.Length];
uint index = 0;
for (var i = 0; i < importSize; i += importInfo.Length) //-V3022
{
Marshal.Copy(new IntPtr(instance + importPos + i), importInfo, 0, importInfo.Length);
uint token = BitConverter.ToUInt32(importInfo, 0) ^ key;
uint delegateToken = BitConverter.ToUInt32(importInfo, 4) ^ key;
uint callType = BitConverter.ToUInt32(importInfo, 8);
MethodBase method = null;
FieldInfo field = null;
try
{
if ((callType & 8) != 0)
field = module.ResolveField((int)token);
else
method = module.ResolveMethod((int)token);
}
catch (Exception e)
{
Win32.ShowMessage(e.InnerException.Message, Assembly.GetExecutingAssembly().GetName().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
Environment.Exit(1);
return;
}
var invoke = (MethodInfo)module.ResolveMethod((int)delegateToken);
var delegateType = invoke.DeclaringType;
object delegateObject;
if (callType == 0 && method.IsStatic)
delegateObject = Delegate.CreateDelegate(delegateType, (MethodInfo)method);
else
{
ParameterInfo[] parameters = invoke.GetParameters();
Type[] paramTypes = new Type[parameters.Length];
for (var j = 0; j < paramTypes.Length; j++)
paramTypes[j] = parameters[j].ParameterType;
Type declType = (method != null) ? method.DeclaringType : field.DeclaringType;
DynamicMethod dynamicMethod = new DynamicMethod("", invoke.ReturnType, paramTypes, (declType.IsInterface || declType.IsArray) ? delegateType : declType, true);
DynamicILInfo dynamicInfo = dynamicMethod.GetDynamicILInfo();
dynamicInfo.SetLocalSignature(new byte[] { 0x7, 0x0 });
if (method != null)
{
parameters = method.GetParameters();
int s = 0;
if (paramTypes.Length > parameters.Length)
{
paramTypes[0] = method.DeclaringType;
s = 1;
}
for (var j = 0; j < parameters.Length; j++)
paramTypes[s + j] = parameters[j].ParameterType;
}
else
{
if (paramTypes.Length > 0)
paramTypes[0] = field.DeclaringType;
}
var code = new byte[7 * paramTypes.Length + 6];
int codePos = 0;
int dynamicToken;
for (var j = 0; j < paramTypes.Length; j++)
{
code[codePos++] = 0x0e; // Ldarg_s
code[codePos++] = (byte)j;
Type type = paramTypes[j];
if ((type.IsClass || type.IsInterface) && !type.IsPointer && !type.IsByRef)
{
code[codePos++] = 0x74; // Castclass
dynamicToken = dynamicInfo.GetTokenFor(type.TypeHandle);
code[codePos++] = (byte)dynamicToken;
code[codePos++] = (byte)(dynamicToken >> 8);
code[codePos++] = (byte)(dynamicToken >> 16);
code[codePos++] = (byte)(dynamicToken >> 24);
}
else
codePos += 5;
}
switch (callType)
{
case 1:
code[codePos++] = 0x73; // Newobj
break;
case 2:
code[codePos++] = 0x6f; // Callvirt
break;
case 8:
code[codePos++] = 0x7e; // Ldsfld
break;
case 9:
code[codePos++] = 0x7b; // Ldfld
break;
default:
code[codePos++] = 0x28; // Call
break;
}
dynamicToken = (method != null) ? dynamicInfo.GetTokenFor(method.MethodHandle) : dynamicInfo.GetTokenFor(field.FieldHandle);
code[codePos++] = (byte)dynamicToken;
code[codePos++] = (byte)(dynamicToken >> 8);
code[codePos++] = (byte)(dynamicToken >> 16);
code[codePos++] = (byte)(dynamicToken >> 24);
code[codePos] = 0x2a; // Ret
dynamicInfo.SetCode(code, paramTypes.Length + 1);
delegateObject = dynamicMethod.CreateDelegate(delegateType);
}
iat[index++] = delegateObject;
}
IAT = iat;
}
ShowMessage((uint)MessageType.UnregisteredVersion);
GlobalData.SetLoaderStatus(1);
}
}
}