Exemple #1
0
        public void TryRestore(GameKB gameKnowledge)
        {
            // Check the options
            CheckOptions();

            // Iterate all known libraries for the game.
            foreach (string gameLibFilePath in gameKnowledge.LibraryFilePaths)
            {
                string backupLibPath = AssemblyHelper.GetPathBackup(gameLibFilePath);
                if (File.Exists(backupLibPath))
                {
                    // Restore the original file.
                    try
                    {
                        File.Copy(backupLibPath, gameLibFilePath, true);
                        Program.Log.Info(FILE_RESTORED, backupLibPath);
                    }
                    catch (Exception e)
                    {
                        // This is actually really bad.. but we'll continue to restore other originals.
                        Program.Log.Exception(ERR_RESTORE_FILE, e, backupLibPath);
                    }
                }
            }
        }
Exemple #2
0
        void CopyHooksLibrary(GameKB knowledgeBase)
        {
            var libTargetPath = Path.Combine(knowledgeBase.LibraryPath,
                                             Path.GetFileName(_options.HooksRegistryFilePath));

            try
            {
                // Copy the HookRegistry library next to the libraries of the game!
                File.Copy(_options.HooksRegistryFilePath, libTargetPath, true);
                // The HookRegistry library file is copied next to the game libraries because
                // hooking a library will add a dependancy towards HookRegistry.
                // HookRegistry is designed to have NO DEPENDANCIES. If you built it with
                // additional dependancies, they will need to be copied manually to the library
                // directory!

                // Update registry file path to be around the targetted libraries.
                _options.HooksRegistryFilePath = libTargetPath;

                // And reload assembly definition
                _options.HooksRegistryAssembly = AssemblyDefinition.ReadAssembly(
                    _options.HooksRegistryFilePath);
            }
            catch (Exception)
            {
                Program.Log.Warn(ERR_COPY_HLIB, libTargetPath);
            }
        }
Exemple #3
0
        void ProcessHookRegistry(GameKB gameKnowledge)
        {
            // We load the HookRegistry dll in a seperate app domain, which allows for dynamic unloading
            // when needed.
            // HookRegistry COULD lock referenced DLL's which we want to overwrite, so unloading releases
            // the locks HookRegistry held.

            // Isolated domain where the library will be loaded into.
            var testingDomain = AppDomain.CreateDomain("HR_Testing");

            using (Program.Log.OpenBlock("Testing Hookregistry library"))
            {
                try
                {
                    // Create an instance of our own assembly in a new appdomain.
                    object instance = testingDomain
                                      .CreateInstanceAndUnwrap(typeof(HookRegistryTester).Assembly.FullName, typeof(HookRegistryTester).FullName);

                    /* All methods used are actually executed in the testing domain! */
                    var hrTester = (HookRegistryTester)instance;
                    hrTester.Analyze(_options.HooksRegistryFilePath, gameKnowledge.LibraryPath);

                    // Load all data from the tester.
                    ExpectedMethods        = hrTester.ExpectedMethods;
                    ReferencedLibraryPaths = hrTester.ReferencedAssemblyFiles.ToArray();
                }
                // Exceptions will flow back into our own AppDomain when unhandled.
                catch (Exception)
                {
                    Program.Log.Warn("FAIL Testing");
                    throw;
                }
                finally
                {
                    AppDomain.Unload(testingDomain);
                }
            }
        }
        static int Main(string[] args)
        {
            bool succeeded = YanderePrepare.PrepareMod();

            if (!succeeded)
            {
                Console.ReadLine();
                return(0);
            }
            if (File.Exists(Environment.CurrentDirectory + "\\hooked"))
            {
                LaunchGame();
                return(0);
            }

            string[] actions = CustomArgs(args);
            //Console.ReadLine();
            // Operation
            string invokedOperation = "";
            // General options.
            GeneralOptions generalOptions = null;
            // Options specific to the action to perform.
            object invokedOperationOptions = null;

            var opts = new Options();

            // Must check for null, because the parser won't..
            if (actions == null || actions.Length == 0)
            {
                Console.WriteLine(opts.GetUsage("help"));
                goto ERROR;
            }

            CommandLine.Parser.Default.ParseArgumentsStrict(actions, opts, (verb, subOptions) =>
            {
                // Action to store correct information for further instructing the processor.
                invokedOperation        = verb;
                invokedOperationOptions = subOptions;
            }, () =>
            {
                // Failed attempt at parsing the provided arguments.
                Environment.Exit(-2);
            });

            try
            {
                // Process general options
                generalOptions = (GeneralOptions)invokedOperationOptions;
                Prepare(generalOptions);
            }
            catch (Exception e)
            {
                Log.Exception(e.Message, e);
                goto ERROR;
            }

            // Use knowledge about the game HearthStone. Game knowledge is defined in the shared code
            // project KnowledgeBase. See `GameKnowledgeBase.HSKB` for more information.
            // Change the following line if you want to hook another game.
            var gameKnowledge = new GameKB(generalOptions.GamePath, new YandereSimulatorKB());

            try
            {
                switch (invokedOperation)
                {
                case OPERATION_HOOK:
                    Log.Info("Hooking operation started!\n");
                    var hookHelper = new HookHelper((HookSubOptions)invokedOperationOptions);
                    hookHelper.TryHook(gameKnowledge);
                    Log.Info("Hooked the game libraries!");

                    break;

                case OPERATION_RESTORE:
                    Log.Info("Restore operation started!\n");
                    var restore = new Restore((RestoreSubOptions)invokedOperationOptions);
                    restore.TryRestore(gameKnowledge);
                    Log.Info("Restored the original game libraries!");
                    break;

                default:
                    throw new ArgumentException("Invalid verb processed");
                }
            }
            catch (Exception e)
            {
                Log.Exception(EXCEPTION_MSG, e);
                goto ERROR;
            }

            //Console.ReadLine();
            // All OK
            if (args.Length == 0)
            {
                LaunchGame();
            }
            return(0);

ERROR:
            var tprocess = new System.Diagnostics.Process();
            var tstartInfo = new System.Diagnostics.ProcessStartInfo
            {
                FileName = Environment.CurrentDirectory + "\\unhook.bat"
            };

            tprocess.StartInfo = tstartInfo;
            tprocess.Start();
            Console.ReadLine();
            return(1);
        }
