如何保护Python代码?


632

我正在用Python开发一款软件,该软件将分发给我的雇主的客户。我的雇主希望通过限时许可文件来限制软件的使用。

如果我们分发.py文件或什至.pyc文件,将很容易(反编译和)删除检查许可证文件的代码。

另一个方面是,我的雇主不希望我们的客户阅读该代码,因为担心该代码可能被盗或至少是“新颖的主意”。

有解决这个问题的好方法吗?最好使用现成的解决方案。

该软件将在Linux系统上运行(因此,我认为py2exe不会成功)。


25
py2exe只是将.pyc字节代码文件存储在.zip存档中,因此,这绝对不是解决方案。不过,将其与合适的starup脚本结合使用以使其在Linux上运行时仍然很有用
Ber


这是对您问题的最全面解答:wiki.python.org/moin/Asking%20for%20Help/…–
Mike

Answers:


378

Python是字节码编译的解释语言,很难锁定。即使您使用py2exe之类的exe打包程序,该可执行文件的布局也是众所周知的,并且Python字节码也很容易理解。

通常在这种情况下,您必须进行权衡。保护代码真的有多重要?那里是否有真正的秘密(例如,对银行转账进行对称加密的密钥),或者您只是偏执?选择一种语言,使您能够最快地开发出最好的产品,并要对您的新颖创意的价值抱有现实的态度。

如果您确定确实需要安全地执行许可证检查,则将其编写为一个小的C扩展,以便可以对许可证检查代码进行额外的难度(但并非不可能!)以进行反向工程,并将大部分代码保留在Python中。


157
即使由于使用C语言编写的许可证检查代码很难进行反向工程,删除对许可证检查代码的调用仍然相对容易吗?
布莱尔·康拉德

59
是的,这取决于执行许可证检查的位置。如果对该分机的呼叫很多,则可能很难消除。或者,您也可以将应用程序的其他一些关键部分移至许可证检查中,以便删除对扩展名的调用会使应用程序瘫痪。
Ned Batchelder

103
确实,所有这些工作不是要防止修改,而是要增加其难度,以至于不再值得。如果有足够的好处,任何东西都可以逆向工程和修改。
Ned Batchelder

11
@Blair Conrad:如果许可证检查代码也隐藏了功能,那不是。例如mylicensedfunction(licenseblob liblob, int foo, int bar, std::string bash)
布赖恩2010年

8
我实际上已经看到了将商业python代码作为嵌入式python运送到C库中的情况。他们没有将代码的某些部分转换为C,而是将整个python代码隐藏在保护性C层内。然后,如果他们希望模块可以通过python导入,则可以在C之上编写一个瘦的python扩展。开源是一种更轻松的生活方式。
Mike McKerns 2014年

454

“有没有解决这个问题的好方法?” 不可以。没有任何东西可以防止逆向工程。DVD机器上的固件甚至都经过了反向工程,并且暴露了AACS加密密钥。尽管DMCA将该行为定为刑事犯罪,但这仍然存在。

由于没有任何一种技术方法可以阻止您的客户阅读您的代码,因此您必须采用普通的商业方法。

  1. 许可证。合同。条款和条件。即使人们可以阅读代码,这仍然有效。请注意,某些基于Python的组件可能要求您先付费,然后再使用这些组件销售软件。另外,某些开源许可证禁止您隐藏该组件的来源或来源。

  2. 提供重大价值。如果您的产品非常好-以难以拒绝的价格出售-则没有动力浪费时间和金钱进行任何逆向工程。逆向工程很昂贵。使您的产品便宜一些。

  3. 提供升级和增强功能,使任何逆向工程成为一个坏主意。当下一个版本中断其逆向工程时,没有任何意义。这可能荒唐至极,但是您应该提供新功能,这些新功能使下一个版本比逆向工程更有价值。

  4. 以极具吸引力的价格提供定制服务,以至于他们宁愿您付钱给您构建并支持增强功能。

  5. 使用过期的许可证密钥。这是残酷的,会给您带来不好的声誉,但是肯定会使您的软件停止工作。

  6. 作为网络服务提供。SaaS不涉及向客户的下载。


