How can I search for a string in the memory of another process?

12,873

Here's a quick and dirty version that searches for data in itself. If you open up Notepad++, type "SomeDataToFind", replace the pid with the correct value, and run it, it should find the data as well. It might give you something to start with and embellish to suit your needs.

Your code was searching for the wrong length, returning the wrong offset, leaking memory like a sieve, and not always returning a value which is undefined behavior.

#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>

char* GetAddressOfData(DWORD pid, const char *data, size_t len)
{
    HANDLE process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
    if(process)
    {
        SYSTEM_INFO si;
        GetSystemInfo(&si);

        MEMORY_BASIC_INFORMATION info;
        std::vector<char> chunk;
        char* p = 0;
        while(p < si.lpMaximumApplicationAddress)
        {
            if(VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info))
            {
                p = (char*)info.BaseAddress;
                chunk.resize(info.RegionSize);
                SIZE_T bytesRead;
                if(ReadProcessMemory(process, p, &chunk[0], info.RegionSize, &bytesRead))
                {
                    for(size_t i = 0; i < (bytesRead - len); ++i)
                    {
                        if(memcmp(data, &chunk[i], len) == 0)
                        {
                            return (char*)p + i;
                        }
                    }
                }
                p += info.RegionSize;
            }
        }
    }
    return 0;
}

int main()
{
    const char someData[] = "SomeDataToFind";
    std::cout << "Local data address: " << (void*)someData << "\n";

    //Pass whatever process id you like here instead.
    DWORD pid = GetCurrentProcessId();
    char* ret = GetAddressOfData(pid, someData, sizeof(someData));
    if(ret)
    {
        std::cout << "Found: " << (void*)ret << "\n";
    }
    else
    {
        std::cout << "Not found\n";
    }

    return 0;
}
Share:
12,873

Related videos on Youtube

Dalton Sandbothe
Author by

Dalton Sandbothe

Updated on September 15, 2022

Comments

  • Dalton Sandbothe
    Dalton Sandbothe over 1 year

    Currently I'm using this function which I've cobbled together from reading several loosely related questions all over the internet. The problem I'm having is that the first time I ran it it returned an error, but unfortunately I haven't been able to reproduce it. Now when I run it it simply returns 0 every time.

    DWORD GetAddressOfString(char *input)
    {
        unsigned char *p = NULL;
        MEMORY_BASIC_INFORMATION info;
        HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, _processID);
    
        for (p = NULL; VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info); p += info.RegionSize)
        {
            if (info.State == MEM_COMMIT && (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
            {
                char *buffer = new char[info.RegionSize];
                SIZE_T bytesRead;
                ReadProcessMemory(process, p, &buffer, info.RegionSize, &bytesRead);
                for (int i = 0; i <= (info.RegionSize - sizeof(input)); i++)
                {
                    if (memcmp(input, &buffer[i], sizeof(input)) == 0)
                    {
                        return i;
                    }
                }
            }
        }
    }
    
    • Retired Ninja
      Retired Ninja about 9 years
      I see several functions that can fail and no error checking. Seems like that would be the place to start. You might also want to make sure something is always returned, you should have gotten a warning about that when you compiled.
    • molbdnilo
      molbdnilo about 9 years
      sizeof(input) does not mean what you think it means.
  • icbytes
    icbytes about 9 years
    Quick and dirty ? Where exactly ? Here for exmple ? chunk.resize(info.RegionSize);
  • Dalton Sandbothe
    Dalton Sandbothe about 9 years
    For my specific case how would the return part of the function need to be changed? I don't believe I could return a pointer to data in another application. So I would need to return it as an integer somehow I believe.
  • icbytes
    icbytes about 9 years
    Why not ? You see, that retired ninja in this case calls HIS example in the codesnippet. You can just introspect any file by OpenProcess. So Your application will examine ANOTHER one.
  • Retired Ninja
    Retired Ninja about 9 years
    It really depends on what you plan to do with the data once you've found it. Your question states no goal other than finding it, and a DWORD isn't guaranteed to be large enough to hold a pointer value.