2016-12-09 74 views
2

我有一個包含多個函數來讀寫內存的類。但它缺少readByte函數和writeByte函數。內存讀寫字節

我試圖創建這些按以下格式:

public byte readByte(IntPtr address) 
{ 
    byte[] buffer = new byte[1]; 
    ReadMemory(address, buffer, 1); 
    //return BitConverter.ToUInt32(buffer, 0); 
} 

但想不出BitConverter返回類型。有沒有人有一個想法,我可以如何創建這些功能?由於返回值只是一個字節,你可以在這個截圖中看到:

enter image description here

從類的一些功能:

/// <summary> 
/// Reads 32 bit signed integer at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <returns></returns> 
public int ReadInt32(IntPtr address) 
{ 
    byte[] buffer = new byte[4]; 
    ReadMemory(address, buffer, 4); 
    return BitConverter.ToInt32(buffer, 0); 
} 

/// <summary> 
/// Reads 32 bit unsigned integer at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <returns></returns> 
public uint ReadUInt32(IntPtr address) 
{ 
    byte[] buffer = new byte[4]; 
    ReadMemory(address, buffer, 4); 
    return BitConverter.ToUInt32(buffer, 0); 
} 

/// <summary> 
/// Reads single precision value at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <returns></returns> 
public float ReadFloat(IntPtr address) 
{ 
    byte[] buffer = new byte[4]; 
    ReadMemory(address, buffer, 4); 
    return BitConverter.ToSingle(buffer, 0); 
} 

/// <summary> 
/// Reads double precision value at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <returns></returns> 
public double ReadDouble(IntPtr address) 
{ 
    byte[] buffer = new byte[8]; 
    ReadMemory(address, buffer, 8); 
    return BitConverter.ToDouble(buffer, 0); 
} 

/// <summary> 
/// Writes 32 bit unsigned integer at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <param name="value">Value</param> 
/// <returns></returns> 
public void WriteUInt32(IntPtr address, uint value) 
{ 
    byte[] buffer = BitConverter.GetBytes(value); 
    WriteMemory(address, buffer, 4); 
} 

/// <summary> 
/// Writes 32 bit signed integer at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <param name="value">Value</param> 
/// <returns></returns> 
public void WriteInt32(IntPtr address, int value) 
{ 
    byte[] buffer = BitConverter.GetBytes(value); 
    WriteMemory(address, buffer, 4); 
} 

/// <summary> 
/// Writes single precision value at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <param name="value">Value</param> 
/// <returns></returns> 
public void WriteFloat(IntPtr address, float value) 
{ 
    byte[] buffer = BitConverter.GetBytes(value); 
    WriteMemory(address, buffer, 4); 
} 

/// <summary> 
/// Writes double precision value at the address 
/// </summary> 
/// <param name="address">Memory address</param> 
/// <param name="value">Value</param> 
/// <returns></returns> 
public void WriteDouble(IntPtr address, double value) 
{ 
    byte[] buffer = BitConverter.GetBytes(value); 
    WriteMemory(address, buffer, 8); 
} 

因爲目前我打電話以下列方式類:

public void updatePlayerStatistic(int prestigeLevel) 
{ 
    Process[] processes = Process.GetProcessesByName("iw7_ship"); 
    if (processes.Length > 0) 
    { 
     using (CheatEngine.Memory memory = new CheatEngine.Memory(processes[0])) 
     { 
      // Prestige code 
      IntPtr prestigeAddress = memory.GetAddress("iw7_ship.exe", (IntPtr)0x04105320, new int[] { 0x6E5 }); 
      //memory.WriteUInt32(prestigeAddress, uint.Parse(prestigeLevel.ToString())); 
      MessageBox.Show(memory.ReadUInt32(prestigeAddress).ToString()); 
     } 
    } 
} 

這將始終返回0。正如你可以在下面的截圖中看到:

Image

但是顯然在CheatEngine中顯示的值是8。

全班同學:

