Exemple #1
0
        static int CompileMethod(
            IntPtr thisPtr,
            IntPtr comp,                  // ICorJitInfo* comp, /* IN */
            ref CORINFO_METHOD_INFO info, // struct CORINFO_METHOD_INFO  *info,               /* IN */
            uint flags,                   // unsigned /* code:CorJitFlag */   flags,          /* IN */
            out IntPtr nativeEntry,       // BYTE                        **nativeEntry,       /* OUT */
            out int nativeSizeOfCode      // ULONG* nativeSizeOfCode    /* OUT */
            )
        {
            if (!isHooked)
            {
                nativeEntry      = IntPtr.Zero;
                nativeSizeOfCode = 0;
                return(0);
            }
            var res = DefaultCompileMethod(thisPtr, comp, ref info, flags, out nativeEntry, out nativeSizeOfCode);

            byte[] ilcodes = new byte[info.ILCodeSize];
            Marshal.Copy(info.ILCode, ilcodes, 0, info.ILCodeSize);

            byte[] nativecodes = new byte[nativeSizeOfCode];
            Marshal.Copy(nativeEntry, nativecodes, 0, nativeSizeOfCode);

            if (isFindingInjectHereAddress)
            {
                isFindingInjectHereAddress = false;
                return(res);
            }

            if (i++ == 0)
            {
                Marshal.WriteByte(nativeEntry, 37, 2);
            }
            return(res);
        }
Exemple #2
0
        unsafe DumpedMethod decryptMethod(uint token)
        {
            if (!canDecryptMethods())
            {
                throw new ApplicationException("Can't decrypt methods since compileMethod() isn't hooked yet");
            }

            ctx          = new DecryptContext();
            ctx.dm       = new DumpedMethod();
            ctx.dm.token = token;

            ctx.method = monoModule.LookupToken((int)token) as MethodDefinition;
            if (ctx.method == null)
            {
                throw new ApplicationException(string.Format("Could not find method {0:X8}", token));
            }

            byte *mh = (byte *)hInstModule + ctx.method.RVA;
            byte *code;

            if (mh == (byte *)hInstModule)
            {
                ctx.dm.mhMaxStack       = 0;
                ctx.dm.mhCodeSize       = 0;
                ctx.dm.mhFlags          = 0;
                ctx.dm.mhLocalVarSigTok = 0;
                code = null;
            }
            else if ((*mh & 3) == 2)
            {
                uint headerSize = 1;
                ctx.dm.mhMaxStack       = 8;
                ctx.dm.mhCodeSize       = (uint)(*mh >> 2);
                ctx.dm.mhFlags          = 2;
                ctx.dm.mhLocalVarSigTok = 0;
                code = mh + headerSize;
            }
            else
            {
                uint headerSize = (uint)((mh[1] >> 4) * 4);
                ctx.dm.mhMaxStack       = *(ushort *)(mh + 2);
                ctx.dm.mhCodeSize       = *(uint *)(mh + 4);
                ctx.dm.mhFlags          = *(ushort *)mh;
                ctx.dm.mhLocalVarSigTok = *(uint *)(mh + 8);
                code = mh + headerSize;
            }

            CORINFO_METHOD_INFO info = default(CORINFO_METHOD_INFO);

            info.ILCode     = new IntPtr(code);
            info.ILCodeSize = ctx.dm.mhCodeSize;
            info.maxStack   = ctx.dm.mhMaxStack;
            info.scope      = moduleToDecryptScope;

            initializeOurComp();
            if (code == null)
            {
                ctx.dm.code = new byte[0];
                updateFromMethodDefTableRow();
            }
            else
            {
                callMethodDelegate(*(IntPtr *)jitterVtbl, jitterInstance, ourCompMem, new IntPtr(&info), 0, new IntPtr(0x12345678), new IntPtr(0x3ABCDEF0));
            }

            var dm = ctx.dm;

            ctx = null;
            return(dm);
        }
