Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net Reflector如何反编译代码?_.net_Cil_Reflection.emit_Il_Reflector - Fatal编程技术网

.net Reflector如何反编译代码?

.net Reflector如何反编译代码?,.net,cil,reflection.emit,il,reflector,.net,Cil,Reflection.emit,Il,Reflector,像RedGate Ant Profiler或Reflector这样的工具如何将IL转换为C或VB.NET代码 我最近注意到红门Ant分析器生成的源代码与最初编写的源代码不同 它生成了一个while循环,我在其中使用了foreach 这让我思考。我在Reflector中打开了Reflector.exe本身,但它们的代码大部分都没有被混淆。在一般工作中,通过查看IL并构造语义上与IL等价的源代码来反编译程序。这并不总是能产生原始的源代码,因为IL会丢失一些高级信息,尽管没有机器代码那么多,而且通常会

像RedGate Ant Profiler或Reflector这样的工具如何将IL转换为C或VB.NET代码

我最近注意到红门Ant分析器生成的源代码与最初编写的源代码不同

它生成了一个while循环,我在其中使用了foreach


这让我思考。我在Reflector中打开了Reflector.exe本身,但它们的代码大部分都没有被混淆。

在一般工作中,通过查看IL并构造语义上与IL等价的源代码来反编译程序。这并不总是能产生原始的源代码,因为IL会丢失一些高级信息,尽管没有机器代码那么多,而且通常会有几段代码编译成同一个IL。例如,foreach循环相当于某种while循环,它首先设置枚举器,然后循环直到枚举器耗尽,并在每一步提升枚举器。

反编译器通常通过查看IL并构造语义上与IL等价的源代码来工作。这并不总是能产生原始的源代码,因为IL会丢失一些高级信息,尽管没有机器代码那么多,而且通常会有几段代码编译成同一个IL。例如,foreach循环相当于某种while循环,它首先设置枚举数,然后循环直到枚举数用尽,并在每一步提升枚举数。

实现反编译的常用技术是使用称为区间分析的方法来识别循环的范围

当与习语识别和被称为派生图序列的模式相结合时,可以从包含汇编语言或MSIL的控制流图开始,迭代地简化它,直到有一个表示程序或方法的源代码级视图的AST抽象语法树节点为止。给定AST,那么生成源代码就很简单了:只需漂亮地打印生成的AST

以下是指向更多信息的链接:

通常,原始源代码和反编译源代码之间永远不会有完全的保真度

foreach循环的控制流图与while循环的控制流图类似。这主要是因为以下代码:

foreach (var x in xs) {
    //body
}
实际上是语法糖:

var enumerator = xs.GetEnumerator()
try {
    while (enumerator.MoveNext()) {
        var x = xs.Current;
        //body
    }
}
finally {
    enumerator.dispose();
}
也就是说,foreach循环基本上被转换成while循环,然后while循环被编译成MSIL

为了让反编译器生成for-each循环,它必须添加特殊的支持,以尝试猜测while循环何时实际上是foreach循环。任何这样的逻辑都不是完美的,上述while循环和foreach循环都应该产生相同或非常相似的MSIL代码

在某些情况下,它会与您编写的源代码匹配,而在其他情况下则不会匹配

很可能你已经为每个循环编写了一个代码,所以从可用性的角度来看,在for-each循环和while循环这两个方面犯错是一个不错的选择

然而,这是额外的工作。反编译器的作者必须开始说,我想添加一些试探法来尝试检测每个循环

最后,有很多事情会阻碍反编译。例如,break和continue语句的存在确实会使事情复杂化。switch语句内部的某些嵌套循环也是如此,反之亦然。它们都会导致CFG循环具有多个入口点和多个出口点。这增加了生成可读源代码的难度

通常处理这些情况的唯一方法是使用启发式。这些启发法有时会做错事

此外,即使是很小的事情,比如用于循环边界的特定表达式,也会破坏习惯用法识别。有时编译器会引入源代码中不存在的临时变量。这可能需要额外的习惯用法检查,或者需要更高级的技术,如数据流分析、活变量分析、定义使用链等


总之:反编译很难,而且永远不会完美。而且,我相信实施者必须考虑权衡。例如,投资于检测每个循环是否有意义,还是应该花时间反编译lambda和推断LINQ查询?

实现反编译的一种常见技术是使用称为区间分析的方法来识别循环的范围

当与习语识别和被称为派生图序列的模式相结合时,可以从包含汇编语言或MSIL的控制流图开始,迭代地简化它,直到有一个表示程序或方法的源代码级视图的AST抽象语法树节点为止。给定AST,那么生成源代码就很简单了:只需漂亮地打印生成的AST

这里有一些链接到 更多信息:

通常,原始源代码和反编译源代码之间永远不会有完全的保真度

foreach循环的控制流图与while循环的控制流图类似。这主要是因为以下代码:

foreach (var x in xs) {
    //body
}
实际上是语法糖:

var enumerator = xs.GetEnumerator()
try {
    while (enumerator.MoveNext()) {
        var x = xs.Current;
        //body
    }
}
finally {
    enumerator.dispose();
}
也就是说,foreach循环基本上被转换成while循环,然后while循环被编译成MSIL

为了让反编译器生成for-each循环,它必须添加特殊的支持,以尝试猜测while循环何时实际上是foreach循环。任何这样的逻辑都不是完美的,上述while循环和foreach循环都应该产生相同或非常相似的MSIL代码

在某些情况下,它会与您编写的源代码匹配,而在其他情况下则不会匹配

很可能你已经为每个循环编写了一个代码,所以从可用性的角度来看,在for-each循环和while循环这两个方面犯错是一个不错的选择

然而,这是额外的工作。反编译器的作者必须开始说,我想添加一些试探法来尝试检测每个循环

最后,有很多事情会阻碍反编译。例如,break和continue语句的存在确实会使事情复杂化。switch语句内部的某些嵌套循环也是如此,反之亦然。它们都会导致CFG循环具有多个入口点和多个出口点。这增加了生成可读源代码的难度

通常处理这些情况的唯一方法是使用启发式。这些启发法有时会做错事

此外,即使是很小的事情,比如用于循环边界的特定表达式,也会破坏习惯用法识别。有时编译器会引入源代码中不存在的临时变量。这可能需要额外的习惯用法检查,或者需要更高级的技术,如数据流分析、活变量分析、定义使用链等


总之:反编译很难,而且永远不会完美。而且,我相信实施者必须考虑权衡。例如,投资于检测每个循环是否有意义,还是应该花时间对lambdas进行反编译并推断LINQ查询?

以满足您的好奇心,这是开源的谢谢,Steve。我的待办事项清单上有它,还有许多其他的事情,包括ILSpy和dotPeek的源代码。下面是我找到的一张清单:为了满足你的好奇心,这里有而且是开源的谢谢,史蒂夫。我的待办事项清单上有它,还有许多其他的事情,包括ILSpy和dotPeek的源代码。以下是我找到的一个列表: