12

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;
                }
            }
        }
    }
}
Yuushi
  • 25,132
  • 7
  • 63
  • 81
Dalton Sandbothe
  • 501
  • 2
  • 7
  • 16
  • 1
    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. – Retired Ninja Jan 30 '15 at 07:39
  • 1
    `sizeof(input)` does not mean what you think it means. – molbdnilo Jan 30 '15 at 08:05

1 Answers1

13

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;
}
Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
  • Quick and dirty ? Where exactly ? Here for exmple ? chunk.resize(info.RegionSize); – icbytes Jan 30 '15 at 12:38
  • 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. – Dalton Sandbothe Jan 30 '15 at 14:10
  • 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. – icbytes Jan 30 '15 at 14:40
  • 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. – Retired Ninja Jan 30 '15 at 18:19