0

Back Story

I am working on learning how to read memory from other processes that are located inside of a VM. I first loaded up AssaultCube along with Cheat Engine inside of VmWare Workstation. I first shot my gun then found where it was being stored in memory. I then used pointer scanner along with closing and reopening my game to narrow down the real persistent memory location of where a pointer to my guns ammo was. After I found it I closed my game multiple more times to ensure it always pointed to my ammos integer value (which would change each time I reopened my game) which it did. At this point I was confident in knowing where my ammo was stored. The real address looked like the following where ac_client is equal to 0x400000.

enter image description here

enter image description here

I then added 0x400000 with 0x00190844 which gave me 0x590844. Next I added 0x590844 as a new pointer address and it did in fact contain the same pointer as "ac_client + 0x00190844" (the pointer to my current ammo count).

enter image description here

Now after some testing I figured out that 0x007FD8A0 which is located at the very top of both pictures is the actual memory location where my guns ammo is stored and that = 13 means I have 13 bullets left. That being said I am still slightly confused by what 0x0A3C5FB8 means but my best guess is that its a pointer? Does 0x590844 just hold a pointer to 0x0A3C5FB8 which holds a pointer to 0x007FD8A0 which is actually where my ammo is stored? I only assume this because in the pictures above it uses -> which I just assumed to mean pointer.


My Issue

Just to make sure we are on the same page everything above is happening inside of my VM while I attempt to read my ammo from my main machine. I first opened task manager and turned on PID's the first thing I noticed is that I am going to have to use the PID of my VM since the PID of Assault Cube is localized to my VM's Windows instance. This did work but when I typed in 0x590844 as the memory address I got an error code 299 (ERROR_PARTIAL_COPY) "Only part of a ReadProcessMemory or WriteProcessMemory request was completed". That description was from Microsoft's system errors website. Here is my code and terminal output.

DWORD pid;
printf("Enter the process id: ");
scanf("%d", &pid);
printf("\n");

HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, pid); //PROCESS_ALL_ACCESS gives all access, PROCESS_VM_READ gives reading access

if(hProcess == NULL) {
    printf("OpenProcess Failed GetLastError: %d \n", GetLastError());
    getchar();
    return pressToClose(EXIT_FAILURE);
}
enter code here

uintptr_t memoryAddress = 0x0061FF1C;
int intRead = 0;

printf("Enter the integers memory address: ");
scanf("%x", &memoryAddress); //Use %x to denote hexidecimal (remember to add 0x to the start if a memory address)
printf("\n");

BOOL rpmReturn = ReadProcessMemory(hProcess, (LPCVOID) memoryAddress, &intRead, sizeof(int), NULL);

if (rpmReturn == FALSE) {
    printf("ReadProcessMemory failed. GetLastError = %d \n", GetLastError());
    CloseHandle(hProcess); 
    getchar(); //This is required to stop the terminal from auto closing
    return pressToClose(EXIT_FAILURE);
}

CloseHandle(hProcess); //This closes the handle object which is doccumented in link 3
printf("INT READ: %i \n", intRead);
getchar();
return pressToClose(EXIT_SUCCESS);

enter image description here

enter image description here

--------------

My Theory

This is the first day I have used Cheat Engine, the second day of ever looking at any internal Windows api plus I am fairly new to C so take my theory with a grain of salt. Anyways I ended up trying all 3 of the above memory addresses along with trying to run my memory reader app in administrator mode but every time it gave the same error code. I have tested my memory reader app with another program on my main machine and it worked perfectly. This means the only issues I can think of is that I may have to do something "different" to read memory of a process running inside of a VM or maybe ReadProcessMemory does not work well with pointers?

Normally when reading the value of a pointer I need to include * in front of it otherwise it does not work. In the bellow example excluding * from in front of pAmmo in int newAmmo = *pAmmo will cause an error.

int ammo = 13;
int *pAmmo;
pAmmo = &ammo;

int newAmmo = *pAmmo;
printf("Value: %i \n", newAmmo);

So my theory is maybe ReadProcessMemory does not include * which is causing this issue. I doubt this is an issue with Microsoft so maybe there is no way for it to know if it is a pointer or not so maybe I have to somehow tell it? But how? All of that being said I think the issue is with the VM and that accessing memory of a process hidden in a VM from user mode does not work. But if that is true is there a way to fix it besides from needing to make a kernel driver? Idk this is just me throwing around ideas I would really appreciate any insightful comments that help me solve this problem!


EDIT

Alright after further testing I don't think it's possible to access memory of a VM from the host machine. Presumably I would need to make a kernel driver to do this but I would greatly appreciate anyone who can explain what exactly that error means and why I was getting some behind the scenes knowledge would be great!

I also decided to run my memory reading program on my VM. This actually worked and yielded the correct results when I used the actual memory location (not the pointers). This however is a problem so my new question is how can I use the Windows ReadProcessMemory function to get the value of the returned pointer because right now its just thinking the pointer is the actual value I am looking for which its not.

  • `Does 0x590844 just hold a pointer to 0x0A3C5FB8 which holds a pointer to 0x007FD8A0 which is actually where my ammo is stored?`: Yes. – SuperUser Jan 16 '23 at 14:38

0 Answers0