這幾天公司的Python3須要加密,網上的文章要麼提供思路不提供代碼,要麼加密以後本身都無法用了。。沒辦法只能本身寫了python
文章總體思路shell
一、修改python源碼opcode爲隨機值app
修改下載後的Python源碼包中opcode值(opcode能夠理解爲python讀取代碼的座標,好比一個變量的opcode是5,則cpython讀取這個變量時是從第5個字符串開始讀的),修改後會致使關鍵變量的opcode混亂,除了本身的環境外,其餘人都執行和解密不了了dom
二、在修改好opcode的python環境,把全部py文件編譯成pyc,而後刪除原始py文件python2.7
修改opcode的腳本:
#!/usr/bin/env python2.7 # encoding:utf-8 #FileName scramble-opcodes.py __author__ = 'mafei' import argparse import re import random import os python_version = 'Python-3.5.3' regex_for_opcode_h = r'^#define\s+(?P<name>[A-Z_]+)\s+(?P<code>\d+)(?P<extra>.*)' regex_for_opcode_py = r'^(?P<key>[a-z_]+)+\(\'+(?P<name>[A-Z_]+)+\'+\,\s+(?P<code>\d+)(?P<extra>.*)' try: from importlib.machinery import SourceFileLoader except ImportError: import imp class replace_opcode(object): def __init__(self): self.replace_dict = {} self.not_have_argument_code_list = [] self.have_argument_code_list = [] def set_list(self, reg, file): f1 = open(file, 'r+') infos = f1.readlines() f1.seek(0, 0) for line in infos: rex = re.compile(reg).match(line) if rex: if rex.group('name') in ['CALL_FUNCTION', 'CALL_FUNCTION_KW', 'CALL_FUNCTION_EX', 'CALL_FUNCTION_VAR', 'CALL_FUNCTION_VAR_KW']: continue elif int(rex.group('code')) < 90: self.not_have_argument_code_list.append(int(rex.group('code'))) else: self.have_argument_code_list.append(int(rex.group('code'))) def replace_file(self, reg, file, is_update=False): if not is_update: self.set_list(reg, file) f1 = open(file, 'r+') infos = f1.readlines() f1.seek(0, 0) for line in infos: rex = re.compile(reg).match(line) if rex: n = self.replace_code(rex, is_update) line = line.replace(rex.group('code'), str(n)) f1.write(line) f1.close() def replace_code(self, rex, is_update): if is_update: try: n = self.replace_dict[rex.group('name')] except: n = rex.group('code') return n if rex.group('name') == "CALL_FUNCTION": n = int(rex.group('code')) elif rex.group('name') in ['CALL_FUNCTION_KW', 'CALL_FUNCTION_EX', 'CALL_FUNCTION_VAR', 'CALL_FUNCTION_VAR_KW']: n = int(rex.group('code')) else: if int(rex.group('code')) < 90: n = random.choice(self.not_have_argument_code_list) self.not_have_argument_code_list.remove(n) else: n = random.choice(self.have_argument_code_list) self.have_argument_code_list.remove(n) self.replace_dict[rex.group('name')] = n return n def run(self, source_directory): OPCODE_PY = 'Lib/opcode.py' OPTARGETS_H = "Include/opcode.h" print source_directory print('start run......', os.path.join(source_directory, OPCODE_PY)) self.replace_file(reg=regex_for_opcode_py, file=os.path.join(source_directory, OPCODE_PY)) print('run {} end'.format(os.path.join(source_directory, OPCODE_PY))) print('start run......', os.path.join(source_directory, OPCODE_PY)) self.replace_file(reg=regex_for_opcode_h, file=os.path.join(source_directory, OPTARGETS_H), is_update=True) print('run {} end'.format(os.path.join(source_directory, OPTARGETS_H))) self.write_opcode_targets_contents() print('run {} end'.format(os.path.join(source_directory, OPTARGETS_H))) def write_opcode_targets_contents(self, file='Python/opcode_targets.h'): """Write C code contents to the target file object. """ targets = ['_unknown_opcode'] * 256 for opname, op in sorted(self.replace_dict.items(), key=lambda nc: nc[1]): targets[op] = "TARGET_%s" % opname with open(os.path.join(source_directory, file), 'w') as f: f.write("static void *opcode_targets[256] = {\n") sep = ',%s' % os.linesep f.write(sep.join([" &&%s" % s for s in targets])) f.write("\n};\n") if __name__ == '__main__': parser = argparse.ArgumentParser(description='Scramble python opcodes table') parser.add_argument('--python-source', dest='src', type=str, help='Python source code', required=True) args = parser.parse_args() source_directory = os.path.abspath(args.src) # main(source_directory) replace_opcode_class = replace_opcode() replace_opcode_class.run(source_directory)
cd /opt/ 下載源碼包 wget 解壓 tar xJf Python-3.5.3.tar.xz
執行修改opcode操做ide
python scramble-opcodes.py --python-source=/opt/Python-3.5.3
#後面幾步就是標準的python安裝步驟啦
ui
cd /opt/Python-3.5.3 加密
./configure --prefix=/opt/python-3.5.3 && make && make installspa
加入系統路徑code
export PATH=/opt/python-3.5.3/bin/:$PATH 這時候執行python3就能夠進入python3.5.3的修改opcode後的環境了
加密Python代碼(必定要在修改過opcode的Python環境執行,不然不生效的)
#!/usr/bin/env python2.7 # encoding:utf-8 __author__ = 'mafei' import os import subprocess import argparse import sys def compile_py3(source_dir): g = os.walk(source_dir) # compileall.compile_dir(source_dir, maxlevels=100) subprocess.check_output('{} -m compileall -b {}'.format(sys.executable,source_dir),shell=True) for path,d,filelist in g: for filename in filelist: #對全部py文件進行加密並刪除原始文件 if os.path.splitext(filename)[-1] =='.py': os.remove(os.path.join(path, filename)) print('compile {}'.format(os.path.join(path, filename))) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Scramble python opcodes table') parser.add_argument('--python-source', dest='src', type=str, help='Python source code', required=True) args = parser.parse_args() source_directory = os.path.abspath(args.src) compile_py3(source_directory)