Я пытаюсь создать тренера для игры. Это вызывает ошибку (я думаю), потому что я пытаюсь получить доступ к игровой памяти 64-битной игры с 32-битной командой.32-разрядный процесс не может получить доступ к модулям в 64-битном процессе
Исходный код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
namespace Infinite_Trainer___Cod_IW
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void bunifuImageButton1_Click(object sender, EventArgs e)
{
this.Close();
}
private void bunifuFlatButton1_Click(object sender, EventArgs e)
{
string prestigeLevel = bunifuDropdown1.selectedValue;
string xp = bunifuSlider1.Value.ToString();
string winrate = bunifuMaterialTextbox1.Text;
string loserate = bunifuMaterialTextbox2.Text;
Process[] process = Process.GetProcessesByName("iw7_ship");
if (process.Length > 0)
{
using (CheatEngine.Memory memory = new CheatEngine.Memory(process[0]))
{
IntPtr prestigeAddress = memory.GetAddress("\"iw7_ship.exe\"+04105320+6E4");
memory.WriteUInt32(prestigeAddress, 1);
}
}
else
{
MessageBox.Show("Game isn't running");
}
}
}
}
А класс memory.cs:
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Infinite_Trainer___Cod_IW.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();
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();
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);
}
}
}
К сожалению, я получаю следующий код ошибки:
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in System.dll
Additional information: A 32-bit process can not access modules in a 64-bit process.
Эта ошибка должна быть вызвана по следующей строке: memory.WriteUInt32(prestigeAddress, 1);
Кто-нибудь знает, что я могу сделать сейчас, или если есть исправление для этого? Или мне нужен совершенно новый класс обработки памяти?
Я был бы признателен за любую помощь
UPDATE
Новая ошибка делает выглядеть следующим образом:
An unhandled exception of type 'System.OverflowException' occurred in mscorlib.dll
Additional information: The arithmetic operation has caused an overflow.
Скриншот: https://gyazo.com/04107c28a4d7af0599f1dd59c72b6020
Полный лог:
System.OverflowException was unhandled
HResult=-2146233066
Message=The arithmetic operation caused an overflow.
Source=mscorlib
StackTrace:
at System.IntPtr.ToInt32()
at Infinite_Trainer___Cod_IW.CheatEngine.Memory.GetAddress(String moduleName, IntPtr baseAddress, Int32[] offsets) in C:\Users\d4ne\documents\visual studio 2015\Projects\Infinite Trainer - Cod IW\Infinite Trainer - Cod IW\CheatEngine\Memory.cs:Line 109.
at Infinite_Trainer___Cod_IW.Form1.bunifuFlatButton1_Click(Object sender, EventArgs e) in C:\Users\d4ne\documents\visual studio 2015\Projects\Infinite Trainer - Cod IW\Infinite Trainer - Cod IW\Form1.cs:Line 40.
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Label.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Infinite_Trainer___Cod_IW.Program.Main() in C:\Users\d4ne\documents\visual studio 2015\Projects\Infinite Trainer - Cod IW\Infinite Trainer - Cod IW\Program.cs:Line 19.
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
«Память» не содержит определения для «WriteUInt64» и не используется метод расширения «WriteUInt64», принимающий первый аргумент типа «Память» (вам не хватает директивы использования или ссылки на сборку?) Таким образом, нет функция внутри класса, как это – user2452165
@ user2452165 см. обновленный ответ. Я думаю, что это должно решить его. – peterpep
https://gyazo.com/a444f47cf263e8c849435c6224c82e70 проверка остатка rn – user2452165