Exemple #5
0
        public void TryHook(GameKB gameKnowledge)
        {
            // Validate all command line options.
            CheckOptions();
            // Copy our injected library to the location of the 'to hook' assemblies.
            CopyHooksLibrary();
            //
            FindNecessaryTypes();
            // Find all expected method fullnames by HookRegistry.
            FetchExpectedMethods();

            var hookEntries = ReadHooksFile(_options.HooksFilePath);

            // Iterate all libraries known for the provided game.
            // An assembly blueprint will be created from the yielded filenames.
            // The blueprints will be edited, saved and eventually replaces the original assembly.
            foreach (string libraryFilePath in gameKnowledge)
            {
                var libBackupPath  = AssemblyHelper.GetPathBackup(libraryFilePath);
                var libPatchedPath = AssemblyHelper.GetPathOut(libraryFilePath);

                // Load the assembly file
                AssemblyDefinition assembly = AssemblyHelper.LoadAssembly(libraryFilePath,
                                                                          gameKnowledge.LibraryPath);
                if (assembly.HasPatchMark())
                {
                    Program.Log.Warn(ASSEMBLY_ALREADY_PATCHED, libraryFilePath);
                    continue;
                }

                // Construct a hooker wrapper around the main Module of the assembly.
                // The wrapper facilitates hooking into method calls.
                ModuleDefinition mainModule = assembly.MainModule;
                Hooker           wrapper    = Hooker.New(mainModule, _options);
                Program.Log.Info(CHECKING_ASSEMBLY, libraryFilePath);

                // Keep track of hooked methods
                bool isHooked = false;
                // Loop each hook entry looking for registered types and methods
                foreach (HOOK_ENTRY hookEntry in hookEntries)
                {
                    try
                    {
                        wrapper.AddHookBySuffix(hookEntry.TypeName, hookEntry.MethodName, ExpectedMethods);
                        isHooked = true;
                    }
                    catch (MissingMethodException)
                    {
                        // The method is not found in the current assembly.
                        // This is no error because we run all hook entries against all libraries!
                    }
                }

                try
                {
                    // Only save if the file actually changed!
                    if (isHooked)
                    {
                        // Generate backup from original file
                        try
                        {
                            // This throws if the file already exists.
                            File.Copy(libraryFilePath, libBackupPath, false);
                        }
                        catch (Exception)
                        {
                            // Do nothing
                        }

                        // Save the manipulated assembly.
                        assembly.Save(libPatchedPath);

                        // Overwrite the original with the hooked one
                        File.Copy(libPatchedPath, libraryFilePath, true);
                    }
                    else
                    {
                        Program.Log.Debug(ASSEMBLY_NOT_PATCHED, libraryFilePath);
                    }
                }
                catch (IOException e)
                {
                    // The file could be locked! Notify user.
                    // .. or certain libraries could not be resolved..
                    // Try to find the path throwing an exception.. but this method is not foolproof!
                    var path = typeof(IOException).GetField("_maybeFullPath",
                                                            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase)?.GetValue(e);
                    Program.Log.Exception(ERR_WRITE_FILE, null, e?.ToString());

                    throw;
                }
            }
        }
