0

I am trying to figure out how to read an integer value by reading a pointer to that integer. I am trying to do this from the user application level by using Windows ReadProcessMemory. I previously was trying to read values from memory through a VM but after assuming that is impossible I switched up my approach. If you want more context on how I got these pointer values check out this post I made Reading an integer from memory located on a VM but in summary I used Cheat Engine to gain access to a pointer which always would point to a specific value despite how many times you close your application. I felt like that previous post was too long and obscure which was why it was overlooked hence why I decided to condense it down in hope I can resolve my core issue.

Firstly, I would like to point out that this may be a large pointer chain meaning the value I read from ReadAccessMemory may point to a pointer which points to another pointer and so on till it finally points to the actual integer value I want to read. The trouble I am having is reading the actual integer value when all I get from ReadAccessMemory is another pointer. I know the pointer does in fact at some point, point to the integer I want to read (I proved that in the link above). Normally to print the value of a pointer you include a * in front of the pointer variable inside your printf statement. This is explained in the short snippet of code...

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

printf("Value: %i PointerValue: %i Pointer: %p \n", pAmmo, *pAmmo, pAmmo);

Here is what the above code printed...

Value: 6422296 PointerValue: 13 Pointer: 0061FF1

All of that being said when I run the following code my application suddenly crashes and closes right after printing this printf("IntNormalRead: %i Pointer: %p \n", intRead, intRead); which means the next print statement which includes *intRead is the cause of the crash. When I comment that line out it runs correctly and stays open which means I found the cause of the crash but that does not help me to determine why it is crashing. I also have the same issue when trying to write to that value but I am hoping a solution to this would also solve my WriteProcessMemory issue. If anyone knows how I can actually get my code to print the target integers value I would be extremely grateful!

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);
}

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());
    getchar(); //This is required to stop the terminal from auto closing
    return pressToClose(EXIT_FAILURE);
}

printf("IntNormalRead: %i Pointer: %p \n", intRead, intRead);
printf("PointerValue: %i \n", *intRead);
printf("Last Error %d \n", GetLastError()); //This does nothing since it crashes before getting here when I dont have the *intRead statement commented out

CloseHandle(hProcess); //This closes the handle object which is doccumented in link 3
getchar();
return pressToClose(EXIT_SUCCESS);

Tests

This pointer value 0x590844 points to a pointer chain that ends up pointing to this address 00710008 which contains the integer value I want to read (in this case my ammo count). Running my program above with the *intRead pintf statement commented out produces the following results...

Enter the process id: 2940

Enter the integers memory address: 00710008

IntNormalRead: 19 Pointer: 00000013
Last Error 126
Press any key to close...

When I dont comment that printf statement out my program instantly crashes without printing out any error messages. However, running my program again with the pintf statement commented out says the last Error had an error code of 126 "The specified module could not be found" was this the error caused by the printf statement in the previous failed execution? Anyways when I run my program again with the pointer value I want to use without the *intRead printf statement I get the following output.

Enter the process id: 2940

Enter the integers memory address: 0x590844

IntNormalRead: 162398256 Pointer: 09AE0030
Last Error 126
Press any key to close...

