简体   繁体   中英

Get specific process memory space

I have a pointer ( void * ) to a function and I want to know which process this function belongs to. I have no idea which way to go about it, but I think it's possible by using some form of VirtualQuery trickery. Any help would be appreciated.

Thanks in advance,

CLARIFICATION: By "belong to process" I mean what process the function is in. For example: say there was an executable ( test.exe ) loaded in memory. This executable contains a function named SayHello , which is located at 0xDEADBEEF in memory. In an entirely different process, how would I know 0xDEADBEEF is in test.exe 's memory space.

Hope that clears things up.

CLARIFICATION 2: I'm sure you're familiar with "VTable hooking", where an external module changes a VTable pointer in a seperate process to point to a different function. Thereby whenever the hooked member is called, it is passed to the external module.

To prevent this (anti-cheat), I want to be able to check whether all methods of a VTable point to the module they reside in.

SOLUTION CODE:

template<class T>
inline void **GetVTableArray(T *pClass, int *pSize)
{
    void **ppVTable = *(void ***)pClass;

    if(pSize)
    {
        *pSize = 0;

        while(!IsBadReadPtr(ppVTable[*pSize], sizeof(UINT_PTR)))
            (*pSize)++;
    }

    return ppVTable;
}

bool AllVTableMembersPointToCurrentModule(void *pClass)
{
    DWORD dwOldProtect;
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 moduleEntry;

    // Take a snapshot of all modules in the specified process
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
    if(hModuleSnap == INVALID_HANDLE_VALUE)
        return false;

    // Set the size of the structure before using it
    moduleEntry.dwSize = sizeof(MODULEENTRY32);

    // Retrieve information about the first module (current process)
    if(!Module32First(hModuleSnap, &moduleEntry))
    {
        CloseHandle(hModuleSnap);
        return false;
    }

    // Grab the base address and size of our module (the address range where
    // the VTable can validly point to)
    UINT_PTR ulBaseAddress = reinterpret_cast<UINT_PTR>(moduleEntry.modBaseAddr);
    UINT_PTR ulBaseSize = moduleEntry.modBaseSize;

    // Get the VTable array and VTable member count
    int nMethods;
    void **ppVTable = GetVTableArray(pClass, &nMethods);

#ifdef VTABLE_FAKING
    // Allow patching
    VirtualProtect(ppVTable, nMethods * sizeof(UINT_PTR), PAGE_EXECUTE_READWRITE, &dwOldProtect);

    // Now take the next module and set the first VTable pointer to point to an
    // invalid address, outside of the current module's address range
    Module32Next(hModuleSnap, &moduleEntry);
    ppVTable[0] = moduleEntry.modBaseAddr;
#endif

    // Don't allow people to overwrite VTables (can easily be bypassed, so make
    // sure you check the VirtualProtect status of the VTable regularly with
    // VirtualQuery)
    VirtualProtect(ppVTable, nMethods * sizeof(UINT_PTR), PAGE_EXECUTE, &dwOldProtect);

    // Clean up the snapshot object
    CloseHandle(hModuleSnap);

    // Ensure all VTable pointers are in our current module's address range
    for(int i = 0; i < nMethods; ++i)
    {
        // Get address of the method this VTable pointer points to
        UINT_PTR ulFuncAddress = reinterpret_cast<UINT_PTR>(ppVTable[i]);

        // Check the address is within our current module range
        if(ulFuncAddress < ulBaseAddress || ulFuncAddress > ulBaseAddress + ulBaseSize)
            return false;
    }

    return true;
}

Each process has its own address space. This means that the same address will contain different things for different processes, so there is no way to do what you're asking.

If this pointer is to a function in the current program (ie a function that you can currently call), then the answer is simple: it belongs to the current process.

To further clarify: A pointer by itself is meaningless unless you already know which process it belongs to. Process #1001 may have a function sayHello at address 0x12345678, while process #1002 has the function sayGoodbye at address 0x12345678, and process #1003 contains some data at the same address. There is no way to know which process the pointer came from.

In any of the Windows operating systems that are descended from Windows NT (so, for all intents and purposes anything including and after XP, and before that NT 4 and NT 3.51) each process has it's own address space. Within reason, any pointer address can be different in every process in the system as they all have an 0xDEADBEEF address and it may, or may not contain the same thing as other processes. This was not the same with Windows 3.0, 3.1, 95, 98 and ME (they had one address space which all processes shared) where your question MAY have made more sense.

So, without a handle to a process to go with your pointer address the address is pretty much useless to you. With a handle to a process you can (possibly) work out what you want by walking the import tables for the DLLs that you import... If the function isn't an imported function then it's unlikely that you could work out what you want to know.

Note that if the address is to a function which is from a 'standard' system DLL then you MAY be able to work out where it lives by finding out what function it represents in the address space of your process as there is a strong chance that the DLL will be mapped to the same base address in your process as it is in every other process.

Why not tell us a little more about what it is, exactly, that you're actually trying to do?

Edit:

Well, as I described above, what you're suggesting is not possible except on very old versions of Windows. What IS possible is that you can inject code into a process to replace that code that should be executed. The address of this injected code is valid in the target process's address space and contains code that you (the hacking process) have created. You do this by a combination of allocating memory in the remote process with VirtualAllocEx() (1) and then writing your code to it with WriteProcessMemory() (2) . You now have code that you wrote in the target process. You can then patch it in so that it's called instead of the code that should be called.

The common way to do this is IAT hooking (Import Address Table hooking) and this lets you replace imported functions from DLLs. To detect this you need to scan the DLL's Import Address Table from the DLL image on disk, work out where the functions are in memory and then scan the in memory IAT to check that the functions are where they should be; if they're not then they've likely been patched.

You're suggesting that someone is replacing an arbitrary C++ vTable entry. This is possible with the same technique but it's harder as there's no convenient table of names to addresses that you can use to work out where to patch. Anyway, assuming the bad guy can find the correct address to patch he can use the same technique as above to create his own function in your process.

Detecting the vTable problem is made more complex by the lack of name to address lookup, but if you're in the process that's being hacked you can simply have written code that takes the address of the function in question at start up. Store that somewhere and compare it later. However, you'd probably best take a copy of the whole function itself in memory and compare with that as you might find that the bad guys simply look for some recognisable function signature bytes and patch a jump into them somewhere to their own code or simply to skip yours.

Good luck and grab yourself a good book, such as one by Jeffrey Richter which will explain much of this far better than I can.

The hijacked function pointer in the VTable can only be inside your process, as the other folks have already answered. The memory address only makes sense for your process. If someone is going to overwrite one of your VTable spots, then they would first have to hook something your process, which means running code inside your process. There exists plenty of win API that provides hooking.

See EnumProcessModule to go through all of the modules in your process. See this about modules info including base address of your module. You would then have to check your VTables to make sure those addressed exist inside of your module's address range.

To prevent VTable hijacking in the first place? I don't know how to do this, other than trying Microsoft's Detours library , which can in theory be used to detour any hook API call inside your process.

如果具有模块句柄,则可以检查映像头以确保vtable指针在该模块的虚拟地址空间中。

I don't really understand your question, so I'm going to take a stab in the dark and answer what I think you're asking.

You're asking how you can find out, from a function pointer, to which module it belongs. The solution is rather simple in theory, scan backwards in memory to find the header, and then enjoy using this function GetModuleFileName.

Since your question isn't well worded, you don't get a well worded answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM