-1

i'm trying to make a little program to my university that can change values in the memory of another process. With the exact address value that the Cheat Engine give me i can do this, but not ever the value is the same then my problem is with the memory pointers. In the following image i has the every offset that i found in the pointer scan map:

enter image description here

I already make a program but it not work and ever gives me 299 error code, i Run it as administrator. The code is the following:

#include <iostream>
#include <Windows.h>
#include <Psapi.h>
#include <TlHelp32.h>
#include <queue>

using namespace std;

   int main() {
   PROCESSENTRY32 pEntry;
   pEntry.dwSize = sizeof(PROCESSENTRY32);

   // Snapshot to list all process
   HANDLE pHandlers = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
   if (pHandlers == NULL) {
       cout << "Error 1";
       return 1;
   }
   // Listing process
   if (Process32First(pHandlers, &pEntry)) {
       while (Process32Next(pHandlers, &pEntry)) {

           // Convert value to string
           wstring wstr(pEntry.szExeFile);
           string str(wstr.begin(), wstr.end());
           // Check if is the process that i wan't
           if (str == "Playgroundd.exe") {
               MODULEENTRY32 mEntry;
               mEntry.dwSize = sizeof(MODULEENTRY32);
            
               // Snapshot to list all modules inside process
               HANDLE mHandlers = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pEntry.th32ProcessID);
               if (mHandlers == NULL) {
                   cout << "Error 2";
                   return 1;
               }
            
               // Usually the first process is the main module
               if (Module32First(mHandlers, &mEntry)) {

                   // Convert the name to string
                   wstring wstrr(mEntry.szExePath);
                   string strr(wstrr.begin(), wstrr.end());
                   if (strr.find("Playgroundd.exe")) {

                       // Get the base address of module
                       DWORD moduleBaseAddress = (DWORD)mEntry.modBaseAddr;

                       // Append initial value
                       moduleBaseAddress += (DWORD)0x000000E8;

                       // Offsets defined
                       DWORD offsets[] = {0x88,0x98,0x90,0x20,0x10,0x48,0x904};

                       // Open process with the right process id
                       cout << "process id: " << pEntry.th32ProcessID << endl << endl;
                       HANDLE processHandler = OpenProcess(PROCESS_ALL_ACCESS, 0, pEntry.th32ProcessID);
                       if (processHandler == NULL) {
                           cout << "Can't open the process";
                           return 1;
                       }
                       // Sum offsets 
                       for (int i = 0; i < 7;i++) {
                           moduleBaseAddress += offsets[i];
                       }

                       int receive = 0;
                       size_t bytesRead = 0;

                       bool resultStatus = ReadProcessMemory(processHandler, 
   (LPCVOID)moduleBaseAddress, &receive, sizeof(receive), &bytesRead);
                       cout << "result status :" << resultStatus << endl;
                       cout << "Received : " << receive << endl;
                       cout << "Bytes read : " << bytesRead << endl;
                       cout <<  "Possible error code : " <<  GetLastError() << endl;
                    
                   }
                   else {
                       cout << "Can't find module";
                       return 1;
                   }
               }
           }
       }
   }
};

This is the output of the above program, the error code can be ignored if the result status be non-zero

result status :0
Received : 0
Bytes read : 0
Possible error code : 299

What i am doing wrong?

  • 2
    Did you look up the meaning of error code 299? – drescherjm Mar 06 '22 at 20:23
  • 1
    This loop is wrong: `for (int i = 0; i < 7;i++) { moduleBaseAddress += offsets[i]; }` Do you really want to add all offsets together then read a single 4 byte integer at the sum of the offsets 1 time instead of reading seven 4 byte integers from the 7 different offsets? – drescherjm Mar 06 '22 at 20:26
  • From [`GetLastError`](https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror): *"The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code."* [`ReadProcessMemory`](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory) states that that condition is if the function returns 0. You don't check for that condition, And by the time you get around to calling `GetLastError` it returns a meaningless value. – IInspectable Mar 06 '22 at 20:56

1 Answers1

0

As pointed by the comment above, your calculation of the target address is questionable.

Your use of GetLastError is unsafe - you should call it immediately after FAILED call to ReadProcessMemory. However, in this case, cout << ... doesn't change that code, so you are OK.

According to docs

ERROR_PARTIAL_COPY

299 (0x12B)

Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

And this post states

ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
Vlad Feinstein
  • 10,960
  • 1
  • 12
  • 27
  • What's the specific justification behind the statement that `cout << ...` wouldn't clobber the calling thread's last error code? Both `WriteFile` and `WriteConsole` set the calling thread's last error code, and it's unclear how `cout` were to bypass those API calls. It's also always **safe** to call `GetLastError`. It's just that the return value is almost always meaningless. – IInspectable Mar 07 '22 at 18:30
  • @IInspectable no justification, just an observation. I guess those API do not clear the last error on success (not that they should). Also, I meant `unsafe` for the purpose of obtaining the correct error code, not that it will cause harm to the caller. – Vlad Feinstein Mar 07 '22 at 19:37