混淆基于C语言的二进制文件以避免反编译

25

有没有方法可以混淆基于C的可执行文件或库以防止反编译?


7
编写意大利面条式代码 ;-) - jldupont
10
我不确定代码能否比自然编译的C语言更加晦涩。 - Matthew Ruston
2
编译后的C二进制文件并不总是可以反编译成它们编译时所使用的代码 - 反编译不能保证提供与编写应用程序时完全相同的源代码。内联函数、宏、编译器优化等都是在保存源文件后处理的。 - FrustratedWithFormsDesigner
1
软件破解者已经反向工程二进制文件多年了。我自己可以在脑海中相当准确地理解C二进制反汇编,尽管如果我一直使用cout和其他函数,即使在源代码调试器中,C++对我来说仍然太过恶心。这是在没有将其作为自己生命的终极目标进行练习的情况下。 - Arthur Kalliokoski
8
各位,请注意,他在询问如何混淆代码,而不是是否应该这样做。请先回答他的问题,然后再转换话题。 - joveha
显示剩余4条评论
13个回答

39

不行。你可以增加反编译的难度,但是不能完全防止它。我建议你停止浪费时间,专注于提供功能不断改进的出色产品。

这样人们就会愿意为其付费。

你的主要问题是使代码无法解密的唯一方法就是使其无法运行。任何可加载到计算机中的内容都可以被破解。那些出于兴趣、利润或声誉而进行反向工程的人通常非常擅长此事,并不会因为你的任何尝试而受到丝毫影响。

他们有许多工具可以更轻松地解密你的代码,而你所做的混淆则相对较难。最好说服广大用户购买你的软件,并将盗版视为一种可能将“窃贼”转变为真正用户的机会。

例如,找出他们为什么不为你的软件支付费用并尝试解决这个问题。你永远无法将所有人转化为用户,一些人只是为了好玩而盗版代码。

查看在techdirt上发布的有关CwF+RtB(与粉丝联系加上理由购买)系列文章。我发现其中提出的许多观点可能适用于软件行业。


4
反作弊软件需要使用邪恶手段来防止主动篡改,不一定需要使用反编译技巧(虽然它们也可能会被使用)。这些手段之所以邪恶,是因为它们会阻止你在自己的计算机上进行合法操作,尽管在未经信任的平台上操作时它们是必要的。 - Colin Newell
16
优秀的(我认为正确的)回答。但你没有回答他的问题。 - joveha
7
如果目标是防止反编译,可能并不是为了防止盗版。还有许多其他原因可以反编译某些东西:以逆向工程的方式了解其功能,或者发现安全漏洞。 我同意,这是一个知情的回复,但它并没有涉及问题的任何部分。 - cazlab
5
我之所以那样回答这个问题,和我会用“不要这样做!”来回答“如何使用冒泡排序对5000万节点的链表进行排序?”的问题是相同的。在 SO 上有许多类似的回答,建议使用更好的方法,或者根本没有方法,或者告诉你不要浪费时间。我需要明确一个事实:_没有_办法防止反编译。就像房子安全一样,你可以让入侵者难以进入,但是决心大的盗贼是无法阻挡的。在我看来,编译本身已足以阻止普通类型的人,不需要更多的措施。 - paxdiablo
2
@Lo'oris,那你也不锁前门吗?它可以被撬开,所以为什么要费心呢?事实是,OP可以花大约10美元购买一个打包产品,然后生成一个大多数人会放弃的二进制文件。他可以在5分钟内完成所有这些操作。锁可以防止盗窃。 - joveha
显示剩余15条评论

18

简单的方法:购买一个打包器/加密器/混淆器产品。有些用于游戏且价格昂贵,有些则不是。通过“剽窃保护”等关键词在Google上搜索。

快速的方法:使用UPX进行打包,然后在某个位置对头部信息进行混淆,以便仍然可以在内存中加载并正常运行,但upx实用程序会失败并显示错误(尝试版本字段)。如果upx实用程序失败,95%的人会放弃。

困难的方法:编写自己的打包器。

哦,我忘了:

真正简单的方法:就按原样发布。不要误解 - 无论你做什么,人们仍然可以反向工程你的代码。你投入的精力只限制了多少人能够反向工程它。


1
“能够”并不保证实际解决方案。虽然从这篇学术论文的角度来看,VM打包器可以被反向操作,但我仍然认为它足够强大,可以抵御普通人可以在网上找到的反汇编工具。 - lllllllllllll
快速的方式与UPX的许可证不兼容。理论上,它会强制你公开混淆程序的源代码。 - undefined

6

进行全面优化编译。


5
为什么要使用SDReyes?如果你不依赖于任何未定义行为,优化就不应该对你的程序产生任何影响... - Billy ONeal
1
@BillyONeal 一些更为激进的优化会以微妙但不符合标准的方式改变代码的含义。例如,改变浮点算术的计算顺序将改变舍入误差,从而改变结果,即使没有利用未定义的行为。 - cmaster - reinstate monica
@cMaster:标准并未定义浮点数的行为,因此依赖该顺序实际上是依赖于未定义的行为。 - Billy ONeal
1
@BillyONeal:对不起,我把C标准和IEEE 754-2008标准搞混了。该标准要求语言提供可重现性;而可重现性意味着由于舍入误差而定义评估顺序。正是在这个标准下,那些编译器优化才会与之冲突。然而,任何行为良好的浮点数单元都将提供IEEE 754数字和算术运算,编译器应努力将标准保证传递到语言层面。因此,从技术上讲,它是“实现”定义的行为,但我们应该能够期望符合IEEE 754标准。 - cmaster - reinstate monica
1
@cmaster:C语言不要求实现使用IEEE 754标准。事实上,许多常见的实现(例如x86)并没有遵循该标准。IEEE 754是处理器制造商的标准,而不是编程语言的标准。 - Billy ONeal