7
第二点更为重要。如果它比逆向工程便宜,再加上每年的更新便宜,那么没有人会尝试,即使这样做,也没有人会向黑客付款,而是向软件提供商付款。
m3nda

确实如此。逆向工程是可行的,但在大多数情况下是昂贵的。@ S.Lott,基于这个问题,我认为第6点更为重要。如果确实需要保护源代码,那么它应该远离最终用户。
assetCorp

7
问题:“有没有一种好的方法来保护我的家人和我自己,使其免于被我们的睡眠者入侵而谋杀?” 互联网:“不会。任何人都可以找到,没有一个住所能百分百地透彻。凡人的家庭是从事这项工作的错误工具。”
一种简单的算法,

第5点不能在可以逆向工程和破解的相同假设下应用。
jjmontes

314

Python不是您需要的工具

您必须使用正确的工具来完成正确的事情,并且Python并非旨在被混淆。恰恰相反;一切都是开放的,或者很容易在Python中显示或修改,因为这是该语言的理念。

如果您想要看不见的东西,请寻找其他工具。这不是一件坏事,重要的是要存在几种不同的工具以用于不同的用途。

混淆真的很难

即使已编译的程序也可以进行逆向工程,所以不要以为您可以完全保护任何代码。您可以分析混淆的PHP,破坏Flash加密密钥等。每次都会破解较新版本的Windows。

有法律要求是一个好方法

您不能阻止某人滥用您的代码,但是您可以轻松地发现某人是否在使用它。因此,这只是一个偶然的法律问题。

代码保护被高估

如今,商业模式倾向于销售服务而不是产品。您不能复制,盗版或盗用服务。也许是时候考虑顺其自然了...


16
Python不是您需要的工具。马尔博格是。:)
johndodo 2011年

7
好的答案,但是“偶然的法律问题”?真?您住在哪里,有任何偶然的法律问题?
Mark E. Haase 2013年

1
我认为,如果我们有一个频率-昂贵的混淆代码被黑客入侵的频率-我们可以说使用Python和混淆代码的实用性。
sergzach

如果您的代码具有有趣的功能,则可以滥用该代码的人可以将其重新分发给@Macke
assetCorp

您将如何“轻松发现某人是否做到了”?
Make42

145

编译python并分发二进制文件!

明智的主意:

使用CythonNuitkaShed Skin或类似于将python编译为C代码的东西,然后将您的应用分发为python二进制库(pyd)。

这样,我认为就没有剩下Python(字节)代码了,而且您已经做了任何人(即您的雇主)可以从常规代码中期望的合理数量的模糊处理。(.NET或Java不如这种情况安全,因为该字节码不会被混淆,并且可以相对容易地反编译为合理的源代码。)

Cython与CPython的兼容性越来越强,因此我认为它应该可以工作。(我实际上正在考虑将其用于我们的产品。。我们已经在构建一些第三方库作为pyd / dll,因此,将我们自己的python代码作为二进制文件交付对我们来说并不是一个太大的步骤。)

有关如何执行此操作的教程,请参阅此博客文章(不是我本人)。(thx @hithwen)

疯狂的主意:

您可能可以让Cython为每个模块分别存储C文件,然后将它们全部串联起来并使用大量的内联代码进行构建。这样,您的Python模块是非常单一的,并且很难用通用工具来实现。

超越疯狂:

如果您可以静态链接到python运行时和所有库(dll),则可以构建一个可执行文件。这样,肯定很难拦截对python和您使用的任何框架库的调用。但是,如果您使用LGPL代码,则无法完成此操作。


使用cython进行编译是否可以与python 3.4 Django应用程序一起使用,还是可以使它无需花费大量精力即可工作?
丹尼尔(Daniel)

@Daniel:不确定。尚未尝试使用Django。随时发布有关此问题的新问题。
Macke 2015年


4
@mlvljr FWIW,恕我直言,编译为二进制文件是出售您所有秘密与尝试防御NSA级反向工程之间的一个不错的折衷。如果您有大量的python代码库,并且有偏执的理由,请使用Esp。;)
Macke

2
Hithwen的POST现在无效。
qg_java_17137

58

我了解您希望客户使用python的功能,但不希望公开源代码。

这是我的建议:

