一日一技:如何對(duì)Python代碼進(jìn)行混淆
目前市面上沒有任何方法能夠完全避免你的程序被人反編譯。即便是3A游戲大作,發(fā)布出來沒多久也會(huì)被人破解?,F(xiàn)在只能做到增大反編譯的難度,讓程序相對(duì)無法那么快被破解。
我們知道,Python代碼默認(rèn)是公開的。當(dāng)你要把一個(gè)Python項(xiàng)目給別人運(yùn)行的時(shí)候,一般來說別人就能看到你的全部源代碼。我們可以使用Cython、Nuitka對(duì)代碼進(jìn)行打包,編譯成.so文件、.dll文件或者是可執(zhí)行文件,從而在一定程度上避免別人看到你的源代碼。我在字節(jié)的時(shí)候,內(nèi)部的一個(gè)系統(tǒng)就是使用Cython打包的,然后部署到客戶的服務(wù)器上。
Cython、Nuitka在打包大型項(xiàng)目時(shí),需要寫大量的配置文件甚至是額外的程序,有一定的使用成本。如果你對(duì)安全的要求并沒有那么高,那么其實(shí)你只需要對(duì)Python代碼進(jìn)行混淆,就能防止自己的代碼被人輕易看到了。
我們可以使用Pyminifier來對(duì)Python代碼進(jìn)行混淆。它的使用方法非常簡(jiǎn)單,pip安裝以后,執(zhí)行幾行命令就可以完成。我們來看幾個(gè)例子。
假設(shè)我有一段Python爬蟲代碼。原始代碼是這樣的:
import glob
import uvicorn
import random
from pathlib import Path
from fastapi import FastAPI
from fastapi.responses import FileResponse
IMAGE_TYPE = ['*.J*', '*.P*', '*.j*', '*.p*', '*.GIF', '*.gif']
app = FastAPI()
def iter_images(folder='*'):
images = []
target_folder = Path('images') / Path(folder)
if folder != '*':
if not Path(target_folder).exists():
return []
for image_type in IMAGE_TYPE:
images.extend(glob.glob(str(target_folder / Path(image_type))))
return images
@app.get('/')
def index():
images = iter_images()
if not images:
return {'success': False, 'msg': 'No Images.'}
path = random.choice(images)
return FileResponse(path)
@app.get('/every/{name}')
def get_one_goddess(name):
images = iter_images(name)
if not images:
return {'success': False, 'msg': 'No Images.'}
path = random.choice(images)
return FileResponse(path)
if __name__ == '__main__':
uvicorn.run(app='main:app')
這段代碼能夠?qū)崿F(xiàn)一個(gè)簡(jiǎn)單的圖片服務(wù)器,當(dāng)我們?cè)L問http://127.0.0.1:8000時(shí),就會(huì)隨機(jī)顯示一張圖片,如下圖所示:
圖片
我們現(xiàn)在來安裝pyminifier。由于這個(gè)程序的代碼很久沒有更新了,因此如果你的Python版本比較高,那么需要首先降一下setuptools的版本,然后再安裝pyminifier:
pip install "setuptools<58.0.0"
pip install pyminifier
安裝完成以后,我們來對(duì)代碼進(jìn)行混淆,執(zhí)行如下命令:
pyminifier --nonlatin --replacement-length=50 main.py > output.py
生成的output.py就是混淆以后的代碼,效果如下圖所示:
圖片
這樣的代碼,顯然已經(jīng)完全沒法看了。除非對(duì)方就是沖著對(duì)你的代碼進(jìn)行破解來的,否則一般人看了這個(gè)混淆以后的代碼,直接就走了。
混淆完成以后,這個(gè)代碼依然是直接運(yùn)行python output.py。功能不受任何影響。
這樣的混淆,屬于『君子鎖』,只放君子不防小人。真的要反混淆其實(shí)并不困難。只是增加了幾步操作而已。在對(duì)保密要求不那么高的情況下可以使用,畢竟非常簡(jiǎn)單,不需要對(duì)已有代碼做任何修改。