我对C ++不太满意,但是在我自己的记忆中扫描字符串时遇到了问题。
这是我的代码的一小部分示例:
for (unsigned int i = 0x400000; i < 0xFFFFFFFFFF; i++) {
string s = (char *) i;
if (s[0] == 'H') {
if (s == "Hello") {
cout << "Found at address: " << i << endl;
}
}
}
它会一直扫描到某个&#34;位置&#34;应用程序崩溃的地方。我猜它是由于未定义的行为而到达未分配的内存并且崩溃。
但问题是,最好的方法是什么?我试图远离ReadProcessMemory和WriteProcessMemory。
一般来说: 在自己的流程中搜索字符串的最佳方法是什么?
提前致谢。
答案 0 :(得分:1)
引用任意指针值(地址)是未定义的行为,因平台和操作系统而异。
崩溃是许多未定义的行为之一。
答案 1 :(得分:1)
虽然标签中没有提到它,但基于ReadProcessMemory
的提及,我假设你想要这个用于Windows。
要在Windows中执行此操作,您几乎需要使用VirtualQuery
来确定地址空间的哪些部分可用(在64位系统上尤为重要,因为有效地址比32-更稀疏比特系统)。
使用VirtualQuery查找可搜索块的代码可能如下所示:
#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <algorithm>
#include <iterator>
template <class InIter1, class InIter2, class OutIter>
void find_all(InIter1 buf_begin, InIter1 buf_end, InIter2 pat_begin, InIter2 pat_end, OutIter output) {
for (auto pos = buf_begin;
buf_end != (pos = std::search(pos, buf_end, pat_begin, pat_end));
++pos)
{
*output++ = (void *)pos;
}
}
template <class outIter>
void find_locs(std::string const &pat, outIter output) {
unsigned char *p;
MEMORY_BASIC_INFORMATION info;
for ( p = nullptr;
VirtualQuery(p, &info, sizeof(info)) == sizeof(info);
p += info.RegionSize )
{
if (info.State == MEM_COMMIT &&
(info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
{
find_all(p, p + info.RegionSize, pat.begin(), pat.end(), output);
}
}
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <pattern>", argv[0]);
return 1;
}
find_locs(argv[1], std::ostream_iterator<void *>(std::cout, "\n"));
}
预计会出现一些“虚假”的比赛。特别是,即使您搜索的字符串没有出现在进程内存空间的任何其他位置,也会有一个副本作为argv
的一部分,并且(至少)一个副本用于临时{{1}那传递给std::string
,所以对于你可能传递的任何字符串,至少要有两个匹配。
您可能还想阅读find_locs
的文档。我选择了一个块的子集(我很确定)可以安全地读取(即那些已提交并映射或私有的块),但根据您要查找的内容,您可能希望将其更改为将其限制为仅通过程序文本而不是文本和数据进行搜索。