using System; 
using System.Diagnostics; 
using System.Text.RegularExpressions; 

namespace InfiniteTrainer.CheatEngine 
{ 
    /// <summary> 
    /// Represents an access to a remote process memory 
    /// </summary> 
    public class Memory : IDisposable 
    { 
     private Process process; 
     private IntPtr processHandle; 
     private bool isDisposed; 

     public const string OffsetPattern = "(\\+|\\-){0,1}(0x){0,1}[a-fA-F0-9]{1,}"; 

     /// <summary> 
     /// Initializes a new instance of the Memory 
     /// </summary> 
     /// <param name="process">Remote process</param> 
     public Memory(Process process) 
     { 
      if (process == null) 
       throw new ArgumentNullException("process"); 

      this.process = process; 
      processHandle = Win32.OpenProcess(
       Win32.ProcessAccessType.PROCESS_VM_READ | Win32.ProcessAccessType.PROCESS_VM_WRITE | 
       Win32.ProcessAccessType.PROCESS_VM_OPERATION, true, (uint)process.Id); 
      if (processHandle == IntPtr.Zero) 
       throw new InvalidOperationException("Could not open the process"); 
     } 

     #region IDisposable 

     ~Memory() 
     { 
      Dispose(false); 
     } 

     public void Dispose() 
     { 
      Dispose(true); 
      GC.SuppressFinalize(this); 
     } 

     private void Dispose(bool disposing) 
     { 
      if (isDisposed) 
       return; 
      Win32.CloseHandle(processHandle); 
      process = null; 
      processHandle = IntPtr.Zero; 
      isDisposed = true; 
     } 

     #endregion 

     #region Properties 

     /// <summary> 
     /// Gets the process to which this memory is attached to 
     /// </summary> 
     public Process Process 
     { 
      get 
      { 
       return process; 
      } 
     } 

     #endregion 

     /// <summary> 
     /// Finds module with the given name 
     /// </summary> 
     /// <param name="name">Module name</param> 
     /// <returns></returns> 
     protected ProcessModule FindModule(string name) 
     { 
      if (string.IsNullOrEmpty(name)) 
       throw new ArgumentNullException("name"); 
      foreach (ProcessModule module in process.Modules) 
      { 
       if (module.ModuleName.ToLower() == name.ToLower()) 
        return module; 
      } 
      return null; 
     } 

     /// <summary> 
     /// Gets module based address 
     /// </summary> 
     /// <param name="moduleName">Module name</param> 
     /// <param name="baseAddress">Base address</param> 
     /// <param name="offsets">Collection of offsets</param> 
     /// <returns></returns> 
     public IntPtr GetAddress(string moduleName, IntPtr baseAddress, int[] offsets) 
     { 
      if (string.IsNullOrEmpty(moduleName)) 
       throw new ArgumentNullException("moduleName"); 

      ProcessModule module = FindModule(moduleName); 
      if (module == null) 
       return IntPtr.Zero; 
      else 
      { 
       //int address = module.BaseAddress.ToInt32() + baseAddress.ToInt32(); 
       long address = module.BaseAddress.ToInt64() + baseAddress.ToInt64(); 
       return GetAddress((IntPtr)address, offsets); 
      } 
     } 

     /// <summary> 
     /// Gets address 
     /// </summary> 
     /// <param name="baseAddress">Base address</param> 
     /// <param name="offsets">Collection of offsets</param> 
     /// <returns></returns> 
     public IntPtr GetAddress(IntPtr baseAddress, int[] offsets) 
     { 
      if (baseAddress == IntPtr.Zero) 
       throw new ArgumentException("Invalid base address"); 

      //int address = baseAddress.ToInt32(); 
      long address = baseAddress.ToInt64(); 

      if (offsets != null && offsets.Length > 0) 
      { 
       byte[] buffer = new byte[4]; 
       foreach (int offset in offsets) 
        address = ReadInt32((IntPtr)address) + offset; 
      } 

      return (IntPtr)address; 
     } 

