我正在尝试扫描第三方应用程序的内存。我已经找到了地址;现在是0x0643FB78
。问题是,由于LPMODULEENTRY32->modBaseAddr
为0x00400000
且LPMODULEENTRY32->modBaseSize
仅为0x006FF000
,因此我永远无法到达那里,因此我可以扫描此模块的最大地址为{{1 }}
这是否意味着我寻求的地址确实存在于另一个进程/模块/线程/内容中?我相信我的过程确实包含了地址。那我该如何访问内存呢?谢谢。
答案 0 :(得分:9)
至少在我看来,如果你涉及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;
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;
}
答案 1 :(得分:3)
进程由内存页面组成,这些页面映射有某些保护。这些页面封装在模块中。每个模块都有一个基础和一个大小。但是,ReadProcessMemory完全从您那里抽象出来。无论模块是什么模块,您都应该能够读取内存。
在这种情况下,内存不在您正在查看的模块中。如果确实需要查找它所属的位置,可以使用CreateToolHelp32Snapshot,Module32First和Module32Next遍历模块检查基础和大小。
发布一些代码,我们可以帮助您找出出错的地方。你为什么这么确定你要找的地址是你说的地址?由于ASLR,通常使用基本模块+偏移指定地址。你是如何得到目标流程的?您需要具有某些访问权限才能使用ReadProcessMemory。