小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

如何保護(hù)你的 Python 代碼 (一)—— 現(xiàn)有加密方案

 highoo 2019-09-30

“Python貓” ,一個(gè)值得加星標(biāo)的公眾號(hào)

花下貓語(yǔ):Python 是一種入門容易的語(yǔ)言,初學(xué)者就可以輕松地完成各種任務(wù),但是,Python 的用處與邊界也很廣,有太多的話題值得我們?nèi)パ芯刻剿鳌?今天,我繼續(xù)給大家分享一篇優(yōu)質(zhì)的進(jìn)階文章,讓我們一起學(xué)習(xí)進(jìn)步吧!

作者:Prodesire(經(jīng)作者授權(quán)轉(zhuǎn)載)

出處:鏈接

劇照 | 《神雕俠侶》

0 前言

去年11月在PyCon China 2018 杭州站分享了 Python 源碼加密,講述了如何通過(guò)修改 Python 解釋器達(dá)到加解密 Python 代碼的目的。然而因?yàn)楣P者拖延癥發(fā)作,一直沒(méi)有及時(shí)整理成文字版,現(xiàn)在終于戰(zhàn)勝了它,才有了本文。

本系列將首先介紹下現(xiàn)有源碼加密方案的思路、方法、優(yōu)點(diǎn)與不足,進(jìn)而介紹如何通過(guò)定制 Python 解釋器來(lái)達(dá)到更好地加解密源碼的目的。

由于 Python 的動(dòng)態(tài)特性和開(kāi)源特點(diǎn),導(dǎo)致 Python 代碼很難做到很好的加密。社區(qū)中的一些聲音認(rèn)為這樣的限制是事實(shí),應(yīng)該通過(guò)法律手段而不是加密源碼達(dá)到商業(yè)保護(hù)的目的;而還有一些聲音則是不論如何都希望能有一種手段來(lái)加密。于是乎,人們想出了各種或加密、或混淆的方案,借此來(lái)達(dá)到保護(hù)源碼的目的。

常見(jiàn)的源碼保護(hù)手段有如下幾種:

發(fā)行.pyc文件

代碼混淆

使用py2exe

使用Cython

下面來(lái)簡(jiǎn)單說(shuō)說(shuō)這些方案。

1 發(fā)行 .pyc 文件 1.1 思路

大家都知道,Python 解釋器在執(zhí)行代碼的過(guò)程中會(huì)首先生成.pyc文件,然后解釋執(zhí)行.pyc文件中的內(nèi)容。當(dāng)然了,Python 解釋器也能夠直接執(zhí)行.pyc文件。而.pyc文件是二進(jìn)制文件,無(wú)法直接看出源碼內(nèi)容。如果發(fā)行代碼到客戶環(huán)境時(shí)都是.pyc而非.py文件的話,那豈不是能達(dá)到保護(hù) Python 代碼的目的?

1.2 方法

.py文件編譯為.pyc文件,是件非常輕松地事情,可不需要把所有代碼跑一遍,然后去撈生成的.pyc文件。

事實(shí)上,Python 標(biāo)準(zhǔn)庫(kù)中提供了一個(gè)名為 compileall 的庫(kù),可以輕松地進(jìn)行編譯。

執(zhí)行如下命令能夠?qū)⒈闅v<src>目錄下的所有.py文件,將之編譯為.pyc文件:

python -m compileall<src>然后刪除<src>目錄下所有.py文件就可以打包發(fā)布了:

\$ find <src> -name '*.py' -type f -print -exec rm {} \\;
1.3 優(yōu)點(diǎn)

簡(jiǎn)單方便,提高了一點(diǎn)源碼破解門檻

平臺(tái)兼容性好,.py能在哪里運(yùn)行,.pyc就能在哪里運(yùn)行

1.4 不足

解釋器兼容性差,.pyc只能在特定版本的解釋器上運(yùn)行

有現(xiàn)成的反編譯工具,破解成本低

python-uncompyle6 就是這樣一款反編譯工具,效果出眾。

