diff options
Diffstat (limited to 'runtime/VMProtect.Runtime/Loader.cs')
-rw-r--r-- | runtime/VMProtect.Runtime/Loader.cs | 703 |
1 files changed, 703 insertions, 0 deletions
diff --git a/runtime/VMProtect.Runtime/Loader.cs b/runtime/VMProtect.Runtime/Loader.cs new file mode 100644 index 0000000..8511045 --- /dev/null +++ b/runtime/VMProtect.Runtime/Loader.cs @@ -0,0 +1,703 @@ +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); + } + } +}
\ No newline at end of file |