c++winapireadprocessmemory

How to read Unicode string from process in Windows?


I'm trying to read a Unicode string from another process's memory with this code:

Function:

bool ReadWideString(const HANDLE& hProc, const std::uintptr_t& addr, std::wstring& out) {
    std::array<wchar_t, maxStringLength> outStr;
    auto readMemRes = ReadProcessMemory(hProc, (LPCVOID)addr,(LPVOID)&out, sizeof(out), NULL);
    if (!readMemRes)
        return false;
    else {
        out = std::wstring(outStr.data());
    }
    return true;
}

Call:

std::wstring name;
bool res = ReadWideString(OpenedProcessHandle, address, name);
std::wofstream test("test.txt");
test << name;
test.close();

This is working well with English letters, but when I try to read Cyrillic, it outputs nothing. I tried with std::string, but all I get is just a random junk like "EC9" instead of "Дебил".

I'm using Visual Studio 17 and the C++17 standard.


Solution

  • You can't read directly into the wstring the way you are doing. That will overwrite it's internal data members and corrupt surrounding memory, which would be very bad.

    You are allocating a local buffer, but you are not using it for anything. Use it, eg:

    bool ReadWideString(HANDLE hProc, std::uintptr_t addr, std::wstring& out) {
        std::array<wchar_t, maxStringLength> outStr;
        SIZE_T numRead = 0;
        if (!ReadProcessMemory(hProc, reinterpret_cast<LPVOID>(addr), &outStr, sizeof(outStr), &numRead))
            return false;
        out.assign(outStr.data(), numRead / sizeof(wchar_t));
        return true;
    }
    

    std::wstring name;
    if (ReadWideString(OpenedProcessHandle, address, name)) {
        std::ofstream test("test.txt", std::ios::binary);
        wchar_t bom = 0xFEFF;
        test.write(reinterpret_cast<char*>(&bom), sizeof(bom));
        test.write(reinterpret_cast<const char*>(name.c_str()), name.size() * sizeof(wchar_t));
    }
    

    Alternatively, get rid of the local buffer and preallocate the wstring's memory buffer instead, then you can read directly into it, eg:

    bool ReadWideString(HANDLE hProc, std::uintptr_t addr, std::wstring& out) {
        out.resize(maxStringLength);
        SIZE_T numRead = 0;
        if (!ReadProcessMemory(hProc, reinterpret_cast<LPVOID>(addr), &out[0], maxStringLength * sizeof(wchar_t), &numRead)) {
            out.clear();
            return false;
        }
        out.resize(numRead / sizeof(wchar_t));
        return true;
    }
    

    Or

    bool ReadWideString(HANDLE hProc, std::uintptr_t addr, std::wstring& out) {
        std::wstring outStr;
        outStr.resize(maxStringLength);
        SIZE_T numRead = 0;
        if (!ReadProcessMemory(hProc, reinterpret_cast<LPVOID>(addr), &outStr[0], maxStringLength * sizeof(wchar_t), &numRead))
            return false;
        outStr.resize(numRead / sizeof(wchar_t));
        out = std::move(outStr);
        return true;
    }