(a)将关键代码段编写为C或C ++库,然后使用SIPSwig将C / C ++ API公开给Python名称空间。

(b)使用cython代替Python

(c)在(a)和(b)中,都应该可以使用Python接口将库作为许可的二进制文件分发。



我只是按照TyPyPy的建议看了一下Shed Skin,看来这真是个好东西!
Filipe

34

您的雇主是否知道他可以“窃取”他人从您的代码中得到的任何想法?我的意思是,如果他们可以阅读您的作品,那么您也可以阅读。也许看着您如何从这种情况中受益会比担心会损失多少更好地获得投资回报。

[编辑]回答尼克的评论:

一无所有,一无所有。客户拥有自己想要的东西(并且自从进行更改以来就为此付费)。由于他没有发布更改,因此好像其他所有人都没有发生过。

现在,如果客户出售软件,则他们必须更改版权声明(这是非法的,因此您可以提起诉讼,将胜诉->简单案例)。

如果他们不更改版权声明,那么第二级客户将注意到该软件来自您原来的产品,并想知道这是怎么回事。他们很可能会与您联系,因此您将了解有关转售作品的信息。

同样,我们有两种情况:原始客户仅售出了几份。那意味着他们无论如何也赚不了多少钱,那为什么还要打扰呢。或者他们批量销售。这意味着您有更多的机会了解他们的工作并为此做些事情。

但是最后,大多数公司都试图遵守法律(一旦声誉受损,开展业务就会困难得多)。因此,他们不会窃取您的工作,而是会与您一起进行改进。因此,如果您包含源代码(具有可以防止您简单转售的许可证),则它们很可能会简单地推回所做的更改,因为这样可以确保更改在下一版本中进行,而不必维护。这是双赢的:您获得更改,并且即使您不愿意将其真正包含在正式版本中,他们也可以根据自己的需要进行更改,即使他们确实需要它。


如果他们向客户发布软件,并且客户在不重新发布软件的情况下在内部对其进行了修改,该怎么办?
尼克T

@Nick:不会以任何方式改变这种情况。查看我的修改。
亚伦·迪古拉

6
+1用于窃取想法。当您可以看到其他人如何在您的解决方案上进行改进并相应地改进自己的产品时,为什么将您的客户服务能力局限于内部解决方案?“如果您有一个苹果,我有一个苹果,我们交换这些苹果,那么您和我仍然会有一个苹果。但是,如果您有一个想法,而我有一个想法,并且我们交换了这些想法,那么我们每个人都会两个想法。”
约旦

如果您的一位客户免费匿名重新发布了您的代码或想法,该怎么办?您无法说出是谁做的并且起诉他们,因为他们没有从中受益,您也不会。这将破坏您的工作,而您的客户中的一个仅支付基本价格。(显然,只有在您的解决方案拥有多个客户的情况下,该方法才有效)
Skandix

1
@Skandix那将如何工作?在Internet上上传您的作品不会对您造成伤害。如果很多人发现它,而那些人却在向客户付款,它将开始对您造成伤害。代码盗窃是一个神话。“我的知识是免费的,我的时间很昂贵”(不确定谁说的)。
亚伦·迪古拉

34

你看过催眠药吗?它会缩小,混淆和压缩Python代码。对于偶然的逆向工程,示例代码看起来很讨厌。

$ pyminifier --nonlatin --replacement-length=50 /tmp/tumult.py
#!/usr/bin/env python3
ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲמּ=ImportError
ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ燱=print
ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ巡=False
ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ澨=object
try:
 import demiurgic
except ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲמּ:
 ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ燱("Warning: You're not demiurgic. Actually, I think that's normal.")
try:
 import mystificate
except ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲמּ:
 ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ燱("Warning: Dark voodoo may be unreliable.")
ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲﺬ=ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ巡
class ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ𐦚(ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ澨):
 def __init__(self,*args,**kwargs):
  pass
 def ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ클(self,dactyl):
  ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ퐐=demiurgic.palpitation(dactyl)
  ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ𠛲=mystificate.dark_voodoo(ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ퐐)
  return ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ𠛲
 def ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ𐠯(self,whatever):
  ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ燱(whatever)
