【问题标题】:Adding memory allocation and memset after a prior call to string::find causes it to return npos. Why?在之前调用 string::find 之后添加内存分配和 memset 会导致它返回 npos。为什么?
【发布时间】:2018-09-18 17:17:47
【问题描述】:

我正在对一款名为 Monster Hunter World 的游戏进行逆向工程,以添加更好的鼠标处理子程序,但我的软件中弹出了一个非常奇怪的错误。我不知道究竟是什么原因造成的,但我可以解释一些症状,我强烈怀疑内存损坏。

当我在包含 MonsterHunterWorld.exe 的整个二进制文件的字符串上使用 string::find 来查找保护机制的字节模式时,就会出现问题,该机制会校验文件并在检测到任何修改时故意使程序崩溃。在最近对我的代码进行更改之前,我的软件能够成功找到这些字节模式,对我的代码进行以下更改会导致 string::find 函数失败:

char buffer2[5000];
memset(buffer2, 0, sizeof(buffer2));

这是在调用 find 函数之后。如果我从程序中删除它,它会按预期工作(对 string::find 的调用正确地找到了我搜索的字节模式)。

作为参考程序的整个源代码可以在这个粘贴bin中找到- https://pastebin.com/7ExgmXNZ

我检查的另一件事是我决定在 x64dbg 中打开软件,我发现我用 string::find 搜索的模式实际上在它正在搜索的字符串中,但由于某种原因它还是失败了。

源代码使用64位MingW 8.1.0版本编译

编辑:将 pastebin 更改为重现问题所需的最少代码

更新:我能够为我的特定程序解决问题,但我不满意,因为我不完全理解解决方案为何有效。在我作为str 参数提供给string::find 的char 数组的末尾,我手动添加了一个以0x00 结尾的空值。 AFAIK char 数组初始化如下:

char foo[] = {0x68, 0x69}; //"hi"

应该自动添加空终止符吗?如果这是不正确的,请有人纠正我,因为这是我的一个非常严重的错误,这意味着程序之前工作的唯一原因是运气不好,与我的 char 数组相邻的内存恰好是 0x00。

【问题讨论】:

  • std::string 完全支持二进制数据,只有当您尝试将数据用作 c 字符串时才会产生混淆。
  • 请提取minimal reproducible example。也就是说,使用向量而不是字符串来包含原始字节会更好,尽管字符串也可以工作(在有限的范围内)。
  • 如果您现在有一个minimal reproducible example,它应该足够小,可以直接包含在问题中,按照 SO 规则的要求。 How to Ask。指向完整项目的链接有时对想要查看上下文的人很有用,但 MCVE 必须在问题中,而不仅仅是链接到。
  • @Peter 也许我错过了,但我在您的链接中没有看到任何地方指定代码必须足够小才能直接包含在问题本身中,以符合最小、完整和可验证的条件。您能否指出明确指出这一点的摘录?
  • How to Ask帮助他人重现问题 部分说您的代码必须在您的问题中,而不仅仅是链接到。它提醒您需要将其归结为 minimal 示例,包括使其失败的输入。鉴于 SO 问题和答案的字符数限制为 30k,如果您的代码不适合问题,那么对于任何理性的人来说,它都太大了,不会认为它是最小的。即使在 BF 或 Brain-Flack 之类的编程语言中(esolangs.org/wiki/Brain-Flak 需要大量字符来做一些简单的事情),30k 字符也是巨大的

标签: c++ x86-64


【解决方案1】:

事实证明,这是因为 string::find(const CharT* str, size_type pos = 0 ); 期望 str 参数有一个空终止符,我认为我的 char 数组会自动给出一个。

情况并非如此,它之前工作的原因完全是由于运气相邻内存为0x00,现在我更改了代码相邻内存更改为0x40并导致string::find搜索错误的字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 2023-03-13
    • 2012-05-09
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    相关资源
    最近更新 更多