All of this checks out since it seems to be printing the address of another pointer however this does not help me solve this problem at all because I need to be able to print the actual value of the pointer which is normally done by using *intRead but that always crashes for some reason.

  • Unrelated, but `pAmmo` is a pointer. You attempt to print it with the `%i` format specifier, when you need to use `%p`. Mismatching format specifier and argument type leads to *undefined behavior*. – Some programmer dude Oct 29 '22 at 23:08
  • The vernacular in `printf("Value: %i PointerValue: %i Pointer: %p \n", pAmmo, *pAmmo, pAmmo);` is odd at-best. A pointer has *two* significant attributes: the address is holds (if any, else NULL or indeterminate), and the content residing at that address when dereferenced. In short, the first 'item' being printed is pointless, especially considering you're using the wrong format specifier whilst doing so; only the last two make any sense. – WhozCraig Oct 29 '22 at 23:09
  • @Someprogrammerdude I did use %p look at the example again. Also I was just printing all of the options as an example to show that the crashing behavior was something unique. – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:10
  • Same problem with using `scanf` and the `%x` format for a value of type `uintptr_t`. The actual underlying type of the *optional* type `uintptr_t` is implementation defined, and might not be `unsigned int` (which is what `%x` expects the type to be). You need to use the `SCNxPTR` format macro to scanf for hexadecimal `uintptr_t` values. As in `scanf("%" SCNxPTR, &memoryAddress);` – Some programmer dude Oct 29 '22 at 23:12
  • @WhozCraig Again like I stated that has nothing to do with my actual question I was just printing all of the options even though they dont serve any purpose. I was just trying to highlight the differences between what I expect and what I get. If the pAmmo example does not help to depict my problem just disregard it. – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:12
  • The `scanf` problem might actually be the cause of your problem. On a 64-bit system `uintptr_t` is likely to be a 64-bit type. And `unsigned int` is commonly a **32**-bit type. That means you might not get the full input value into `memoryAddress`. – Some programmer dude Oct 29 '22 at 23:14
  • @Someprogrammerdude I am manually typing in the memory addresses so I know it will always be in unsigned format meaning there won't be any negative values. I try your scanf change but that wont solve the issue since that is unrelated to the problem at hand. – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:16
  • @Someprogrammerdude The problem is when printing a normal int not uintptr_t since *intRead is the cause of my crash. Also my program runs perfectly when I use the integers memory address directly. The issue only arises when I try to use a pointer to that integer value. This is why I was saying uintptr_t is not the issue. – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:16
  • What is the actual value of `intRead`, i.e. where does it point? And how can you access memory of another process, if you close that process handle (which might unmap the pages of the other process from your own process)? – Some programmer dude Oct 29 '22 at 23:20
  • 1
    Also, all the mismatching formats *do* lead to undefined behavior. If your program have undefined behavior, *any* behavior could be seen as invalid. Once you have undefined behavior, the whole program is suspect and can't be trusted. And yes, even such small things could lead to unforeseen problems. Fix all undefined behavior, and we can continue to focus on the actual problem (because otherwise we can't tell what *is* the actual problem). – Some programmer dude Oct 29 '22 at 23:21
  • I commented out closeHandle() to test that as well and the issue still persisted so I know that is also not the problem. I explained how I got the value of intRead in that link above but its equal to my guns ammo so it will range from 0 - 20. When I read the memory address of my guns ammo directly it works but I cant do that since that value changes everytime I close my game. This is why I need to use a pointer which always points to that value. The issue is I can't seem to read the value when using the pointer. – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:23
  • Also please take some time to refresh [the help pages](http://stackoverflow.com/help), take the SO [tour], read [ask], as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). Then [edit] your question to tell us the actual input you give, and (until the crash) the actual output you get. And to be sure that output is actually written, add a few `fflush(stdout)`. – Some programmer dude Oct 29 '22 at 23:25
  • @Someprogrammerdude Like I said I already did that you just have to click the link... Whenever I make a massive post no one ever reads it so I have been conditioned to make shorter posts that get negative attention because any advice is better than no advice. What does my SCNxPTR macro need to look like in order to fix the issue you pointed out? I never heard about that acronym before. Also I moved Closehandle() to the code under my printf() statement what else do you want me to do? – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:30
  • Questions should really be self-contained. The linked question also have plenty of images which is [a big no-no](https://meta.stackoverflow.com/questions/285551/why-should-i-not-upload-images-of-code-data-errors-when-asking-a-question). – Some programmer dude Oct 29 '22 at 23:33
  • 1
    If you're going to call `GetLastError()` you must do it before you call any other Win32 functions, like `CloseHandle` since they might overwrite the actual error. – Retired Ninja Oct 29 '22 at 23:33
  • @RetiredNinja I moved CloseHandle to the bottom but I still have the same issue. I also added updated examples to my question above. – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:54
  • @Someprogrammerdude I could of change that console image to code but the PID image has a purpose since I cant copy and paste that. Anyways I added more examples in my question above but I still dont know how to print the values of a pointer when that pointer is retrieved via ReadProcessMemory (reading a pointer normally is super easy so idk what is going on). – IDontWantToMakeAnotherAccount Oct 29 '22 at 23:56

0 Answers0