if __name__=="__main__":
 ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ燱("Forming...")
 ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲﺃ=ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ𐦚("epicaricacy","perseverate")
 ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲﺃ.ﺭ异𞸐𐤔ﭞﰣﺁں𝕌𨿩𞸇뻛𐬑𥰫嬭ﱌ𢽁𐡆𧪮Ꝫﴹ뙫𢤴퉊ﳦﲣפּܟﺶ𐐤ﶨࠔ𐰷𢡶𧐎𐭈𞸏𢢘𦘼ﶻ𩏃𦽨𞺎𠛘𐠲䉊ﰸﭳᣲ𐠯("Codswallop")
# Created by pyminifier (https://github.com/liftoff/pyminifier)

6
这样做的好处是,使尝试解码功能的人士气低落。将其与Cython以及模块或互联网电话上的一些额外加密结合起来,您可能会获得奖励。
m3nda

该程序包唯一可以完成的事情就是愚弄代码被混淆的“混淆器”。
markroxor

当我尝试时,这是犯错误。我认为它处理了数据,并且没有完全转换它。
Vicrobot

不适用于整个项目或模板引擎,因为它需要变量名称才能在模板上显示
TomSawyer

25

不要依靠混淆。正如您已经正确得出的结论,它提供的保护非常有限。更新:这是指向论文链接,该论文在Dropbox中反向工程了经过混淆的python代码。这种方法-操作码重映射是一个很好的障碍,但显然可以克服。

相反,正如许多海报提到的那样做到:

  • 不值得进行反向工程的时间(您的软件是如此出色,值得付出)
  • 让他们签署合同,并在可行时进行许可证审核。

另外,就像踢屁股的Python IDE WingIDE一样:放弃代码。没错,请放弃代码,让人们回来进行升级和支持。


1
喜欢这个极端的想法。以巨大的方式和庞大的市场份额将其推向市场,那么您就拥有大量的支持和插件客户群。我也一直在努力解决这个问题,并且所有“许可”答案基本上都是牛市,因为它不能防止普遍复制,但不能给您带来任何市场份额优势。
Thomas Browne

但是,升级也只是赠品……那么他们将如何收费?难道不只是支持吗?
Make42

关于WingIDE商业模式:支持是服务,软件是产品。产品规模大,服务规模大。只有在没有其他商业模式的情况下,支持才是一种好的商业模式-意味着,如果没有人会购买您的产品(无论出于何种原因),您就会放弃产品,以便拥有至少可以购买服务的客户群。
Make42


19

运送.pyc文件存在问题-它们与使用其创建的python版本不兼容,与任何其他python版本都不兼容,这意味着您必须知道要在其上运行该产品的系统上正在运行哪个python版本。这是一个非常有限的因素。


是的,但是如果您使用混淆的代码分发该确切的Python版本,则不会。
亚历克斯

17

在某些情况下,有可能将软件(全部或至少关键部分)移入组织托管的Web服务中。

这样,可以在您自己的服务器机房中安全地执行许可证检查。


+1(返回0):这似乎是问题的唯一真正解决方案,假设这种方法对设置很实用。
直觉

10
请注意,如果您的许可Web服务器出现故障或客户的互联网访问中断,您的客户会因为失去获得许可检查的权限而无法经营自己的业务而感到不高兴。
DevPlayer 2012年

1
@DevPlayer对此有解决方案。您可以实现本地密钥机制,该机制允许在软件无法访问远程许可服务器时进行临时访问。
杰弗里

1
@Jeffrey:这样可以使您回到开始的地方-如何保护该代码。为了安全起见,您需要在自己的服务器上放置一些关键功能,因此更换它会涉及很多工作(在这一点上,为什么不成立一个开源竞争对手?)
奇怪的是,2015年

14

尽管没有完美的解决方案,但可以执行以下操作:

  1. 将一些关键的启动代码移到本机库中。
  2. 在本机库中强制执行许可证检查。

如果要删除对本机代码的调用,则该程序无论如何都不会启动。如果未删除,则将强制执行许可证。

尽管这不是跨平台或纯Python解决方案,但它可以工作。


3
本机库方法使某人可以轻松地以编程方式暴力破解您的许可证密钥系统,因为他们可以使用自己的代码和API来验证其许可证。
汤姆·莱斯

8
所以?使用RSA签署您的许可证,然后让它们通过蛮力来强制您的私钥,例如包含1024位。可能,但是要花很多时间,因此要花钱。
Abgan

