【问题标题】:8 bytes of data being written to file by an empty method通过空方法写入文件的 8 字节数据
【发布时间】:2015-12-29 23:07:55
【问题描述】:

我一直在搞乱驻留在 dll 中的游戏的保存代码,并发现了一些有趣的东西。

我正在使用带有 Reflexil 的 ILSpy 来读取和更改 dll 的代码。

好的,我有以下 sn-p 代码(如 ILSpy 所示):

stream.Write(this.V.Count); //this is signed 4-byte integer, it equals 1 in this case (10 00 00 00)
using (List<StatModifier>.Enumerator enumerator = this.V.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        StatModifier current = enumerator.Current;
        current.Write(stream);
    }

}

在此之前有一些代码写入同一个 BinaryWriter,但我稍后会谈到,因为它与这个问题无关。

current.Write(stream); 是对该方法的调用:

public virtual void Write(BinaryWriter stream)
{
}

这是一个空方法(我使用 Reflexil 删除了它的内容)。只有其中的 IL 代码是这个单一命令(如 ILSpy 中所示):

     Offset  OpCode   Operand
>0   0       ret

接下来运行的代码(在方法调用之后)被 ret 命令缩短,因此它不会向二进制文件写入任何其他内容。然后游戏代码会正确关闭文件 (stream.Close();)。这与问题无关,但我知道你会问。如果有人要求,我可以添加之前和之后的代码,但我没有看到这样做的意义。

我测试的方式:

  1. 我用干净的游戏代码创建了一个保存文件,以便加载它。
  2. 我将它复制到另一个文件夹。
  3. 我修改了代码来测试它。
  4. 我把原来的复制回来了。
  5. 我已进入和退出游戏(执行此代码 - 将游戏保存到文件的代码)。
  6. 我用十六进制编辑器检查了文件。
  7. 重复 3-6。

这会加载保存文件,进入游戏,然后在退出时使用更改后的代码覆盖它。我知道这部分代码保存了游戏方面的哪一部分,并且我知道在我短暂的进入和退出会话期间它保持不变。这样,除了保存代码之外,一切都保持不变。

当我用这段代码启动游戏并让它运行时,它会创建这个二进制文件。该代码已被更改,因此大多数通常保存的数据都已删除,因此更容易查找更改:

74 74 70 00 18 05 00 00    00 9A 99 19 3F 00 00 00
00 00 00 00 00 00 00 80    3F 00 00 80 3F 00 00 80
3F 01 01 00 00 00 9A 99    19 3F 9A 99 19 3F 

二进制文件的第一部分是由我在开头省略的代码编写的,因为它跨越了几个类和方法调用,但我认为这里没有任何意义。这是重要的部分:

01 00 00 00 9A 99    19 3F 9A 99 19 3F

这是最后 12 个字节。前四个表示从第一个代码 sn-p (this.V.Count) 开始的有符号 4 字节整数。

最后八个是神秘的。我不知道他们是从哪里来的。于是又玩了一些。我把第一个 sn-p 改成这样:

stream.Write(this.V.Count); //this is signed 4-byte integer, it equals 1 in this case (10 00 00 00)
using (List<StatModifier>.Enumerator enumerator = this.V.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        StatModifier current = enumerator.Current;
    }

}

如您所见,current.Write(stream) 不再被调用。

当我再次运行游戏时,我得到了这个输出:

7C 74 70 00 18 05 00 00    00 9A 99 19 3F 00 00 00
00 00 00 00 00 00 00 80    3F 00 00 80 3F 00 00 80
3F 01 01 00 00 00

你有没有发现有什么遗漏?第一次运行的最后 8 个字节消失了。唯一的变化是删除了空方法调用。

当我查看完整的保存文件时,我第一次注意到这一点,试图在源代码中跟踪它的创建。我只是找不到那些 8 字节的来源,所以我最终修改了代码,删除了这个和那个,看看我错过了什么。事实证明我并没有错过任何东西。所以这也发生在完全干净的代码中。

如果有人真的感兴趣,我可以告诉他们这是关于哪款游戏,并将相关文件发送给他们,以便他们自己尝试。

那么,有人知道这些字节的来源吗?这怎么可能?

编辑由于不清楚而投票关闭的人: 我所问的究竟是在哪个宇宙中不清楚?

【问题讨论】:

  • 函数是虚函数,实际运行的实现是在从StatModifier派生的子类中,你看错了类。
  • 如何找到该课程?所有代码都一样吗?如何阅读?
  • 哦,我想我明白了。有一个从代码中读取的枚举(当查看加载代码时),其中包含 StatModifierOT、StatModifierMax 和一些类似的名称,这些名称都是具有覆盖(whatsitcall)字的写入方法的类。我敢打赌,如果我从正确的课程中阅读,一切都会再次变得有意义。将您的评论作为答案,它将被接受。

标签: c# byte binaryfiles cil binarywriter


【解决方案1】:

函数是虚函数,实际运行的实现是在从StatModifier派生的子类中,你看错了类

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 2016-11-04
    相关资源
    最近更新 更多