6

反编译(没有更多的跳转)以及混淆实践(流表)和理论(不可区分混淆)都是活跃的研究领域,因此没有解决方案 - 只有工具、技术和专业知识。如果您真的希望您的代码对反编译无懈可击,创建一个Web应用程序,并将敏感代码放在服务器端。但是,如果您坚持给某人提供二进制文件的模式,则必须明智地权衡您想要在安全性和性能之间做出的折衷。混淆是有代价的,而且仍然不完美。一些选项

  • 使用除UPX之外的打包工具(UPX已经预装在许多Linux发行版中)。性能损失很低,大多数人没有手动解包二进制文件进行静态分析的技能。但对于有经验的逆向工程师来说,解包的成本是微不足道的。
  • 了解Tigress,这是一个多样化的虚拟机/混淆器,具有丰富的C源到源混淆功能。为了获得更好的性能,请依赖支持转换、控制流平坦化、函数合并/分裂、文字编码等。
  • 如果您想要更高级别的保护,请查看Tigress的主要转换:虚拟化、JITing等,但我相当确定这些转换更昂贵,如果您使用这些转换,您的用户可能会注意到速度变慢。

不要因Barak等人关于黑盒混淆的不可能性的开创性工作而感到沮丧。他只证明了黑盒混淆器的不可能性,而不是许多实际和有价值的混淆。 (黑盒混淆是程序的内部工作完全不可理解)也不要因海盗而气馁。总有一些人会特意购买您的产品,如果它很好。


3
我认为,如果你在谈论已编译的二进制代码,你所能做的并不多(也许只能应用 UPX 或类似工具),但这没有太多意义,因为它可以被反向工程。
如果你想写新代码,请尝试使用自修改的 C 代码,这可能是重新设计你的应用程序最困难的方式。

请记住,花费时间在高度风险的混淆上会使您的产品在市场上变得不太受欢迎。 - David Thornley
5
你们一直在彼此告诉对方混淆代码是浪费时间,但这根本不是问题。楼主准确地提出了问题并得到了恰当的答案。 - alexkr

3
使用优化编译器编译C代码可以使恢复原始源代码或任何相似的内容变得不可能。这比现今流行的任何Java或.NET混淆器都更安全。如果您想使可执行文件更小并隐藏任何符号名称,请务必剥离它。但是请注意,这也使得调试(当应用程序崩溃时)几乎不可能。
即便如此,如果有人真的想黑掉您的软件,他将在汇编级别上进行操作,可能使用加载程序或其他诡计-无论您尝试什么来防止他。许多公司尝试过,但没有成功。像这样使用hack只会使最终用户感到沮丧,因为它们可能会使应用程序崩溃甚至崩溃Windows的内置调试器。
不要浪费时间思考混淆,而应该改善程序。

在调试时,请使用调试版本,当然,假设您不会遇到仅在发布构建中出现的错误,这在任何启用预处理器的语言(如C(++))中都很容易发生。 - Mr. Boy
应用一些优化后,汇编代码通常变得更易读,因为所有混淆的无操作指令都会首先被清除。然而,一些更高级的优化会使代码变得更加混淆(例如循环展开和内联)。要获得最可读的汇编代码,请使用“-Os”。 - cmaster - reinstate monica

2

要让它更难?好的。但请不要这样做。

要预防它?不行。任何运行您二进制文件的系统都需要软件来解密您想出的任何方案。他们将能够反编译它,然后看到您的模糊二进制文件如何被解释。


2
"

混淆的可执行文件"没有意义。硬件必须能够“理解”代码才能执行它,如果硬件可以理解它,那么逆向工程人员也可以理解它。你最多只能使其更加繁琐,但代价可能不小。

"

1
为什么要混淆代码,如果从中可以获得商业利益?说实话,假设商业代码已经足够优化和混淆,并且运行正常,那么最尴尬的事情发生了——出现了一个故障...你会陷入困境,因为生产二进制代码被混淆,很难调试故障所在的位置并且难以复制,它将永远卡在BUGS列表上...
例如,试图查找堆栈跟踪,你会失去更多的头发,然后试图弄清楚反汇编代码中到底发生了什么,无休止的意大利面条式循环。简而言之,不要这样做!
你最终会在尝试调试故障时浪费金钱...要么你必须成为一个出色的汇编专家,才能阅读内存转储并从混淆的代码中解决问题...不要放弃它,只需让你美丽的产品工作并销售...当然,有很多人有时间通过反向工程来破解代码...
打败这个问题的秘诀在于遵循原则 - 频繁发布,经常发布,随着频繁发布进行改进,这样最新和最棒的功能将比破解者拆解并开发出来的时间更加更新!看看Linux源代码,补丁不断涌现,然后发布...如果你记住这个原则,通过以比以前更快的速度发布新版本并增加更多功能,你就赢了!

3
这并不适用于这个问题。 - cazlab
1
@cazlab:我指出混淆和代码保护是浪费时间!! - t0mm13b
那么关于Android设备上的DRM呢?我的意思是,是否有可能访问某些应用程序获得访问权限的加密内容? - VSB

0

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