免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
python文件編譯與pyc反編譯

pyc是編譯py之后生成的二進(jìn)制文件。當(dāng)我們發(fā)布系統(tǒng)的時(shí)候不想讓別人看到源代碼,就需要將py文件編譯生成pyc文件,對外只提供pyc文件。同樣,如果拿到一個(gè)python程序,只有pyc文件,我們就無法看到源碼,希望有辦法反編譯pyc文件以獲得源碼。

既然有反編譯的需求,為了保護(hù)pyc文件不被反編譯,我們又希望找到一個(gè)方法來防止pyc文件被反編譯。

本文介紹了如何將py文件編譯成pyc和pyo文件,也介紹了如何反編譯pyc文件, 又給出了一種字節(jié)碼混淆方法來防止pyc文件被反編譯。

1 編譯py文件到pyc和pyo

pyc是編譯py之后生成的二進(jìn)制文件,由python虛擬機(jī)來執(zhí)行的。當(dāng)我們發(fā)布系統(tǒng)的時(shí)候不想讓別人看到源代碼,就需要將py文件編譯生成pyc文件,對外只提供pyc文件。

同時(shí),在模塊被加載時(shí),.pyc文件比.py文件更快

但是pyc的內(nèi)容跟python的版本相關(guān),不同的版本編譯后的pyc文件不同,2.5編譯的pyc文件不能到3.5上執(zhí)行.

發(fā)布python軟件的過程為:

1. 生產(chǎn)pyc文件: python -m compileall .

2. 刪除py文件: find . -name “*.py” |xargs rm -rf

3. 刪除pycache目錄: find . -name “pycache” |xargs rm -rf

1.1 Python2 編譯

命令:

python -m py_compile file.py

python -m py_compile {file1,file2}.py

編譯完成后,生成的 .pyc文件在當(dāng)前目錄。

可以使用-O或者-OO轉(zhuǎn)換python命令來減少編譯模塊的大小

    -O轉(zhuǎn)換會(huì)幫你去掉assert語句

    -OO轉(zhuǎn)換會(huì)幫你去掉assert語句和__doc__文檔字符串

由于一些程序可能依賴于assert語句或文檔字符串,應(yīng)該在確認(rèn)需要的情況下使用這些選項(xiàng)。

例如 python –O -m py_compile file.py 會(huì)在本目錄生成 file.pyo

1.2 python3 編譯

Python3的編譯和python2一樣,只是在python3之后編譯后的文件在pycache目錄下,而不是與源文件同一目錄。

那么如何讓python3實(shí)現(xiàn)生成的pyc與源代碼在同一目錄呢?可以加上-b參數(shù),例如

Python3 -m py_compile -b file.py

1.3 批量編譯

python -m compileall DIR

python3 -m compileall –b DIR

DIR為需要編譯的目錄

例如: python -m compileall .

參數(shù)說明:

usage: python compileall.py [-l] [-f] [-q] [-d destdir] [-x regexp] [-i list] [directory|file ...]

arguments: zero or more file and directory names to compile; if no arguments given,

           defaults to the equivalent of -l sys.path

options:

-l: don't recurse into subdirectories

-f: force rebuild even if timestamps are up-to-date

-q: output only error messages

-d destdir: directory to prepend to file paths for use in compile-time tracebacks and in

            runtime tracebacks in cases where the source file is unavailable

-x regexp: skip files matching the regular expression regexp; the regexp is searched for

           in the full path of each file considered for compilation

-i file: add all the files and directories listed in file to the list considered for

         compilation; if "-", names are read from stdin

1.4 代碼實(shí)現(xiàn)

單文件編譯:

import py_compile
py_compile.compile('path') //path
是包括.py文件名的路徑

批量編譯:

      import compileall

compileall.compile_dir('$dir')

2反編譯pyc

如果只有pyc文件,我們是無法直接查看內(nèi)容的,這時(shí),就需要反編譯工具將pyc文件反編譯成py源程序。 這里介紹uncompyle6反編譯工具。Pyc文件能夠反編譯的前提是文件沒有被加密或者代碼混淆。

2.1 Uncompyle6安裝

> git clone https://github.com/rocky/python-uncompyle6.git

> git checkout python-2.4

> sudo python setup.py install

如果沒有報(bào)錯(cuò),則安裝成功了。

2.2反編譯

執(zhí)行命令:

>uncompyle6 -o . *.pyc

這時(shí)會(huì)在當(dāng)前目錄生成.py源文件。

3 防止反編譯pyc文件

如何防止pyc文件被反編譯呢? 這里介紹字節(jié)碼混淆的方法,此方法能夠抵擋低端的反編譯手段,例如第2章的方法,但是,要到高手,還是抵擋不住。

字節(jié)碼混淆可以非常容易的欺騙通常的反匯編器和反編譯器,同時(shí)不影響代碼的正常執(zhí)行。下面這個(gè)例子展示了如何欺騙Uncompyle6反編譯器以及dis反匯編器:

#一個(gè)簡單的Python應(yīng)用 sample1.py

print 'Hello World'

對其進(jìn)行編譯:

python -m py_compile sample1.py

對編譯后的sample1.pyc使用Python內(nèi)置dis模塊反匯編:

      >>> import marshal,dis

>>> fd = open('sample1.pyc', 'rb')