12

我认为还有另一种方法可以保护您的Python代码;混淆方法的一部分。我相信曾经有一款类似Mount and Blade的游戏,或者是某些东西进行了更改并重新编译了自己的python解释器(我认为它是开源的原始解释器),只是将OP代码表中的OP代码更改为与标准python OP不同代码。

因此python源代码未修改,但* .pyc文件的文件扩展名不同,并且操作码与公共python.exe解释器不匹配。如果您检查了游戏数据文件,则所有数据均为Python源格式。

各种各样的恶作剧都可以通过这种方式与未成熟的黑客打成一片。阻止一堆没有经验的黑客很容易。这是您不可能击败的专业黑客。但是我想象大多数公司不会让专业黑客长期待命(可能是因为事情被黑客入侵了)。但是到处都是不成熟的黑客(以好奇的IT员工的身份阅读)。

例如,您可以在经过修改的解释器中,允许其检查源中的某些注释或文档字符串。对于此类代码行,您可能具有特殊的OP代码。例如:

OP 234用于源代码行“#我写的版权”,或者将该行编译为等效于“如果为False:”的操作代码,如果缺少“#版权所有”。出于某些晦涩的原因,基本上禁用了整个代码块。

重新编译经过修改的解释器可能可行的一个用例是,您没有编写该应用程序,但该应用程序很大,但是却得到了保护它的报酬,例如当您是金融应用程序的专用服务器管理员时。

我发现让源代码或操作码开放供人们注意有点矛盾,但是使用SSL进行网络流量。SSL也不是100%安全的。但这是用来阻止MOST的眼睛阅读它的。采取一点预防措施是明智的。

另外,如果足够多的人认为Python源代码和操作码太明显,那么最终有人可能至少会为其开发一个简单的保护工具。因此,越来越多的人问“如何保护Python应用程序”只会促进这种发展。


11

保护代码的唯一可靠方法是在您控制的服务器上运行该代码,并为客户端提供与该服务器连接的客户端。


10

我很惊讶没有在任何答案中看到pyconcrete。也许是因为它比问题新?

它可能正是您所需要的。

它不会混淆代码,而是在加载时对其进行加密和解密。

pypi页面

保护python脚本工作流程

  • your_script.py import pyconcrete
  • pyconcrete将挂钩导入模块
  • 当脚本导入时 MODULE,pyconcrete导入钩子将尝试先查找MODULE.pye然后MODULE.pye通过解密_pyconcrete.pyd并执行解密的数据(如.pyc内容)
  • 加密和解密密钥记录_pyconcrete.pyd (例如DLL或SO),密钥将隐藏在二进制代码中,无法在十六进制视图中直接看到

9

根据客户的身份,将简单的保护机制与明智的许可协议相结合将是远远的。超过任何复杂的许可/加密/模糊系统更有效。

最好的解决方案是将代码作为服务出售,例如通过托管服务或提供支持-尽管这并不总是可行的。

将代码作为.pyc文件发送将防止您的保护被一些人破坏#秒钟,但是它几乎不是有效的反盗版保护(好像有这种技术),并且最终,它应该不会实现将与公司达成体面的许可协议。

专注于使您的代码尽可能地好用-使满意的客户比防止理论上的盗版给您的公司带来更多的收益。


8

使代码更难于窃取的另一种尝试是使用jython,然后使用java obfuscator

当jythonc将python代码转换为java,然后将java编译为字节码时,这应该可以很好地工作。因此,如果您对类进​​行了混淆处理,那么在反编译之后将很难理解其内容,更不用说恢复实际的代码了。

jython的唯一问题是您不能使用用c编写的python模块。


6

通过对重要文件进行散列和签名并使用公钥方法对其进行检查,使用标准的加密方案对代码签名怎么办?

这样,您可以为每个客户颁发带有公钥的许可证文件。

另外,您可以使用像这样的python混淆器(只需在Google上对其进行搜索)。


1
+1进行签名;混淆器的-1至少可以防止代码被更改。
阿里·阿夫沙尔

2
在这种情况下,签名不起作用。总是可以绕过签名检查加载程序。要获得有用的软件保护,第一件事是不透明的引导程序机制。Python并非易事。
ddaa

