混淆技术的效果如何?

31
一个不同的问题,即最佳.NET混淆工具/策略,问是否使用工具实现混淆容易。
我的问题是,混淆是否有效?在回复这个答案的评论中,有人说:“如果你担心源代码被盗...混淆对于真正的破解者来说几乎是微不足道的。”。
我看过Dotfuscator社区版的输出:它看起来对我来说已经混淆了!我不想维护那个!
我明白,简单地“破解”混淆软件可能相对容易:因为你只需要找到软件中实现你想要破解的任何内容的位置(通常是许可证保护),并添加一个跳转以跳过它。
如果担心不仅仅是由终端用户或“盗版者”而引起的破解问题,而是“源代码盗窃”的话,换句话说,如果您是软件供应商,担心的是其他供应商(潜在竞争对手)会逆向工程重构您的源代码,然后将其用于自己的产品中或添加到其自己的产品中……那么简单混淆对抗这种风险足够还是不足呢?

第一次编辑:

所涉及的代码大约有20万行,运行在最终用户的计算机上(是一个用户控件,而不是远程服务)。

如果混淆确实对于真正的破解者来说“几乎是微不足道的”,我想要一些关于为什么它无效(而不仅仅是它的无效程度)的见解。


第二次编辑:

我不担心有人会反向算法:更担心他们将算法的实际实现(即源代码)重新用于他们自己的产品。

考虑到20 KLOC需要几个月的时间来开发,解密所有内容需要更多还是更少的时间(几个月)?

为了“窃取”某些东西,是否有必要解密它:或者一个理智的竞争对手是否可以将其整体纳入其产品中,同时仍然模糊不清,并接受它作为维护噩梦,并希望它需要很少的维护? 如果这种情况是可能的,那么混淆的.Net代码是否比编译的机器代码更容易受到攻击?

大部分混淆“军备竞赛”主要是为了防止人们甚至“破解”某些东西(例如找到并删除实施许可证保护/执行的代码片段),而不是防止“源头盗窃”?


