Search code examples
c++processconsole

"ReadProcessMemory" how to get std::string?


Programm_A

int main()
{
    std::cout << "Process ID = " << GetCurrentProcessId() << "\n"; // Id my process (i get something like '37567')
    std::string My_String = "JoJo"; // My string
    std::cout << &My_String << std::endl; //here i get something like '0x0037ab7'
    system("pause");
}

This program just outputs reference of string "JoJo" to console.

Programm_B

int main()
{
    int id;
    std::cin >> id;
    DWORD ProcessId = id;
    HANDLE ProcessHandle = OpenProcess(PROCESS_VM_READ, FALSE, ProcessId);
    if (!ProcessHandle) { 
        std::cout << "Process is not found...\n";
        return 0;
    }
    std::string r;
    std::cin >> r; // this is me writing the link that I get in programs_A
    DWORD address = std::strtoul(r.c_str(), NULL, 16);
    std::string JoJo_string = " ";
    ReadProcessMemory(ProcessHandle, (LPVOID)(address), &JoJo_string, sizeof(JoJo_string), 0); //here I want to get the JoJo_string value by reference from programm_A
    std::cout << JoJo_string << std::endl;
}

The funny thing is that everything works fine with the "int" variable type. But std::string is not working. The exact value reads, but the program immediately gives an error:

[-- programm_B --]

[-- error --]


Solution

  • You can't easily read a std::string across process boundaries.

    Different standard library implementations of std::string use different memory layouts for its data members. The std::string in your program may be using a different implementation than the program you are trying to read from.

    But even if the two programs used the exact same implementation, it still wouldn't matter, because std::string is simply too complex to read with a single ReadProcessMemory() call. std::string uses dynamic memory for its character data, so one of its data members is a char* pointer to the data stored elsewhere in memory. Which is complicated by the fact that std::string might also implement a local Short-String Optimization buffer so short string values are stored directly in the std::string object itself to avoid dynamic memory allocations.

    So, you would have to know the exact implementation of std::string being used by the target program in order to decipher its data members to discover where the character data is actually being stored, and in the case where SSO is not active then read the char* pointer, as well as the number of characters being pointed at (which itself is also determinate in an implementation-specific way), so you could then read the character data with another ReadProcessMemory() call.

    In short, what you are attempting to do is a futile effort.