1

所以我的雇主有这个旧的 .NET / C# 程序需要重写并且源代码已经丢失。它是由一位前雇员开发的,但他们已经好几年没来过这里了。也许这是他们的疏忽,也可能不是——在这一点上,这并不重要。

无论如何,所以我试图弄清楚它的作用,这让我开始思考 .NET 反编译器的局限性。

尝试反编译 .NET 就像尝试使缩小的 js 文件可读一样?使用缩小的 js,您可以将代码缩进到一些预先确定的编码标准,并且您可以重命名变量以匹配为它们分配值的函数的名称,但您仍然会丢失很多信息。您将丢失实际的变量名称和开发人员所做的任何评论。

这是一个公平的类比吗?

似乎这就是我的情况,或者开发人员真的没有留下任何评论,他确实根据变量的类型而不是它们的应用程序命名了一半的变量(我猜这与系统匈牙利语一致) .

4

2 回答 2

2

注意:我所说的大部分内容都是基于 Java 的,但据我了解,CLR 的运行方式几乎相同。

基本上,它的工作方式是编译器将您的源代码转换为一种称为字节码的格式,然后可以由 VM 执行。通常,编译器不会费心优化它们生成的代码,因为无论如何它都会在运行时由 VM 进行优化。因此,如果代码是由标准编译器编译的并且没有经过混淆处理,那么字节码的翻译是非常直接且可预测的,这意味着您可以将其反编译成看起来合理的源代码。

但是,您仍然会丢失任何基本上是语法糖的东西。编译器将仅包含执行所需的内容。幸运的是,反射支持(如果启用了调试)意味着很多源代码级别的信息将保留在字节码中,可能是通过可选的元数据。但是即使使用反射也无法访问诸如空格和注释之类的内容,因此无法恢复它们。

与缩小 JS 的类比并不准确,但它仍然有用。对于 Javascript,源文件是 VM 的输入,因此没有可见的中间字节码阶段。缩小是优化器检查并重新格式化源代码的结果,但它仍然是源代码。另一方面,在这两种情况下,丢失的信息都是工具没有保存它的结果,因为它不需要执行。

如果文件被混淆了,那么所有这些都会消失。混淆器故意弄乱编译器引入的模式,并将删除所有可以选择的元数据。您通常仍然可以反编译混淆代码,但它会变得一团糟,并且不包含原始源的有用信息,例如格式和变量名。

于 2013-04-10T22:03:29.997 回答
1

反射不需要局部变量名称,因此它们被丢弃了。事实上,在字节码级别没有实际的局部变量,只有堆栈位置。评论也是如此——它们不会被保留。

您可以使用 MSIL 反汇编程序 (Ildasm.exe) 查看可执行文件中实际保留的内容。名称 strNN 等由反编译器生成,旨在帮助您恢复代码的逻辑。

于 2013-04-11T13:11:18.327 回答