執(zhí)行如下命令,即可將.pyc文件反編譯為.py文件:

\$ uncompyle6 *compiled-python-file-pyc-or-pyo*
2 代碼混淆

如果代碼被混淆到一定程度,連作者看著都費(fèi)勁的話,是不是也能達(dá)到保護(hù)源碼的目的呢?

2.1 思路

既然我們的目的是混淆,就是通過(guò)一系列的轉(zhuǎn)換,讓代碼逐漸不讓人那么容易明白,那就可以這樣下手:- 移除注釋和文檔。沒(méi)有這些說(shuō)明,在一些關(guān)鍵邏輯上就沒(méi)那么容易明白了。- 改變縮進(jìn)。完美的縮進(jìn)看著才舒服,如果縮進(jìn)忽長(zhǎng)忽短,看著也一定鬧心。- 在tokens中間加入一定空格。這就和改變縮進(jìn)的效果差不多。- 重命名函數(shù)、類、變量。命名直接影響了可讀性,亂七八糟的名字可是閱讀理解的一大障礙。- 在空白行插入無(wú)效代碼。這就是障眼法,用無(wú)關(guān)代碼來(lái)打亂閱讀節(jié)奏。

2.2 方法 方法一:使用 oxyry 進(jìn)行混淆

鏈接 是一個(gè)在線混淆 Python 代碼的網(wǎng)站,使用它可以方便地進(jìn)行混淆。

假定我們有這樣一段 Python 代碼,涉及到了類、函數(shù)、參數(shù)等內(nèi)容:

# coding: utf-8
class A(object):
'''
Description
'''
def __init__(self, x, y, default=None):
self.z = x + y
self.default = default
def name(self):
return 'No Name'
def always():
return True
num = 1
a = A(num, 999, 100)
a.name()
always()

經(jīng)過(guò)Oxyry的混淆,得到如下代碼:

class A (object ):#line:4
''#line:7
def __init__ (O0O0O0OO00OO000O0 ,OO0O0OOOO0000O0OO ,OO0OO00O00OO00OOO ,OO000OOO0O000OOO0 =None ):#line:9
O0O0O0OO00OO000O0 .z =OO0O0OOOO0000O0OO +OO0OO00O00OO00OOO #line:10
O0O0O0OO00OO000O0 .default =OO000OOO0O000OOO0 #line:11
def name (O000O0O0O00O0O0OO ):#line:13
return 'No Name'#line:14
def always ():#line:17
return True #line:18
num =1 #line:21
a =A (num ,999 ,100 )#line:22
a .name ()#line:23
always ()

混淆后的代碼主要在注釋、參數(shù)名稱和空格上做了些調(diào)整,稍微帶來(lái)了點(diǎn)閱讀上的障礙。

方法二:使用 pyobfuscate 庫(kù)進(jìn)行混淆

pyobfuscate 算是一個(gè)頗具年頭的 Python 代碼混淆庫(kù)了,但卻是“老當(dāng)益壯”了。

對(duì)上述同樣一段 Python 代碼,經(jīng)pyobfuscate混淆后效果如下:

# coding: utf-8
if 64 - 64: i11iIiiIii
if 65 - 65: O0 / iIii1I11I1II1 % OoooooooOO - i1IIi
class o0OO00 ( object ) :
if 78 - 78: i11i . oOooOoO0Oo0O
if 10 - 10: IIiI1I11i11
if 54 - 54: i11iIi1 - oOo0O0Ooo
if 2 - 2: o0 * i1 * ii1IiI1i % OOooOOo / I11i / Ii1I
def __init__ ( self , x , y , default = None ) :
self . z = x + y
self . default = default
if 48 - 48: iII111i % IiII + I1Ii111 / ooOoO0o * Ii1I
def name ( self ) :
return 'No Name'
if 46 - 46: ooOoO0o * I11i - OoooooooOO
if 30 - 30: o0 - O0 % o0 - OoooooooOO * O0 * OoooooooOO
def Oo0o ( ) :
return True
if 60 - 60: i1 + I1Ii111 - I11i / i1IIi
if 40 - 40: oOooOoO0Oo0O / O0 % ooOoO0o + O0 * i1IIi
I1Ii11I1Ii1i = 1
Ooo = o0OO00 ( I1Ii11I1Ii1i , 999 , 100 )
Ooo . name ( )
Oo0o ( ) # dd678faae9ac167bc83abf78e5cb2f3f0688d3a3

