0

Summary:

So basically I'm trying to read/write to the target process ConsoleApplication1.exe using ReadProcessMemory and WriteProcessMemory functions in the winapi. I am able to read from the target process memory but I'm not able to write to the memory.

Details:

GetBaseAddress (Process that is used to read/write to the memory)

Code:

// GetBaseAddress.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <sstream>
#include <iostream>
#include <windows.h>
#include <psapi.h>
#include <processthreadsapi.h>
#include <tlhelp32.h>
#include <string.h>
using namespace std;

DWORD FindID(char *name );
void errExit(const char msg[50], HANDLE handle = 0);
int main()
{
    std::cout << "Hello World!\n";
    /*Find Process ID by Name*/
    char name[] = "ConsoleApplication1.exe";
    DWORD processID = FindID(name);
    HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID);
    if (snapshot == INVALID_HANDLE_VALUE || processHandle == NULL||processHandle == INVALID_HANDLE_VALUE) {
        errExit("Counldn't create snapshot exiting...", snapshot);
    }
    cout << "[+]Snapshot created for PID:" << processID << endl;
    cout << "[+]Retriving Module Info..." << endl;
    MODULEENTRY32 moduleEntry  ;
    moduleEntry.dwSize = sizeof(MODULEENTRY32);
    if (Module32First(snapshot, &moduleEntry) == FALSE) {
        errExit("Counldn't retrive entry exiting...",processHandle);
    }
    //stringstream address;
    //
    char buff[12] = "Hello World";
    DWORD offset = 0x19B44; //HelloWorld - [H]
    //
    //BYTE word = *moduleEntry.modBaseAddr;
    DWORD_PTR dwModuleBaseAddress = (DWORD_PTR)moduleEntry.modBaseAddr+offset;
    std::stringstream stream;
    stream << std::hex << dwModuleBaseAddress;
    std::string hexAddress = stream.str();
   
    cout << "[+]Base Address of the module is:" << hexAddress << endl;
    cout << "[+]Reading Memory..." << endl;
    BOOL rslt = ReadProcessMemory(processHandle, moduleEntry.modBaseAddr + offset, buff, sizeof(buff) - 1, NULL);
    if (rslt == FALSE) {
        errExit("Couldn't read memory region exiting...");
    }
    //char buff2[] = "Hacked     ";
    cout << "[+]Memory Data:" << buff << endl;
    cout << endl;
  
     rslt= WriteProcessMemory(processHandle, moduleEntry.modBaseAddr + offset,buff,sizeof(buff)-1,NULL);
    if (rslt == FALSE) {
        errExit("Couldn't write to the Memory Address");
    }
    
}

DWORD FindID(char *name) {
    cout << name << endl;
    DWORD procIDs[1024],needed=0;
    
    std::wstring str = L"ConsoleApplication1.exe";
    int rslt = EnumProcesses(procIDs, sizeof(procIDs), &needed);
    if (rslt==0) {
        errExit("Procees IDs list couldn't be retrived exiting...");
    }
    cout << "[+]Process IDs List Retrived..." << endl;
    cout << "[+]Bytes Returned:" << needed << endl;
    cout << "[+]sizeof(DWORD):" << sizeof(DWORD) << endl;
    cout << "[+]Number of Process Retrived:" << needed / sizeof(DWORD) << endl;
    
    for (int i = 0;i <= needed / sizeof(DWORD); i++) {
        HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, procIDs[i]);
        if (processHandle == NULL) {
            //CloseHandle(processHandle);
            continue;
        }
        wchar_t processFileName[MAX_PATH];
        GetModuleBaseNameW(processHandle, NULL, processFileName, sizeof(processFileName));
        
        
        if (std::wstring(processFileName) == str) {
            cout << "[+]Found:" << procIDs[i] << endl;
            cout << "[+]Process " <<":" << i << endl;
            wcout << "[+]Process Name" << ":" << processFileName << endl;
            return procIDs[i];
        }
        CloseHandle(processHandle);
    }


}

void errExit(const char msg[50], HANDLE handle) {
    cout << "[-]"<<msg << endl;
    cout << "[-]Retriving Last Error:" << GetLastError() << endl;
    CloseHandle(handle);
    system("pause");
    exit(1);
}

Here I'm using modEntry.modBaseAddr + offset to read and write to the memory location of the target process.
modEntry.modBaseAddr holds the base address of the first module of the process and modEntry.modBaseAddr + offset is the location of the first character of the string "Hello World" located in the target process.

This is the error I'm getting with WriteProcessMemory:

998 - ERROR_NOACCESS
Invalid access to memory location.

Things I've already tried:

1. Using VirtualProtect function to change protect region returns FALSE with Old Protect being:

-PAGE_NOACCESS
0x01

According to Microsoft:

PAGE_NOACCESS 0x01

Disables all access to the committed region of pages. An attempt to read from, write to, or execute the committed region results in an access violation. This flag is not supported by the CreateFileMapping function.

2. Trying Multiple times - returns the same error

3. Using a hard-coded address - returns the same error
I tried to set the address directly as (LPVOID)0x619b44 Here, modEntry.modBaseAddr + offset = 0x619b44

4. Trying to CloseHandle and reopen the process using OpenProcess using PROCESS_VM_WRITE constraint - returns the same error

