保护可执行文件免受逆向工程?

gra*_*ter 205 c c++ obfuscation assembly

我一直在考虑如何保护我的C/C++代码免于反汇编和逆向工程.通常我永远不会在我的代码中宽恕这种行为; 然而,为了各种人的安全,我一直在努力的现行协议绝不能被检查或理解.

现在这对我来说是一个新的主题,互联网并不是真正有效防范逆向工程,而是描绘了大量有关如何逆向工程的信息

到目前为止我想到的一些事情是:

  • 代码注入(在实际函数调用之前和之后调用虚函数)
  • 代码obfustication(破坏二进制的反汇编)
  • 编写我自己的启动例程(调试器更难绑定)

    void startup();  
    int _start()   
    {  
        startup( );  
        exit   (0)   
    }  
    void startup()  
    {  
        /* code here */  
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 运行时检查调试器(如果检测到则强制退出)

  • 功能蹦床

     void trampoline(void (*fnptr)(), bool ping = false)  
     {  
       if(ping)  
         fnptr();  
       else  
         trampoline(fnptr, true);  
     }
    
    Run Code Online (Sandbox Code Playgroud)
  • 无意义的分配和解除分配(堆栈变化很多)

  • 毫无意义的虚拟呼叫和蹦床(在反汇编输出中大量跳跃)
  • 铸造吨(用于混淆的拆卸)

我的意思是这些是我所想到的一些事情,但是在适当的时间范围内,它们都可以被代码分析师解决或者解决.我还有其他选择吗?

Amb*_*ber 174

但是在适当的时间范围内,它们都可以由代码分析师解决或解决.

如果你给人们一个他们能够运行的程序,那么他们也可以在给定足够时间的情况下对其进行逆向工程.这是计划的性质.只要二进制文件可供想要解密它的人使用,就无法阻止最终的逆向工程.毕竟,计算机必须能够解密它才能运行它,而人类只是一台速度较慢的计算机.

  • +1.去了解关于Apple II复制保护的辉煌岁月,混淆器和破解者之间不断升级的战争,软盘的步进电机和无证6502指令的疯狂伎俩等等......然后自己哭睡觉,因为你不会实现任何近乎精细的东西,最终它们都会被破解. (113认同)
  • 今天唯一合理运行的DRM是密钥和互联网服务器的组合,验证在一个时间内只有一个密钥实例是活动的. (5认同)
  • 此时有人会尝试对计算机进行逆向工程,除非它仅在您控制的环境中可用. (3认同)
  • 更容易使用模拟器并获得更好的可视性,而不是尝试直观地或使用反汇编程序进行逆向工程.如果安全性没有内置到您正在使用的硬件中,我认为世界平均需要两天到两周的时间来进行逆向工程并击败几乎所有出现的内容.如果创建和实现它需要两天以上的时间,那么您花费了太多时间. (2认同)
  • @Rotsor:计算机无法理解它,因为我们还没有能够将这种智能降低到算法(还有),而不是因为存在某种物理或技术障碍.人类可以理解它,因为他可以做任何事情,计算机可以(尽管速度较慢)*以及理由*. (2认同)
  • 防止逆向工程的唯一理论方法是仅在专用计算机上运行该程序,该计算机隐藏其用户自己的指令集. (2认同)

Ste*_*non 149

Amber所说的是完全正确的.您可以更加努力地进行逆向工程,但是您永远无法阻止它.你永远不应该相信依靠防止逆向工程的"安全".

也就是说,我所见过的最好的反逆向工程技术不是专注于混淆代码,而是打破人们通常用来理解代码如何工作的工具.寻找创造性的方法打破反汇编程序,调试程序等,可能比仅仅生成大量可怕的意大利面条代码更有效,也更具智力上的满足感.这对阻止一个坚定的攻击者没有任何作用,但它确实增加了J Random Cracker徘徊并更容易处理某些事情的可能性.

  • 我理解这一点,并且我已经阅读了一些关于*Skype安全解释*的文章,我一直在考虑Skype已经尝试过的相同想法,作为一种不能阻止而是保护我的协议的方法.鉴于Skype的明显情况,已经证明有足够的价值. (14认同)
  • Skype实际上是我想到的第一个例子,所以我很高兴你已经开始考虑模仿他们的方法了. (8认同)

Rya*_*anR 41

Safe Net Sentinel(原阿拉丁).虽然注意事项 - 他们的API很糟糕,文档很糟糕,而且与SDK工具相比,这两者都很棒.

我已经使用了他们的硬件保护方法(Sentinel HASP HL)多年.它需要专有的USB密钥卡,作为软件的"许可".他们的SDK会对您的可执行文件和库进行加密和混淆,并允许您将应用程序中的不同功能与刻录到密钥中的功能联系起来.如果没有由许可方提供和激活的USB密钥,则软件无法解密,因此无法运行.Key甚至使用定制的USB通信协议(在我的知识范围之外,我不是设备驱动程序),使得构建虚拟密钥变得困难,或者篡改运行时包装器和密钥之间的通信.他们的SDK不是非常开发人员友好的,并且将添加保护与自动构建过程集成非常痛苦(但可能).

在我们实施HASP HL保护之前,有7名已知的盗版者剥夺了该产品的dotfuscator'保护'.我们在对软件进行重大更新的同时添加了HASP保护,该软件实时对视频进行了大量计算.从分析和基准测试中我可以看出,HASP HL保护只能将密集计算减慢约3%.由于该软件大约在5年前发布,因此没有发现该产品的新版盗版.它所保护的软件在其市场领域中有很高的需求,并且客户知道有几个竞争者正在积极尝试逆向工程(到目前为止没有成功).我们知道他们已经尝试向俄罗斯的一些团体寻求帮助,这些团体宣传破坏软件保护的服务,因为各种新闻组和论坛上的大量帖子都包含了受保护产品的新版本.

最近,我们在一个较小的项目上尝试了他们的软件许可证解决方案(HASP SL),如果您已经熟悉HL产品,那么这个项目很简单.它似乎有效; 没有报道盗版事件,但这款产品的需求量要低得多.

当然,没有任何保护是完美的.如果某人有足够的动力并且有足够的现金来燃烧,我相信HASP提供的保护可以被规避.

  • **主持人注:**_由于偏离了对抗性噪音,此答案下的评论已被删除._ (18认同)
  • 我还想从使用HASP安全软件的人的角度出发.HASP是最终用户**的王室痛苦**.我已经处理了一个达拉斯iButton和一个阿拉丁HASP,并且*两个*真的**错误,导致软件随机停止工作,需要断开连接并重新连接HASP. (5认同)
  • 此外,值得注意的是,HASP安全措施不一定比代码混淆更安全 - 确保它们需要不同的方法来进行逆向工程,但是很有可能逆转它们 - 请参阅:http://www.flylogic.net/博客/?p = 14 http://www.flylogic.net/blog/?p=16 http://www.flylogic.net/blog/?p=11 (4认同)
  • +1经验,但我想回应它并不完美.Maya(3D套件)使用了一个硬件加密狗(不确定它是否是HASP),它不能长时间阻止海盗.当有遗嘱时,有办法. (2认同)

old*_*mer 22

最好的反分解器技巧,特别是在可变字长指令集上是汇编程序/机器代码,而不是C.例如

CLC
BCC over
.byte 0x09
over:
Run Code Online (Sandbox Code Playgroud)

反汇编程序必须解决分支目标是多字节指令中的第二个字节的问题.但是,指令集模拟器没有问题.分支到计算地址(可以从C引起)也使得反汇编变得困难.指令集模拟器没有任何问题.使用模拟器为您分拣分支目的地可以帮助您进行反汇编过程.对于反汇编程序,编译的代码相对干净且容易.所以我认为需要一些装配.

我认为它接近迈克尔·阿布拉什的汇编语言禅的开头,他展示了一个简单的反反汇编和反调试器技巧.8088/6有一个预取队列,你所做的是有一条指令修改了下一条指令或前面几条指令.如果单步执行则执行修改后的指令,如果指令集模拟器未完全模拟硬件,则执行修改后的指令.在真正运行的硬件上,实际指令已经在队列中,只要你没有再次执行该指令串,修改后的内存位置就不会造成任何损坏.你今天可能仍然会使用这样的技巧,因为流水线处理器会获取下一条指令.或者,如果你知道硬件有一个单独的指令和数据缓存,你可以修改前面的字节数,如果你正确地在缓存行中对齐这个代码,修改后的字节将不会通过指令缓存而是数据缓存写入,并且没有适当的缓存模拟器的指令集模拟器将无法正常执行.我认为只有软件解决方案不会让你走得太远.

以上是古老的,众所周知的,我不知道当前的工具,知道他们是否已经解决了这些问题.自修改代码可以/将使调试器绊倒,但是人类可以/将缩小问题,然后查看自修改代码并解决它.

过去,黑客需要大约18个月才能完成某些工作,例如dvds.现在他们平均大约2天到2周(如果有动力)(蓝光,iphone等).这对我来说,如果我在安全上花费超过几天,我可能会浪费我的时间.您将获得的唯一真正的安全性是通过硬件(例如,您的指令是加密的,只有芯片内部的处理器核心在执行之前解密,其方式是它不能暴露解密的指令).这可能会花费你几个月而不是几天.

另外,阅读凯文米特尼克的书"欺骗的艺术".像这样的人可以拿起电话,让你或同事向系统分发秘密,认为它是公司另一部分的经理或其他同事或硬件工程师.而且你的安全感很糟糕.安全不仅仅是管理技术,还要管理人类.

  • 自修改代码存在很大问题.没有非常高的权限,大多数现代操作系统/硬件都不允许你这样做,可能存在缓存问题,而且代码不是线程安全的. (2认同)
  • 对于现代 x86 处理器,此类技巧通常会降低性能。使用相同的内存位置作为多个指令的一部分可能会产生类似于错误预测的分支的效果。自修改代码会导致处理器丢弃高速缓存行,以保持指令和数据高速缓存之间的一致性(如果您执行修改的代码的频率远高于修改代码的频率,那么它仍然可能是胜利)。 (2认同)
  • 我在20年前遇到过这个问题.花了将近半个小时来弄清楚发生了什么.如果需要更长时间的保护,效果不是很好 (2认同)

Phi*_*hil 21

AES算法为例.这是一个非常非常公开的算法,它非常安全.为什么?有两个原因:它已被很多聪明人审查过,而"秘密"部分不是算法本身 - 秘密部分是关键,它是算法的输入之一.使用生成的代码之外的"秘密"来设计协议是一种更好的方法,而不是让代码本身保密.无论你做什么,代码都可以被解释,并且(理想情况下)生成的秘密只能通过大规模的蛮力方法或盗窃来危害.

我认为一个有趣的问题是" 为什么要混淆代码?" 您想让攻击者难以破解您的算法吗?为了让他们更难在代码中找到可利用的错误?如果代码首先无法破解,则不需要对代码进行模糊处理.问题的根源是可破解的软件.修复问题的根源,不要只是混淆它.

此外,您制作代码越混乱,您就越难找到安全漏洞.是的,这对黑客来说很难,但你也需要找到漏洞.从现在开始,代码应该易于维护,即使是编写良好的清晰代码也难以维护.不要让它变得更糟.

  • +1常识:为什么在设计更好的系统时会让自己变得更难. (3认同)

Gil*_*il' 20

使代码难以进行逆向工程称为代码混淆.

你提到的大多数技术都很容易解决.他们的中心是添加一些无用的代码.但无用的代码很容易检测和删除,为您留下一个干净的程序.

为了进行有效的混淆,您需要使程序的行为取决于正在执行的无用位.例如,而不是这样做:

a = useless_computation();
a = 42;
Run Code Online (Sandbox Code Playgroud)

做这个:

a = complicated_computation_that_uses_many_inputs_but_always_returns_42();
Run Code Online (Sandbox Code Playgroud)

或者不是这样做:

if (running_under_a_debugger()) abort();
a = 42;
Run Code Online (Sandbox Code Playgroud)

这样做(running_under_a_debugger不应该很容易识别为测试代码是否在调试器下运行的函数 - 它应该将有用的计算与调试器检测混合):

a = 42 - running_under_a_debugger();
Run Code Online (Sandbox Code Playgroud)

有效的混淆不是纯粹在编译阶段可以做的事情.无论编译器能做什么,反编译器都可以做到.当然,你可以增加反编译器的负担,但它不会走得太远.有效的混淆技术,因为它们存在,涉及从第1天开始编写混淆源.使代码自我修改.使用从大量输入派生的计算跳转来丢弃代码.例如,而不是简单的调用

some_function();
Run Code Online (Sandbox Code Playgroud)

这样做,你碰巧知道的位的确切预期布局some_data_structure:

goto (md5sum(&some_data_structure, 42) & 0xffffffff) + MAGIC_CONSTANT;
Run Code Online (Sandbox Code Playgroud)

如果您认真对待混淆,请在计划中添加几个月; 混淆不便宜.并且考虑到目前为止避免人们对代码进行逆向工程的最佳方法是使其无用,以免他们烦恼.这是一个简单的经济考虑因素:如果它们的价值高于成本,它们将进行逆向工程; 但是提高成本也会增加你的成本,所以试着降低它们的价值.

现在我已经告诉过你,混淆是困难和昂贵的,我会告诉你,无论如何它都不适合你.你写

为了各种人的安全,我一直在努力的现行协议绝不能被检查或理解

这引起了一面红旗.它的安全性是默默无闻的,其记录非常糟糕.如果协议的安全性取决于不了解协议的人,那么你已经失去了.

推荐阅读:

  • @ Rotsor`4`和`2 + 2`在观察上是等价的,因此它们*为此目的*相同*,即弄清楚程序正在做什么.是的,当然,反编译器无法重建源代码,但这是无关紧要的.该Q&A是关于重建行为(即算法,更准确地说是协议). (7认同)
  • @Gilles我无法用苹果扩展你的类比,因为我无法想象一个结构上不同但行为上等同的苹果.:) (2认同)

