【问题标题】:Compiling C# to Native?将 C# 编译为本机?
【发布时间】:2009-12-17 13:03:47
【问题描述】:

我想我对将 .NET 字节码编译为本机代码感到有些困惑,或者我对最终结果感到困惑。因此,请耐心等待我尝试整理我认为我理解的内容,以便您帮助我弄清楚我缺少什么。

我想做的是将我用 C# 编写的应用程序编译成常规的本机代码,就像我用 C 编写的那样。我的推理与性能无关,而是带有某种程度的保护。我知道我的最终目标并非不可能(甚至真的那么难以规避),但我只是觉得逆转 x86 组装比逆转 Reflector 给我的东西更困难。

现在,如果我将我的 C# 应用程序放入 Reflector,我基本上可以取回我的源代码。通常,当我将我的非托管 C/C++ 应用程序放入 IDAPro 并使用 HexRays 反编译器时,我不会得到相同程度的反编译,我不得不求助于 x86 反汇编来理解逻辑流程。据我了解,如此出色的反编译来自 Reflector,因为应用程序位于 MSIL 中,而不是 HexRays 尝试反编译的更简洁的本机代码。

我不担心仍然需要 .NET 运行时的客户端机器,我并没有试图规避这些。我想在我的程序上运行像 upx 这样的普通软件混淆程序,但将其作为 .NET 二进制文件执行失败。

我从this 相关问题中了解到ngen 做了我想做的事。我试过使用ngen。但是在将输出文件从C:\Windows\assemblies\...\applicationName.ni.exe 目录复制到某个我可以双击的地方后,尝试运行它会产生一个错误,表明它不是“有效的 Win32 应用程序”。此外,当我将applicationName.ni.exe 扔进Reflector 时,我得到的输出与我从applicationName.exe 得到的输出相同。由于applicationName.ni.exe 应该是本机代码,我预计 Reflector 会出错,但事实并非如此。如果这是我应该这样做的方式,为什么 Reflector 仍然给我这么好的反编译?

所以,再次总结一下我的主要问题:如何将我的 .NET 程序编译成 Reflector 不容易反编译的本机二进制文件?或者有哪些最佳实践可以保护用 .NET 语言编写的产品免受新手逆向工程师的攻击?

如果我需要不同的工具,我更喜欢免费的,而不是像 Codewall 这样的工具。

谢谢!

更新:我知道我正在寻找的内容可能会限制语言的某些功能,例如反射,但我认为我可以接受。我的代码都没有做任何明确的Assembly.Load 调用或任何类似的调用。但是这些就不能用GetProcAddress/LoadLibrary 电话代替吗?

【问题讨论】:

  • 在代码保护器/障碍物上,如果您不是一家软件开发公司,它们中的大多数都是商业的,而且价格适中,但是即使是顶级的商业公司也可能会遇到很多问题,您的代码实际上在它完成后就可以正常工作是的。
  • 我需要一个类似的功能,也是出于安全原因。我的 C# 应用程序需要解密一个单独分发给每个用户的配置文件(每个文件都不同)。问题当然是解密的代码和算法需要在 C# 中,如果可以如此轻松地重新创建,这是有风险的。我很难找到替代解决方案。

标签: c# .net compiler-construction native


【解决方案1】:

ngen.exe 不是这样工作的。它只是预先运行 JIT 编译器来生成 .ni.exe 或 .ni.dll 模块。该二进制文件不包含元数据,仅包含从 IL 为方法体生成的机器代码。 CLR 仍然必须找到原始程序集。只有这样,它才能确定存在可用的 ngen-ed 图像,以便它可以使用其中的机器代码,而不是从程序集的 IL 生成它。

Ngen.exe 加快了应用的热启动时间,仅此而已。

对于任何可能有兴趣拆卸我的程序集的人,我通常的建议是将它们指向 sourceforge.net。它有 TB 的源代码,由通常比我更好的程序员编写和维护。有时即使有好的cmets。如果你的混淆器不能很好地工作,那就到处找一个更好的。有很多。