Robert,使用.Net(例如C#),你的源代码仍然在程序中(仅减去任何注释):在编译后的程序上运行http://www.red-gate.com/products/reflector/是很有启发性的。 - ChrisW
但这只显示类和函数(如果我没记错的话),而不是实现,尽管你仍然可以获取调用堆栈。 - Robert Gould
1
我可以在调试器中看到同样的步骤。而且使用调用图程序,你可以从x86汇编中获得相同类型的信息,Red-gate只是让它更漂亮。你无法使某些东西对机器来说不可读,因为那样它就无法运行。 - Robert Gould
重点是,你的算法真的那么独特吗?如果是,虽然我不想这样说,你应该像微软、Fmod或GIF的人一样申请专利。法律途径是保护这种东西的唯一方式。 - Robert Gould
使用本地调试器,您将看到未命名的机器地址,而不是符号。使用反编译器,您将看到源代码。使用混淆技术,您将看到混淆后的源代码。有人说混淆是“微不足道”的,另一个人说混淆使得编写代码比从头开始困难了一个数量级。 - ChrisW
显示剩余8条评论
9个回答

44
我已经在这里讨论了为什么我认为混淆不是有效的反破解保护手段:
保护 .NET 代码免受反向工程

然而,你的问题特别涉及源代码盗窃,这是一个有趣的话题。在Eldad Eilam的书《逆向工程的秘密》中,作者在前两章中讨论了源代码盗窃作为逆向工程的原因之一。

基本上,问题在于只有当你拥有一些与你的领域相关的非常特定、难以工程化的算法,从而使你比竞争对手更具优势时,你才有可能成为源代码盗窃的目标。这几乎是唯一一种情况,尝试逆向工程应用程序的一小部分才会具有成本效益。

因此,除非你有一些绝密算法不想让竞争对手知道,否则你不需要担心源代码盗窃。将任何大量源代码从应用程序中逆向工程的成本很快就会超过从头开始重新编写它的成本。

即使你确实有一些不想让他们拥有的算法,也没有太多办法阻止决心坚定、技术娴熟的人获取它(如果应用程序在他们的机器上执行)。

一些常见的反逆向措施包括:

  • 混淆 - 在保护源代码或防止其被破解方面并没有太大作用。但我们可能不希望让它变得完全容易,对吧?
  • 第三方打包工具 - Themida 是其中较好的一个。将可执行文件打包成加密的 win32 应用程序。如果应用程序是 .NET 应用程序,则可以防止反射。
  • 自定义加壳器 - 如果您有能力编写自己的加壳程序,则有时编写自己的加壳程序是有效的,因为破解场景中对于如何取消包装您的应用程序几乎没有任何信息。这可以阻止经验不足的逆向工程师。此教程提供了一些关于编写自己的加壳程序的好信息。
  • 将行业保密算法保存在用户计算机之外。作为远程服务执行它们,以便指令永远不会在本地执行。这是唯一“百分百”有效的保护方法。

然而,加壳程序是可以被取消加壳的,混淆也无法真正阻碍那些想要查看您的应用程序正在做什么的人。如果程序在用户计算机上运行,则它是易受攻击的。

最终,代码必须作为机器代码执行,通常是启动调试器,设置几个断点并在相关操作期间监视正在执行的指令,再花费一些时间研究这些数据。


你提到你用了几个月的时间编写了约20k行代码的应用程序。如果你采取了最基本的预防措施,反向工程那等效的20k行代码将需要花费近10倍的时间来还原成可用的源代码。

这就是为什么只有从您的应用程序中反转小型、行业特定算法才具有成本效益。其他任何东西都不值得这样做。

接下来是一个虚构的例子:假设我刚开发了一款全新的iTunes竞争应用程序,它有很多强项。 假设它需要几十万行代码和2年时间来开发。 我有一个关键功能,是一种基于您的音乐听觉品味提供音乐的新方法。

苹果(作为他们是海盗)得知这一点,决定非常喜欢你的音乐建议功能,所以他们决定反向它。然后他们会集中精力只研究那个算法,逆向工程师最终会想出一个可行的算法,根据相同的数据提供等效的建议。然后他们在自己的应用程序中实施该算法,称其为“Genius”,并赚取他们的下一个10万亿美元。

这就是源代码盗窃的过程。

没有人会坐在那里逆向所有100k LOC,以窃取您编译的应用程序的重要部分。这将是过于昂贵和时间-consuming。大约90%的时间,他们将逆向处理按钮按下或处理用户输入的无聊、非业界秘密的代码。相反,他们可以雇用自己的开发人员,以较少的资金从头开始重新编写大部分代码,并简单地反向关键算法,这些算法难以工程化并给您带来优势(例如音乐建议功能)。


1
@ChrisW,完全不是这样。源代码盗窃 != 破解。将一个应用程序反向至能够破解它的程度与从中反向一个重要的源代码块根本不一样。混淆也不是使得反向任何可观的应用程式部分变得困难的原因。 - mmcdole
...更多地是防止人们“破解”某些东西(例如找到并删除许可证),而不是防止“源代码盗窃”吗? - ChrisW
@ChrisW,如果我真的很担心的话,我会使用任何混淆器(Dotfuscator很好),并且我会使用第三方打包工具。由于您正在使用.NET,这具有防止人们在应用程序上使用反编译器的额外优势,并且解包可能会很麻烦。 - mmcdole
1
@Simucal,你完全没有暗示这一点,但我认为ChrisW可能会认为源代码可以从可执行文件中获取,而实际上不是这样。他似乎更关心他的代码行数而不是他的算法。因此,我认为他有一个误解,这使他无法正确理解问题。 - Robert Gould
这就是突然赞数增加的原因。 - displayName
显示剩余14条评论

10
混淆是一种安全性通过模糊的形式,虽然它提供了一定的保护,但显然安全性非常有限。
对于您所描述的目的,混淆肯定可以帮助,并且在许多情况下,它是足以防止代码盗窃的适当保护措施。但是,如果给予足够的时间和精力,肯定仍存在解密代码的风险。解密整个代码库将是事实上不可能的,但是如果感兴趣的人只想确定您如何执行某些特定部分的实现,则风险更高。
最终,只有您才能确定是否为您或您的业务值得冒这个风险。但是,在许多情况下,如果您希望将产品出售给客户以在其自己的环境中使用,则这是您唯一的选择。
关于“为什么无效”的问题-原因是黑客可以使用调试器来查看您的代码运行的位置,无论使用什么混淆技术都是如此。然后,他们可以使用此方法绕过您设置的任何保护机制,例如序列号或“电话回家”系统。
我认为该评论并没有真正涉及“代码盗窃”,即您的代码将被窃取并用于另一个项目中。因为他们使用了“黑客”一词,我认为他们谈论的是软件盗版方面的“盗窃”。黑客专门研究绕过保护机制;他们不感兴趣将您的源代码用于其他目的。

你说,“只要付出足够的时间和努力。” 你知道如何量化这个问题吗:需要多少时间和努力? - ChrisW
实际上,我认为你没有太多需要担心的。完全解密你的20k LOC项目可能需要数年时间;重新实现它会更快。你代码中真正新颖的部分可以申请专利,这将是除了你的混淆之外的另一种防御措施。 - wuputah
事实仍然存在,这就是混淆的目的;任何看到你的代码被混淆的人都不会费心去破解。这场“军备竞赛”要么是为了销售新产品(超越竞争对手),要么是为了尝试让破解者更难攻克。 - wuputah
相信“完全解密您的20k行代码项目可能需要数年时间;重新实现它会更快”这种说法会让人感到安心。你是否了解有关这一观点的任何证据?为什么你认为这是正确的呢? - ChrisW
我可以给你反证的证据,即使是配备了专门加密、价值数百万美元和硬件密钥的游戏主机,也会在几个月内(如果幸运的话)或者几天内(如果不幸的话)被破解。 - Robert Gould
罗伯特,我明确不是在询问“破解”许可证保护(即查找然后跳过小部分功能)。 - ChrisW

7
大多数人倾向于编写看起来混淆不清的代码,但这并没有阻止黑客,那么有什么区别呢?
编辑:
好的,现在是认真的时间。如果你真的想制作一个难以破解的东西,请了解一下多态编码(不要与多态性混淆)。制作自我变异的代码,这将是一件严重的痛苦,也会让他们猜测。

http://en.wikipedia.org/wiki/Polymorphic_code

最终,没有什么是无法进行逆向工程的。

2
非常滑稽,应该作为注释而不是答案。 - Kevin Loney
虽然我曾经遇到过使用混淆策略编写的代码存在严重问题,但是在那个混淆社区中有些人能够轻松地处理和反混淆这种混淆。 - displayName

6
你担心人们窃取你产品中使用的特定算法。无论你是公平艾萨克还是需要通过更多方式来区分自己,如果你解决了某些代码问题,而其他人苦思冥想几个小时都无法解决,那么你应该拥有计算机科学博士学位和/或专利来保护你的发明。99%的软件产品之所以成功或特别,并不是因为算法,而是因为它们的作者付出了艰苦努力,将众所周知且易于理解的概念组合成一个能够满足客户需求并以比雇佣他人重新完成相同工作更便宜的价格出售的产品。

没错。 "重活" 不是什么超级秘密算法,而是 20 KLOC 的经过精心设计和测试的源代码。如果每个人都能比我更容易地反向工程化它,那么我很难通过“以更便宜的价格出售”来与他们竞争。 - ChrisW
1
@ChrisW,没有人会反转你的“重活”,因为这并不特别!就像Rex所说的那样,他们只是会自己编写。唯一需要考虑源代码盗窃的情况是,如果你有某些复杂或新颖到其他人没有的特定算法。 - mmcdole
1
假设行动的合法性不重要,只有在自行编写比撤销更便宜时,他们才会编写代码。是否有证据表明混淆源代码比从头开始编写更昂贵? - ChrisW

3

从这个角度来看,你输入问题的WMD编辑器是由SO团队反向工程而来的,以修复一些错误并进行一些增强。该代码已经混淆。你永远不可能阻止聪明有动力的人黑客攻击你的代码,你所能做的最好的希望是让诚实的人保持诚实,并使其难以破解。


2
如果你曾经看过反汇编器的输出,你就会意识到为什么混淆永远不可能成功。

1

我倾向于认为,如果您想保护您的源代码,混淆实际上并不是非常有效的方法。对于该领域的真正专家(我指的不是软件专家或黑客,而是代码功能领域的专家),通常他或她不需要看代码,只需要查看如何对特殊输入、边缘案例等作出反应,就能得到实现复制或等效于受保护功能的代码的想法。因此,混淆对保护您的专业技能没有太大帮助。


我将尝试防止可维护实现(即源代码)的盗窃,而不是防止算法的逆向工程。 - ChrisW

1
如果您的代码中有必须绝对保护的IP,那么您应该将软件功能作为服务提供,在安全的远程服务器上进行。良好的混淆可以在一定程度上保护您,但这取决于破解所需的努力与拥有代码的“回报”之间的平衡。如果您想要阻止普通商业用户,则商业混淆器应该足够。

0

简短的回答是肯定和否定都有可能,这完全取决于你想要防范什么。 安全编程菜谱 的第12节在第653页上(这在Google图书预览中方便地不可用)发表了一些有趣的评论。 它将反篡改分类为四种类型:零日攻击(减缓攻击者的速度,使其需要很长时间才能完成他们想要的操作),保护专有算法以防止逆向工程,“因为我可以”攻击和我记不住第四种。 你必须问自己要防范什么,如果你真正关心个人查看你的源代码,那么混淆就有一定的价值。 仅使用它通常只会对试图干扰应用程序的人造成麻烦,并像任何好的安全措施一样,最好与其他反篡改技术结合使用。


我所说的是我试图防止的事情:竞争软件供应商窃取源代码,然后将其合并到他们自己的产品中。 - ChrisW
我的答案旨在广泛涵盖混淆作为一种通用的反篡改方法。 - Kevin Loney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接