iam*_*ind 12

很多时候,对产品进行逆向工程的担心是错误的.是的,它可以进行逆向工程; 但它会在很短的时间内变得如此有名,黑客会发现它可以逆转.它?(对于大量的代码行,这项工作不是一个小时间活动).

如果它真的成为赚钱的人,那么你应该收集足够的资金来保护它,使用合法和/或版权等合法方式.

恕我直言,采取你将采取的基本预防措施并释放它.如果它成为逆向工程的一个点意味着你已经做得很好,你自己会找到更好的方法来克服它.祝好运.


asm*_*rer 11

阅读http://en.wikipedia.org/wiki/Security_by_obscurity#Arguments_against.我相信其他人也可能会提供一个更好的来源,说明为什么安全隐患是一件坏事.

使用现代加密技术完全可以让你的系统开放(我不是说它应该是开放的,只是它可能是),并且仍然具有完全的安全性,只要加密算法不它有一个洞(不太可能,如果你选择一个好的),你的私钥/密码保持私密,你的代码中没有安全漏洞(是你应该担心的).

  • 我同意这一点.我想你可能有概念或设计问题.是否有使用私钥 - 公钥对解决方案的模拟?您永远不会透露私钥,它会与安全客户端处理它的所有者保持一致.您是否可以将安全代码保留在计算机上并仅将结果传递给用户? (2认同)