【讨论】:

  • 谢谢!这正是我正在寻找的关于ngen 正在做什么的解释。您对一个好的、免费的混淆器有什么建议吗?
  • 我只知道好的免费反汇编程序。反汇编程序必须是免费的,要钱就违背了使用反汇编程序的目的。好的混淆器要花钱。 Visual Studio 附带一个 Dotfuscator。我从未听说过有一家公司销售基于受 Dotfuscator 保护的破解源代码的产品。这表明它运作良好。
【解决方案2】:

我刚刚在 VS2015Windows 8.1验证 .Net Native(正确配置后,检查 .proj验证)并为特定架构构建(可能是矫枉过正,尚未验证),将生成一个本机文件,该文件将为您提供您正在寻找的“更难逆向工程”代码我无法通过 DotPeek(来自 JetBrains 的免费 .Net 反编译器)读取 .dll

【讨论】:

  • 太棒了!六年后,我的梦想终于实现了。 ;)
  • 请注意,这适用于 Windows 10 通用应用程序,而不是 WPF 或 WinForms。即,Windows 8.1 及更高版本。
  • @EricEskildsen,所以你不能为 WPF/WinForms 编译为本机?
  • @jj_ 使用 .NET Native?从来没听说过。也就是说,今天可能还有其他方法可以将 WPF/WinForms 编译为本机——我已经有一段时间没有检查那个空间了。
  • @EricEskildsen 是的,Delphi 就是其中之一(及其对应的开源项目 Lazarus)。
【解决方案3】:

昨天,在Build 2014,微软宣布了.NET Native。根据FAQ 的说法,“......最初,我们专注于使用 .NET Native 的 Windows 应用商店应用程序。从长远来看,我们将继续改进所有 .NET 应用程序的原生编译。”

【讨论】:

  • 但是如何在VS2013中使用呢?我没有 VS2015 许可证,所以我想在 VS2013 中使用 .Net Native
  • @EldarZeynalov 也许你应该看看 VS2015 社区版?
【解决方案4】:

如果您想保护您的代码,混淆器是典型的方法。 Dotfuscator 与反射器进行了一段时间的军备竞赛,我们在产品上使用它。然而,在实践中,熟练的人可以轻松阅读混淆代码。

编译为本机代码违背了使用托管语言的目的。主要好处是允许目标运行时将 IL 即时化为最适合目标 CPU 的东西。如果您愿意,可以使用 ahead-of-time option in mono 之类的东西。

【讨论】:

  • Dotfuscator 不只是混淆变量名,使其更难阅读吗?而且我知道我不会收到运行时优化,我可以接受。我使用 C# 的主要目的是语言的语法和库的易用性和美观性,漂亮的优化排在第二位。
  • “编译为本机代码违背了拥有托管语言的目的”——这不是真的。
  • 托管 .NET 语言的一个特点是,它们可以可验证安全。将可验证安全的 IL 编译为本机代码不会失去此特定功能。此外,您所描述的 “主要好处” 在现实中甚至都不存在(甚至在您最初编写此答案之后的 5 年):虽然理论上可能,.NET 的 JIT 编译器非常保守,并且自其成立以来发生的唯一值得注意的优化是改进的代码吞吐量。尚未对发出的本机代码进行优化。
  • 也许拥有一种托管语言最终会破坏拥有机器代码的目的,即速度和能力——计算机本身存在的理由
【解决方案5】:

Spoon(以前的 Xenocode)有 a product that might fit your needs。我们将它用于基于 WPF 的安装程序 UI,因此我们不必引导 .net 来加载安装程序本身。

【讨论】:

  • 这看起来棒极了,它只是比我想要的贵一点,因为我只是一个单独的开发人员,而不是为公司做这件事。
  • 确实价格有点高。不过效果很好。不确定是否有任何开源或其他替代方案。另一个缺点是它会导致非常大的可执行文件,但环境虚拟化非常流畅。
【解决方案6】:

其他答案提到了微软的.NET Native 编译器,但没有告诉你怎么做。

Here 是一个使用CoreRT 的教程,介绍如何将您的C# 项目编译为本机代码。

注意: 我还必须注释掉以下行才能正常工作:

