为什么难以反汇编本机Win32,但很容易拆解.NET应用程序?

Sec*_*ret 11 .net c# c++ winapi native

为什么拆分原生Win32图像(例如用C/C++构建)的里程比拆卸.NET应用程序更困难?

主要原因是什么?因为什么?

Ste*_*eve 16

.net程序集内置于Common Intermediate Language中.在CLR将其编译为在适当的系统上运行时,它将被编译,直到它即将被执行.CIL具有大量元数据,因此可以将其编译到不同的处理器体系结构和不同的操作系统上(在Linux上,使用Mono).类和方法基本保持不变.

.net还允许反射,这需要将元数据存储在二进制文件中.

编译时,C和C++代码将编译为选定的处理器体系结构和系统.为Windows编译的可执行文件在Linux上不起作用,反之亦然.C或C++编译器的输出是汇编指令.源代码中的函数可能不作为二进制函数存在,而是以某种方式进行优化.编译器还可以拥有相当激进的优化器,它们将采用逻辑结构化代码并使其看起来非常不同.代码将更有效(在时间或空间上),但可能使其更难以逆转.


Jes*_*mos 14

由于.NET的实现允许通过CLI和CLR在C#,VB甚至C/C++等语言之间实现互操作,这意味着必须将额外的元数据放入目标文件中以正确传输类和对象属性.这使得更容易反汇编,因为二进制对象仍然包含该信息,而C/C++可以抛弃该信息,因为它不是必需的(至少对于代码的执行,当然在编译时仍需要信息).

此信息通常仅限于与类相关的字段和对象.在堆栈上分配的变量可能在发布版本中没有注释,因为互操作性不需要它们的信息.


Ale*_*kov 6

另一个原因 - 大多数C++编译器在生成最终二进制文件时执行的优化不会在IL级别上针对托管代码执行.

因此,与IL中有意义的名称的函数调用相比,像容器上的迭代看起来像本机代码的耦合inc/ jnc汇编指令.由于JIT编译器将内联一些类似于本机编译器的调用,因此生成的执行代码可能相同(或至少接近),但在CLR版本中,可以看到的代码更具可读性.