See More

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using Process.NET.Memory; namespace Process.NET.Modules { ///

/// Class providing tools for manipulating modules and libraries. /// public class ModuleFactory : IModuleFactory { /// /// The list containing all injected modules (writable). /// protected readonly List InternalInjectedModules; protected readonly IProcess ProcessPlus; /// /// Initializes a new instance of the class. /// /// The reference of the object. public ModuleFactory(IProcess processPlus) { // Save the parameter ProcessPlus = processPlus; // Create a list containing all injected modules InternalInjectedModules = new List(); } /// /// Gets a pointer from the remote process. /// /// The address of the pointer. /// A new instance of a class. public IPointer this[IntPtr address] => new MemoryPointer(ProcessPlus, address); /// /// Gets the main module for the remote process. /// public IProcessModule MainModule => FetchModule(ProcessPlus.Native.MainModule); /// /// Gets the modules that have been loaded in the remote process. /// public IEnumerable RemoteModules => NativeModules.Select(FetchModule); /// /// Gets the native modules that have been loaded in the remote process. /// public IEnumerable NativeModules => ProcessPlus.Native.Modules.Cast(); /// /// Gets the specified module in the remote process. /// /// The name of module (not case sensitive). /// A new instance of a class. public IProcessModule this[string moduleName] => FetchModule(moduleName); /// /// Releases all resources used by the object. /// public virtual void Dispose() { // Release all injected modules which must be disposed foreach (var injectedModule in InternalInjectedModules.Where(m => m.MustBeDisposed)) injectedModule.Dispose(); // Clean the cached functions related to this process foreach ( var cachedFunction in RemoteModule.CachedFunctions.ToArray() .Where(cachedFunction => cachedFunction.Key.Item2 == ProcessPlus.Handle)) RemoteModule.CachedFunctions.Remove(cachedFunction); // Avoid the finalizer GC.SuppressFinalize(this); } /// /// A collection containing all injected modules. /// public IEnumerable InjectedModules => InternalInjectedModules.AsReadOnly(); /// /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. /// /// The name of module to eject. public void Eject(string moduleName) { // Fint the module to eject var module = RemoteModules.FirstOrDefault(m => m.Name == moduleName); // Eject the module is it's valid if (module != null) RemoteModule.InternalEject(ProcessPlus, module); } /// /// Injects the specified module into the address space of the remote process. /// /// /// The path of the module. This can be either a library module (a .dll file) or an executable module /// (an .exe file). /// /// The module will be ejected when the finalizer collects the object. /// A new instance of the class. public InjectedModule Inject(string path, bool mustBeDisposed = true) { // Injects the module var module = InjectedModule.InternalInject(ProcessPlus, path); // Add the module in the list InternalInjectedModules.Add(module); // Return the module return module; } /// /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. /// /// The module to eject. public void Eject(IProcessModule module) { // If the module is valid if (!module.IsValid) return; // Find if the module is an injected one var injected = InternalInjectedModules.FirstOrDefault(m => m.Equals(module)); if (injected != null) InternalInjectedModules.Remove(injected); // Eject the module RemoteModule.InternalEject(ProcessPlus, module); } /// /// Frees resources and perform other cleanup operations before it is reclaimed by garbage collection. /// ~ModuleFactory() { Dispose(); } /// /// Fetches a module from the remote process. /// /// /// A module name (not case sensitive). If the file name extension is omitted, the default library /// extension .dll is appended. /// /// A new instance of a class. public IProcessModule FetchModule(string moduleName) { // Convert module name with lower chars moduleName = moduleName.ToLower(); // Check if the module name has an extension if (!Path.HasExtension(moduleName)) moduleName += ".dll"; // Fetch and return the module return new RemoteModule(ProcessPlus, NativeModules.First(m => m.ModuleName.ToLower() == moduleName)); } /// /// Fetches a module from the remote process. /// /// A module in the remote process. /// A new instance of a class. public IProcessModule FetchModule(ProcessModule module) { return FetchModule(module.ModuleName); } } }