I'm trying to read a string "845120" from a process memory but I have some trouble...
I know "845120" is a numeric value, but in some cases it can be alphanumeric, that's why it's a string and not a 4 byte int.
Here is my Memory class, where I have all functions that deal with memory:
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
public static IntPtr FindDMAAddy(IntPtr hProc, IntPtr ptr, int[] offsets)
{
var buffer = new byte[IntPtr.Size];
foreach (int i in offsets)
{
ReadProcessMemory(hProc, ptr, buffer, buffer.Length, out var read);
ptr = (IntPtr.Size == 4)
? IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), i)
: ptr = IntPtr.Add(new IntPtr(BitConverter.ToInt64(buffer, 0)), i);
}
return ptr;
}
public static IntPtr GetModuleBaseAddress(Process proc, string modName)
{
IntPtr addr = IntPtr.Zero;
foreach (ProcessModule m in proc.Modules)
{
if (m.ModuleName == modName)
{
addr = m.BaseAddress;
break;
}
}
return addr;
}
public static string ReadStringUntilNULL(string EXENAME, int Address)
{
string value = "";
bool endOfString = false;
int counter = 0;
while (!endOfString)
{
if (ReadInt8(EXENAME, Address + counter) > (byte)0)
{
value += (char)ReadInt8(EXENAME, Address + counter);
}
else
{
return value;
}
counter++;
}
return value;
}
And here's the code that I'm using to invoke that functions:
Process process = null;
while(process == null)
{
process = Process.GetProcessesByName("client_dx").FirstOrDefault();
}
var hProc = Memory.OpenProcess(0x00000010, false, process.Id);
var modBase = Memory.GetModuleBaseAddress(process, "client_dx.exe");
var addr = Memory.FindDMAAddy(hProc, (IntPtr)(modBase + 0x003393AC), new int[] { 0x30, 0x374, 0x2C, 0x0, 0x14, 0x48, 0x10 });
var acc = Memory.ReadStringUntilNULL("client_dx.exe", addr);
Debug.WriteLine(acc);
It's working perfectly until this line:
var acc = Memory.ReadStringUntilNULL("client_dx.exe", addr);
So var addr
have the correct address but var acc
it's not getting the expected results.
Here I'm getting this error: cannot convert from 'System.IntPtr' to 'int'
Ok, so it expects an integer where I'm giving a pointer... so I tested with ToInt32()
var acc = Memory.ReadStringUntilNULL("client_dx.exe", addr.ToInt32());
The addr.ToInt32()
operation returns 262959880
and as far as I know that's not even an address
I'm getting an empty string, the ReadStringUntilNULL function from Memory class it's only looping once..
Values are: addr 0x0fac7308 System.IntPtr
and acc "" string
How can I read that string from memory? Or how can I pass the parameter correctly?
I finally wrote a class that lets me read strings until null:
public class NewMem
{
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
public Process Process { get; set; }
public static IntPtr GetModuleBaseAddress(Process proc, string modName)
{
IntPtr addr = IntPtr.Zero;
foreach (ProcessModule m in proc.Modules)
{
if (m.ModuleName == modName)
{
addr = m.BaseAddress;
break;
}
}
return addr;
}
public static IntPtr FindDMAAddy(IntPtr hProc, IntPtr ptr, int[] offsets)
{
var buffer = new byte[IntPtr.Size];
foreach (int i in offsets)
{
ReadProcessMemory(hProc, ptr, buffer, buffer.Length, out var read);
ptr = (IntPtr.Size == 4)
? IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), i)
: ptr = IntPtr.Add(new IntPtr(BitConverter.ToInt64(buffer, 0)), i);
}
return ptr;
}
public string ReadStringASCII(IntPtr address)
{
var myString = "";
for (int i = 1; i < 50; i++)
{
var bytes = ReadMemory(address, i);
if (bytes[(i-1)] == 0)
{
return myString;
}
myString = Encoding.ASCII.GetString(bytes);
}
return myString;
}
public byte[] ReadMemory(IntPtr address, int size)
{
var buffer = new byte[size];
var bytesRead = 0;
ReadProcessMemory((int)Process.Handle, (int)address, buffer, buffer.Length, ref bytesRead);
return buffer;
}
}
This is my code:
NewMem MClass = new NewMem();
var client = Process.GetProcessesByName("client_dx").FirstOrDefault();
MClass.Process = client;
// Get handle to process
var hProc = NewMem.OpenProcess(0x00000010, false, client.Id);
// Get base module
var modBase = NewMem.GetModuleBaseAddress(client, "client_dx.exe");
// Get relative base address
var vBasePointer = NewMem.FindDMAAddy(hProc, (IntPtr)(modBase + 0x55F870), new int[] { 0 });
// Get string
if (vBasePointer != IntPtr.Zero)
{
var vNameAddress = vBasePointer + 0x20;
var vName = MClass.ReadStringASCII(vNameAddress);
}
It's stopping reading when finds a '0', but you can always set up some exceptions or tricks, I didn't find a cleaner way to do this but it's working :)
User contributions licensed under CC BY-SA 3.0