>>> fd.seek(8)

>>> sample1_code_obj = marshal.load(fd)

>>> fd.close()

>>> dis.dis(sample1_code_obj)

  1           0 LOAD_CONST               0 ('Hello World')

              3 PRINT_ITEM

              4 PRINT_NEWLINE

              5 LOAD_CONST               1 (None)

              8 RETURN_VALUE

>>>

以上的匯編代碼筆者肉眼反匯編的結(jié)果如下:

0 LOAD_CONST     0 ('Hello World') #加載co_consts[0]到棧頂,co_consts[0]存儲著常量字符串'Hello World'

3 PRINT_ITEM                       #打印棧頂?shù)?/span>sys.stdout,即print 'Hello World'

4 PRINT_NEWLINE                    #打印新行到sys.stdout,此指令因print語句而由編譯器自動(dòng)生成

5 LOAD_CONST     1 (None)          #加載co_consts[1]到棧頂,co_consts[1]存儲著None

8 RETURN_VALUE                     #將棧頂返回給調(diào)用者,此兩條指令為編譯器自動(dòng)生成

現(xiàn)在我們修改sample1.pyc,在程序入口增加一條絕對跳轉(zhuǎn)指令(可以使用UltraEdit 16進(jìn)制插入功能修改pyc文件,”JUMP_ABSOLUTE 3”在Python 2.7中對應(yīng)的字節(jié)碼為 0x71 0x03 0x00。修改code string內(nèi)容的同時(shí)應(yīng)修改code string的長度,此處增加了一個(gè)3字節(jié)指令),使用內(nèi)置dis模塊反匯編的結(jié)果如下:

  1           0 JUMP_ABSOLUTE            3                 #自行添加

        >>    3 LOAD_CONST               0 ('Hello World')

              6 PRINT_ITEM

              7 PRINT_NEWLINE

              8 LOAD_CONST               1 (None)

             11 RETURN_VALUE

如果讀者對匯編代碼有一定認(rèn)識,就會(huì)明白此處的絕對跳轉(zhuǎn)對Python虛擬機(jī)執(zhí)行此程序基本沒有影響(除了增加一個(gè)指令執(zhí)行周期),然而這個(gè)絕對跳轉(zhuǎn)將成功欺騙反編譯器。使用Uncompyle6反編譯的結(jié)果如下:

<<< Error: Decompiling stopped due to <class 'uncompyle6.semantics.pysource.ParserError'>

如果一個(gè)pyc文件無法被反編譯,初級的破解者可能就會(huì)止步于此了,但對于有經(jīng)驗(yàn)的工程師來說這還遠(yuǎn)遠(yuǎn)不夠。同樣的,我們還要讓通常的反匯編器也無法工作才行。按下面的匯編代碼繼續(xù)加工上面的sample1.pyc。

|   1           0 JUMP_ABSOLUTE        [71 06 00]     6

|               3 LOAD_CONST           [64 FF FF] 65535 (FAKE!)

|         >>    6 LOAD_CONST           [64 00 00]     0 (Hello World)

|               9 PRINT_ITEM           [47 -- --]

|              10 PRINT_NEWLINE        [48 -- --]

|              11 LOAD_CONST           [64 01 00]     1 (None)

|              14 RETURN_VALUE         [53 -- --]

以上第二條指令的意思是加載code object常量表的第65535項(xiàng)到棧頂。在上述sample1.pyc中,常量表的長度為2,下標(biāo)65535已超出常量表的范圍,所以這是條非法指令。但由于第一條絕對跳轉(zhuǎn)的存在,第二條指令永遠(yuǎn)都不會(huì)被執(zhí)行。通常的反匯編器如dis會(huì)盡全力列舉有用的信息,但并不能理解實(shí)際執(zhí)行的控制流,當(dāng)反匯編器嘗試反匯編第二條指令時(shí),會(huì)試著去讀取code object常量表的第65535項(xiàng)并且拋出一個(gè)’tuple index out of range’的意外。Python內(nèi)置dis模塊的出錯(cuò)信息如下:

>>> fd = open('sample1.pyc', 'rb')

>>> fd.seek(8)

>>> import marshal,dis

>>> sample1_code_obj = marshal.load(fd)

>>> dis.dis(sample1_code_obj)

  1           0 JUMP_ABSOLUTE            6

              3 LOAD_CONST           65535

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

  File "C:\Python27\lib\dis.py", line 43, in dis

    disassemble(x)

  File "C:\Python27\lib\dis.py", line 96, in disassemble

    print '(' + repr(co.co_consts[oparg]) + ')',

IndexError: tuple index out of range

>>>

現(xiàn)在Uncompyle6和dis都被欺騙了,代碼得到了有效的保護(hù)。

4 Reference

https://blog.csdn.net/ir0nf1st/article/details/61650984

https://www.cnblogs.com/nickchen121/p/10802465.html

https://www.cnblogs.com/dkblog/archive/2009/04/16/1980757.html

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Pyc文件編譯和運(yùn)行
python學(xué)習(xí)
[Python] python代碼加密
什么是pyc文件
python下編譯py成pyc和pyo
云計(jì)算開發(fā)技術(shù),Python自動(dòng)化運(yùn)維開發(fā)實(shí)戰(zhàn)三部分
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服