     /// <summary> 
     /// Gets address pointer 
     /// </summary> 
     /// <param name="address">Address</param> 
     /// <returns></returns> 
     public IntPtr GetAddress(string address) 
     { 
      if (string.IsNullOrEmpty(address)) 
       throw new ArgumentNullException("address"); 

      string moduleName = null; 
      int index = address.IndexOf('"'); 
      if (index != -1) 
      { 
       // Module name at the beginning 
       int endIndex = address.IndexOf('"', index + 1); 
       if (endIndex == -1) 
        throw new ArgumentException("Invalid module name. Could not find matching \""); 
       moduleName = address.Substring(index + 1, endIndex - 1); 
       address = address.Substring(endIndex + 1); 
      } 

      int[] offsets = GetAddressOffsets(address); 
      int[] _offsets = null; 
      IntPtr baseAddress = offsets != null && offsets.Length > 0 ? 
       (IntPtr)offsets[0] : IntPtr.Zero; 
      if (offsets != null && offsets.Length > 1) 
      { 
       _offsets = new int[offsets.Length - 1]; 
       for (int i = 0; i < offsets.Length - 1; i++) 
        _offsets[i] = offsets[i + 1]; 
      } 

      if (moduleName != null) 
       return GetAddress(moduleName, baseAddress, _offsets); 
      else 
       return GetAddress(baseAddress, _offsets); 
     } 

     /// <summary> 
     /// Gets address offsets 
     /// </summary> 
     /// <param name="address">Address</param> 
     /// <returns></returns> 
     protected static int[] GetAddressOffsets(string address) 
     { 
      if (string.IsNullOrEmpty(address)) 
       return new int[0]; 
      else 
      { 
       MatchCollection matches = Regex.Matches(address, OffsetPattern); 
       int[] offsets = new int[matches.Count]; 
       string value; 
       char ch; 
       for (int i = 0; i < matches.Count; i++) 
       { 
        ch = matches[i].Value[0]; 
        if (ch == '+' || ch == '-') 
         value = matches[i].Value.Substring(1); 
        else 
         value = matches[i].Value; 
        offsets[i] = Convert.ToInt32(value, 16); 
        if (ch == '-') 
         offsets[i] = -offsets[i]; 
       } 
       return offsets; 
      } 
     } 

     /// <summary> 
     /// Reads memory at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <param name="buffer">Buffer</param> 
     /// <param name="size">Size in bytes</param> 
     public void ReadMemory(IntPtr address, byte[] buffer, int size) 
     { 
      if (isDisposed) 
       throw new ObjectDisposedException("Memory"); 
      if (buffer == null) 
       throw new ArgumentNullException("buffer"); 
      if (size <= 0) 
       throw new ArgumentException("Size must be greater than zero"); 
      if (address == IntPtr.Zero) 
       throw new ArgumentException("Invalid address"); 

      uint read = 0; 
      if (!Win32.ReadProcessMemory(processHandle, address, buffer, (uint)size, ref read) || 
       read != size) 
       throw new AccessViolationException(); 
     } 

     /// <summary> 
     /// Writes memory at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <param name="buffer">Buffer</param> 
     /// <param name="size">Size in bytes</param> 
     public void WriteMemory(IntPtr address, byte[] buffer, int size) 
     { 
      if (isDisposed) 
       throw new ObjectDisposedException("Memory"); 
      if (buffer == null) 
       throw new ArgumentNullException("buffer"); 
      if (size <= 0) 
       throw new ArgumentException("Size must be greater than zero"); 
      if (address == IntPtr.Zero) 
       throw new ArgumentException("Invalid address"); 

      uint write = 0; 
      if (!Win32.WriteProcessMemory(processHandle, address, buffer, (uint)size, ref write) || 
       write != size) 
       throw new AccessViolationException(); 
     } 

