See More

using System; using System.Collections.Concurrent; using System.Diagnostics; using ProcessNET.Extensions; using ProcessNET.Memory; using ProcessNET.Modules; using ProcessNET.Native.Types; using ProcessNET.Threads; using ProcessNET.Utilities; using ProcessNET.Windows; namespace ProcessNET { ///

/// A class that offsers several tools to interact with a process. /// /// public class ProcessSharp : IProcess { /// /// Initializes a new instance of the class. /// /// The native process. /// The type of memory being manipulated. public ProcessSharp(System.Diagnostics.Process native, MemoryType type) { native.EnableRaisingEvents = true; native.Exited += (s, e) => { ProcessExited?.Invoke(s, e); HandleProcessExiting(); }; Native = native; Handle = MemoryHelper.OpenProcess(ProcessAccessFlags.AllAccess, Native.Id); switch (type) { case MemoryType.Local: Memory = new LocalProcessMemory(Handle); break; case MemoryType.Remote: Memory = new ExternalProcessMemory(Handle); break; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } native.ErrorDataReceived += OutputDataReceived; native.OutputDataReceived += OutputDataReceived; ThreadFactory = new ThreadFactory(this); ModuleFactory = new ModuleFactory(this); MemoryFactory = new MemoryFactory(this); WindowFactory = new WindowFactory(this); } /// /// Initializes a new instance of the class. /// /// Name of the process. /// The type of memory being manipulated. public ProcessSharp(string processName, MemoryType type) : this(ProcessHelper.FromName(processName), type) { } /// /// Initializes a new instance of the class. /// /// The process id of the process to open with all rights. /// The type of memory being manipulated. public ProcessSharp(int processId, MemoryType type) : this(ProcessHelper.FromProcessId(processId), type) { } /// /// Raises when the object is disposed. /// public event EventHandler OnDispose; /// /// Class for reading and writing memory. /// public IMemory Memory { get; set; } /// /// Provide access to the opened process. /// public System.Diagnostics.Process Native { get; set; } /// /// The process handle opened with all rights. /// public SafeMemoryHandle Handle { get; set; } /// /// Factory for manipulating threads. /// public IThreadFactory ThreadFactory { get; set; } /// /// Factory for manipulating modules and libraries. /// public IModuleFactory ModuleFactory { get; set; } /// /// Factory for manipulating memory space. /// public IMemoryFactory MemoryFactory { get; set; } /// /// Factory for manipulating windows. /// public IWindowFactory WindowFactory { get; set; } protected string ownerUser = null; /// /// Gets the name of the user this process belongs to. /// public string OwnerUser { get { if(string.IsNullOrWhiteSpace(ownerUser)) { ownerUser = ProcessHelper.GetProcessUser(Native.Id); } return ownerUser; } } /// /// Gets the with the specified module name. /// /// Name of the module. /// IProcessModule. public IProcessModule this[string moduleName] => ModuleFactory[moduleName]; /// /// Gets the with the specified address. /// /// The address the pointer is located at in memory. /// IPointer. public IPointer this[IntPtr intPtr] => new MemoryPointer(this, intPtr); protected bool IsDisposed { get; set; } protected bool MustBeDisposed { get; set; } = true; /// /// Releases unmanaged and - optionally - managed resources. /// public virtual void Dispose() { //TODO Consider adding a null check here, or a nasty crash deadlock can make it in here occasionally. //TODO followup: did the invoke threadsafety characterstics fix the deadlock? if (!IsDisposed) { IsDisposed = true; OnDispose?.Invoke(this, EventArgs.Empty); ThreadFactory?.Dispose(); ModuleFactory?.Dispose(); MemoryFactory?.Dispose(); WindowFactory?.Dispose(); Handle?.Close(); GC.SuppressFinalize(this); } } /// /// Handles the process exiting. /// /// Created 2012-02-15 protected virtual void HandleProcessExiting() { } #region Pointers /// /// Calculates the final address a pointer is pointing at in a module, knowing it's base address and offsets. /// /// The module name to calculate the pointer at. /// The base address of the pointer. /// The offsets of the pointer. /// The final address the pointer is pointing at. public IntPtr GetPointerAddress(string moduleName, IntPtr baseAddress, params int[] offsets) { if (string.IsNullOrWhiteSpace(moduleName)) { throw new ArgumentException($"'{nameof(moduleName)}' cannot be null or whitespace.", nameof(moduleName)); } return GetPointerAddress(this[moduleName], baseAddress, offsets); } /// /// Calculates the final address a pointer is pointing at in a module, knowing it's base address and offsets. /// /// The module to calculate the pointer at. /// The base address of the pointer. /// The offsets of the pointer. /// The final address the pointer is pointing at. public IntPtr GetPointerAddress(IProcessModule module, IntPtr baseAddress, params int[] offsets) { if (module is null) { throw new ArgumentNullException(nameof(module)); } IntPtr finalBaseAddress; if (Memory.Is32Bit) finalBaseAddress = module.BaseAddress + baseAddress.ToInt32(); else finalBaseAddress = new IntPtr(module.BaseAddress.ToInt64() + baseAddress.ToInt64()); return GetPointerAddress(finalBaseAddress, offsets); } /// /// Calculates the final address a pointer is pointing at, knowing it's base address and offsets. /// /// The base address of the pointer. /// The offsets of the pointer. /// The final address the pointer is pointing at. public IntPtr GetPointerAddress(IntPtr baseAddress, params int[] offsets) { if (baseAddress.MayBeValid() == false) return IntPtr.Zero; IntPtr address = baseAddress; if (offsets != null && offsets.Length > 0) { for(int i = 0; i < offsets.Length; i++) { try { address = Memory.Read(address + offsets[i]); } catch(Exception ex) { return IntPtr.Zero; } } } return address; } #endregion /// /// Event queue for all listeners interested in ProcessExited events. /// public event EventHandler ProcessExited; private static void OutputDataReceived(object sender, DataReceivedEventArgs e) { Trace.WriteLine(e.Data); } ~ProcessSharp() { if (MustBeDisposed) { Dispose(); } } } }