获取特定的进程内存空间

Sau*_*aul 1 c++ windows winapi

我有一个void *函数的指针(),我想知道这个函数属于哪个进程.我不知道采用哪种方式,但我认为通过使用某种形式的VirtualQuery技巧是可能的.任何帮助,将不胜感激.

提前致谢,

澄清: "属于进程"是指函数所处的进程.例如:假设test.exe在内存中加载了可执行文件().此可执行文件包含一个名为的函数SayHello,该函数位于内存中的0xDEADBEEF.在一个完全不同的过程中,我怎么知道0xDEADBEEF在test.exe内存空间中.

希望这能说明问题.

澄清2:我确定你熟悉"VTable挂钩",其中外部模块在单独的进程中更改VTable指针以指向不同的功能.因此,每当调用钩状构件时,它就被传递到外部模块.

为了防止这种情况(反作弊),我希望能够检查VTable的所有方法是否指向它们所在的模块.

解决方案代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

int*_*jay 13

每个进程都有自己的地址空间.这意味着相同的地址将包含不同进程的不同内容,因此无法按照您的要求进行操作.

如果此指针指向当前程序中的某个函数(即您当前可以调用的函数),那么答案很简单:它属于当前进程.

进一步澄清:指针本身没有意义,除非你已经知道它属于哪个进程.进程#1001可以sayHello在地址0x12345678处具有功能,而进程#1002具有sayGoodbye在地址0x12345678处的功能,并且进程#1003包含在相同地址处的一些数据.无法知道指针来自哪个进程.

  • @Saul:指针不是相对的.问题是它们不直接映射到物理内存,而是映射到虚拟地址空间,这对每个进程都是唯一的.请参见http://en.wikipedia.org/wiki/Virtual_address_space (6认同)