Search code examples
c++readprocessmemory

WriteProcessMemory on returned addresses


So my program basically search for "specified strings" in other process memory, and then outputs the memory address that contains those strings, but i want to be able to then do a WriteProcessmemory to replace all that addresses. I just need to have all the writeprocessmemory on all that returned addresses, the program is already done i just need that, maybe it could work storing the addresses into a vector or i don't know.

#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <algorithm>
#include <iterator>
const char someDatanew[] = "\0";
template <class InIter1, class InIter2, class OutIter>
void find_all(unsigned char* base, InIter1 buf_start, InIter1 buf_end, InIter2 pat_start, InIter2 pat_end, OutIter res) {
    for (InIter1 pos = buf_start;
        buf_end != (pos = std::search(pos, buf_end, pat_start, pat_end));
        ++pos)
    {
        *res++ = base + (pos - buf_start);
    }
}

template <class outIter>
void find_locs(HANDLE process, std::string const &pattern, outIter output) {

    unsigned char* p = NULL;
    MEMORY_BASIC_INFORMATION info;

    for (p = NULL;
        VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
        p += info.RegionSize)
    {
        std::vector<char> buffer;
        std::vector<char>::iterator pos;

        if (info.State == MEM_COMMIT &&
            (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
        {
            SIZE_T bytes_read;
            buffer.resize(info.RegionSize);
            ReadProcessMemory(process, p, &buffer[0], info.RegionSize, &bytes_read);
            buffer.resize(bytes_read);
            find_all(p, buffer.begin(), buffer.end(), pattern.begin(), pattern.end(), output);
            //if (WriteProcessMemory(process, (LPVOID)here all returned addresses, someDatanew, sizeof(someDatanew), 0))
            ////    std::cout << "done";
            //}
        }
    }
}
void EnableDebugPriv() {
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = luid;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);

    CloseHandle(hToken);
}

bool getMaximumPrivileges(HANDLE h_Process) {

    HANDLE h_Token;
    DWORD dw_TokenLength;

    if (OpenProcessToken(h_Process, TOKEN_READ | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &h_Token)) {
        // Read the old token privileges
        TOKEN_PRIVILEGES* privilages = new TOKEN_PRIVILEGES[100];
        if (GetTokenInformation(h_Token, TokenPrivileges, privilages, sizeof(TOKEN_PRIVILEGES) * 100, &dw_TokenLength)) {
            // Enable all privileges
            for (int i = 0; i < privilages->PrivilegeCount; i++) {
                privilages->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
            }

            // Adjust the privilges
            if (AdjustTokenPrivileges(h_Token, false, privilages, sizeof(TOKEN_PRIVILEGES) * 100, NULL, NULL)) {
                delete[] privilages;
                return true;
            }
        }
        delete[] privilages;

    }
    return false;
} //get all tokens

int main() {
    EnableDebugPriv();
    getMaximumPrivileges(GetCurrentProcess());


    DWORD pid;
    std::cout << "Enter PID: ";
    std::cin >> pid;

    std::cin.get();

    std::string pattern;

    std::cout << "pattern to find: ";
    std::getline(std::cin, pattern);

    HANDLE process = OpenProcess(
        PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION,
        false,
        pid);

    find_locs(process, pattern,
        std::ostream_iterator<void*>(std::cout, "\n")); //outputs addresses that contains the strings

    system("pause");

    return 0;
}

I expect to just replace all the returned addresses with someDatanew


Solution

  • Instead of outputting the results from find_locs() to the console you should log each string address to an array. Then after this is completed, loop through them and call WriteProcessMemory, overwriting them with whatever you want, just ensure you have the correct size/null termination.

    Or you can scan memory for a single pattern, overwrite the result, scan again for the next one, overwrite again until PatternScan() returns no result. But this is less efficient.

    For the fastest resolution of your question, I have edited find_all() to include a call to WriteProcessMemory, which is the fastest way to accomplish what you want. I changed a couple other things so be sure to copy and paste this entire source code, overwriting yours.

    I removed the SeDebug token elevation stuff, it's not necessary. You only need to run your program as administrator to use these APIs.

    Tested working, just ensure that the string you overwrite is at least the same length as someDataNew

    #include <iostream>
    #include <vector>
    #include <string>
    #include <windows.h>
    #include <algorithm>
    #include <iterator>
    
    const char * someDatanew = "Foobar\0";
    
    HANDLE process = 0;
    
    template <class InIter1, class InIter2, class OutIter>
    
    void find_all(unsigned char* base, InIter1 buf_start, InIter1 buf_end, InIter2 pat_start, InIter2 pat_end, OutIter res) {
        for (InIter1 pos = buf_start;
            buf_end != (pos = std::search(pos, buf_end, pat_start, pat_end));
            ++pos)
        {
            *res++ = base + (pos - buf_start);
    
            if (WriteProcessMemory(process, (LPVOID)(base + (pos - buf_start)), (LPCVOID)someDatanew, strlen(someDatanew), 0))
            std::cout << "done";
    
        }
    }
    
    template <class outIter>
    void find_locs(HANDLE process, std::string const &pattern, outIter output) {
    
        unsigned char* p = NULL;
        MEMORY_BASIC_INFORMATION info;
    
        for (p = NULL;
            VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
            p += info.RegionSize)
        {
            std::vector<char> buffer;
            std::vector<char>::iterator pos;
    
            if (info.State == MEM_COMMIT &&
                (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
            {
                SIZE_T bytes_read;
                buffer.resize(info.RegionSize);
                ReadProcessMemory(process, p, &buffer[0], info.RegionSize, &bytes_read);
                buffer.resize(bytes_read);
                find_all(p, buffer.begin(), buffer.end(), pattern.begin(), pattern.end(), output);
    
            }
        }
    }
    
    int main()
    {
        DWORD pid;
        std::cout << "Enter PID: ";
        std::cin >> pid;
    
        std::cin.get();
    
        std::string pattern;
    
        std::cout << "pattern to find: ";
        std::getline(std::cin, pattern);
    
        process = OpenProcess(
            PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION,
            false,
            pid);
    
        find_locs(process, pattern,
            std::ostream_iterator<void*>(std::cout, "\n")); //outputs addresses that contains the strings
    
        system("pause");
    
        return 0;
    }