我正在尝试扫描第三方应用程序的内存。 我已经find了地址; 现在是0x0643FB78
。 因为LPMODULEENTRY32->modBaseAddr
是0x00400000
, LPMODULEENTRY32->modBaseSize
只是0x006FF000
,所以我永远不会在那里0x006FF000
,因此我可以扫描这个模块的最大地址是0x00AFF000
。
这是否意味着我寻找的地址是否存在于另一个进程/模块/线程/内? 我非常有信心,我所拥有的过程确实包含了地址。 那么我应该如何访问内存呢? 谢谢。
至少在我看来,如果你有一个LPMODULEENTRY
参与,你可能开始在错误的方向。 我将使用VirtualQueryEx
代替目标进程中的内存块。 这会给你一个MEMORY_BASIC_INFORMATION
关于每个块的过程。 然后,您可以使用ReadProcessMemory
并扫描块来查找您要查找的内容。
下面是我写的一些旧代码,它们大致是一样的,但是寻找一个字符串而不是一个指针:
#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; std::vector<char>::iterator pos; 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; }
一个进程由内存页面组成,这些页面被映射到某些保护。 这些页面被封装在模块中。 每个模块都有一个基础和一个大小。 但是,ReadProcessMemory完全从你的文摘中提取出来。 你应该能够读取内存,不管它在哪个模块。
在这种情况下,内存不在您正在查看的模块中。 如果您确实需要找到它所属的位置,可以使用CreateToolHelp32Snapshot,modulee32First和modulee32Next来遍历模块检查基础和大小。
发布一些代码,我们可以帮助你找出你出错的地方。 你为什么这么确定你要找的地址是你所说的地址? 由于ASLR的原因,地址通常由基本模块+偏移指定。 你如何获得目标流程句柄? 您需要具有某些访问权限才能使用ReadProcessMemory。