.NET 调用和数据访问 IL 指令中的操作数字节结构?

逆向工程 艾达 视窗 恶意软件 。网
2021-06-16 18:36:44

我尝试使用谷歌搜索,但找不到任何解释内存访问指令(如 ldstr 和 call 指令)结构的好来源

例如根据经验,API/库调用指令的最后一个字节总是 0x0A(如果我错了,请告诉我),但为什么呢?调用操作数的4个字节的结构是什么?ldstr 指令的操作数呢?

因为它们与本机应用程序不同,它们不是原始偏移量,它们似乎是表中的偏移量,但我找不到任何详细解释这一点的帖子?

我发现的最好的事情是:

https://www.red-gate.com/simple-talk/blogs/anatomy-of-a-net-assembly-clr-metadata-1/

但它仍然不能解释很多事情

1个回答

API/库调用指令的最后一个字节总是 0x0A

这是因为调用需要将方法 (ref) 作为参数,并且方法在具有 id 的表中定义0x0A

有这样的调用字节280600000A让我们一一进行。

  • 0x28 - 是操作码“调用”的值,它需要一个操作数。
  • 操作码的其余部分是元数据令牌,所以基本上是应该调用哪个方法的信息

但为什么0x0A是最后呢?它应该被读作一个 little-endian,所以值应该是0x0A000006. 但是字节是什么?

来自维基百科

当 CIL 代码使用元数据时,它是通过元数据令牌来实现的。这是一个 32 位值,其中前 8 位标识适当的元数据表,其余 24 位给出表中元数据的索引。

所以第一个值是表 id - 正如我所提到的,成员 ref 表的 id 是 value 0x0A其余的是表中的索引(在我们的例子中0x6)。

更多关于桌子的信息?这些基本上是 .NET 元数据信息的一部分,当您在 ie dnSpy 中打开时可以看到这些信息

在此处输入图片说明

如您所见,0x0A被分配给了MemberRef(包含方法和字段引用)

ldstr 指令的操作数呢?

在这种情况下,指令具有以下结构72XXXX00700x70指示不同的流 - 即用户定义的字符串或#US. 其余的(再次解释为一个小结尾的 32 位 val)是表中的偏移量(以字节为单位)#US

一般来说,dnSpy 是一个很好的工具,可以像元数据表一样验证这些值。

链接的文章(以及整个系列是一个很好的资源)它确实解释了(我认为)结构,但可能是间接的 - 只需找到有关元数据令牌的信息。

我们可以从中推断出元数据令牌的整个结构。