使用 dnlib 重写 .NET CLR 堆中的字符串

Rewriting string in .NET CLR heaps using dnlib

我需要在 .NET 文件中重写 #US 堆中的字符串。我决定使用看起来像一个功能强大的库的 dnlib 来操作 .NET 文件。不幸的是,它的文档不足。

我以通常的方式加载文件。 ModuleDefMD Load() 方法似乎是加载文件的唯一方法:

ModuleDefMD module = ModuleDefMD.Load("test.dll");

现在,dnlib 具有 Writer 命名空间,表明它应该用于写入 .NET 结构。它包含 USHeap class 看起来很有希望。

Writer 似乎需要创建它可以处理的元数据:

dnlib.DotNet.Writer.MetaData metadata = dnlib.DotNet.Writer.MetaData.Create(module, null, null, null);

在 USHeap class 中有 SetRawData() method with description "Overrides what value should be written to the heap"。其余的不清楚,让我们用它来写入 3 个原始任意字节。根据 CLI 标准,第一个有效偏移量是 1:

byte[] raw_data = { 0x61, 0x62, 0x63 };   // "abc"
uint offset = 1;   // the least valid offset in #US heap
metadata.USHeap.SetRawData(offset, raw_data);

dnlib Examples 显示如何写入文件:

module.Write("test-out.dll");

这段代码编译并运行没有错误。不幸的是,新文件与原始文件具有相同的#US 流内容。

我好像没弄明白 Writer 是怎么工作的。研究源代码并不容易,因为 dnlib 包含相当多的源文件和行。

dnlib documentation refers to ConfuserEx - 使用 dnlib 来操作文件的混淆器。但是,查看它的来源,它似乎根本没有操纵#US 堆。

在调用 module.Write() 之前,初始化编写器选项 class。将侦听器设置为您的编写器侦听器,然后将选项传递给 Write()。在某些编写器事件之后,您可以在元数据写入文件之前开始对其进行操作。然后,您可以将任意字符串添加到#US 堆或任何其他堆。

您可以查看一个示例:https://github.com/0xd4d/dnlib/blob/master/Examples/Example6.cs