• 基于Cython和内置distutils库,实现python源码加密(非混淆模式)


    起因

    python本身只能做混淆,不能加密,多年的商业软件开发导致有某种“洁癖”:欲将py编译打包

    尝试

    • pyinstaller原理是freeze打包pyc文件,利用工具可完美逆行出源码
    • 各种混淆脚本,版本兼容很差,配置繁琐
    • cython 常规使用只能编译单个特殊模块

    解决

    反复尝试摸索后,还是利用了cython和distutils库,自动化识别并转换py到c源码并编译,放出源码供大家参考

    """ 
    利用cython和distutils编译py到pyd[so] 注意安装cython及本地平台对应编译器
    http://flywuya.cnblogs.com/
     """
    import os
    import shutil
    from distutils.core import setup
    from distutils.command.build_ext import build_ext
    from Cython.Build import cythonize
    
    BUILD_CONFIG = {
        'SupportExt': ['.py', '.pyx'],
        'CopyOnlyFile': ['__main__.py', '__init__.py'],
        'CopyOnlyDir': ['assets'],
        'IgnoreDir': ['dist', 'build', '__pycache__'],
    }
    
    
    def copy_tree(src, dst):
        """ not like shutil.copytree, dst can be exists  """
        assert os.path.exists(src)
        assert os.path.isdir(src)
        os.makedirs(dst, exist_ok=True)
    
        for fn in os.listdir(src):
            s = os.path.join(src, fn)
            t = os.path.join(dst, fn)
            if os.path.isfile(s):
                shutil.copy2(s, t)
            elif os.path.isdir(s):
                copy_tree(s, t)
    
    
    def build_module(source_file, dst_dir, tmp_dir):
        """ cythonize && build ext """
        assert os.path.isfile(source_file)
        assert not os.path.isabs(source_file)
        assert os.path.exists(dst_dir)
        os.makedirs(tmp_dir, exist_ok=True)
    
        build_cython = os.path.join(tmp_dir, 'build.cython')
        build_temp = os.path.join(tmp_dir, 'build.temp')
        build_lib = dst_dir
    
        ext_modules = cythonize(
            source_file,
            build_dir=build_cython,
            language_level=3,
        )
    
        class build_here(build_ext):
            def initialize_options(self):
                super().initialize_options()
                self.build_temp = build_temp
                self.build_lib = build_lib
        setup(
            ext_modules=ext_modules,
            script_args=['build_ext'],
            cmdclass=dict(build_ext=build_here)
        )
    
    
    def build_modules(source_dir, dst_dir, tmp_dir):
        """ scan && build modules in source_dir """
        assert os.path.exists(source_dir)
        assert not os.path.isabs(source_dir)
        assert not os.path.isabs(dst_dir)
        os.makedirs(dst_dir, exist_ok=True)
    
        for root, dirs, files in os.walk(source_dir):
            rel_pth = root[len(source_dir)+1:]
    
            for ignore in BUILD_CONFIG['IgnoreDir']:
                if ignore in dirs:
                    dirs.remove(ignore)
    
            for dn in dirs:
                if dn in BUILD_CONFIG['CopyOnlyDir']:
                    copy_tree(
                        os.path.join(root, dn),
                        os.path.join(dst_dir, rel_pth, dn)
                    )
                    dirs.remove(dn)
    
            for fn in files:
                _, ext = os.path.splitext(fn)
                os.makedirs(
                    os.path.join(dst_dir, rel_pth),
                    exist_ok=True
                )
                if fn in BUILD_CONFIG['CopyOnlyFile']:
                    shutil.copy2(
                        os.path.join(root, fn),
                        os.path.join(dst_dir, rel_pth, fn)
                    )
                elif ext.lower() in BUILD_CONFIG['SupportExt']:
                    build_module(
                        os.path.join(root, fn),
                        dst_dir,
                        os.path.join(tmp_dir, rel_pth),
                    )
                else:
                    shutil.copy2(
                        os.path.join(root, fn),
                        os.path.join(dst_dir, rel_pth, fn)
                    )
    
    
    if __name__ == "__main__":
    
        # 这里填写要编译的目录
        tasks = [
            'app',
        ]
    
        others = [
            'requirements.txt',
            'packages',
        ]
    
        BUILD_CONFIG['CopyOnlyFile'].extend(['settings.py'])
    
        for task in tasks:
            build_modules(
                task,
                os.path.join('dist', task),
                os.path.join('build', task),
            )
    
        for other in others:
            if os.path.isfile(other):
                bn = os.path.basename(other)
                shutil.copy2(other, os.path.join('dist', bn))
            elif os.path.isdir(other):
                bn = os.path.basename(other)
                copy_tree(other, os.path.join('dist', bn))
    
    
  • 相关阅读:
    c++继承与多态
    逻辑运算符
    页面分栏布局
    js中的三大特殊数据:undefined,null,NaN
    逻辑分支中if小括号中的隐式转换
    最小高度的兼容方法
    js数据类型的转换
    ognl.OgnlException: target is null for setProperty(null, "goodsSize", [Ljava.lang.String;@c3bb5。
    解决拦截器的对于参数传递无效问题
    引用外部js乱码问题
  • 原文地址:https://www.cnblogs.com/wuyaSama/p/10774094.html
Copyright © 2020-2023  润新知