#region Logging Defines // include this any class or method that required logging, and comment-out what is not needed #region Enabled logging levels #define LOGGING_ENABLE_INFO #define LOGGING_ENABLE_WARN #define LOGGING_ENABLE_DEBUG #define LOGGING_ENABLE_VERBOSEDEBUG #define LOGGING_ENABLE_ERROR #define LOGGING_ENABLE_VERBOSEERROR #define LOGGING_ENABLE_PROFILER #endregion #endregion using System; using System.Collections.Generic; using System.Linq; using System.Text; using RomCheater.Logging; using System.Diagnostics; using System.IO; using ManagedWinapi; using RomCheater.Interfaces; using Enterprise.Logging; namespace Sojaner.MemoryScanner.MemoryProviers { #region public abstract class BaseMemoryProvider public abstract class BaseMemoryProvider : IPatchMemory, IReadMemory, IAcceptsProcess, IAcceptsPlugin, IMemoryReader, IMemoryWriter, IFileWriter, IDisposable, Events.IAcceptsBytesReadEvent { private ProcessMemoryReader provider; public BaseMemoryProvider() { this.AcceptedPlugin = null; this.AcceptedProcess = null; isClosed = true; isOpen = false; } public BaseMemoryProvider(IConfigPlugin config) : this() { this.AcceptedPlugin = config; } public BaseMemoryProvider(IConfigPlugin config, Process process) : this() { this.AcceptedPlugin = config; this.AcceptedProcess = process; } public BaseMemoryProvider(IAcceptsProcessAndConfig pconfig) : this() { this.AcceptedPlugin = pconfig.AcceptedPlugin; this.AcceptedProcess = pconfig.AcceptedProcess; } public event BaseEventHandler OnBytesRead; private bool isOpen { get; set; } private bool isClosed { get; set; } private void provider_OnBytesRead(Events.OnBytesReadEventArgs e) { e.Sender = this; if (this.OnBytesRead != null) this.OnBytesRead.Invoke(e); } #region Open/Close Provider #region public virtual void OpenProvider() public virtual void OpenProvider() { if (isOpen) { gLog.Warn.WriteLine("Provider has already been opened."); return; } try { provider = new ProcessMemoryReader(); provider.ReadProcess = this.AcceptedProcess; provider.OnBytesRead += new BaseEventHandler(provider_OnBytesRead); if (provider.ReadProcess == null) { gLog.Error.WriteLine("{0}.OpenProvider() Could not attach to process: {1}", "", this.GetType().Name, this.AcceptedProcess.ToString()); return; } //provider.OpenProcess(); isOpen = true; isClosed = false; } catch (Exception ex) { gLog.Error.WriteLine("Failed to open provider: {0}{1}", System.Environment.NewLine, ex.ToString()); isOpen = false; isClosed = true; } } #endregion #region public virtual void CloseProvider() public virtual void CloseProvider() { if (isClosed) { gLog.Warn.WriteLine("Provider has already been closed."); return; } if (!isOpen) { gLog.Warn.WriteLine("Provider cannot be closed, it was never opened...attempting to open provider."); OpenProvider(); if (!isOpen) { gLog.Warn.WriteLine("Could not open provider"); return; } } try { //logger.VerboseDebug.WriteLine("CloseProvider(): System.Environment.StackTrace: {0}{1}", System.Environment.NewLine, System.Environment.StackTrace); if (provider == null) return; //provider.CloseHandle(); provider = null; // free any memory associated with the provider isClosed = true; isOpen = false; } catch (Exception ex) { gLog.Error.WriteLine("Failed to close provider: {0}{1}", System.Environment.NewLine, ex.ToString()); isClosed = false; if (isOpen) { throw new Exception("Provider is failed to close and still open."); } } } #endregion #endregion #region IAcceptsProcess Members public Process AcceptedProcess { get; set; } #endregion #region IAcceptsPlugin Members public IConfigPlugin AcceptedPlugin { get; set; } #endregion #region EnsureProviderIsOpen methods : log and/or throw errors private bool EnsureProviderIsOpen() { return EnsureProviderIsOpenOrThrowError(); } private bool EnsureProviderIsOpenOrLogError() { return EnsureProviderIsOpenOrThrowOrLogError(false, true); } private bool EnsureProviderIsOpenOrThrowError() { return EnsureProviderIsOpenOrThrowOrLogError(true, true); } private bool EnsureProviderIsOpenOrThrowOrLogError(bool ThrowError, bool LogError) { if (!isOpen) { try { throw new Exception("Memory operation could not be completed because the provider is not open"); } catch (Exception ex) { if (LogError) gLog.Verbose.Error.WriteLine(ex.ToString()); if (ThrowError) throw ex; return false; } } return true; } #endregion #region IPatchMemory members #region public virtual bool PatchMemory(uint address, byte value) public virtual bool PatchMemory(ulong address, byte value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #region public virtual bool PatchMemory(uint address, sbyte value) public virtual bool PatchMemory(ulong address, sbyte value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #region public virtual bool PatchMemory(uint address, ushort value) public virtual bool PatchMemory(ulong address, ushort value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #region public virtual bool PatchMemory(uint address, short value) public virtual bool PatchMemory(ulong address, short value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #region public virtual bool PatchMemory(uint address, uint value) public virtual bool PatchMemory(ulong address, uint value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #region public virtual bool PatchMemory(uint address, int value) public virtual bool PatchMemory(ulong address, int value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #region public virtual bool PatchMemory(uint address, ulong value) public virtual bool PatchMemory(ulong address, ulong value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #region public virtual bool PatchMemory(uint address, long value) public virtual bool PatchMemory(ulong address, long value) { if (!EnsureProviderIsOpen()) { return false; } return provider.PatchMemory(address, value); } #endregion #endregion #region IReadMemory members #region public virtual bool ReadMemory(uint address, out byte value) public virtual bool ReadMemory(ulong address, out byte value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #region public virtual bool ReadMemory(uint address, out sbyte value) public virtual bool ReadMemory(ulong address, out sbyte value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #region public virtual bool ReadMemory(uint address, out ushort value) public virtual bool ReadMemory(ulong address, out ushort value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #region public virtual bool ReadMemory(uint address, out short value) public virtual bool ReadMemory(ulong address, out short value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #region public virtual bool ReadMemory(uint address, out uint value) public virtual bool ReadMemory(ulong address, out uint value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #region public virtual bool ReadMemory(uint address, out int value) public virtual bool ReadMemory(ulong address, out int value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #region public virtual bool ReadMemory(uint address, out ulong value) public virtual bool ReadMemory(ulong address, out ulong value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #region public virtual bool ReadMemory(uint address, out long value) public virtual bool ReadMemory(ulong address, out long value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } return provider.ReadMemory(address, out value); } #endregion #endregion #region IMemoryReader member #region public void QueryMemoryRegion() public List QueryMemoryRegions(ulong start, ulong size) { if (!EnsureProviderIsOpen()) { return new List(); } try { return provider.QueryMemoryRegions(start,size); } catch { return new List(); } } #endregion #region public virtual bool ReadFirstNonZeroByte(int MemoryAddress, uint bytesToRead, out int address) public virtual bool ReadFirstNonZeroByte(ulong MemoryAddress, ulong bytesToRead, out ulong address) { address = 0; if (!EnsureProviderIsOpen()) { return false; } try { provider.ReadFirstNonZeroByte(MemoryAddress, bytesToRead, out address); return true; } catch { address = 0x00; return false; } } #endregion #region public virtual void ReadProcessMemoryAtOnce(int MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data) public virtual void ReadProcessMemoryAtOnce(ulong MemoryAddress, ulong bytesToRead, object UserState) { if (!EnsureProviderIsOpen()) { return; } try { provider.ReadProcessMemoryAtOnce(MemoryAddress, bytesToRead, UserState); } catch { } } public virtual void ReadProcessMemoryAtOnce(ulong MemoryAddress, ulong bytesToRead, out ulong bytesRead, out byte[] data) { bytesRead = 0x00; data = new byte[bytesToRead]; if (!EnsureProviderIsOpen()) { return; } try { provider.ReadProcessMemoryAtOnce(MemoryAddress, bytesToRead, out bytesRead, out data); } catch { bytesRead = 0x00; data = new byte[] { }; } } public virtual void UpdateAddressArray(ulong[] addresses, ulong size, out byte[][] values) { values = new byte[addresses.Length][]; for (int x = 0; x < values.Length; x++) { values[x] = new byte[size]; } if (!EnsureProviderIsOpen()) { return; } try { provider.UpdateAddressArray(addresses, size, out values); } catch { values = new byte[addresses.Length][]; for (int x = 0; x < values.Length; x++) { values[x] = new byte[size]; } } } #endregion #region public virtual void ReadProcessMemory(int MemoryAddress, int bytesToRead, out int bytesRead, out byte[] data) public virtual void ReadProcessMemory(ulong MemoryAddress, ulong bytesToRead, out ulong bytesRead, out byte[] data) { bytesRead = 0x00; data = new byte[bytesToRead]; if (!EnsureProviderIsOpen()) { return; } try { provider.ReadProcessMemory(MemoryAddress, bytesToRead, out bytesRead, out data); } catch { bytesRead = 0x00; data = new byte[] { }; } } public virtual void ReadProcessMemory(long MemoryAddress, long bytesToRead, out ulong bytesRead, out byte[] data) { bytesRead = 0x00; data = new byte[bytesToRead]; if (!EnsureProviderIsOpen()) { return; } try { provider.ReadProcessMemory(MemoryAddress, bytesToRead, out bytesRead, out data); } catch { bytesRead = 0x00; data = new byte[] { }; } } #endregion #region IMemoryWriter members //#region public virtual void WriteProcessMemory(int MemoryAddress, byte byteToWrite, out int bytesWritten) //public virtual void WriteProcessMemory(int MemoryAddress, byte byteToWrite, out int bytesWritten) //{ // bytesWritten = 0; // if (!EnsureProviderIsOpen()) { return; } // try { provider.WriteProcessMemory(MemoryAddress, new byte[] { byteToWrite }, out bytesWritten); } // catch { bytesWritten = 0x00; } //} //#endregion #region public virtual void WriteProcessMemory(int MemoryAddress, byte[] bytesToWrite, out int bytesWritten) public virtual void WriteProcessMemory(long MemoryAddress, byte[] bytesToWrite, out ulong bytesWritten) { bytesWritten = 0; if (!EnsureProviderIsOpen()) { return; } try { provider.WriteProcessMemory(MemoryAddress, bytesToWrite, out bytesWritten); } catch { bytesWritten = 0x00; } } public virtual void WriteProcessMemory(ulong MemoryAddress, byte[] bytesToWrite, out ulong bytesWritten) { bytesWritten = 0; if (!EnsureProviderIsOpen()) { return; } try { provider.WriteProcessMemory(MemoryAddress, bytesToWrite, out bytesWritten); } catch { bytesWritten = 0x00; } } #endregion #endregion #endregion #region IFileWriter members #region public virtual bool WriteProcessMemoryToFile(string filename, int MemoryAddress, uint bytesToRead, out int bytesRead) public virtual bool WriteProcessMemoryToFile(string filename, ulong MemoryAddress, ulong bytesToRead, out ulong bytesRead) { bytesRead = 0; if (!EnsureProviderIsOpen()) { return false; } try { provider.WriteProcessMemoryToFile(filename, MemoryAddress, bytesToRead, out bytesRead); return true; } catch { bytesRead = 0x00; return false; } } #endregion #endregion #region IDisposable Support // Track whether Dispose has been called. private bool disposed = false; // Implement IDisposable. // Do not make this method virtual. // A derived class should not be able to override this method. public void Dispose() { Dispose(true); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC.SupressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time. GC.SuppressFinalize(this); } // Dispose(bool disposing) executes in two distinct scenarios. // If disposing equals true, the method has been called directly // or indirectly by a user's code. Managed and unmanaged resources // can be disposed. // If disposing equals false, the method has been called by the // runtime from inside the finalizer and you should not reference // other objects. Only unmanaged resources can be disposed. protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this.disposed) { // If disposing equals true, dispose all managed // and unmanaged resources. if (disposing) { // Dispose managed resources. //component.Dispose(); } // Call the appropriate methods to clean up // unmanaged resources here. // If disposing is false, // only the following code is executed. if (!isClosed) CloseProvider(); // Note disposing has been done. disposed = true; } } // Use C# destructor syntax for finalization code. // This destructor will run only if the Dispose method // does not get called. // It gives your base class the opportunity to finalize. // Do not provide destructors in types derived from this class. ~BaseMemoryProvider() { // Do not re-create Dispose clean-up code here. // Calling Dispose(false) is optimal in terms of // readability and maintainability. Dispose(false); } #endregion } #endregion }