是的,在非python中引导。
阿里·阿夫沙尔

或者不仅在启动时还要在其他几个地方验证许可证。可以轻松实施,并且可以大大增加旁路时间。
Abgan

6

您应该看看getdropbox.com上的家伙如何为他们的客户端软件(包括Linux)做到这一点。破解起来非常棘手,并且需要一些创造性的拆卸才能通过保护机制。


8
但是事实已经过去了,这意味着他们失败了-底线是不要尝试,而要寻求法律保护。
CHII

是否发布了有关如何通过这种保护机制的任何信息?
Mitar 2012年

6

使用Python最好的办法就是使事物变得晦涩难懂。

  • 删除所有文档字符串
  • 仅分发.pyc编译文件。
  • 冻结它
  • 在类/模块中隐藏常量,以免help(config)不能显示所有内容

您可能可以通过加密一部分并将其动态解密并将其传递给eval()来添加一些其他模糊性。但是,无论您做什么,都可以打破它。

所有这些都不会阻止坚定的攻击者拆卸字节码或使用帮助,目录等在您的api中进行挖掘。


5

具有时间限制的许可证并在本地安装的程序中进行检查的想法将不起作用。即使进行了完美的混淆,也可以删除许可证检查。但是,如果您在远程系统上检查许可证并在封闭的远程系统上运行程序的重要部分,则可以保护您的IP。

为了防止竞争者将源代码用作自己的源代码或编写受启发的同一代码版本,一种保护方法是在程序逻辑中添加签名(某些秘密能够证明代码已从您那里被盗)并混淆了python源代码,因此很难阅读和利用。

良好的混淆功能为您的代码增加了基本上相同的保护,与将其编译为可执行文件(和剥离二进制文件)的保护相同。弄清楚混淆后的复杂代码的工作原理可能比实际编写自己的实现还要困难。

这无助于防止程序被黑客入侵。即使混淆了代码,许可证内容也会被破解,程序可能会被修改为具有稍微不同的行为(以将代码编译为二进制无助于保护本机程序的相同方式)。

除了符号混淆外,取消代码重构也是个好主意,如果例如调用图指向许多不同的地方,即使实际上这些不同的地方最终做同样的事情,这也会使一切变得更加混乱。

混淆代码内部的逻辑签名(例如,您可以创建由程序逻辑使用但也用作签名的值表),可以用来确定代码是否源自您。如果有人决定使用混淆的代码模块作为自己产品的一部分(即使在对其进行混淆以使其看起来有所不同之后),您也可以证明,该代码已被您的秘密签名窃取。


4

我已经为自己的项目研究了软件保护,并且总体上认为完全保护是不可能的。您唯一希望达到的目的是将保护级别提高到一个比购买另一个许可证要花更多的钱的客户。

话虽这么说,我只是检查google的python混淆,没有发现很多东西。在.Net解决方案中,混淆将是在Windows平台上解决问题的第一种方法,但我不确定是否有人在Linux上具有可与Mono配合使用的解决方案。

接下来的事情是用一种编译语言编写代码,或者如果您真的想一路走下去,则使用汇编器。剥离的可执行文件比解释的语言难于反编译。

一切都取决于权衡。一方面,您可以轻松地使用python进行软件开发,但在其中隐藏秘密也是非常困难的。另一方面,您有用汇编器编写的软件,它很难编写,但是更容易隐藏秘密。

您的老板必须在该连续体中的某个位置选择一个可以满足其要求的点。然后他必须给您工具和时间,以便您可以构建他想要的东西。但是我敢打赌,他将反对实际的开发成本与潜在的金钱损失。


4

长话短说:

  1. 加密您的源代码
  2. 编写自己的python模块加载器,以在导入时解密代码
  3. 在C / C ++中实现模块加载器
  4. 您可以向模块加载器添加更多功能,例如反调试器,许可证控制,硬件指纹绑定等。

有关更多详细信息,请查看此答案

如果您对该主题感兴趣,该项目将为您提供-pyprotect


3

对于在内存中加载并执行C启动器的加密资源,可能有py2exe字节码。这里这里的一些想法。