tne*_*tne 8

自2013年7月以来,人们对密码强大的混淆(以不可区分混淆的形式)重新产生兴趣,这似乎是由Amit Sahai的原始研究引起的.

您可以在此Quanta杂志文章IEEE Spectrum文章中找到一些提炼信息.

目前使用这种技术所需的资源量使其不切实际,但AFAICT的共识对未来相当乐观.

我非常随便地说这个,但对于那些习惯性地忽视混淆技术的人来说 - 这是不同的.如果它被证明是真正有效并且变得实用,那么这确实很重要,而不仅仅是为了混淆.


M. *_*gan 7

最近有一篇名为" 程序混淆和一次性程序 "的论文.如果您真的认真保护您的应用程序.一般来说,本文通过使用简单和通用的硬件来解决理论上的不可能性结果.

如果你不能要求额外的硬件,那么还有另一篇论文在理论上给出了最佳可能的混淆" 最佳可能的混淆 ",在具有相同功能和相同大小的所有程序中.然而,本文表明信息理论最佳可能意味着多项式层次结构的崩溃.

如果这些结果不符合您的需求,那些论文至少应该给您足够的书目引导来参与相关文献.

更新:一种新的混淆概念,称为无法区分的混淆,可以减轻不可能性的结果(纸张)


Nor*_*sey 7