Exemple #6
0
        public void TryHook(GameKB gameKnowledge)
        {
            // Validate all command line options.
            CheckOptions();
            // Test HookRegistry library.
            ProcessHookRegistry(gameKnowledge);
            // Copy our injected library to the location of the 'to hook' assemblies.
            CopyLibraries(gameKnowledge);

            List <HOOK_ENTRY> hookEntries = ReadHooksFile(_options.HooksFilePath);

            using (Program.Log.OpenBlock("Parsing libary files"))
            {
                // Iterate all libraries known for the provided game.
                // An assembly blueprint will be created from the yielded filenames.
                // The blueprints will be edited, saved and eventually replaces the original assembly.
                foreach (string libraryFilePath in gameKnowledge.LibraryFilePaths)
                {
                    using (Program.Log.OpenBlock(libraryFilePath))
                    {
                        if (!File.Exists(libraryFilePath))
                        {
                            Program.Log.Warn("File does not exist!");
                            continue;
                        }

                        string libBackupPath  = AssemblyHelper.GetPathBackup(libraryFilePath);
                        string libPatchedPath = AssemblyHelper.GetPathOut(libraryFilePath);

                        AssemblyDefinition assembly = null;
                        try
                        {
                            // Load the assembly file
                            assembly = AssemblyHelper.LoadAssembly(libraryFilePath, gameKnowledge.LibraryPath);
                        }
                        catch (BadImageFormatException e)
                        {
                            Program.Log.Warn("Library file is possibly encrypted!");
                            Program.Log.Info("Library skipped because it cannot be read.");
                            Program.Log.Debug("Full exception: {0}", e.Message);
                            continue;
                        }

                        if (assembly.HasPatchMark())
                        {
                            Program.Log.Warn(ASSEMBLY_ALREADY_PATCHED);
                            continue;
                        }

                        // Construct a hooker wrapper around the main Module of the assembly.
                        // The wrapper facilitates hooking into method calls.
                        ModuleDefinition mainModule = assembly.MainModule;
                        var wrapper = HookLogic.New(mainModule, _options);

                        // Keep track of hooked methods
                        bool isHooked = false;
                        // Loop each hook entry looking for registered types and methods
                        foreach (HOOK_ENTRY hookEntry in hookEntries)
                        {
                            try
                            {
                                wrapper.AddHookBySuffix(hookEntry.TypeName, hookEntry.MethodName, ExpectedMethods);
                                isHooked = true;
                            }
                            catch (MissingMethodException)
                            {
                                // The method is not found in the current assembly.
                                // This is no error because we run all hook entries against all libraries!
                            }
                        }

                        try
                        {
                            // Only save if the file actually changed!
                            if (isHooked)
                            {
                                // Generate backup from original file
                                try
                                {
                                    // This throws if the file already exists.
                                    File.Copy(libraryFilePath, libBackupPath, false);
                                }
                                catch (Exception)
                                {
                                    // Do nothing
                                }

                                // Save the manipulated assembly.
                                assembly.Save(libPatchedPath);

                                // Overwrite the original with the hooked one
                                File.Copy(libPatchedPath, libraryFilePath, true);
                            }
                            else
                            {
                                Program.Log.Warn(ASSEMBLY_NOT_PATCHED, libraryFilePath);
                            }
                        }
                        catch (IOException e)
                        {
                            // The file could be locked! Notify user.
                            // .. or certain libraries could not be resolved..
                            // Try to find the path throwing an exception.. but this method is not foolproof!
                            object path = typeof(IOException).GetField("_maybeFullPath",
                                                                       BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase)?.GetValue(e);
                            Program.Log.Warn("Could not write patched data to file `{0}`!", path);

                            throw e;
                        }
                    }
                }
            }
        }
