我一直在考虑如何保护我的C / C ++代码免于反汇编和逆向工程。通常我永远不会在我的代码中宽恕这种行为;但是,为了各种人的安全,我一直在努力的现行协议绝不能被检查或理解。
现在这对我来说是一个新主题,互联网对于防范逆向工程并不是真正足智多谋,而是描绘了关于如何进行逆向工程的大量信息 < / p>
到目前为止我想到的一些事情是:
编写我自己的启动例程(调试器更难绑定)
void startup();
int _start()
{
startup( );
exit (0)
}
void startup()
{
/* code here */
}
运行时检查调试器(如果检测到则强制退出)
功能蹦床
void trampoline(void (*fnptr)(), bool ping = false)
{
if(ping)
fnptr();
else
trampoline(fnptr, true);
}
无意义的分配和解除分配(堆栈变化很多)
我的意思是这些是我想到过的一些事情,但是在适当的时间范围内,它们都可以被代码分析师解决或者解决。我还有其他选择吗?
答案 0 :(得分:170)
但是在适当的时间范围内,它们都可以由代码分析师处理或解决。
如果你给人们一个他们能够运行的程序,那么他们也可以在给定足够时间的情况下对其进行逆向工程。这是计划的性质。只要二进制文件可供想要解密它的人使用,就无法阻止最终的逆向工程。毕竟,计算机必须能够解密才能运行它,而人类只是一台较慢的计算机。
答案 1 :(得分:146)
Amber所说的是完全正确的。您可以更加努力地进行逆向工程,但是您永远无法阻止它。你永远不应该相信"security" that relies on the prevention of reverse engineering。
也就是说,我所见过的最好的反逆向工程技术不是专注于混淆代码,而是打破人们通常用来理解代码如何工作的工具。找到创造性的方法来打破反汇编程序,调试程序等,可能比仅仅生成大量可怕的意大利面条代码更有效,也更具智力上的满足感。这对阻止一个坚定的攻击者没有任何作用,但它确实增加了J Random Cracker徘徊并更容易处理的可能性。
答案 2 :(得分:40)
Safe Net Sentinel(原阿拉丁)。虽然注意事项 - 他们的API很糟糕,文档很糟糕,而且与SDK工具相比,这两者都很棒。
我已经使用了他们的硬件保护方法(Sentinel HASP HL)多年。它需要专有的USB密钥卡,作为软件的“许可”。他们的SDK加密和混淆你的可执行文件&amp;库,允许您将应用程序中的不同功能绑定到密钥中的功能。如果没有由许可方提供和激活的USB密钥,则软件无法解密,因此无法运行。 Key甚至使用定制的USB通信协议(在我的知识范围之外,我不是设备驱动程序),使得构建虚拟密钥变得困难,或者篡改运行时包装器和密钥之间的通信。他们的SDK不是非常开发人员友好,并且将添加保护与自动构建过程集成非常痛苦(但可能)。
在我们实施HASP HL保护之前,已有7名已知的海盗从产品中删除了dotfuscator'保护'。我们在对软件进行重大更新的同时添加了HASP保护,该软件实时对视频进行了大量计算。从分析和基准测试中我可以看出,HASP HL保护只能将密集计算减慢约3%。由于该软件大约在5年前发布,因此没有发现该产品的新版盗版。它所保护的软件在其市场领域中有很高的需求,并且客户知道有几个竞争者正在积极尝试逆向工程(到目前为止没有成功)。我们知道他们已经尝试向俄罗斯的一些团体寻求帮助,这些团体宣传破坏软件保护的服务,因为各种新闻组和论坛上的大量帖子都包含了受保护产品的新版本。
最近,我们在一个较小的项目中尝试了他们的软件许可证解决方案(HASP SL),如果您已经熟悉HL产品,那么该项目很简单。它似乎有效;没有报道盗版事件,但这种产品的需求量要低很多。
当然,没有任何保护是完美的。如果某人有足够的动力并且有大量现金可以焚烧,我相信HASP提供的保护可以被规避。
答案 3 :(得分:21)
最好的反汇编程序技巧,特别是在可变字长指令集上是汇编程序/机器代码,而不是C.例如
CLC
BCC over
.byte 0x09
over:
反汇编程序必须解决分支目标是多字节指令中的第二个字节的问题。但是,指令集模拟器没有问题。分支到计算地址(可以由C引起)也使得反汇编变得困难。指令集模拟器没有任何问题。使用模拟器为您分拣分支目的地可以帮助您进行反汇编过程。对于反汇编程序,编译的代码相对干净且容易。所以我认为需要一些装配。
我认为这是迈克尔·阿布拉什的汇编语言禅的开始,他展示了一个简单的反反汇编和反调试器技巧。 8088/6有一个预取队列,你所做的是有一条指令修改了下一条指令或前面几条指令。如果单步执行则执行修改后的指令,如果指令集模拟器未完全模拟硬件,则执行修改后的指令。在真正运行的硬件上,实际指令已经在队列中,只要你没有再次执行该指令串,修改后的内存位置就不会造成任何损坏。你今天可能仍然会使用这样的技巧,因为流水线处理器会获取下一条指令。或者,如果你知道硬件有一个单独的指令和数据缓存,你可以修改前面的字节数,如果你正确地在缓存行中对齐这个代码,修改后的字节将不会通过指令缓存而是数据缓存写入,并且没有适当的缓存模拟器的指令集模拟器将无法正常执行。我认为仅软件解决方案不会让你走得太远。
以上是古老而众所周知的,我对目前的工具知之甚少,不知道他们是否已经解决了这些问题。自修改代码可以/将使调试器绊倒,但是人类可以/将会缩小问题范围,然后查看自修改代码并解决它。
过去,黑客需要花费大约18个月的时间才能解决问题,例如dvds。现在他们平均大约2天到2周(如果有动力)(蓝光,iphone等)。这对我来说,如果我在安全上花费超过几天,我可能会浪费我的时间。您将获得的唯一真正的安全性是通过硬件(例如,您的指令是加密的,只有芯片内部的处理器核心在执行之前解密,其方式是它不能暴露解密的指令)。这可能会花费你几个月而不是几天。另外,阅读凯文米特尼克的书“欺骗的艺术”。像这样的人可以拿起电话,让你或同事向系统分发秘密,认为它是公司另一部分的经理或其他同事或硬件工程师。而且你的安全感很糟糕。安全不仅仅是管理技术,还要管理人类。
答案 4 :(得分:21)
以AES algorithm为例。这是一个非常非常公开的算法,它非常安全。为什么?有两个原因:它已被很多聪明人审查过,而“秘密”部分不是算法本身 - 秘密部分是关键,它是算法的输入之一。使用生成的代码之外的“秘密”设计协议是一种更好的方法,而不是让代码本身保密。无论你做什么,代码都可以被解释,并且(理想情况下)生成的秘密只能通过大规模的蛮力方法或盗窃来危害。
我认为一个有趣的问题是“为什么你想混淆你的代码?”您想让攻击者难以破解您的算法吗?为了让他们更难在代码中找到可利用的错误?如果代码首先无法破解,则不需要对代码进行模糊处理。问题的根源是可破解的软件。修复问题的根源,不要只是混淆它。
此外,您制作代码越混乱,您就越难找到安全漏洞。是的,这对黑客来说很难,但你也需要找到漏洞。从现在开始,代码应该易于维护,即使是编写良好的清晰代码也难以维护。不要让它变得更糟。
答案 5 :(得分:19)
使代码难以进行逆向工程称为代码混淆。
您提到的大多数技术都很容易解决。他们的中心是添加一些无用的代码。但无用的代码很容易检测和删除,为您留下一个干净的程序。
为了进行有效的混淆,您需要使程序的行为依赖于正在执行的无用位。例如,而不是这样做:
a = useless_computation();
a = 42;
这样做:
a = complicated_computation_that_uses_many_inputs_but_always_returns_42();
或者不是这样做:
if (running_under_a_debugger()) abort();
a = 42;
执行此操作(其中running_under_a_debugger
不应该很容易识别为测试代码是否在调试器下运行的函数 - 它应该将有用的计算与调试器检测混合在一起):
a = 42 - running_under_a_debugger();
有效的混淆不是纯粹在编译阶段可以做的事情。无论编译器能做什么,反编译器都可以做到。当然,你可以增加反编译器的负担,但它不会走得太远。有效的混淆技术,因为它们存在,涉及从第1天开始编写混淆源。使代码自我修改。使用从大量输入派生的计算跳转来丢弃代码。例如,而不是简单的调用
some_function();
执行此操作,您恰好知道some_data_structure
中的位的确切预期布局:
goto (md5sum(&some_data_structure, 42) & 0xffffffff) + MAGIC_CONSTANT;
如果您认真对待混淆,请在计划中添加几个月;混淆不便宜。并且考虑到目前为止避免人们对代码进行逆向工程的最佳方法是使其无用,以免他们烦恼。这是一个简单的经济考虑因素:如果它们的价值高于成本,它们将进行逆向工程;但是提高成本也会增加你的成本,所以试着降低它们的价值。
现在我已经告诉过你混淆很难而且价格昂贵,我会告诉你它不适合你。你写了
为了各种人的安全,我一直在努力的现行协议绝不能被检查或理解
那引起了一面红旗。它是security by obscurity,其记录非常糟糕。如果协议的安全性取决于不了解协议的人,you've lost already。
推荐阅读:
答案 6 :(得分:12)
很多时候,对产品进行逆向工程的担心是错误的。是的,它可以进行逆向工程;但是它会在很短的时间内变得如此有名,黑客会觉得逆转它是值得的。它?(对于大量的代码行,这项工作不是一个小时间活动。)
如果它真的成为赚钱者,那么你应该收集足够的资金来保护它,使用合法的方式,如专利和/或版权。
恕我直言,采取你将要采取的基本预防措施并将其释放。如果它成为逆向工程的一个点意味着你已经做得很好,你自己会找到更好的方法来克服它。祝你好运。
答案 7 :(得分:11)
阅读http://en.wikipedia.org/wiki/Security_by_obscurity#Arguments_against。我相信其他人也可能会提供一个更好的来源,说明为什么安全隐患是一件坏事。
使用现代加密技术完全可以让你的系统开放(我不是说应该是开放的,只是它可能是),并且仍然具有完全的安全性,只要加密算法没有漏洞(不太可能选择一个好的),你的私钥/密码仍然是私有的,你的代码中没有安全漏洞( this 是你应该担心的事情。)
答案 8 :(得分:7)
自2013年7月以来,人们对密码强大的混淆(以不可区分混淆形式)的兴趣重新出现,这似乎是来自Amit Sahai的原始研究。
您可以在此Quanta Magazine article和IEEE Spectrum article中找到一些提炼信息。
目前使用这种技术所需的资源数量使其不切实际,但AFAICT对未来的共识相当乐观。
我非常随便地说这个,但对于那些习惯性地忽视混淆技术的人来说 - 这是不同的。如果它被证明是真正有效并且变得实用,那么这确实很重要,而不是只是为了混淆。
答案 9 :(得分:7)
要了解情况,请阅读代码混淆的学术文献。亚利桑那大学的克里斯蒂安科尔伯格是该领域着名的学者;哈佛大学的Salil Vadhan也做了一些很好的工作。
我落后于这些文献,但我所知道的基本想法是你不能阻止攻击者看到你将要执行的代码,但你可以用代码包围它不执行,并且花费攻击者指数时间(使用最熟知的技术)来发现代码的哪些片段已执行,哪些片段未执行。
答案 10 :(得分:6)
最近有一篇名为“Program obfuscation and one-time programs”的论文。如果您真的认真保护您的应用程序。本文一般通过使用简单通用的硬件来解决理论上的不可能性结果。
如果你无法承受需要额外的硬件,那么还有另一篇文章在理论上给出了最好的混淆“On best-possible obfuscation”,在具有相同功能和相同大小的所有程序中。然而,本文表明信息理论最佳可能意味着多项式层次结构的崩溃。
如果这些结果无法满足您的需求,那些论文至少应该为您提供足够的书目指导,以便参与相关文献。
更新:一种新的混淆概念,称为无法区分的混淆,可以减轻不可能性结果(paper)
答案 11 :(得分:6)
如果有人想花时间扭转你的二进制文件,那么你绝对没有办法阻止它们。如果中等程度更难,你就可以做到,但这就是它。如果您真的想了解这一点,请获取http://www.hex-rays.com/idapro/的副本并反汇编一些二进制文件。
CPU需要执行代码的事实是你的撤销。 CPU只执行机器代码......程序员可以读取机器代码。
话虽如此......你可能有另一个问题可以通过另一种方式解决。你想保护什么?根据您的问题,您可以使用加密来保护您的产品。
答案 12 :(得分:5)
没有骰子,你无法保护你的代码免遭反汇编。您可以做的是为业务逻辑设置服务器,并使用webservice为您的应用程序提供服务。当然,这种情况并非总是可行。
答案 13 :(得分:5)
为了能够选择正确的选项,您应该考虑以下几个方面:
如果对问题5的回答是“是”,那么不要担心非法复制。无论如何它们都没用。
如果问题1的答案为“是”,那么首先考虑定价(见问题3)。
如果您回答问题2“是”,那么“按使用付费”模式可能会 适合你。
根据我的经验,按使用付费+定制和培训是最好的保护 对于您的软件,因为:
在考虑引入DRM或混淆之前,您可能会想到这些要点以及它们是否适用于您的软件。
答案 14 :(得分:4)
可能你最好的选择仍然是使用虚拟化,它引入了旁路所需的另一级间接/混淆,但正如SSpoke在他的answer中所说,这种技术也不是100%安全。
关键是你不会获得终极保护,因为没有这样的东西,如果有的话,它将不会持续很长时间,这意味着它首先不是最终的保护。
无论男人组装,都可以拆卸。
通常情况下(正确的)反汇编通常是(一点或多点)更难的任务,所以你的对手必须更熟练,但你可以认为那里总是有这样的品质,这是一个安全的赌注。
如果你想保护某些东西不受RE影响,你必须至少知道RE使用的常用技术。
这样的话
互联网对防止逆向工程并不是真正足智多谋,而是描绘了大量关于如何进行逆向工程的信息
显示你的态度不好。我不是说要使用或嵌入保护你必须知道如何打破它,但明智地使用它你应该知道它的弱点和陷阱。你应该理解它。
(有些软件以错误的方式使用保护,实际上不存在这种保护的例子。为了避免模糊地说话,我将给你一个在互联网上简要描述的例子:牛津英语词典第二版CD-ROM v4。你可以在以下页面中阅读有关SecuROM使用失败的信息:Oxford English Dictionary (OED) on CD-ROM in a 16-, 32-, or 64-bit Windows environment: Hard-disk installation, bugs, word processing macros, networking, fonts, and so forth)
一切都需要时间。
如果您是这个主题的新手并且没有几个月或几年时间来适当地进入RE的东西,那么请使用其他人提供的可用解决方案。这里的问题很明显,它们已经存在,所以你已经知道它们不是100%安全,但是制作你自己的新保护只会给你一种虚假的保护感,除非你知道最先进的技术。逆向工程和保护(但至少在目前,你没有)。
软件保护的目的是吓唬新手,阻止常见的RE,并在她/他(希望有趣的)旅程到你的应用程序中心之后,在经验丰富的RE面前微笑。
在商业谈话中,你可能会说尽可能延迟竞争。
(看看Philippe Biondi和Fabrice Desclaux在Black Hat 2006上展示的精彩演讲Silver Needle in the Skype。)
你知道有关RE的很多东西,所以开始阅读它。 :)
我说过虚拟化,所以我会给你一个来自EXETOOLS FORUM Best software protector: Themida or Enigma Protector?的示例线程的链接。它可能会帮助您进一步搜索。
答案 15 :(得分:4)
正如许多人已经说过的那样:在常规CPU上你不能阻止它们做,你可以耽误它们。正如我的老加密老师告诉我的那样:你不需要完美的加密,打破代码必须比收益更贵。同样适合你的混淆。
但还有3个注释:
有可能使逆向工程不可能,但(这是一个非常大的但是),你不能在传统的cpu上做。我也进行了很多硬件开发,并且经常使用FPGA。例如。 Virtex 5 FX上有一个PowerPC CPU,您可以使用APU在硬件中实现自己的CPU操作码。您可以使用此工具真正解密PowerPC的incstuctions,外部或其他软件无法访问,甚至可以在硬件中执行命令。由于FPGA为其配置比特流内置了AES加密,因此无法对其进行逆向工程(除非有人设法破坏AES,但我猜我们还有其他问题......)。这种方式硬件IP供应商也可以保护他们的工作。
你说的是协议。你不会说它是什么类型的协议,但是当它是一个网络协议时,你至少应该保护它免受网络嗅探。这确实可以通过加密来实现。但是如果你想保护软件所有者的en / decryption,你就会回到模糊处理。
确保您的程序不可判坏/不可用。尝试使用某种类型的调试检测并应用它,例如在某些公式中或者将调试寄存器内容添加到魔术常量。如果你的程序在调试模式下运行它是否运行正常,但是完全错误的计算,操作或其他一些更难。例如。我知道一些生态游戏,有一个非常讨厌的复制保护(我知道你不想要copyprotection,但它是类似的):被盗的版本在30分钟的游戏后改变了开采的资源,突然你只得到一个资源。海盗刚刚破解它(即逆向工程) - 检查它是否运行,并且volia释放它。这种轻微的行为变化很难被发现,尤其是如果他们没有立即出现检测,但只是延迟。
所以最后我会建议: 估计人们对软件进行逆向工程的收益是什么,将其转化为一段时间(例如使用最便宜的印度薪水)并进行逆向工程,以便花费更多的时间。
答案 16 :(得分:4)
我不认为任何代码是不可攻击的,但是对于想要尝试它的人来说,奖励需要很大。
说过你应该做的事情如下:
尝试自己破解汇编代码,看看哪些是简单的,哪些是难以做到的。应该提出一些想法,你可以尝试使代码更难以进行逆向工程,并使调试变得更加困难。
答案 17 :(得分:4)
虚拟机中受保护的代码最初似乎无法进行逆向工程。 Themida Packer
但它不再那么安全..无论你如何打包你的代码,你总是可以对任何加载的可执行文件进行内存转储,并用任何像IDA Pro这样的反汇编程序进行反汇编。
IDA Pro还带有一个漂亮的汇编代码到C源代码转换器,虽然生成的代码看起来更像是一个指针/地址数学混乱..如果你把它与原始数据进行比较,你可以修复所有错误并撕掉任何东西。< / p>答案 18 :(得分:4)
为避免逆向工程,您不得将代码提供给用户。也就是说,我建议使用在线应用程序...但是(因为你没有提供任何背景信息),这对您来说毫无意义。
答案 19 :(得分:3)
与大多数人所说的相反,基于他们的直觉和个人经验,我认为加密安全程序混淆一般不会被证明是不可能的。
这是一个完美混淆的程序声明的一个例子来证明我的观点:
printf("1677741794\n");
人们永远无法猜到它真正做的是
printf("%d\n", 0xBAADF00D ^ 0xDEADBEEF);
有一篇关于这个主题的有趣论文,证明了一些不可能的结果。它被称为"On the (Im)possibility of Obfuscating Programs"。
尽管该论文确实证明了使程序与其实现的功能无法区分的混淆是不可能的,但仍然可能以某种较弱的方式定义混淆!
答案 20 :(得分:3)
通过默默无闻的安全措施不起作用,因为人们已经证明了这一点 我们俩。如果您必须保护客户的通信协议,那么您就是 在道德上有义务使用公开的最佳代码,并由专家仔细审查。
这适用于人们可以检查代码的情况。如果您的应用程序要在嵌入式微处理器上运行,您可以选择一个具有密封功能的应用程序,这使得无法检查代码或观察运行时的当前使用情况等多个简单参数。 (除了通过硬件入侵技术,您可以小心地拆除芯片并使用先进的设备来检查各个晶体管上的电流。)
我是x86的逆向工程汇编程序的作者。如果你已经准备好感冒了 惊喜,发给我最好的努力结果。 (通过我的网站与我联系。) 我在答案中看到的很少,对我来说是一个很大的障碍。如果你想看到 如何复杂的逆向工程代码,你应该真正研究网站 逆向工程挑战。
您的问题可以使用一些澄清。你如何期待保密协议的秘密 计算机代码是否适合逆向工程?如果我的协议是发送RSA加密消息(甚至是公钥),你通过保密协议获得了什么? 出于所有实际目的,检查员将面临一系列随机比特。
Groetjes Albert
答案 21 :(得分:3)
传统的逆向工程技术取决于智能代理使用反汇编程序回答有关代码的问题的能力。如果您想要强大的安全性,那么您可以做一些可以阻止代理获得此类答案的事情。
你可以依靠停止程序(&#34;程序X停止?&#34;)来做到这一点,这通常是无法解决的。将难以推理的程序添加到您的程序中会使您的程序难以推理。构建这样的程序比拆除它们更容易。您还可以将代码添加到具有不同推理难度的程序中;一个伟大的候选人是关于别名的推理程序(&#34;指针&#34;)。
Collberg等人有一篇论文(&#34;制造廉价,弹性和隐身不透明构造&#34;),讨论了这些主题并定义了各种不透明的&#34;谓词很难推理代码:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.39.1946&rep=rep1&type=pdf
我没有看到Collberg的特定方法应用于生产代码,特别是C或C ++源代码。
DashO Java混淆器似乎使用了类似的想法。 http://www.cs.arizona.edu/~collberg/Teaching/620/2008/Assignments/tools/DashO/
答案 22 :(得分:2)
首先要记住隐藏您的代码:并非所有代码都需要隐藏。
最终目标:我的大多数软件程序的最终目标是能够销售不同的许可证,以打开和关闭程序中的特定功能。
最佳技巧:我发现在像WordPress提供的钩子和过滤器系统中构建,是试图混淆对手时绝对最好的方法。这允许您加密某些触发器关联,而无需实际加密代码。
您执行此操作的原因是因为您希望加密尽可能少的代码。
了解您的破解程序:了解这一点:破解代码的主要原因不是因为恶意分发许可,实际上是因为需要更改代码并且他们并不真正需要免费分发副本。
开始使用:留出您要加密的少量代码,其余的代码应该尝试并塞进一个文件中以增加复杂性和理解。
准备加密:您将使用我的系统在层中进行加密,这也将是一个非常复杂的过程,因此需要构建另一个负责加密过程的程序。 / p>
第一步:使用base64名称对所有内容进行模糊处理。完成后,将64位混淆代码保存到临时文件中,该文件稍后将用于解密和运行此代码。有意义吗?
我会重复,因为你会一次又一次地这样做。您将创建一个base64字符串并将其另存为另一个文件,作为将被解密和呈现的变量。
第二步:你将把这个临时文件作为一个字符串读入并对其进行模糊处理,然后对其进行base64并将其保存到第二个临时文件中,该文件将用于解密和呈现它对于最终用户。
第三步:根据需要重复第二步。一旦你在没有解密错误的情况下正常工作,那么你将要开始为你的对手开始建造地雷。
LAND MINE ONE :您将要保留通知您绝对秘密的事实。因此,为第2层构建一个破解者尝试安全警告邮件系统。如果出现任何问题,这将被解雇让您了解对手的具体信息。
LAND MINE TWO :依赖关系。你不希望你的对手能够在没有第3层或第4层或第5层的情况下运行第一层,甚至不能为它设计的实际程序。因此,请确保在第一层中包含某种kill脚本,如果程序不存在则会激活该脚本,或者其他层。
我相信你可以拿出自己的地雷,玩得开心。
要记住:您实际上可以加密代码而不是base64'。这样一个简单的base64就不会解密该程序。
奖励:请记住,这实际上可能是你和你的对手之间的共生关系。我总是在第一层发表评论,评论祝贺破解者并给他们一个促销代码,以便从你那里获得现金奖励。
使现金奖励显着,不涉及任何偏见。我通常会说500美元。如果你的家伙是第一个破解密码的人,那就给他钱,然后成为他的朋友。如果他是你的朋友,他不会分发你的软件。问他如何做到这一点,以及如何改进!
好运,祝你好运!答案 23 :(得分:2)
有人试过CodeMorth:http://www.sourceformat.com/code-obfuscator.htm吗? 或Themida:http://www.oreans.com/themida_features.php?
后来看起来更有希望。