1

I have a vague knowledge of C++, but I have some extensive experience in C#, though it's not so useful in this instance. I have some code in C#, and it works just fine. I have what I presume is very similar code in C++, and I can't seem to get it working nor debug it. So, here is the C# code I've written and tested quite thoroughly:

    [DllImport("kernel32.dll")]
    public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
        [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

    public byte[] ReadBytes(IntPtr Handle, Int64 Address, uint BytesToRead)
    {
        IntPtr ptrBytesRead;
        byte[] buffer = new byte[BytesToRead];
        ReadProcessMemory(Handle, new IntPtr(Address), buffer, BytesToRead, out ptrBytesRead);
        return buffer;
    }

    public int ReadInt32(long Address, uint length = 4, IntPtr? Handle = null)
    {
        return BitConverter.ToInt32(ReadBytes(getIntPtr(Handle), Address, length), 0);
    }

So, this function ReadInt32 takes an address, adds it to the base address I've stored upon initialising my Util class, and reads the memory up to 4 bytes, using a handle which once again is acquired upon initialisation. I know 100% that this works provided I set the values correctly.

This code is a little long, excuse my ignorance but I don't want to leave any of this to imagination, I can't begin to suggest what may be incorrect, as I'm not too well trained in the world of C++.

DWORD address = 0x3C02A8;
int value = 0;
DWORD pid;
HWND hwnd;
DWORD baseAddress;
DWORD toread;
SIZE_T bytesRead;

// Get a process handle
hwnd = FindWindow(NULL,L"Tibia - Knightski"); //Finds the Window called "Minesweeper"
if(!hwnd) //If none, display an error
{
    cout <<"Window not found!\n";
    cin.get();
}
else
{
    cout << "Window found: " << hwnd << endl;
    cin.get();
}

// Get a base address
GetWindowThreadProcessId(hwnd,&pid); //Get the process id and place it in pid
HANDLE phandle = OpenProcess(PROCESS_VM_READ,0,pid); //Get permission to read
if(!phandle) //Once again, if it fails, tell us
{
    cout <<"Could not get handle!\n";
    cin.get();
}
else
{
    cout << "Handle obtained: " << phandle << endl;
    cin.get();
    baseAddress = (DWORD)phandle;
    cout << "Base Address obtained: " << baseAddress << endl;
    cin.get();
}

toread = baseAddress + address;

// Read memory at base + address
if (ReadProcessMemory(phandle, (void*)address, &value, 4, &bytesRead))
{
    cout << value;
    cin.get();
}
else
{
    cout << "Failed to read memory" << GetLastError() << endl;
    cout << "Bytes read: " << bytesRead << endl;
    cin.get();
}

The memory address I'm trying to read is 0x3BE1E0, but I've added the base address (0x20C8) to this to get 0x3C02A8. I will assume that the readers on this site know of the handle and what not...

Thank you for your time. Note that I'm hoping for an explanation of what I'm doing wrong more so than an answer, so please bare that in mind if you've the time free. An answer will do, as I can most likely research the result anyway.

The output is this:

Window found: 00D5014C

Handle obtained: 00000044

Base Address obtained: 68

Failed to read memory299
Bytes read: 0
XtrmJosh
  • 889
  • 2
  • 14
  • 33
  • 1
    So, what is your question? – wjmolina Jul 03 '13 at 21:22
  • What's the output of your C++ code? Is your application 64-bit? – nullptr Jul 03 '13 at 21:23
  • 1
    What you're doing wrong will become obvious when you add error-checking code to **all** the API calls. I can understand skipping the error checks when you first write it, but it should be the first step in troubleshooting, long before you come here. Because we're going to ask "what is the return value of `GetWindowThreadProcessId` and what call failed, with what `GetLastError()` value. – Ben Voigt Jul 03 '13 at 21:26
  • possible duplicate of [ReadProcessMemory fails on some Pages (GetLastError()=299)](http://stackoverflow.com/questions/12122323/readprocessmemory-fails-on-some-pages-getlasterror-299) – Ben Voigt Jul 03 '13 at 21:27
  • @JosuéMolina Sorry for not clarifying, the output is incorrect and I get no compiler error to suggest why. I'm effectively trying to debug it, but with no experience of such actions. – XtrmJosh Jul 03 '13 at 21:27
  • @Inspired I added the output to the original post, thanks for your consideration. The application is Win32, and compiles to 32 bit as far as I am aware. – XtrmJosh Jul 03 '13 at 21:28
  • FYI: "ERROR_PARTIAL_COPY 299 (0x12B) Only part of a ReadProcessMemory or WriteProcessMemory request was completed" from http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx – Ben Voigt Jul 03 '13 at 21:28
  • @BenVoigt Sorry for not clarifying sooner, but as you can see from the output the part of the code which is causing the issue is using GetLastError and reporting error code 299, which on MSDN says that the memory read partially failed. The output, however, is still 0, though I expect a number somewhere around the 4,000,000 mark. – XtrmJosh Jul 03 '13 at 21:29
  • @BenVoigt I understand your concern for duplicates, but please understand that question is similar to, but not "the same" as that one. I mean, it's about memory reading, but I can't find any solution to my problem in it. Rest assured I have explored it and it was the first result on google when I started searching. Also, yes I am aware of the error message, but it doesn't really fit in with my issue. I will also point out that I should be reading a 32 bit int (4 bytes), so perhaps the int I'm declaring is the wrong size or something? – XtrmJosh Jul 03 '13 at 21:30
  • I'd say that the address 0x3C02A8 is incorrect (most likely it isn't mapped in the process). Does the working code in C# uses the same address for ReadProcessMemory? Where does that `0x20C8` 'base' come from? – nullptr Jul 03 '13 at 21:34
  • The address itself (0x3BE1E0) is correct, in my C# code if I do Util.Base + 0x3BE1E0, and read that address, I get the correct result. Obtaining the BaseAddress in C# meant acquiring it from the Process.MainModule, as opposed to the process itself (if that makes any difference). The base address is from CheatEngine, and I've confirmed it in OllyDBG, I didn't yet check it in C#, but I can do so if you think it's incorrect? – XtrmJosh Jul 03 '13 at 21:38
  • @XtrmJosh: So far you've given no reason to think that your error is any different from the one in the other question. It sure looks like you are trying to read an inaccessible page (just like the other question). Whether it has the guard page flag or simply is the wrong address is something you will have to test yourself. Please understand that you chose not to tell us the error number or anything useful up front, or that you'd seen the other question. You want good answers, ask a question with the relevant details. – Ben Voigt Jul 03 '13 at 21:41
  • @Inspired - Thank you once more for your answers, I have found the result. In my experience the BaseAddress has varied drastically, and I was never suspicious of the value because I always understood it to be a bit "random" in that sense. It turns out that actually the base address I'm reading is incorrect, I believe it may be something to do with the handle I'm obtaining, too! If you'd like to post an answer saying that the BaseAddress looks wrong, please do so and I'll mark it and give you the brownie points! Thanks! – XtrmJosh Jul 03 '13 at 21:41
  • For what it's worth, your base address is almost surely wrong. Maybe it needs to be multiplied by the page size. But modules have to be mapped onto page boundaries, it's a requirement of `MapViewOfFile` and the virtual memory manager. – Ben Voigt Jul 03 '13 at 21:41
  • @BenVoigt - Are you able to clarify why the base address would need to be multiplied by the page size? As I mentioned I don't know C++ too well, I fear this may be one thing I'm missing! – XtrmJosh Jul 03 '13 at 21:42
  • 1
    @XtrmJosh: I just saw how you're determining the "base address". Totally wrong. That's a process handle, not a module handle. A "module handle" is the base address of the module, but a process handle is *completely* unrelated. – Ben Voigt Jul 03 '13 at 21:43
  • Well, I've just never heard of a base address that is not page-aligned (and 0x20C8 is not). I'm glad you have solved your trouble :) – nullptr Jul 03 '13 at 21:43
  • @BenVoigt - I noticed somewhere that someone said the BaseAddress was the same as the handle, and as such when I first wrote the code I used that as a "quickfix", thinking if I found an error I would replace it. Then when it failed, I took the base address directly from CheatEngine to try read, and it still didn't work, so I asked here... I did try a lot of other stuff, too, but I couldn't work it out... – XtrmJosh Jul 03 '13 at 21:45
  • @Inspired - Could you confirm if by page alignment you mean it is a multiple of 4096 (4096 being a standard 32-bit page, as far as I'm aware)? thanks – XtrmJosh Jul 03 '13 at 21:46
  • 1
    @XtrmJosh Yes, I mean a multiple of 4KB. A handle of a module (HMODULE) is indeed the same as base address, but a handle of a process is not. – nullptr Jul 03 '13 at 21:50
  • So what I'm actually looking for is the module, not the process, it does make sense after reviewing the C# code I had, and to cut a long story short I believe that to be the actual "result" of this problem. Thanks again, your help is endlessly useful to me! – XtrmJosh Jul 03 '13 at 21:52

1 Answers1

2

This conversion is completely wrong.

baseAddress = (DWORD)phandle;

A process handle isn't a memory address at all (although a module handle is). A process handle is an index into an array kept by the kernel.

You'll need to enumerate the process's modules remotely.

or

will allow you to get module base addresses.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720