C# - 相同的代码块,但更新后 IL 指令发生了变化。如何修改更复杂的更新?

逆向工程 C#
2021-06-22 20:48:01

背景信息 - 对于游戏 7 Days To Die,有一个实现 Harmony API 的 C# 包装器,它允许我们拦截游戏的函数调用,以及更改 IL 指令本身。

我最初使用 Transpiler 功能来删除两个检查中使用的条件。这很容易,因为我只需要删除三个指令。这是显示它们的屏幕截图:

左边是旧代码,很容易修改。我只需要删除索引798081处的指令它改变了 C# 代码:

this.cmds[1].enabled = (_world.IsEditor() && flag);

到:

this.cmds[1].enabled = (flag);

哪个工作得很好。但是,DLL 已在更新中更改。C# 代码完全相同,但 IL 指令在最后一次条件检查时有所不同。我无法完全理解它。

原来很容易。IL 79为下一个函数调用准备一些东西,IL 80进行调用,IL 81如果返回 false ,则跳过接下来的几条指令。在 ASM 中,这三个指令基本上是pop(通过指针调用类的函数)、cmp(检查布尔结果)和jz(如果为假则跳转)。

但是右侧更新的 IL 说明对我来说没有任何意义。没有分支,没有跳跃。我如何使用它来消除_world.IsEditor()条件?

编辑:C# 函数的 Pastebin

1个回答

看起来之前的代码已经完成了优化,因此如果左侧的值被评估为false右侧的值,则在&&操作中根本不会评估,因为它永远不会产生true任何结果并且false可以直接使用。

目前没有这样的代码,但您可以清楚地看到and正在完成的工作,前面是ldloc.0. 这个函数的开头缺少一个代码,但是如果索引 0 处的局部变量是你的,flag你可以删除这两条指令(第 81 行和第 82 行)。从代码来看,堆栈上应该已经有了 a1以便存储值的指令stfld可以工作。如果没有,您可以添加一个ldc.i4.1而不是您删除的那两个。