Python加密器:修改CPython解释器来保护Python代码

写在前面

大家好,我是刘聪NLP。

今天给大家带来一个Python加密器,通过修改CPython解释器,使之能运行加密后的源代码,从而**「保护源码」** 。

修改后的CPython解释器拥有全部的Python功能,且能执行加密后的源码,从底层修改CPython,几乎不存在兼容性问题,理论上说正常CPython能做的,本人的CPython也能做。


            
本工具思路主要参考:https://zhuanlan.zhihu.com/p/54297880  
源地址:https://zhuanlan.zhihu.com/p/464198228  

        

适用场景

本地部署且想保护Python项目代码。

其他加密方案介绍

  • Pyinstaller:将源码和依赖打包,笨重,有一定的学习成本
  • pyc:提前将源码变为字节码文件,可以修改OPCode来提升安全性,但还是极易被破解
  • pyd:由Cython把Py源码翻译成了.c文件,过程基本不可逆,然后vs再把这个.c文件编译成了pyd文件,安全性有保证,可用于核心模块的加密,会存在不兼容的问题
  • 代码混淆:目前未找到开源好用的项目
  • nuitka:牛逼哄哄的感觉,但自己没用过

预备知识

如果要自己实现本博客介绍的方案,需要简单了解以下知识:

  • CPython:Python语言的官方实现,官方解释器,C语言编写
  • C语言:入门即可
  • 加密解密:对称、非对称加密概念,C如何使用加解密算法
  • gdb调试工具:需了解常用命令
  • linux相关:常规操作,文件监控,进程监控等方法

基本思路

限定运行Python项目的方式,只对python xxx.py的方式加密,其他方式比如-c-m都不予支持,这样可以减小工作量。

思路:使用密钥对Py源码进行加密,可使用对称或非对称方式进行加密。CPython若要执行代码,必然先会fopen文件,但此时的fopen打开的文件里面是加密内容,直接执行会报错,因此修改或替换fopen函数,对加密文件进行解密后再返回文件描述符或指针。

「上述就是核心加密思路,可以按照这个思路对任意版本的CPython进行修改」

实操

本节介绍基于上述思路的修改CPython的完整过程,抛砖引玉,希望能获得更优秀的方案。

  • Step1:编写加密函数,用于加密源文件,本功能应该单独作为一个模块,且**「仅加密人员有权限使用」。**
  • Step2:编写解密函数,用于解密内容
  • Step3:获取密钥,密钥可以是全局变量
  • Step4:找到CPython源码中读取源代码文件的位置,注意要所有位置!
  • Step5:基于Step4找到的位置和Step3获取的密钥,对加密内容进行解密
  • Step6:对解密后的内容生成新的文件指针或文件描述符

细节和技巧

  • 加解密函数可以去网上找找开源的或者使用openssl库
  • 部署后,其实密钥对客户是可见的,为了防止逆向,可以对密钥使用内置密钥进行加密
  • 密钥可以在CPython入口函数中进行读取保存,位置为“./Programs/python.c:14”
  • 为了获取读取源代码文件的位置,可以使用各种奇淫巧计,比如全文检索fopen字段,gdb在fopen中下断点,监控文件读写情况(“inotifywait -m target_file”),直接阅读CPython源码(硬核做法)
  • 对解密后的内容生成新的文件指针或文件描述符,可以使用fmemopen或临时文件

开源镜像介绍

本人已经将修改好的**「CPython解释器」** 和**「加密工具」** 置于docker镜像中,可以拉取镜像后体验使用。注意:真实场景中修改后的CPython解释器不应与加密工具在一个环境中。

真实场景中的使用流程:开发人员项目编码->加密人员进行项目加密->客户本地化部署。其中:

  • 开发人员只有项目源码权限
  • 加密人员有项目源码和加密工具权限
  • 部署人员有加密文件和密钥权限

使用方法

  • Step1:拉取镜像

已经发布在了dockerhub中,可以直接拉取:


          
docker pull dunzhang/encrypted\_py\_37:release_20220205  

      

如果嫌速度慢,可以直接下载镜像:


          
链接:https://pan.baidu.com/s/1guC2wSvnO-sjvk2lK2su0Q   
提取码:nzdp  

      
  • Step2:编写自己的源码

平常怎么写这次就怎么写,注意源码文件夹不要有其他文件,尽量做到数据与代码分离,外部数据路径不要写死,要通过配置路径的方式。最后运行方式一定要是:


          
cd proj_dir && python xxx.py  

      

其中,xxx.py相当于是入口文件。为了方便测试,本人在镜像中放置了测试代码,位置在“/home/example_code”,后面操作均以这份代码为例。

  • Step3:加密源码

加密工具路径为 /home/encrypt_src使用方法:


          
enctypt\_src [src\_dir] [entry\_file\_name] [pwd] [save_path]  
src_dir: Py项目文件夹,代码和数据分离,里面只应有Py文件,必须是绝对路径  
entry\_file\_name: 项目入口文件,要包含后缀,要保证项目运行方式为:'cd src\_dir && python entry\_file_name'  
pwd: 加密密钥,长度小于13  
save_path: 加密文件保存路径,必须是绝对路径"  

      

工具示例 :


          
cd /home  
chmod a+x encrypt_src   
./encrypt\_src /home/example\_code run.py 10242048 /home/enc_proj.bin  

      
  • Step4:测试运行

在本镜像中,修改后的CPython解释器为pyen,使用方式和正常的python命令一样,对应的pip命令为pipen,使用方式也和pip一致。本解释器所用的密码为环境变量PY37ENPWD的值。下面是测试结果:1、运行未加密项目:picture.image

总结

为了提升本开源工具的安全性,有兴趣的朋友可以尝试逆向等操作,即模拟真实环境,在只有加密解释器、加密代码和密钥的情况下尝试获取程序源码。本人做了比较简单的保护措施,比如加壳等。希望以此能进一步提升安全性。

往期推荐

PairSCL:句子对级别的有监督对比学习方法

COLD:中文冒犯性语言检测数据集

SNCSE:一种基于软负例的无监督句向量对比学习方法

ExtraPhrase:一种针对抽象式(生成式)摘要的数据增强方法

MatchSum-一种基于语义匹配的抽取式摘要框架

BertSum-基于BERT模型的抽取式文本摘要

CPT模型:一种中文兼顾NLU和NLG的非平衡预训练语言模型

EMNLP2021之AEDA:一种更简单的文本分类数据增强技术

常用预训练语言模型(PTMs)总结

一个使模型训练速度提升20%的Trick--BlockShuffle

0
0
0
0
评论
未登录
暂无评论