要了解自己,请阅读有关代码混淆的学术文献.亚利桑那大学的克里斯蒂安科尔伯格是该领域着名的学者; 哈佛大学的Salil Vadhan也做了一些很好的工作.

我对这些文献的支持不多,但我所知道的基本思想是你不能阻止攻击者看到你将要执行的代码,但你可以使用执行的代码将其包围起来,并且成本高昂攻击者指数时间(使用最熟知的技术)来发现代码的哪些片段已执行,哪些片段未执行.


Bri*_*kin 6

如果有人想花时间扭转你的二进制文件,那么你绝对没有办法阻止它们.如果中等程度更难,你就可以做到,但这就是它.如果您真的想了解这一点,那么请获取http://www.hex-rays.com/idapro/的副本并反汇编一些二进制文件.

CPU需要执行代码的事实是你的撤销.CPU只执行机器代码......程序员可以读取机器代码.

话虽如此......你可能有另一个问题可以用另一种方式解决.你想保护什么?根据您的问题,您可以使用加密来保护您的产品.


Bla*_*ack 6

为了能够选择正确的选项,您应该考虑以下几个方面:

  1. "新用户"是否可能不想付费而是使用您的软件?
  2. 现有客户是否可能需要比他们更多的许可证?
  3. 潜在用户愿意支付多少钱?
  4. 您是否想为每个用户/并发用户/工作站/公司提供许可证?
  5. 您的软件是否需要培训/定制才有用?

