Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read process memory of a process does not return everything

I am trying to scan memory of a 3rd party application. I have already found out the address; right now is at 0x0643FB78. The thing is, I can never get up there since LPMODULEENTRY32->modBaseAddr is 0x00400000 and LPMODULEENTRY32->modBaseSize is merely 0x006FF000, thus the max address I can scan for this module is 0x00AFF000.

Does that mean the address I seek does live inside another process/module/thread/something? I am quite confident the process I have does contain the address though. How should I access the memory then? Thank you.

like image 676
Mikulas Dite Avatar asked Apr 29 '12 14:04

Mikulas Dite


2 Answers

At least in my opinion, if you have an LPMODULEENTRY involved, you're probably starting in the wrong direction. I'd walk through the blocks of memory in the target process with VirtualQueryEx instead. This will give you a MEMORY_BASIC_INFORMATION about each block in that process. You can then use ReadProcessMemory and scan through the blocks to find what you're looking for.

Here's some old code I wrote to do roughly the same thing, but looking for a string rather than a pointer:

#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <algorithm>
#include <iterator>

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;

        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(int argc, char **argv) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <process ID> <pattern>", argv[0]);
        return 1;
    }

    int pid;
    sscanf(argv[1], "%i", &pid);

    std::string pattern(argv[2]);

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

    find_locs(process, pattern, 
        std::ostream_iterator<void *>(std::cout, "\n"));

    return 0;
}
like image 51
Jerry Coffin Avatar answered Nov 13 '22 16:11

Jerry Coffin


A process consists of pages of memory which are mapped with certain protections. These pages are encapsulated in modules. Each module has a base and a size. However, ReadProcessMemory abstracts this from you completely. You should be able to read memory regardless of what module it is in.

In this case, the memory is not in the module you are looking at. If you do need to find where it belongs, you can iterate through the modules checking base and size with CreateToolHelp32Snapshot, Module32First and Module32Next.

Post some code and we can help you find out where you've gone wrong. Why are you so sure the address of what you are looking for is the address you state? Addresses are often specified with a base module + offset because of ASLR. How are you getting the target process handle? You need to have certain access rights to use ReadProcessMemory.

like image 40
Mike Kwan Avatar answered Nov 13 '22 16:11

Mike Kwan