我知道对于这个问题,任何答案都可能非常“hacky”(指粗糙的、不规范的技术手段)。但我非常支持尝试这些方法,因为它们可以拓展我们的技术边界,让我们能够在实践中学习。
我的目标是编写一个程序,可以操作一个已知的.exe文件,并修改其中的一个字符串。我目前有一个非常简单的C#程序,就是这个已知的.exe文件:
using System;
namespace Target {
class Program {
public static String str = "TESTSTRING";
static void Main(string[] args) {
Console.WriteLine(str);
}
}
}
编译后,在十六进制编辑器中,我发现该字符串的第一个字母位于第1898个字节处。从那里开始,它似乎以Unicode方式存储。
一些编译器优化直接将字符串放在Console.WriteLine调用中,并且似乎调用了某个构造函数(至少我认为.cctor是这样的)。我玩弄了一些同样长度的其他字符串,以确保我知道每件事情都是什么。我编写了一个应用程序,成功地将TESTSTRING替换为XXXXXXXXXX(请注意它们的长度相同),并运行修改后的exe。效果很好。
但是,如果我尝试使用不同长度的字符串替换该字符串,则输出的exe无法运行。我发现字符串之前的字节似乎包含长度。它似乎是unicode字符串的字节数+1(我不知道+1是什么,也许是空终止符?)。然而,如果我用正确的更新值替换该长度,它仍然无法运行。在字符串结尾后面似乎有几个不同长度的字节。我的猜测是构造函数类似于new String(...),而那些其他字节是构造函数的其他参数(第一个参数是char[]或byte[],其前面跟着它的长度),但我无法解释其他参数具体是什么。
我知道我正在打破通常不会碰的东西,但我对可能性很感兴趣。我不知道.NET exe的结构,如果知道将使我能够做到这一点?用一个不同长度的字符串替换已编译的EXE中的一个字符串?还要如何处理长度超过127的字符串?任何长度超过127的字符串都会影响存储字符串长度所需的字节数。
我希望能够使用任意替换字符串来做到这一点。因此,预编译特定字符串,然后仅使用该预编译字符串及其元数据修补exe不是选项。我应该能够在没有反编译器/编译器的情况下完成此操作。我肯定想以编程方式完成此操作,因此Reflector不是选项。这可以可靠地完成吗?