-1

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?

1
  • 1
    You have to read all the character until you get the 0x00. I have know idea what you code is doing. I'm just telling you the correct way of getting the correct results. Using string methods in a binary file is wrong. Commented Nov 27, 2019 at 12:55

1 Answer 1

1

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 :)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.