有些人还想到了一种自我修改程序,以使逆向工程变得昂贵。

您还可以找到防止调试器,使反汇编器失败,设置错误的调试器断点以及使用校验和保护代码的教程。搜索[“加密代码”,在“内存中”执行]以获取更多链接。

但是正如其他人已经说过的那样,如果您的代码值得,那么逆向工程师将最终获得成功。


3

如果我们专注于软件许可,我建议您看一下我在这里写的另一个Stack Overflow答案以期获得如何构建许可密钥验证系统的灵感。

GitHub上有一个开源库,可以帮助您进行许可证验证。

您可以通过pip install licensing以下方式安装它,然后添加以下代码:

pubKey = "<RSAKeyValue><Modulus>sGbvxwdlDbqFXOMlVUnAF5ew0t0WpPW7rFpI5jHQOFkht/326dvh7t74RYeMpjy357NljouhpTLA3a6idnn4j6c3jmPWBkjZndGsPL4Bqm+fwE48nKpGPjkj4q/yzT4tHXBTyvaBjA8bVoCTnu+LiC4XEaLZRThGzIn5KQXKCigg6tQRy0GXE13XYFVz/x1mjFbT9/7dS8p85n8BuwlY5JvuBIQkKhuCNFfrUxBWyu87CFnXWjIupCD2VO/GbxaCvzrRjLZjAngLCMtZbYBALksqGPgTUN7ZM24XbPWyLtKPaXF2i4XRR9u6eTj5BfnLbKAU5PIVfjIS+vNYYogteQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"

res = Key.activate(token="WyIyNTU1IiwiRjdZZTB4RmtuTVcrQlNqcSszbmFMMHB3aWFJTlBsWW1Mbm9raVFyRyJd",\
                   rsa_pub_key=pubKey,\
                   product_id=3349, key="ICVLD-VVSZR-ZTICT-YKGXL", machine_code=Helpers.GetMachineCode())

if res[0] == None not Helpers.IsOnRightMachine(res[0]):
    print("An error occured: {0}".format(res[1]))
else:
    print("Success")

您可以在此处详细了解RSA公钥等的配置方式。


2

使用相同的方法来保护c / c ++的二进制文件,即在可执行文件或库二进制文件中混淆每个函数主体,在每个函数条目的开头插入一条指令“ jump”,跳转到特殊函数以恢复混淆的代码。字节码是Python脚本的二进制代码,因此

  • 首先将python脚本编译为代码对象
  • 然后迭代每个代码对象,如下混淆每个代码对象的co_code
    0 JUMP_ABSOLUTE n = 3 + len(字节码)

    3
    ...
    ...这是混淆的字节码
    ...

    n LOAD_GLOBAL?(__pyarmor__)
    n + 3 CALL_FUNCTION 0
    n + 6个POP_TOP
    n + 7 JUMP_ABSOLUTE 0
  • 将混淆的代码对象另存为.pyc或.pyo文件

当第一次调用这些代码对象时,那些混淆的文件(.pyc或.pyo)可以由普通的python解释器使用。

  • 第一个操作是JUMP_ABSOLUTE,它将跳转到偏移量n

  • 在偏移量n处,指令将调用PyCFunction。此函数将恢复偏移量3和n之间的混淆字节码,并将原始字节码放在偏移量0处。混淆码可以通过以下代码获得

        char * obfucated_bytecode;
        Py_ssize_t len;
        PyFrameObject *框架= PyEval_GetFrame();
        PyCodeObject * f_code = frame-> f_code;
        PyObject * co_code = f_code-> co_code;      
        PyBytes_AsStringAndSize(co_code,&obfucated_bytecode,&len)
    
  • 此函数返回后,最后一条指令是跳转到偏移量0。现在将执行实际的字节码。

有一个Pyarmor工具可以通过这种方式混淆python脚本。



1

关于隐藏python源代码有一个全面的答案,可以在此处找到。

讨论的可能技术是:
-使用编译的字节码(python -m compileall
-可执行文件的创建者(或PyInstaller之类的安装程序)
-软件即服务(我认为隐藏代码的最佳解决方案)-python
源代码混淆器


链接转到example.com。
Darian

@Darian感谢您指出这一点。我更新了链接。
迈克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.