我知道这个问题的任何答案都可能非常棘手。我完全支持这一点,我喜欢突破一些界限,看看有什么可能,并一路学习。
我想编写一个程序来操纵已知的 exe 来更改其中的字符串。我目前有一个非常简单的 C# 程序,即已知的 exe:
using System;
namespace Target {
class Program {
public static String str = "TESTSTRING";
static void Main(string[] args) {
Console.WriteLine(str);
}
}
}
Run Code Online (Sandbox Code Playgroud)
编译后,在十六进制编辑器中,我看到字符串的第一个字母位于字节 1898 处。它似乎是从那里存储在 Unicode 中的。

一些编译器优化将字符串直接放入调用中Console.WriteLine,并且似乎正在调用一些构造函数(至少我认为是这样.cctor)。我尝试过其他相同长度的字符串,以确保我知道所有的东西是什么。我编写了一个应用程序,可以成功替换TESTSTRING为XXXXXXXXXX(请注意,它们的长度相同)并运行修改后的exe。效果很好。
但是,如果我尝试用不同长度的字符串替换该字符串,则输出 exe 将无法运行。我发现字符串之前的字节似乎包含长度。它似乎是unicode字符串的字节数+1(我不知道+1是做什么用的,也许是一个空终止符?)。但是,如果我用适当的更新值替换该长度,它仍然无法运行。字符串末尾后似乎有几个字节对于不同长度的字符串是不同的。我的猜测是,构造函数类似于,new String(...)并且那些其他字节是构造函数的其他参数(第一个参数是 achar[]或byte[]前面带有它的长度),但我无法解释其他参数是什么具体是。
我知道我正在破坏通常不会发生的事情,但我很好奇这种可能性。关于 .Net exe 的结构,我有什么不知道的地方,而知道了它就可以让我做到这一点?将已编译的 EXE 中的一个字符串替换为另一个不同长度的字符串?另外,如何解释长度超过 127 的字符串?任何超过此长度的值都会影响存储字符串长度所需的字节数。
我希望能够使用任意替换字符串来完成此操作。因此,预编译特定字符串,然后仅使用该预编译字符串及其元数据修补 exe 是不可行的。我应该能够在没有反编译器/编译器的情况下做到这一点。我绝对想以编程方式执行此操作,因此 Reflector 不是一个选项。这可以可靠地完成吗?
您可以使用ildasm来做到这一点。它不是反编译器,而是反汇编器。它将生成一个 MSIL 文本输出,您可以更改然后使用ilasm重新编译。
编辑:我怎么会忘记?您应该对Mono.Cecil非常感兴趣。
一些备注:
.cctor是类构造函数(也称为静态构造函数)的缩写,而不是实例构造函数。