我正在尝试搜索一个以null结尾的字符串的所有实例作为进程的内存。我使用VirtualQueryEx编写了所有已分配的内存区域,然后用ReadProcessMemory将它们读取为字节数组并使用此算法进行搜索(我在此处找到并且作者声称是最快的)
public static unsafe List<long> IndexesOf(byte[] Haystack, byte[] Needle) {
List<long> Indexes = new List<long>();
fixed (byte* H = Haystack) fixed (byte* N = Needle) {
long i = 0;
for (byte* hNext = H, hEnd = H + Haystack.LongLength; hNext < hEnd; i++, hNext++) {
bool Found = true;
for (byte* hInc = hNext, nInc = N, nEnd = N + Needle.LongLength; Found && nInc < nEnd; Found = *nInc == *hInc, nInc++, hInc++) ;
if (Found) Indexes.Add(i);
}
return Indexes;
}
}
它有效,但速度太慢了。有没有办法在内存中映射进程或以某种方式在内存中搜索更快?
答案 0 :(得分:3)
从外部流程中,您几乎拥有正确的方法。但是,如果您正在寻找一个字符串,您可能不关心某些区域(例如可执行内存),因此您可以将它们从搜索区域中排除。您很可能只对PAGE_READONLY
和PAGE_READWRITE
感兴趣。
您应该使用ReadProcessMemory()以尽可能大的块读取内存。主要的瓶颈是磁盘IO(来自交换),你真的无法做到这一点。多线程它会加快速度,因为在处理上一次读取时你会“缓慢读取”。
如果你真的需要速度,正确的做法不是通过你现在正在做的外部过程。您应该注入一个DLL,以便直接访问进程的虚拟内存空间。
在您的搜索算法中,您也可以做一些小动作。例如,如果您知道字符串总是以4字节对齐方式分配,那么您可以只搜索它们。您将获得的最大加速是多线程和/或DLL注入。