编译后,操作.net exe中的字符串?

时间:2014-10-03 19:48:36

标签: .net executable

我知道对此的任何答案都可能非常黑客。我全力以赴,我喜欢一点点地去看看有什么可能并且一路上学习。

我想编写一个程序来操作已知的exe来改变其中的字符串。我目前有这个非常简单的C#程序,它是已知的exe:

using System;

namespace Target {
    class Program {

        public static String str = "TESTSTRING";

        static void Main(string[] args) {
            Console.WriteLine(str);
        }
    }
}

编译完成后,在十六进制编辑器中,我看到字符串的第一个字母是在字节1898处找到的。它似乎是从那里以Unicode格式存储的。

Hex editor screenshot showing string in compiled exe

一点编译器优化将字符串直接放在Console.WriteLine调用中,并且似乎在调用一些构造函数(至少我认为.cctor是这样)。我已经玩弄了同样长度的其他琴弦,以确保我知道一切都是什么。我已经编写了一个应用程序,可以用TESTSTRING成功替换XXXXXXXXXX(注意它们的长度相同)并运行修改过的exe。它很棒。

但是,如果我尝试用不同长度的字符串替换字符串,则输出exe是不可运行的。我发现字符串前面的字节似乎包含长度。它似乎是unicode字符串+ 1的字节数(我不知道+1是什么,可能是一个空终止符?)。但是,如果我用适当的更新值替换该长度,它仍然不会运行。在字符串结尾之后似乎有几个字节对于不同长度的字符串是不同的。我的猜测是构造函数与new String(...)类似,而其他字节是构造函数的其他参数(第一个参数是char[]byte[],其前面是它的长度),但我无法解释具体的其他参数。

我知道我打破的事情通常是孤立的,但我对这种可能性感到好奇。我不知道.Net exe的结构知道能让我做到这一点吗?要将已编译的EXE中的一个字符串替换为另一个不同长度的字符串?另外,如何计算长度超过127的字符串?任何比这更长的事情都会影响存储字符串长度所需的字节数。

我希望能够使用任意替换字符串执行此操作。因此,预编译一个特定的字符串,然后只用该预编译的字符串修补exe,它的元数据不是一个选项。我应该能够在没有反编译器/编译器的情况下做到这一点。我绝对想以编程方式执行此操作,因此Reflector不是一个选项。这可以可靠地完成吗?

1 个答案:

答案 0 :(得分:3)

您可以使用ildasm执行此操作。它不是反编译器,而是反汇编程序。它将生成一个MSIL文本输出,您可以更改,然后使用ilasm重新编译。

编辑:我怎么能忘记? Mono.Cecil应该是伟大感兴趣的。


一些评论:

  • .cctor类构造函数的缩写,也就是静态构造函数,而不是实例构造函数
  • 字符串的内部表示仍然以空值终止,这就是为什么在文件中看到长度为+的原因。这仅用于更容易的互操作性(P / Invoke)
  • 更改长度和偏移字节不起作用,因为我猜它会破坏存储偏移量的文件中的其他一些数据。您必须更新存储在exe中的每个偏移量才能使其正常工作。这可能意味着...拆解它。这就是ildasm的用途。