c++winapisearchmemoryreadprocessmemory

Can't find an array of bytes match from another process' memory


I'm currently trying to verify whether or not a code I wrote using this as reference works. I've managed to get it to run without crashing, but once I began checking whether or not the code actually does what I want it to do, I ran into a problem.

While I think that the code goes through all the memory regions belonging to the process I'm trying to search, it probably isn't doing that?

I'm honestly not sure where the problem lies here, am I searching for my array of bytes in the memory buffer incorrectly, or am I actually reading the wrong memory?


When checking whether or not my code finds an array of bytes match from the process, I used cheat engine to scan beforehand and then compare the results with what my program returned. I used an array of bytes I knew from beforehand will always exist at least once in the program I'm scanning.

Now comparing the results I got from cheat engine: ce results

And the ones I got from my program, which is 0 results. That doesn't seem quite right.


I open the process which I want to read the memory from with the following flags:

PROCESS_VM_READ | PROCESS_QUERY_INFORMATION

And the way I call my pattern matching function:

testy.patternMatch("000000000000000001000000000000001CC80600");

As for my current code:

The function I'm calling (m_localprocess is an open handle to the process I got beforehand)

void process_wrapper::patternMatch(std::string pattern)
{
    MEMORY_BASIC_INFORMATION sys_info;

    std::vector<char> pattern_conv(pattern.begin(), pattern.end());


    for (unsigned char * pointer = NULL;
        VirtualQueryEx(m_localprocess, pointer, &sys_info, sizeof(sys_info)) == sizeof(sys_info);
        pointer += sys_info.RegionSize) {

        std::vector<char> mem_buffer;

        if (sys_info.State == MEM_COMMIT && (sys_info.Type == MEM_MAPPED || sys_info.Type == MEM_PRIVATE)) {

            SIZE_T bytes_read;
            mem_buffer.resize(sys_info.RegionSize);

            ReadProcessMemory(m_localprocess, pointer, &mem_buffer[0], sys_info.RegionSize, &bytes_read);
            if (GetLastError() != 0) {
                std::cout << "Error: " << GetLastError();
                SetLastError(0);
            }

            mem_buffer.resize(bytes_read);


            std::cout << "\nSize: "<< mem_buffer.size() << "\n";
            if (mem_buffer.size() != 0) {
                find_all(mem_buffer.begin(), mem_buffer.end(), pattern_conv.begin(), pattern_conv.end(), pointer);
            }
        }

    }

    std::cout << "Results: " << results.size() << "\n";
    for (void* x : results) {
        std::cout << x << "\n";
    }

}

And this function calls find_all function, which looks like this:

void find_all(std::vector<char>::iterator beg, std::vector<char>::iterator end,
    std::vector<char>::iterator beg_pattern, std::vector<char>::iterator end_pattern, 
    const unsigned char * baseAddr) {

    std::vector<char>::iterator walk = beg;

    while (walk != end) {
        walk = std::search(walk, end, beg_pattern, end_pattern);

        if (walk != end) {
            std::cout << (void*)(baseAddr + (walk - beg)) << "\n";
            results.emplace_back((void*)(baseAddr + (walk - beg)));
            ++walk;
        }
    }
}

Any suggestions on other ways of implementing what I'm trying to do are more than welcome.


Solution

  • Thanks to the comment left by Jonathan pointing out I was actually comparing ASCII values instead of actual hex values.

    The code works now: working

    The change I did to my code (got it from here):

    void process_wrapper::patternMatch(std::string patternOrig)
    {
        MEMORY_BASIC_INFORMATION sys_info;
    
        int len = patternOrig.length();
        std::string pattern;
        for (int i = 0; i < len; i += 2)
        {
            std::string byte = patternOrig.substr(i, 2);
            char chr = (char)(int)strtol(byte.c_str(), NULL, 16);
            pattern.push_back(chr);
        }
        //...