So I have been trying to read variables with ReadProcessMemory and finding the adresses in cheat engine worked perfectly, but as soon as I got to programming I encountered some problems. I searched for the ammo and health addresses in cheat engine and the health was a one level pointer and the ammo was a three level pointer. I tried reading the health, but everytime I read it, it returns 0.
namespace AssaultCubeTrainer
{
public partial class MainWindow : Window
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(IntPtr pHandle, IntPtr Address, byte[] Buffer, int Size, IntPtr NumberofBytesRead);
public static Process myProc;
public static Player p1;
public MainWindow()
{
InitializeComponent();
p1 = new Player();
MessageBox.Show("Please press the attach button as soon as the game has started", " Information",MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
}
private void AttachProcButton_Click(object sender, RoutedEventArgs e)
{
try
{
myProc = Process.GetProcessesByName("ac_client")[0];
if (myProc.Handle != null)
{
MessageBox.Show("Process successfully attached", "Success", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
}
}
catch
{
MessageBox.Show("The process was not found","Error", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
}
}
private void ButtonTest_Click(object sender, RoutedEventArgs e)
{
lbHealthInfo.Content = p1.GetHealthInfo();
}
}
}
namespace AssaultCubeTrainer
{
public class Player
{
private byte[] buffer;
public bool ReadSuccess;
public int HealthAddress;
public int HealthOffset;
public int AmmoAddress;
public int AmmoOffset;
public int Health;
public int Ammo;
public IntPtr bytesRead;
public Player()
{
HealthAddress = 0x00509B74;
HealthOffset = 0xF8;
AmmoAddress = 0x00509B74;
AmmoOffset = 0x374;
Health = HealthAddress + HealthOffset;
Ammo = AmmoAddress + AmmoOffset;
}
//Here I have the problem when reading variable
public int GetHealthInfo()
{
**buffer = new byte[4];
ReadSuccess = MainWindow.ReadProcessMemory(MainWindow.myProc.Handle, (IntPtr)Health, buffer, buffer.Length, bytesRead);
return BitConverter.ToInt32(buffer, 0);**
}
}
}
Heres the links to the addresses in cheat engine Couldnt upload them here :P
How do I use pointers and offsets from cheat engine properly in my code and how do I implement multi-level pointers into my code? Please excuse my shitty english.
ReadProcessMemory(MainWindow.myProc.Handle, ...)
hProcess [in]
A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process.
To get this handle, you need to use OpenProcess
:
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr OpenProcess(
int dwDesiredAccess,
IntPtr bInheritHandle,
IntPtr dwProcessId
);
public const int PROCESS_VM_READ = 0x10;
var handle = OpenProcess(PROCESS_VM_READ, IntPtr.Zero, new IntPtr(MainWindow.myProc.Id)); // note: use the id
ReadProcessMemory(handle, ...);
EDIT: Also make sure your application runs on elevated privileges, which means you should start VStudio or your application with Run as Admin
.
EDIT2: You should use ref
for the lpBuffer
to avoid stepping into unsafe
territory:
[DllImport("kernel32", SetLastError = true)]
public static extern int ReadProcessMemory(
IntPtr hProcess,
int lpBase,
ref int lpBuffer,
int nSize,
int lpNumberOfBytesRead
);
As for multi-level pointers, you read the value of base address, and add the offset and read again and again.
ReadProcessMemory(handle, BaseAddress, ref value, sizeof(int), 0);
ReadProcessMemory(handle, value + 0x508, ref value, sizeof(int), 0);
ReadProcessMemory(handle, value + 0xF8, ref value, sizeof(int), 0);
Or, you could use my Pointer
class in Xy.DataAnalysis
. Usage example can be found in Xy.PerfectWorld.Models
:
https://github.com/Xiaoy312/Xy.PerfectWorld/tree/master/Xy.DataAnalysis