Here is the code for ConsoleApplication.exe (The target process in which I'm trying to overwrite data):

#include<Windows.h>
//#include<unistd.h>
#include <iostream>
using namespace std;
int main()
{
    HANDLE d = GetModuleHandle(NULL);
    cout << "Module Handle:"<<d<<endl;
    int gold = 0;
    int* ptr = &gold;
    char buff[] = "Hello World\n";
    std::cout << buff;
    system("title hackme");
    std::cout << "Enter something:";
    std::cin >> gold;
    for (;;) {
        std::cout << buff;
        //gold++;
        std::cout << "Address:";
        std::cout << &gold<< std::endl;
        std::cout << gold << std::endl;
        Sleep(1000);
        
    }
    cout << "Congrats Pro!!!" << endl;

    
}

OUTPUT for GetBaseAddress:

GetBaseAddress

OUTPUT for ConsoleApplication1.exe

ConsoleApplication1

Software Details:

  1. Microsoft Visual Studio Community 2019
  2. Version 16.11.23
  3. Optimization: Disabled
  4. OS: Window 10
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
SUDO HERO
  • 11
  • 1
  • 1
    [Please don't post pictures of text](https://meta.stackoverflow.com/questions/285551/why-should-i-not-upload-images-of-code-data-errors). Program output is text. Post text as text. – Jabberwocky May 02 '23 at 11:11
  • 1
    [This](https://stackoverflow.com/questions/36223809/write-in-another-process-memory-with-writeprocessmemory-and-a-pointer) might help. – Jabberwocky May 02 '23 at 11:21
  • Start by **properly** diagnosing the issue. `GetLastError` is a helpful tool, so long as it is used as designed. Specifically: **No** code in between observing the condition under which the last error code is valid and the call to `GetLastError`. – IInspectable May 02 '23 at 13:31
  • What makes you think that the correct address is `0x619b44`? – Raymond Chen May 02 '23 at 16:03
  • @Jabberwocky okay sorry i'll remember this next time :) – SUDO HERO May 02 '23 at 18:05
  • @IInspectable wdym i have put errExit function for every value ? is these something im missing ? – SUDO HERO May 02 '23 at 18:08
  • @RaymondChen I attached a debugger to find out that address. And also if it was a wrong address i shouldn't be able to read data from that address – SUDO HERO May 02 '23 at 18:09
  • Actually when i was trying to print the BaseAddress as cout << modEntry.modBaseAddr it was trying to access the memory location instead. Im sorry for the confusion actually the base address is 60 0000 and as for how i determined that offset is, 619B44 - 60 0000 = 19B44 is the address to the Hello World – SUDO HERO May 02 '23 at 18:20
  • @SUDOHERO You have hard-coded the offset as `0x19B44`, where did you get that value from? Nowhere in your `ConsoleApplication.exe` code are you outputting the address of your `buff` that you are trying to write to. `ConsoleApplication.exe` is printing out its true base address (but the screenshot you have provided is missing that info), whereas `GetBaseAddress` is printing out the *adjusted* address being accessed, not the base module address itself. Based on what has been shown, you are trying to access address `0x619B44`, is that the correct memory address of `buff`? We can't see that. – Remy Lebeau May 02 '23 at 18:21
  • @SUDOHERO "*when i was trying to print the BaseAddress as `cout << modEntry.modBaseAddr` it was trying to access the memory location instead*" - that is because `modBaseAddr` is a `BYTE*` pointer, ie `unsigned char*`, and `operator<<` has overloads that treat all `[(un)signed] char*` pointers as null-terminated strings. You need to cast the pointer to `void*` to print the address itself: `cout << (void*) modEntry.modBaseAddr`. And FYI, you don't need to use `std::stringstream` to print a hex string to `std::cout`, you can use `std::hex` with `std::cout` directly. – Remy Lebeau May 02 '23 at 18:23
  • this offest will be different for each machine you compile in you have to attach a debugger to a do the math as baseAddress - StringAddr = offset i have given you up how i got that – SUDO HERO May 02 '23 at 18:23
  • Ohh thanks for that. I was confused as why it is behaving like this for BYTE*.Cuz when i did this for DWORD it worked normally. Thanks bro i'll remember for next time :) – SUDO HERO May 02 '23 at 18:25
  • @SUDOHERO "*this offest will be different for each machine*" - yes, it can be, which is why you should not be hard-coding it at all. Let the user enter the desired address/offset at runtime, and you should have `ConsoleApplication.exe` print out the correct address/offset, too. "*the math as `baseAddress - StringAddr = offset`*" - you have that backwards, it should be `StringAddr - baseAddress = offset` instead. – Remy Lebeau May 02 '23 at 18:28
  • oh yeah sorry you are right i did'nt noticed that that's i wrote it incorrectly sorry for that. I still have much to learn :). I'll remember this things – SUDO HERO May 02 '23 at 18:33
  • Actually im not outputting the Address for ```buff``` the address is for ```gold``` variable. Sorry when took the screenshot i missed the ```Module Handle:[ADDRESS]``` part. – SUDO HERO May 02 '23 at 18:46
  • *"i have put errExit function for every value ? is these something im missing ?"* - Clearly. I emphasized "**No** code in between" which apparently went right past you. `cout << "Whatever"` **is** code. – IInspectable May 02 '23 at 18:57
  • I don't understand whoever closed it as a duplicate, did he/she even looked at the reference they provided i have clearly stated that i've already used VirtualProtect . It doesn't matter now i had already found the solution yesterday i was just looking if someone has some alternative to this. I see people instead of trying for solution just talking here and there this missing that missing,etc. If someone needs the solution check here :https://www.unknowncheats.me/forum/programming-for-beginners/581349-write-process-memory-writeprocessmemory.html. I've had already provided everything needed. – SUDO HERO May 03 '23 at 04:50
  • But instead of looking for solution they are focusing on things missing that, before providing the question i knew are not even required cuz they and nothing to do with the problem. I appreciate the suggestion. Some things require common sense don't expect people to spoon feed you. – SUDO HERO May 03 '23 at 04:59

0 Answers0