如果问题5的答案是"是",那么不要担心非法复制.无论如何它们都没用.

如果问题1的答案是"是",那么首先考虑定价(见问题3).

如果您回答问题2"是",那么"按使用付费"模式可能适合您.

根据我的经验,按使用付费+定制和培训是对您的软件的最佳保护,因为:

  • 定价模式吸引新用户(少用 - >小工资)
  • 几乎没有"匿名用户",因为他们需要培训和定制.
  • 没有软件限制可以吓跑潜在客户.
  • 现有客户不断涌现资金.
  • 由于长期的业务关系,您可以从客户那里获得有价值的开发反馈.

在您考虑引入DRM或混淆之前,您可能会想到这些要点以及它们是否适用于您的软件.


SSp*_*oke 5

首先,虚拟机中受保护的代码似乎不可能进行反向工程。塞米达·帕克(Themida Packer)

但这不再那么安全了。无论您如何打包代码,都可以对任何已加载的可执行文件进行内存转储,并使用诸如IDA Pro之类的反汇编程序对其进行反汇编。

尽管生成的代码看起来更像是指针/地址的数学混乱,但IDA Pro还附带了一个漂亮的汇编代码,可以转换为C源代码。如果您将其与原始代码进行比较,则可以修复所有错误并消除所有错误。


prz*_*moc 5

可能您最好的选择仍然是使用虚拟化,它会引入绕过旁路所需要的另一种间接/混淆功能,但是正如SSpoke在回答中所说的那样,这种技术也不是100%安全的。


关键是您将不会获得最终保护,因为没有这样的东西,而且即使有,它也不会持续很长时间,这意味着它最初并不是最终保护。

任何人组装,都可以拆卸。

通常,(适当)拆卸通常是(有点或更多)艰巨的任务,因此您的对手必须更熟练,但是您可以假设总会有这样素质的人,这是一个安全的选择。