     /// <summary> 
     /// Reads 32 bit signed integer at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <returns></returns> 
     public int ReadInt32(IntPtr address) 
     { 
      byte[] buffer = new byte[4]; 
      ReadMemory(address, buffer, 4); 
      return BitConverter.ToInt32(buffer, 0); 
     } 

     /// <summary> 
     /// Reads 32 bit unsigned integer at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <returns></returns> 
     public uint ReadUInt32(IntPtr address) 
     { 
      byte[] buffer = new byte[4]; 
      ReadMemory(address, buffer, 4); 
      return BitConverter.ToUInt32(buffer, 0); 
     } 

     /// <summary> 
     /// Reads single precision value at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <returns></returns> 
     public float ReadFloat(IntPtr address) 
     { 
      byte[] buffer = new byte[4]; 
      ReadMemory(address, buffer, 4); 
      return BitConverter.ToSingle(buffer, 0); 
     } 

     /// <summary> 
     /// Reads double precision value at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <returns></returns> 
     public double ReadDouble(IntPtr address) 
     { 
      byte[] buffer = new byte[8]; 
      ReadMemory(address, buffer, 8); 
      return BitConverter.ToDouble(buffer, 0); 
     } 

     /// <summary> 
     /// Writes 32 bit unsigned integer at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <param name="value">Value</param> 
     /// <returns></returns> 
     public void WriteUInt32(IntPtr address, uint value) 
     { 
      byte[] buffer = BitConverter.GetBytes(value); 
      WriteMemory(address, buffer, 4); 
     } 

     /// <summary> 
     /// Writes 32 bit signed integer at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <param name="value">Value</param> 
     /// <returns></returns> 
     public void WriteInt32(IntPtr address, int value) 
     { 
      byte[] buffer = BitConverter.GetBytes(value); 
      WriteMemory(address, buffer, 4); 
     } 

     /// <summary> 
     /// Writes single precision value at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <param name="value">Value</param> 
     /// <returns></returns> 
     public void WriteFloat(IntPtr address, float value) 
     { 
      byte[] buffer = BitConverter.GetBytes(value); 
      WriteMemory(address, buffer, 4); 
     } 

     /// <summary> 
     /// Writes double precision value at the address 
     /// </summary> 
     /// <param name="address">Memory address</param> 
     /// <param name="value">Value</param> 
     /// <returns></returns> 
     public void WriteDouble(IntPtr address, double value) 
     { 
      byte[] buffer = BitConverter.GetBytes(value); 
      WriteMemory(address, buffer, 8); 
     } 
    } 
} 
+1

當你想從一個字節數組中獲得一個*單個字節時,沒有'BitConverter'函數,因爲你可以很容易地使用索引器來編寫,並且也不會出現字節順序問題。 –

+0

您需要在代碼中全局聲明一個變量byte [] memory = new byte [large number]。讀取將是:內存[地址]。 – jdweng

+0

@jdweng你在說什麼?你所描述的是不可能的(創建一個覆蓋所有內存的數組),並且與OP的問題無關,這顯然是使用現有的API訪問另一個進程的內存。 –

回答

5

如果你仔細閱讀你寫的代碼,你會看到,沒有轉換是必要的,因此你很難找到這個(不必要的)BitConverter功能。

只需返回你讀過的唯一字節:

public byte readByte(IntPtr address) 
{ 
    byte[] buffer = new byte[1]; 
    ReadMemory(address, buffer, 1); 
    return buffer[0]; 
} 
1

你並不需要一個BitConverter。你已經有一個byte,您可以返回:

public byte readByte(IntPtr address) 
{ 
    byte[] buffer = new byte[1]; 
    ReadMemory(address, buffer, 1); 
    return buffer[0]; 
} 

一些背景信息:BitConverter有沒有轉換原始二進制數據(表示爲byte[])特定類型。它存在你不必擔心各自類型的內部結構(特別是字節序可能是一個無賴)。對於byte來說,這是完全不必要的,因爲你已經有了你的數組中的字節。