相比于方法一,方法二的效果看起來(lái)更好些。除了類和函數(shù)進(jìn)行了重命名、加入了一些空格,最明顯的是插入了若干段無(wú)關(guān)的代碼,變得更加難讀了。

2.3 優(yōu)點(diǎn)

簡(jiǎn)單方便,提高了一點(diǎn)源碼破解門檻

兼容性好,只要源碼邏輯能做到兼容,混淆代碼亦能

2.4 不足

只能對(duì)單個(gè)文件混淆,無(wú)法做到多個(gè)互相有聯(lián)系的源碼文件的聯(lián)動(dòng)混淆

代碼結(jié)構(gòu)未發(fā)生變化,也能獲取字節(jié)碼,破解難度不大

3 使用 py2exe 3.1 思路

py2exe 是一款將 Python 腳本轉(zhuǎn)換為 Windows 平臺(tái)上的可執(zhí)行文件的工具。其原理是將源碼編譯為.pyc文件,加之必要的依賴文件,一起打包成一個(gè)可執(zhí)行文件。

如果最終發(fā)行由py2exe打包出的二進(jìn)制文件,那豈不是達(dá)到了保護(hù)源碼的目的?

3.2 方法

使用py2exe進(jìn)行打包的步驟較為簡(jiǎn)便。

1)編寫入口文件。本示例中取名為hello.py

print 'Hello World'

2)編寫setup.py

from distutils.core import setup
import py2exe
setup(console=['hello.py'])

3)生成可執(zhí)行文件

python setup.py py2exe

生成的可執(zhí)行文件位于dist\\hello.exe。

3.3 優(yōu)點(diǎn)

能夠直接打包成 exe,方便分發(fā)和執(zhí)行

破解門檻比 .pyc 更高一些

3.4 不足

兼容性差,只能運(yùn)行在 Windows 系統(tǒng)上

生成的可執(zhí)行文件內(nèi)的布局是明確、公開(kāi)的,可以找到源碼對(duì)應(yīng)的.pyc文件,進(jìn)而反編譯出源碼

4 使用 Cython 4.1 思路

雖說(shuō)Cython的主要目的是帶來(lái)性能的提升,但是基于它的原理:將.py/.pyx編譯為.c文件,再將.c文件編譯為.so(Unix) 或.pyd(Windows),其帶來(lái)的另一個(gè)好處就是難以破解。

4.2 方法

使用Cython進(jìn)行開(kāi)發(fā)的步驟也不復(fù)雜。

1)編寫文件hello.pyxhello.py

def hello():
print('hello')

2)編寫setup.py

from distutils.core import setup
from Cython.Build import cythonize
setup(name='Hello World app',
ext_modules=cythonize('hello.pyx'))

3)編譯為.c,再進(jìn)一步編譯為.so.pyd

python setup.py build_ext --inplace

執(zhí)行python -c 'from hello import hello;hello()'即可直接引用生成的二進(jìn)制文件中的hello()函數(shù)。

4.3 優(yōu)點(diǎn)

生成的二進(jìn)制 .so 或 .pyd 文件難以破解

同時(shí)帶來(lái)了性能提升

4.4 不足

兼容性稍差,對(duì)于不同版本的操作系統(tǒng),可能需要重新編譯

雖然支持大多數(shù) Python 代碼,但如果一旦發(fā)現(xiàn)部分代碼不支持,完善成本較高

下篇文章我們將重點(diǎn)介紹一種新的保護(hù)源碼的方法。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多