예제 #1
0
        /// <summary>
        /// Certain games distribute modified assemblies which disable
        ///  reflection and impede modding.
        /// </summary>
        private void EnableReflection(string strDataPath)
        {
            string          strMscorlib = Path.Combine(strDataPath, Constants.MSCORLIB);
            FileVersionInfo fvi         = FileVersionInfo.GetVersionInfo(strMscorlib);
            string          version     = fvi.FileVersion;
            string          strLib      = LIB_REPLACEMENTS
                                          .Where(replacement => replacement.Substring(Constants.MSCORLIB.Length + 1, 1) == version.Substring(0, 1))
                                          .SingleOrDefault();

            if (null != strLib)
            {
                try
                {
                    WebClient wc  = new WebClient();
                    Uri       uri = new Uri(Constants.GITHUB_LINK + strLib);
                    wc.DownloadDataAsync(uri, Path.Combine(strDataPath, strLib));
                    wc.DownloadDataCompleted += (sender, e) =>
                    {
                        string strFileName = e.UserState.ToString();
                        File.WriteAllBytes(strFileName, e.Result);
                        Util.ReplaceFile(strMscorlib, strFileName);
                        m_eInjectorState = Enums.EInjectorState.FINISHED;
                    };
                }
                catch (Exception exc)
                {
                    m_eInjectorState = Enums.EInjectorState.FINISHED;
                    string           strMessage  = "Unhandled mscorlib version.";
                    Enums.EErrorCode err         = Enums.EErrorCode.MISSING_FILE;
                    string           strResponse = JSONResponse.CreateSerializedResponse(strMessage, err, exc);
                    Console.Error.WriteLine(strResponse);
                    Environment.Exit((int)(err));
                }
            }
            else
            {
                m_eInjectorState = Enums.EInjectorState.FINISHED;
                string           strMessage  = "Unhandled mscorlib version.";
                Enums.EErrorCode err         = Enums.EErrorCode.UNHANDLED_FILE_VERSION;
                string           strResponse = JSONResponse.CreateSerializedResponse(strMessage, err);
                Console.Error.WriteLine(strResponse);
                Environment.Exit((int)(err));
            }
        }
예제 #2
0
        public void Inject()
        {
            m_eInjectorState = Enums.EInjectorState.RUNNING;
            string             strTempFile   = null;
            AssemblyDefinition unityAssembly = null;

            try
            {
                // Ensure we have reflection enabled - there's no point
                //  in continuing if reflection is disabled.
                if (!Util.IsReflectionEnabled(m_strDataPath))
                {
                    EnableReflection(m_strDataPath);
                }
                else
                {
                    m_eInjectorState = Enums.EInjectorState.FINISHED;
                }
                // Deploy patcher related files.
                DeployFiles();

                // Start the patching process.
                string[] patcherPoints = Constants.VORTEX_PATCH_METHOD.Split(new string[] { "::" }, StringSplitOptions.None);
                string[] entryPoint    = m_strEntryPoint.Split(new string[] { "::" }, StringSplitOptions.None);

                strTempFile = Util.GetTempFile(m_strGameAssemblyPath);
                using (unityAssembly = AssemblyDefinition.ReadAssembly(strTempFile,
                                                                       new ReaderParameters {
                    ReadWrite = true, AssemblyResolver = m_resolver
                }))
                {
                    if (IsInjected(unityAssembly, entryPoint))
                    {
                        unityAssembly.Dispose();
                        Util.DeleteTemp(strTempFile);
                        return;
                    }

                    // Back up the game assembly before we do anything.
                    Util.BackupFile(m_strGameAssemblyPath);

                    AssemblyDefinition vrtxPatcher   = AssemblyDefinition.ReadAssembly(Path.Combine(m_strDataPath, Constants.VORTEX_LIB));
                    MethodDefinition   patcherMethod = vrtxPatcher.MainModule.GetType(patcherPoints[0]).Methods.First(x => x.Name == patcherPoints[1]);
                    TypeDefinition     type          = unityAssembly.MainModule.GetType(entryPoint[0]);
                    if ((type == null) || !type.IsClass)
                    {
                        throw new EntryPointNotFoundException("Invalid entry point");
                    }

                    MethodDefinition methodDefinition = type.Methods.FirstOrDefault(meth => meth.Name == entryPoint[1]);
                    if ((methodDefinition == null) || !methodDefinition.HasBody)
                    {
                        throw new EntryPointNotFoundException("Invalid entry point");
                    }

                    methodDefinition.Body.GetILProcessor().InsertBefore(methodDefinition.Body.Instructions[0], Instruction.Create(OpCodes.Call, methodDefinition.Module.ImportReference(patcherMethod)));
                    unityAssembly.Write(m_strGameAssemblyPath);
                    unityAssembly.Dispose();
                    Util.DeleteTemp(strTempFile);
                }
            }
            catch (Exception exc)
            {
                Enums.EErrorCode errorCode = Enums.EErrorCode.UNKNOWN;

                if (unityAssembly != null)
                {
                    unityAssembly.Dispose();
                }

                if (strTempFile != null)
                {
                    Util.DeleteTemp(strTempFile);
                }

                Util.RestoreBackup(m_strGameAssemblyPath);
                if (exc is FileNotFoundException)
                {
                    errorCode = Enums.EErrorCode.MISSING_FILE;
                }
                else if (exc is EntryPointNotFoundException)
                {
                    errorCode = Enums.EErrorCode.INVALID_ENTRYPOINT;
                }

                string strMessage  = "Failed to inject patcher.";
                string strResponse = JSONResponse.CreateSerializedResponse(strMessage, errorCode, exc);
                Console.Error.WriteLine(strResponse);
                Environment.Exit((int)(errorCode));
            }

            while (InjectorState != Enums.EInjectorState.FINISHED)
            {
                // Do nothing.
            }
        }