Exemple #3
0
    static unsafe void ParseLocalVars(CORINFO_METHOD_INFO* info, ICorJitInfo* comp, uint localVarToken)
    {
        ICorModuleInfo* modInfo = ICorStaticInfo.ICorModuleInfo(ICorDynamicInfo.ICorStaticInfo(ICorJitInfo.ICorDynamicInfo(comp)));
        findSig findSig = Marshal.GetDelegateForFunctionPointer(modInfo->vfptr[4], typeof(findSig)) as findSig;

        void* sigInfo;

        if (ver)
        {
            if (IntPtr.Size == 8)
                sigInfo = (CORINFO_SIG_INFO_x64*)((uint*)(info + 1) + 5) + 1;
            else
                sigInfo = (CORINFO_SIG_INFO_x86*)((uint*)(info + 1) + 4) + 1;
        }
        else
        {
            if (IntPtr.Size == 8)
                sigInfo = (CORINFO_SIG_INFO_x64*)((uint*)(info + 1) + 3) + 1;
            else
                sigInfo = (CORINFO_SIG_INFO_x86*)((uint*)(info + 1) + 3) + 1;
        }
        findSig((IntPtr)modInfo, info->scope, localVarToken, info->ftn, sigInfo);

        byte* sig;
        if (IntPtr.Size == 8)
            sig = (byte*)((CORINFO_SIG_INFO_x64*)sigInfo)->sig;
        else
            sig = (byte*)((CORINFO_SIG_INFO_x86*)sigInfo)->sig;
        sig++;
        byte b = *sig;
        ushort numArgs;
        IntPtr args;
        if ((b & 0x80) == 0)
        {
            numArgs = b;
            args = (IntPtr)(sig + 1);
        }
        else
        {
            numArgs = (ushort)(((uint)(b & ~0x80) << 8) | *(sig + 1));
            args = (IntPtr)(sig + 2);
        }

        if (IntPtr.Size == 8)
        {
            CORINFO_SIG_INFO_x64* sigInfox64 = (CORINFO_SIG_INFO_x64*)sigInfo;
            sigInfox64->callConv = 0;
            sigInfox64->retType = 1;
            sigInfox64->flags = 1;
            sigInfox64->numArgs = numArgs;
            sigInfox64->args = args;
        }
        else
        {
            CORINFO_SIG_INFO_x86* sigInfox86 = (CORINFO_SIG_INFO_x86*)sigInfo;
            sigInfox86->callConv = 0;
            sigInfox86->retType = 1;
            sigInfox86->flags = 1;
            sigInfox86->numArgs = numArgs;
            sigInfox86->args = args;
        }
    }
