using System; using System.Collections.Generic; using System.Linq; using System.Text; using RomCheater.Logging; using System.Diagnostics; using RomCheater.PluginFramework.Interfaces; using System.IO; namespace Sojaner.MemoryScanner.MemoryProviers { public abstract class BaseMemoryProvider : IPatchMemory, IReadMemory, IAcceptsProcess, IAcceptsPlugin, IMemoryReader, IMemoryWriter, IFileWriter { 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 config) : this() { this.AcceptedPlugin = config.AcceptedPlugin; this.AcceptedProcess = config.AcceptedProcess; } private bool isOpen { get; set; } private bool isClosed { get; set; } #region Open/Close Provider #region public virtual void OpenProvider() public virtual void OpenProvider() { if (isOpen) { logger.Warn.WriteLine("Provider has already been opened."); return; } try { provider = new ProcessMemoryReader(); provider.ReadProcess = this.AcceptedProcess; if (provider.ReadProcess == null) { logger.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) { logger.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) { logger.Warn.WriteLine("Provider has already been closed."); return; } if (!isOpen) { logger.Warn.WriteLine("Provider cannot be closed, it was never opened...attempting to open provider."); OpenProvider(); if (!isOpen) { logger.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) { logger.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) logger.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(uint address, byte value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); byte check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #region public virtual bool PatchMemory(uint address, sbyte value) public virtual bool PatchMemory(uint address, sbyte value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); sbyte check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #region public virtual bool PatchMemory(uint address, ushort value) public virtual bool PatchMemory(uint address, ushort value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); ushort check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #region public virtual bool PatchMemory(uint address, short value) public virtual bool PatchMemory(uint address, short value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); short check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #region public virtual bool PatchMemory(uint address, uint value) public virtual bool PatchMemory(uint address, uint value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); uint check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #region public virtual bool PatchMemory(uint address, int value) public virtual bool PatchMemory(uint address, int value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); int check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #region public virtual bool PatchMemory(uint address, ulong value) public virtual bool PatchMemory(uint address, ulong value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); ulong check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #region public virtual bool PatchMemory(uint address, long value) public virtual bool PatchMemory(uint address, long value) { if (!EnsureProviderIsOpen()) { return false; } int bytesWritten; byte[] bitData = BitConverter.GetBytes(value); provider.WriteProcessMemory(address, bitData, out bytesWritten); long check = 0; ReadMemory(address, out check); if (check == value) return true; return false; } #endregion #endregion #region IReadMemory members #region public virtual bool ReadMemory(uint address, out byte value) public virtual bool ReadMemory(uint address, out byte value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = bitData[0]; return true; } catch { value = 0x00; return false; } } #endregion #region public virtual bool ReadMemory(uint address, out sbyte value) public virtual bool ReadMemory(uint address, out sbyte value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = Convert.ToSByte(bitData[0]); return true; } catch { value = 0x00; return false; } } #endregion #region public virtual bool ReadMemory(uint address, out ushort value) public virtual bool ReadMemory(uint address, out ushort value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = BitConverter.ToUInt16(bitData, 0); return true; } catch { value = 0x00; return false; } } #endregion #region public virtual bool ReadMemory(uint address, out short value) public virtual bool ReadMemory(uint address, out short value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = BitConverter.ToInt16(bitData, 0); return true; } catch { value = 0x00; return false; } } #endregion #region public virtual bool ReadMemory(uint address, out uint value) public virtual bool ReadMemory(uint address, out uint value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = BitConverter.ToUInt32(bitData, 0); return true; } catch { value = 0x00; return false; } } #endregion #region public virtual bool ReadMemory(uint address, out int value) public virtual bool ReadMemory(uint address, out int value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = BitConverter.ToInt32(bitData, 0); return true; } catch { value = 0x00; return false; } } #endregion #region public virtual bool ReadMemory(uint address, out ulong value) public virtual bool ReadMemory(uint address, out ulong value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = BitConverter.ToUInt64(bitData, 0); return true; } catch { value = 0x00; return false; } } #endregion #region public virtual bool ReadMemory(uint address, out long value) public virtual bool ReadMemory(uint address, out long value) { value = 0; if (!EnsureProviderIsOpen()) { return false; } try { int bytesReadSize; byte[] bitData; provider.ReadProcessMemory(address, sizeof(byte), out bytesReadSize, out bitData); value = BitConverter.ToInt64(bitData, 0); return true; } catch { value = 0x00; return false; } } #endregion #endregion #region IMemoryReader members #region public virtual bool ReadFirstNonZeroByte(uint MemoryAddress, uint bytesToRead, out uint address) public virtual bool ReadFirstNonZeroByte(uint MemoryAddress, uint bytesToRead, out uint 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 ReadProcessMemory(uint MemoryAddress, int bytesToRead, out int bytesRead, out byte[] data) public virtual void ReadProcessMemory(uint MemoryAddress, uint bytesToRead, out int bytesRead, out byte[] data) { bytesRead = 0x00; data = new byte[] { }; 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(uint MemoryAddress, byte byteToWrite, out int bytesWritten) public virtual void WriteProcessMemory(uint 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(uint MemoryAddress, byte[] bytesToWrite, out int bytesWritten) public virtual void WriteProcessMemory(uint MemoryAddress, byte[] bytesToWrite, out int 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, uint MemoryAddress, uint bytesToRead, out int bytesRead) public virtual bool WriteProcessMemoryToFile(string filename, uint MemoryAddress, uint bytesToRead, out int bytesRead) { bytesRead = 0; if (!EnsureProviderIsOpen()) { return false; } try { provider.WriteProcessMemoryToFile(filename, MemoryAddress, bytesToRead, out bytesRead); return true; } catch { bytesRead = 0x00; return false; } } #endregion #endregion } }