如果要保护某些产品免受RE影响,则必须至少了解RE使用的常见技术。

因此话

互联网对于防止逆向工程并不是真正有用的资源,而是描述了大量有关如何进行逆向工程的信息

对你的态度不好。我并不是说要使用或嵌入保护,您必须知道如何打破它,但要明智地使用它,您应该知道其弱点和陷阱。您应该了解它。

(有一些软件以错误的方式使用保护的示例,使得这种保护几乎不存在。为避免含糊其辞,我将为您提供一个在Internet上简要描述的示例:CD-ROM v4上的牛津英语词典第二版。您可以阅读有关在以下页面中未能成功使用SecuROM:在16位,32位或64位Windows环境中的CD-ROM上的牛津英语词典(OED):硬盘安装,错误,文字处理宏,网络,字体和以此类推

一切都需要时间。

如果您是该主题的新手,并且没有几个月甚至几年的时间无法完全熟悉可再生能源,那么请使用其他人提供的可用解决方案。这里的问题很明显,因为它们已经存在,所以您已经知道它们不是100%安全的,但是进行自己的新保护只会给您一种虚假的被保护感,除非您真正了解最新技术。逆向工程和保护(但至少现在还没有)。

软件保护的重点是吓new新手,拖延常见的RE,并在经验丰富的RE(希望很有趣)到达您的应用程序中心之后向经验丰富的RE露出微笑。

在商务谈话中,您可能会说这是尽可能延迟竞争的全部。

(看看Philippe Biondi和Fabrice Desclaux 在Skype上发表的精彩演讲《银针在黑帽》(Black Hat 2006))。


您知道那里有很多关于RE的东西,所以开始阅读它。:)

我说过关于虚拟化的问题,所以我将给您提供指向EXETOOLS FORUM的一个示例线程的链接:最佳软件保护程序:Themida还是Enigma Protector?。它可能会帮助您进一步搜索。


Rot*_*sor 5

与大多数人所说的相反,根据他们的直觉和个人经验,我认为密码安全的程序混淆通常不会被证明是不可能的。

这是一个完全混淆的程序语句的示例,用于证明我的观点:

printf("1677741794\n");
Run Code Online (Sandbox Code Playgroud)

人们永远猜不到它真正的作用是

printf("%d\n", 0xBAADF00D ^ 0xDEADBEEF);
Run Code Online (Sandbox Code Playgroud)

关于这个主题有一篇有趣的论文,它证明了一些不可能的结果。它的名字是“论混淆程序的可能性”

尽管论文确实证明了使程序与它实现的功能无法区分的混淆是不可能的,但以某种较弱的方式定义的混淆仍然是可能的!

  • 1.你的例子与这里无关;您展示的两个程序在行为上是等效的,这个问题是关于弄清楚程序的行为,而不是重建其源代码(显然,这是不可能的)。2.本文为理论论文;编写完美的混淆器是不可能的,但也不可能编写完美的反编译器(与不可能编写完美的程序分析器的原因大致相同)。实际上,这是一场军备竞赛:谁能编写出更好的(去)混淆器。 (7认同)

Luk*_*don 5

没有骰子,你无法保护你的代码免于反汇编.您可以做的是为业务逻辑设置服务器,并使用webservice为您的应用程序提供服务.当然,这种情况并非总是可行.

  • 很好地说,避免人们反汇编代码的唯一方法就是永远不要让他们对它进行物理访问,这意味着将您的应用程序专门用作SAAS,从远程客户端接收请求并回收处理过的数据.将服务器放置在一个地下掩体的一个锁着的房间里,这个地下沙坑被鳄鱼沟和5米高的电动剃须刀线包围,你把钥匙扔掉,然后用10米的钢筋混凝土覆盖它,然后希望你不要忘记安装吨软件系统,以防止通过网络入侵. (8认同)
  • 我希望我永远不会得到维护你的服务器的合同 (6认同)

小智 5

为避免逆向工程,您不得将代码提供给用户。也就是说,我建议使用在线应用程序……但是(因为您没有提供上下文)这对您的应用程序可能毫无意义。