See More

using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Process.NET.Extensions; using Process.NET.Memory; using Process.NET.Native.Types; using Process.NET.Utilities; namespace Process.NET.Modules { ///

/// Class repesenting a module in the remote process. /// public class RemoteModule : MemoryRegion, IProcessModule { /// /// The dictionary containing all cached functions of the remote module. /// internal static readonly IDictionary, IProcessFunction> CachedFunctions = new Dictionary, IProcessFunction>(); /// /// Initializes a new instance of the class. /// /// /// The native object corresponding to this module. public RemoteModule(IProcess processPlus, ProcessModule module) : base(processPlus, module.BaseAddress) { // Save the parameter Native = module; } /// /// State if this is the main module of the remote process. /// public bool IsMainModule => Process.Native.MainModule.BaseAddress == BaseAddress; /// /// Gets if the is valid. /// public override bool IsValid { get { return base.IsValid && Process.Native.Modules.Cast() .Any(m => m.BaseAddress == BaseAddress && m.ModuleName == Name); } } /// /// The name of the module. /// public string Name => Native.ModuleName; /// /// The native object corresponding to this module. /// public ProcessModule Native { get; } /// /// The full path of the module. /// public string Path => Native.FileName; /// /// The size of the module in the memory of the remote process. /// public int Size => Native.ModuleMemorySize; /// /// Gets the specified function in the remote module. /// /// The name of the function. /// A new instance of a class. public IProcessFunction this[string functionName] { get { return FindFunction(functionName); } set { CachedFunctions[Tuple.Create(functionName, Process.Handle)] = value; } } /// /// Ejects the loaded dynamic-link library (DLL) module. /// public void Eject() { // Eject the module Process.ModuleFactory.Eject(this); // Remove the pointer BaseAddress = IntPtr.Zero; } /// /// Finds the specified function in the remote module. /// /// The name of the function (case sensitive). /// A new instance of a class. /// /// Interesting article on how DLL loading works: http://msdn.microsoft.com/en-us/magazine/bb985014.aspx /// public IProcessFunction FindFunction(string functionName) { // Create the tuple var tuple = Tuple.Create(functionName, Process.Handle); // Check if the function is already cached if (CachedFunctions.ContainsKey(tuple)) return CachedFunctions[tuple]; // If the function is not cached // Check if the local process has this module loaded var localModule = System.Diagnostics.Process.GetCurrentProcess() .Modules.Cast() .FirstOrDefault(m => m.FileName.ToLower() == Path.ToLower()); var isManuallyLoaded = false; try { // If this is not the case, load the module inside the local process if (localModule == null) { isManuallyLoaded = true; localModule = ModuleHelper.LoadLibrary(Native.FileName); } // Get the offset of the function var offset = localModule.GetProcAddress(functionName).ToInt64() - localModule.BaseAddress.ToInt64(); // Rebase the function with the remote module var function = new RemoteFunction(Process, new IntPtr(Native.BaseAddress.ToInt64() + offset), functionName); // Store the function in the cache CachedFunctions.Add(tuple, function); // Return the function rebased with the remote module return function; } finally { // Free the module if it was manually loaded if (isManuallyLoaded) localModule.FreeLibrary(); } } /// /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. /// /// The reference of the object. /// The module to eject. internal static void InternalEject(IProcess memorySharp, IProcessModule module) { // Call FreeLibrary remotely memorySharp.ThreadFactory.CreateAndJoin(memorySharp["kernel32"]["FreeLibrary"].BaseAddress, module.BaseAddress); } /// /// Returns a string that represents the current object. /// public override string ToString() { return $"BaseAddress = 0x{BaseAddress.ToInt64():X} Name = {Name}"; } } }