Exemple #4
0
    //static unsafe void Parse(byte* body, CORINFO_METHOD_INFO* info, ICorJitInfo* comp, out CORINFO_EH_CLAUSE[] ehs)
    //{
    //    //Refer to SSCLI
    //    if ((*body & 0x3) == 0x2)
    //    {
    //        if (ver)
    //        {
    //            *((uint*)(info + 1) + 0) = 8;   //maxstack
    //            *((uint*)(info + 1) + 1) = 0;   //ehcount
    //        }
    //        else
    //        {
    //            *((ushort*)(info + 1) + 0) = 8;
    //            *((ushort*)(info + 1) + 1) = 0;
    //        }
    //        info->ILCode = body + 1;
    //        info->ILCodeSize = (uint)(*body >> 2);
    //        ehs = null;
    //        return;
    //    }
    //    else
    //    {
    //        ushort flags = *(ushort*)body;
    //        if (ver)    //maxstack
    //            *((uint*)(info + 1) + 0) = *(ushort*)(body + 2);
    //        else
    //            *((ushort*)(info + 1) + 0) = *(ushort*)(body + 2);
    //        info->ILCodeSize = *(uint*)(body + 4);
    //        var localVarTok = *(uint*)(body + 8);
    //        if ((flags & 0x10) != 0)
    //        {
    //            if (ver)    //options
    //                *((uint*)(info + 1) + 2) |= (uint)CorInfoOptions.OPT_INIT_LOCALS;
    //            else
    //                *((uint*)(info + 1) + 1) |= (ushort)CorInfoOptions.OPT_INIT_LOCALS;
    //        }
    //        info->ILCode = body + 12;
    //        if (localVarTok != 0)
    //            ParseLocalVars(info, comp, localVarTok);
    //        if ((flags & 0x8) != 0)
    //        {
    //            body = body + 12 + info->ILCodeSize;
    //            var list = new ArrayList();
    //            byte f;
    //            do
    //            {
    //                body = (byte*)(((uint)body + 3) & ~3);
    //                f = *body;
    //                uint count;
    //                bool isSmall = (f & 0x40) == 0;
    //                if (isSmall)
    //                    count = *(body + 1) / 12u;
    //                else
    //                    count = (*(uint*)body >> 8) / 24;
    //                body += 4;
    //                for (int i = 0; i < count; i++)
    //                {
    //                    var clause = new CORINFO_EH_CLAUSE();
    //                    clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(*body & 0x7);
    //                    body += isSmall ? 2 : 4;
    //                    clause.TryOffset = isSmall ? *(ushort*)body : *(uint*)body;
    //                    body += isSmall ? 2 : 4;
    //                    clause.TryLength = isSmall ? *(byte*)body : *(uint*)body;
    //                    body += isSmall ? 1 : 4;
    //                    clause.HandlerOffset = isSmall ? *(ushort*)body : *(uint*)body;
    //                    body += isSmall ? 2 : 4;
    //                    clause.HandlerLength = isSmall ? *(byte*)body : *(uint*)body;
    //                    body += isSmall ? 1 : 4;
    //                    clause.ClassTokenOrFilterOffset = *(uint*)body;
    //                    body += 4;
    //                    if ((clause.ClassTokenOrFilterOffset & 0xff000000) == 0x1b000000)
    //                    {
    //                        if (ver)    //options
    //                            *((uint*)(info + 1) + 2) |= (uint)CorInfoOptions.GENERICS_CTXT_KEEP_ALIVE;
    //                        else
    //                            *((uint*)(info + 1) + 1) |= (ushort)CorInfoOptions.GENERICS_CTXT_KEEP_ALIVE;
    //                    }
    //                    list.Add(clause);
    //                }
    //            }
    //            while ((f & 0x80) != 0);
    //            ehs = new CORINFO_EH_CLAUSE[list.Count];
    //            for (int i = 0; i < ehs.Length; i++)
    //                ehs[i] = (CORINFO_EH_CLAUSE)list[i];
    //            if (ver)    //ehcount
    //                *((uint*)(info + 1) + 1) = (ushort)ehs.Length;
    //            else
    //                *((ushort*)(info + 1) + 1) = (ushort)ehs.Length;
    //        }
    //        else
    //        {
    //            ehs = null;
    //            if (ver)    //ehcount
    //                *((uint*)(info + 1) + 1) = 0;
    //            else
    //                *((ushort*)(info + 1) + 1) = 0;
    //        }
    //    }
    //}
    static unsafe uint Interop(IntPtr self, ICorJitInfo* comp, CORINFO_METHOD_INFO* info, uint flags, byte** nativeEntry, uint* nativeSizeOfCode)
    {
        if (self == IntPtr.Zero) return 0;

        if (info != null &&
            (ulong)info->ILCode > s &&
            (ulong)info->ILCode < s + l &&
            info->ILCodeSize == 0x11 &&
            info->ILCode[0] == 0x21 &&
            info->ILCode[9] == 0x20 &&
            info->ILCode[14] == 0x26)
        {
            ulong num = *(ulong*)(info->ILCode + 1);
            uint key = (uint)(num >> 32);
            uint ptr = (uint)(num & 0xFFFFFFFF) ^ key;
            uint len = ~*(uint*)(info->ILCode + 10) ^ key;

            byte[] buff = new byte[len];
            fixed (byte* arr = buff)
            {
                Marshal.Copy(data, (int)ptr, (IntPtr)arr, (int)len);

                uint k = key * (uint)Mutation.Key4I;
                for (uint i = 0; i < buff.Length; i++)
                {
                    arr[i] ^= (byte)(k & 0xff);
                    k = (k * arr[i] + key) % 0xff;
                }

                MethodData* dat = (MethodData*)arr;
                info->ILCodeSize = dat->ILCodeSize;
                if (ver)
                {
                    *((uint*)(info + 1) + 0) = dat->MaxStack;
                    *((uint*)(info + 1) + 1) = dat->EHCount;
                    *((uint*)(info + 1) + 2) = dat->Options & 0xff;
                }
                else
                {
                    *((ushort*)(info + 1) + 0) = (ushort)dat->MaxStack;
                    *((ushort*)(info + 1) + 1) = (ushort)dat->EHCount;
                    *((uint*)(info + 1) + 1) = dat->Options & 0xff;
                }
                if (dat->LocalVars != 0)
                    ParseLocalVars(info, comp, dat->LocalVars);

                CORINFO_EH_CLAUSE[] ehs;
                byte* body = (byte*)(dat + 1);
                if ((dat->Options >> 8) == 0)
                {
                    info->ILCode = body;
                    body += info->ILCodeSize;
                    ehs = new CORINFO_EH_CLAUSE[dat->EHCount];
                    CORINFO_EH_CLAUSE* ehPtr = (CORINFO_EH_CLAUSE*)body;
                    for (int i = 0; i < dat->EHCount; i++)
                    {
                        ehs[i] = *ehPtr;
                        *ehPtr = new CORINFO_EH_CLAUSE();
                        ehPtr++;
                    }
                }
                else
                {
                    ehs = new CORINFO_EH_CLAUSE[dat->EHCount];
                    CORINFO_EH_CLAUSE* ehPtr = (CORINFO_EH_CLAUSE*)body;
                    for (int i = 0; i < dat->EHCount; i++)
                    {
                        ehs[i] = *ehPtr;
                        *ehPtr = new CORINFO_EH_CLAUSE();
                        ehPtr++;
                    }
                    info->ILCode = (byte*)ehPtr;
                }

                *((ulong*)dat) = 0;
                *((ulong*)dat + 1) = 0;
                *((uint*)dat + 4) = 0;

                var hook1 = CorMethodInfoHook.Hook(comp, info->ftn, ehs);
                var hook2 = CorDynamicInfoHook.Hook(comp);
                uint ret = originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode);
                hook2.Dispose();
                hook1.Dispose();
                return ret;
            }
        }
        else
            return originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode);
    }
		static uint HookHandler(IntPtr self, ICorJitInfo* comp, CORINFO_METHOD_INFO* info, uint flags, byte** nativeEntry, uint* nativeSizeOfCode) {
			if (info != null && info->scope == moduleHnd && info->ILCode[0] == 0x14) {
				uint token;
				if (ver5) {
					var getMethodDef = (getMethodDefFromMethod)Marshal.GetDelegateForFunctionPointer(comp->vfptr[0x64], typeof(getMethodDefFromMethod));
					token = getMethodDef((IntPtr)comp, info->ftn);
				}
				else {
					ICorClassInfo* clsInfo = ICorStaticInfo.ICorClassInfo(ICorDynamicInfo.ICorStaticInfo(ICorJitInfo.ICorDynamicInfo(comp)));
					int gmdSlot = 12 + (ver4 ? 2 : 1);
					var getMethodDef = (getMethodDefFromMethod)Marshal.GetDelegateForFunctionPointer(clsInfo->vfptr[gmdSlot], typeof(getMethodDefFromMethod));
					token = getMethodDef((IntPtr)clsInfo, info->ftn);
				}

				uint lo = 0, hi = len;
				uint? offset = null;
				while (hi >= lo) {
					uint mid = lo + ((hi - lo) >> 1);
					uint midTok = *(ptr + (mid << 1));
					if (midTok == token) {
						offset = *(ptr + (mid << 1) + 1);
						break;
					}
					if (midTok < token)
						lo = mid + 1;
					else
						hi = mid - 1;
				}
				if (offset == null)
					return originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode);

				uint* dataPtr = ptr + (uint)offset;
				uint dataLen = *dataPtr++;
				var newPtr = (uint*)Marshal.AllocHGlobal((int)dataLen << 2);
				try {
					var data = (MethodData*)newPtr;
					uint* copyData = newPtr;

					uint state = token * (uint)Mutation.KeyI0;
					uint counter = state;
					for (uint i = 0; i < dataLen; i++) {
						*copyData = *dataPtr++ ^ state;
						state += (*copyData++) ^ counter;
						counter ^= (state >> 5) | (state << 27);
					}

					info->ILCodeSize = data->ILCodeSize;
					if (ver4) {
						*((uint*)(info + 1) + 0) = data->MaxStack;
						*((uint*)(info + 1) + 1) = data->EHCount;
						*((uint*)(info + 1) + 2) = data->Options;
					}
					else {
						*((ushort*)(info + 1) + 0) = (ushort)data->MaxStack;
						*((ushort*)(info + 1) + 1) = (ushort)data->EHCount;
						*((uint*)(info + 1) + 1) = data->Options;
					}

					var body = (byte*)(data + 1);

					info->ILCode = body;
					body += info->ILCodeSize;

					if (data->LocalVars != 0) {
						ExtractLocalVars(info, data->LocalVars, body);
						body += data->LocalVars;
					}

					var ehPtr = (CORINFO_EH_CLAUSE*)body;

					uint ret;
					if (ver5) {
						CorJitInfoHook hook = CorJitInfoHook.Hook(comp, info->ftn, ehPtr);
						ret = originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode);
						hook.Dispose();
					}
					else {
						CorMethodInfoHook hook = CorMethodInfoHook.Hook(comp, info->ftn, ehPtr);
						ret = originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode);
						hook.Dispose();
					}

					return ret;
				}
				finally {
					Marshal.FreeHGlobal((IntPtr)newPtr);
				}
			}
			return originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode);
		}
		static void ExtractLocalVars(CORINFO_METHOD_INFO* info, uint len, byte* localVar) {
			void* sigInfo;
			if (ver4) {
				if (IntPtr.Size == 8)
					sigInfo = (CORINFO_SIG_INFO_x64*)((uint*)(info + 1) + (ver5 ? 7 : 5)) + 1;
				else
					sigInfo = (CORINFO_SIG_INFO_x86*)((uint*)(info + 1) + (ver5 ? 5 : 4)) + 1;
			}
			else {
				if (IntPtr.Size == 8)
					sigInfo = (CORINFO_SIG_INFO_x64*)((uint*)(info + 1) + 3) + 1;
				else
					sigInfo = (CORINFO_SIG_INFO_x86*)((uint*)(info + 1) + 3) + 1;
			}

			if (IntPtr.Size == 8)
				((CORINFO_SIG_INFO_x64*)sigInfo)->sig = (IntPtr)localVar;
			else
				((CORINFO_SIG_INFO_x86*)sigInfo)->sig = (IntPtr)localVar;
			localVar++;
			byte b = *localVar;
			ushort numArgs;
			IntPtr args;
			if ((b & 0x80) == 0) {
				numArgs = b;
				args = (IntPtr)(localVar + 1);
			}
			else {
				numArgs = (ushort)(((uint)(b & ~0x80) << 8) | *(localVar + 1));
				args = (IntPtr)(localVar + 2);
			}

			if (IntPtr.Size == 8) {
				var sigInfox64 = (CORINFO_SIG_INFO_x64*)sigInfo;
				sigInfox64->callConv = 0;
				sigInfox64->retType = 1;
				sigInfox64->flags = 1;
				sigInfox64->numArgs = numArgs;
				sigInfox64->args = args;
			}
			else {
				var sigInfox86 = (CORINFO_SIG_INFO_x86*)sigInfo;
				sigInfox86->callConv = 0;
				sigInfox86->retType = 1;
				sigInfox86->flags = 1;
				sigInfox86->numArgs = numArgs;
				sigInfox86->args = args;
			}
		}