Exemple #7
0
        void CopyLibraries(GameKB knowledgeBase)
        {
            // The original folder containing HookRegistry library.
            string origHRFolderPath = Path.GetDirectoryName(_options.HooksRegistryFilePath);
            // The library folder of our game.
            string gameLibFolder = knowledgeBase.LibraryPath;

            // List of all assemblies to copy to the game library folder.
            IEnumerable <string> assembliesToCopy = new List <string>(ReferencedLibraryPaths)
            {
                _options.HooksRegistryFilePath
            };

            // Only keep unique entries.
            assembliesToCopy = assembliesToCopy.Distinct();

            // If TRUE, existing files in gameLibFolder will be overwritten if a dependancy has the
            // same name.
            bool overwriteDependancies = _options.OverwriteDependancies;

            using (Program.Log.OpenBlock("Copying HookRegistry dependancies"))
            {
                Program.Log.Info("Source directory `{0}`", origHRFolderPath);
                Program.Log.Info("Target directory `{0}`", gameLibFolder);

                foreach (string referencedLibPath in ReferencedLibraryPaths)
                {
                    // Only copy the libraries which come from the same path as HookRegistry originally.
                    string libFolderPath = Path.GetDirectoryName(referencedLibPath);
                    if (!libFolderPath.Equals(origHRFolderPath))
                    {
                        continue;
                    }

                    // Construct name for library file under the game library folder.
                    string libFileName   = Path.GetFileName(referencedLibPath);
                    string targetLibPath = Path.Combine(gameLibFolder, libFileName);

                    try
                    {
                        if (!overwriteDependancies && File.Exists(targetLibPath))
                        {
                            Program.Log.Info("Skipped `{0}`", libFileName);
                        }
                        else
                        {
                            File.Copy(referencedLibPath, targetLibPath, true);
                            Program.Log.Info("SUCCESS Copied binary `{0}`", libFileName);

                            if (referencedLibPath == _options.HooksRegistryFilePath)
                            {
                                // Update the options object to reflect the copied library.
                                _options.HooksRegistryFilePath          = targetLibPath;
                                _options.HooksRegistryAssemblyBlueprint = AssemblyHelper.LoadAssembly(targetLibPath, gameLibFolder);
                            }
                        }
                    }
                    catch (Exception)
                    {
                        Program.Log.Warn("FAIL Error copying `{0}`. Manual copy is needed!", libFileName);
                    }
                }
            }
        }
Exemple #8
0
        static int Main(string[] args)
        {
            // Operation
            string invokedOperation = "";
            // General options.
            GeneralOptions generalOptions = null;
            // Options specific to the action to perform.
            object invokedOperationOptions = null;

            var opts = new Options();

            // Must check for null, because the parser won't..
            if (args == null || args.Length == 0)
            {
                Console.WriteLine(opts.GetUsage("help"));
                goto ERROR;
            }

            CommandLine.Parser.Default.ParseArgumentsStrict(args, opts, (verb, subOptions) =>
            {
                // Action to store correct information for further instructing the processor.
                invokedOperation        = verb;
                invokedOperationOptions = subOptions;
            }, () =>
            {
                // Failed attempt at parsing the provided arguments.
                Environment.Exit(-2);
            });

            try
            {
                // Process general options
                generalOptions = (GeneralOptions)invokedOperationOptions;
                Prepare(generalOptions);
            }
            catch (Exception e)
            {
                Log.Exception(e.Message, e);
                goto ERROR;
            }

            // Use knowledge about the game HearthStone. Game knowledge is defined in the shared code
            // project KnowledgeBase. See `GameKnowledgeBase.HSKB` for more information.
            // Change the following line if you want to hook another game.
            GameKB gameKnowledge = HSKB.Get(generalOptions.GamePath);

            try
            {
                switch (invokedOperation)
                {
                case OPERATION_HOOK:
                    var hookHelper = new HookHelper((HookSubOptions)invokedOperationOptions);
                    hookHelper.TryHook(gameKnowledge);
                    Log.Info("Succesfully hooked the game libraries!");
                    break;

                case OPERATION_RESTORE:
                    var restore = new Restore((RestoreSubOptions)invokedOperationOptions);
                    restore.TryRestore(gameKnowledge);
                    Log.Info("Succesfully restored the original game libraries!");
                    break;

                default:
                    throw new ArgumentException("Invalid verb processed");
                }
            }
            catch (Exception e)
            {
                Log.Exception(EXCEPTION_MSG, e);
                goto ERROR;
            }

            // All OK
            return(0);

ERROR:
            return(1);
        }