<!-- <add key="helloworld" value="https://api.helloworld.org/v3/index.json" /> -->

输出是一个大致4MB 大小的可执行文件:

确实,使用.NET 反编译器和IDA Pro(本机代码反汇编程序)将无法再读取代码,并将其识别为本机代码。

【讨论】:

    【解决方案7】:

    NGEN 添加本机代码,但不会删除 MSIL。因此,在 MSIL 上运行的任何工具仍然可以工作。您还需要它来进行反射,这对于真正的本机编译器来说是非常困难的。

    【讨论】:

    • 我的代码都没有明确使用反射,没有它我也可以。除非对语言本身有一些限制,否则这可能吗?
    • 你知道,但假设的 C# 到原生编译器并不能真正假设它。
    【解决方案8】:

    这终于可以使用微软的 .NET Native 编译器实现了

    它会自动将使用托管代码(C# 或 Visual Basic)编写且面向 .NET Framework 和 Windows 10 的应用的发布版本编译为本机代码。

    ..

    •您的应用程序将提供本机代码的卓越性能。

    •您可以继续使用 C# 或 Visual Basic 进行编程。

    •您可以继续利用 .NET Framework 提供的资源,包括其类库、自动内存管理和垃圾收集以及异常处理。

    对于您的应用程序的用户,.NET Native 提供以下优势:

    •快速执行时间

    •始终如一的快速启动时间

    •低部署和更新成本

    •优化应用内存使用

    但 .NET Native 涉及的不仅仅是对本机代码的编译。它改变了 .NET Framework 应用程序的构建和执行方式。特别是:

    •在预编译期间,.NET Framework 的必需部分静态链接到您的应用程序中。这允许应用程序与 .NET Framework 的应用程序本地库一起运行,并且编译器可以执行全局分析以提供性能优势。因此,即使在 .NET Framework 更新后,应用程序的启动速度也始终如一。

    •.NET Native 运行时针对静态预编译进行了优化,因此能够提供卓越的性能。同时,它保留了开发人员认为非常高效的核心反射功能。

    •.NET Native 使用与 C++ 编译器相同的后端,针对静态预编译场景进行了优化。

    https://msdn.microsoft.com/en-us/library/dn584397(v=vs.110).aspx

    这仅适用于 VS.NET 2015。

    【讨论】:

      【解决方案9】:

      这是一个免费的混淆器,非常安静: eazfuscator

      【讨论】:

      • 免费使用 30 天。*
      【解决方案10】:

      我可能会退后一步,问您为什么要寻找这种类型的保护。我并不是要争辩说您不需要保护,但我认为值得了解其动机。

      例如,如果您需要保护,因为您的系统中有一种算法,如果有人对其进行逆向工程将对安全性造成破坏,那么您可能需要考虑另一种方法。这意味着算法中存在缺陷,再多的混淆或原生编译都无济于事。

      如果是 IP 问题,那么我认为混淆可能是您最好的方法。这有点像在你的门上放一把锁。有人可以打破锁并进入,但他们是故意这样做的,而不是仅仅走进门。

      【讨论】:

      • 哦不,我的算法没有做任何花哨的事情。它介于学术好奇心和知识产权问题之间。我认为一个不错的(但免费的)混淆器可能适合我的 IP 问题,但我确实有一个我之前编写的自定义代码打包器,我也想在我的 .NET 应用程序上使用它。对混淆器有什么建议吗?
      【解决方案11】:

      使用 IL2CPU 编译器可以做到这一点。 IL2CPU 由制作 COSMOS(C# 开源托管操作系统)的同一个人开发,只能通过下载 cosmos 获得。 IL2CPU 产生可以通过 Nasm 编译的 ASM 文件(其他一些汇编器可能工作,但最好使用 nasm)。 IL2CPU 的唯一问题是它内置在 Cosmos 项目中,很难让它自己运行。

      【讨论】:

      • 这看起来像是基于csnative.codeplex.com 的 IL2C 的工作(该链接可能会随着 codeplex 关闭而很快消失)
      猜你喜欢
      • 2013-11-06
      • 1970-01-01
      • 2011-10-06
      • 1970-01-01
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多