Exemple #7
0
        private int CompileMethod(
            IntPtr thisPtr,
            IntPtr comp,                  // ICorJitInfo* comp, /* IN */
            ref CORINFO_METHOD_INFO info, // struct CORINFO_METHOD_INFO  *info,               /* IN */
            uint flags,                   // unsigned /* code:CorJitFlag */   flags,          /* IN */
            out IntPtr nativeEntry,       // BYTE                        **nativeEntry,       /* OUT */
            out int nativeSizeOfCode      // ULONG* nativeSizeOfCode    /* OUT */
            )
        {
            var compileEntry = _compileTls ?? (_compileTls = new CompileTls());

            compileEntry.EnterCount++;
            try
            {
                // Early exit gracefully. We are entering this if when calling the trampoline
                // As our JIT is not yet compile, but we still want this method to be compiled by the
                // original JIT!
                if (!_isHookInstalled)
                {
                    nativeEntry      = IntPtr.Zero;
                    nativeSizeOfCode = 0;
                    return(0);
                }

                // We always let the default JIT compile the method
                var result = DefaultCompileMethod(thisPtr, comp, ref info, flags, out nativeEntry, out nativeSizeOfCode);

                // If we are at a top level method to compile, we wil recompile it
                if (compileEntry.EnterCount == 1)
                {
                    var vtableCorJitInfo = Marshal.ReadIntPtr(comp);

                    var getMethodDefFromMethodPtr = Marshal.ReadIntPtr(vtableCorJitInfo, IntPtr.Size * ICorJitInfo_getMethodDefFromMethod_index);
                    var getMethodDefFromMethod    = (GetMethodDefFromMethodDelegate)Marshal.GetDelegateForFunctionPointer(getMethodDefFromMethodPtr, typeof(GetMethodDefFromMethodDelegate));
                    var methodToken = getMethodDefFromMethod(comp, info.ftn);

                    var getModuleAssemblyDelegatePtr = Marshal.ReadIntPtr(vtableCorJitInfo, IntPtr.Size * ICorJitInfo_getModuleAssembly_index);
                    var getModuleAssemblyDelegate    = (GetModuleAssemblyDelegate)Marshal.GetDelegateForFunctionPointer(getModuleAssemblyDelegatePtr, typeof(GetModuleAssemblyDelegate));
                    var assemblyHandle = getModuleAssemblyDelegate(comp, info.scope);

                    // Check if this assembly was not already found
                    Assembly assemblyFound;

                    // Map AssemblyHandle to the Managed Assembly instance
                    // (use JitLock and MapHandleToAssembly, as the CompileMethod can be called concurrently from different threads)
                    lock (JitLock)
                    {
                        if (!MapHandleToAssembly.TryGetValue(assemblyHandle, out assemblyFound))
                        {
                            var getAssemblyNamePtr = Marshal.ReadIntPtr(vtableCorJitInfo, IntPtr.Size * 44);
                            var getAssemblyName    = (GetAssemblyNameDelegate)Marshal.GetDelegateForFunctionPointer(getAssemblyNamePtr, typeof(GetAssemblyNameDelegate));
                            var assemblyNamePtr    = getAssemblyName(comp, assemblyHandle);

                            var assemblyName = Marshal.PtrToStringAnsi(assemblyNamePtr);

                            // TODO: Very inefficient way of finding the assembly
                            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                            {
                                if (assembly.GetName().Name == assemblyName)
                                {
                                    assemblyFound = assembly;
                                    break;
                                }
                            }

                            // Register the assembly
                            MapHandleToAssembly.Add(assemblyHandle, assemblyFound);
                        }
                    }

                    // Find the method with the token
                    MethodBase method = null;
                    if (assemblyFound != null)
                    {
                        foreach (var module in assemblyFound.Modules)
                        {
                            try
                            {
                                method = module.ResolveMethod(methodToken);
                            }
                            catch (Exception)
                            {
                            }
                        }
                    }

                    if (method != null)
                    {
                        ReplaceCompile(method, info.ILCode, info.ILCodeSize, nativeEntry, nativeSizeOfCode);
                    }
                }

                return(result);
            }
            finally
            {
                compileEntry.EnterCount--;
            }
        }