获取特定的进程内存空间

我有一个指针( void * )函数,我想知道这个函数属于哪个进程。 我不知道该怎么VirtualQuery ,但我认为这是可能的通过使用某种forms的VirtualQuery欺骗。 任何帮助,将不胜感激。

提前致谢,

澄清: “属于进程”是指函数所在的进程。例如:说有一个可执行文件( test.exe )加载到内存中。 该可执行文件包含名为SayHello的函数,该函数位于内存中的0xDEADBEEF处。 在一个完全不同的过程中,我将如何知道0xDEADBEEF在test.exe的内存空间中。

希望这能说明问题。

澄清2:我确定你熟悉“VTable hooking”,在这种情况下,外部模块在一个单独的进程中改变一个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; } 

VTable中被劫持的函数指针只能在你的进程中,因为其他人已经回答了。 内存地址只对您的进程有意义。 如果有人要覆盖你的一个VTable点,那么他们将首先挂钩你的进程,这意味着在你的进程中运行代码。 有大量的win API提供了钩子。

请参阅EnumProcessmodulee以遍历过程中的所有模块。 查看关于模块信息的信息,包括模块的基址。 然后你将不得不检查你的VTable,以确保这些地址存在于你的模块的地址范围内。

为了防止VTable劫持在第一位? 我不知道该怎么做,除了尝试微软的Detours库 ,理论上它可以用来绕过你的进程中的任何钩子API调用。

每个进程都有自己的地址空间。 这意味着相同的地址将包含不同的进程不同的东西,所以没有办法做你在问什么。

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

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

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

在任何Windows NT操作系统下(所有意图和目的,包括XP之后,以及之前的NT 4和NT 3.51),每个进程都有自己的地址空间。 在合理的范围内,任何指针地址在系统的每个进程中都可能是不同的,因为它们都有一个0xDEADBEEF地址,并且可能包含或不包含与其他进程相同的东西。 这与Windows 3.0,3.1,95,98和ME(他们有一个共享所有进程的地址空间)不一样,你的问题可能更有意义。

所以,如果没有一个处理你的指针地址的地址,你的地址几乎是无用的。 通过一个进程的句柄,你可以(可能)通过遍历你导入的DLL的导入表来计算出你想要的结果…如果这个函数不是一个导入的函数,那么你不可能计算出你想要的知道。

请注意,如果地址是来自“标准”系统DLL的函数,那么您可以通过找出它在过程的地址空间中表示的函数来确定它的存在位置,因为这很有可能该DLL将被映射到您的进程中的相同的基址,就像在其他进程中一样。

为什么不告诉我们更多关于它究竟是什么的呢?

编辑:

那么,正如我上面所描述的,除了非常老的Windows版本之外,你所建议的是不可能的。 什么是可能的是,你可以注入代码到一个进程,以取代应执行的代码。 这个注入代码的地址在目标进程的地址空间中是有效的,并包含你(黑客进程)创建的代码。 您可以通过在VirtualAllocEx() (1)中分配远程进程中的内存,然后使用WriteProcessMemory() (2)将代码WriteProcessMemory()它来完成此操作。 您现在拥有您在目标流程中编写的代码。 然后你可以修补它,使它被调用,而不是应该被调用的代码。

执行此操作的常用方法是IAT挂接 (导入地址表挂接),这可以让您从DLL中替换导入的函数。 为了检测这个,你需要从磁盘上的DLL映像中扫描DLL的导入地址表,找出函数在内存中的位置,然后扫描内存中的IAT来检查函数是否应该在哪里; 如果他们不是那么他们可能已经修补。

你建议有人替换一个任意的C ++ vTable条目。 这是可能的相同的技术,但它是困难的,因为没有方便的名称地址表,你可以用来找出补丁的位置。 无论如何,假设坏人可以找到正确的补丁地址,他可以使用与上面相同的技术在您的过程中创建自己的功能。

检测vTable问题变得更加复杂,因为缺乏名称来解决查找问题,但是如果你正在被黑客攻击,你可以简单地编写代码,在启动时读取相关函数的地址。 存储在某个地方,稍后再进行比较。 不过,你最好把整个函数本身拷贝到内存中,并与之相比,你可能会发现坏人只是寻找一些可识别的函数签名字节,并跳转到他们自己代码的某处跳过你的。

祝你好运,并抓住一本好书,比如杰弗里·里希特(Jeffrey Richter)的一本书,这本书将会比我更好地解释这一点。

我真的不明白你的问题,所以我要在黑暗中刺探,回答我认为你在问什么。

你问的是如何从函数指针中找出它属于哪个模块。 理论上这个解决方案相当简单,在内存中向后扫描以找到头文件,然后使用GetmoduleeFileName函数来享受它。

既然你的问题措辞不好,你没有得到一个措辞良好的答案。