0

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.

  • 1
    You're not converting the input string into hex values, you're leaving it as ASCII. So your search function will literally be looking for '0', '0', '0', .... – Jonathan Potter Feb 01 '19 at 23:35
  • @JonathanPotter the input string is the array of bytes I'm searching for is presented in hex values. Maybe I'm misunderstanding how the values I'm getting are presented as? –  Feb 01 '19 at 23:42
  • Start here: https://stackoverflow.com/questions/17261798/converting-a-hex-string-to-a-byte-array to convert your hex string to a byte array. Then search for the bytes. – drescherjm Feb 02 '19 at 00:00
  • @drescherjm I just used this and I'm currently waiting for my memory search to finish: https://stackoverflow.com/a/3790661/7346067 –  Feb 02 '19 at 00:01
  • Your error checking is wrong too. You have to check return values. – David Heffernan Feb 02 '19 at 08:52
  • @DavidHeffernan you mean putting the ReadProcessMemory inside an if statement? –  Feb 02 '19 at 14:34
  • Yes. It indicates error by its return value, like so many Win32 functions. – David Heffernan Feb 02 '19 at 14:44

1 Answers1

0

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);
    }
    //...