Esempio n. 1
0
def licenses(name='reg-001', expired=None, bind_disk=None, bind_mac=None,
             bind_ipv4=None, bind_data=None, key=None):
    pytransform_bootstrap()

    capsule = DEFAULT_CAPSULE
    if not os.path.exists(capsule):
        make_capsule(capsule)

    fmt = '' if expired is None else '*TIME:%.0f\n' % (
        expired if isinstance(expired, (int, float))
        else float(expired) if expired.find('-') == -1
        else time.mktime(time.strptime(expired, '%Y-%m-%d')))

    if bind_disk:
        fmt = '%s*HARDDISK:%s' % (fmt, bind_disk)

    if bind_mac:
        fmt = '%s*IFMAC:%s' % (fmt, bind_mac)

    if bind_ipv4:
        fmt = '%s*IFIPV4:%s' % (fmt, bind_ipv4)

    fmt = fmt + '*CODE:'
    extra_data = '' if bind_data is None else (';' + bind_data)

    return make_license_key(capsule, fmt + name + extra_data, key=key)
Esempio n. 2
0
def _obfuscate(args):
    '''Obfuscate scripts without project'''
    path = args.src
    logging.info('Obfuscate scripts in path "%s" ...', path)

    capsule = os.path.join(path, capsule_filename)
    if not os.path.exists(capsule):
        logging.info('Generate capsule %s', capsule)
        make_capsule(capsule)

    output = args.output
    files = Project.build_globfiles(args.patterns, path)
    filepairs = [(os.path.join(path, x), os.path.join(output, x))
                 for x in files]
    mode = Project.map_obfuscate_mode(default_obf_module_mode,
                                      default_obf_code_mode)

    logging.info('Obfuscate scripts with mode %s', mode)
    logging.info('Save obfuscated scripts to "%s"', output)
    for a, b in filepairs:
        logging.info('\t%s -> %s', a, b)
    obfuscate_scripts(filepairs, mode, capsule, output)

    logging.info('Make runtime files')
    make_runtime(capsule, output)

    for entry in args.entry.split(','):
        filename = os.path.join(output, entry.strip())
        if not os.path.exists(filename):
            shutil.copy(os.path.join(path, entry.strip()), filename)
        logging.info('Update entry script %s', filename)
        make_entry(filename)

    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 3
0
def _capsule(args):
    '''Make capsule separately'''
    capsule = os.path.join(args.path, capsule_filename)
    logging.info('Generating capsule %s ...', capsule)
    if os.path.exists(capsule):
        logging.info('Do nothing, capsule %s has been exists', capsule)
    else:
        make_capsule(capsule)
Esempio n. 4
0
def _capsule(args):
    '''Generate public capsule explicitly.'''
    capsule = os.path.join(args.path, capsule_filename)
    if args.force or not os.path.exists(capsule):
        logging.info('Generating public capsule ...')
        make_capsule(capsule)
    else:
        logging.info('Do nothing, capsule %s has been exists', capsule)
Esempio n. 5
0
def _capsule(args):
    '''Make project capsule used to obfuscate scripts'''
    capsule = os.path.join(args.path, capsule_filename)
    logging.info('Generating capsule %s ...', capsule)
    if os.path.exists(capsule):
        logging.info('Do nothing, capsule %s has been exists', capsule)
    else:
        make_capsule(capsule)
Esempio n. 6
0
def _init(args):
    '''Create an empty project or reinitialize an existing one

EXAMPLES

    pyarmor init --src=examples/simple --entry=queens.py project1
    '''
    if args.clone:
        logging.info(
            'Warning: option --clone is deprecated, use --capsule instead ')
        _clone(args)
        return

    path = args.project
    logging.info('Create project in %s ...', path)

    if not os.path.exists(path):
        logging.info('Make project directory %s', path)
        os.makedirs(path)

    src = os.path.abspath(args.src)
    logging.info('Python scripts base path: %s', src)

    name = os.path.basename(os.path.abspath(path))
    if (args.type == 'pkg') or \
       (args.type == 'auto' and os.path.exists(os.path.join(src,
                                                            '__init__.py'))):
        logging.info('Project is configured as package')
        project = Project(name=name,
                          title=name,
                          src=src,
                          entry=args.entry if args.entry else '__init__.py',
                          is_package=1,
                          obf_code_mode='wrap')
    else:
        logging.info('Project is configured as standalone application.')
        project = Project(name=name, title=name, src=src, entry=args.entry)

    if args.capsule:
        capsule = os.path.abspath(args.capsule)
        logging.info('Share capsule with %s', capsule)
        project._update(dict(capsule=capsule))
    else:
        logging.info('Create project capsule ...')
        filename = os.path.join(path, capsule_filename)
        make_capsule(filename)
        logging.info('Project capsule %s created', filename)

    logging.info('Create configure file ...')
    filename = os.path.join(path, config_filename)
    project.save(path)
    logging.info('Configure file %s created', filename)

    logging.info('Create pyarmor command ...')
    script = make_command(plat_name, sys.executable, sys.argv[0], path)
    logging.info('Pyarmor command %s created', script)

    logging.info('Project init successfully.')
Esempio n. 7
0
def _init(args):
    '''Create an empty project or reinitialize an existing one

This command creates an empty project in the specified path -
basically a configure file .pyarmor_config, a project capsule
.pyarmor_capsule.zip, and a shell script "pyarmor" will be created (in
windows, it called "pyarmor.bat").

Option --src specifies where to find python source files. By default,
all .py files in this directory will be included in this project.

Option --entry specifies main script, which could be run directly
after obfuscated.

Option --clone specifies another project path. It it is set, no new
project capsule is generated, just copy capsule from this project.

EXAMPLES

    python pyarmor.py init --src=examples --entry=queens.py project1
    cd project1/
    ./pyarmor info

    '''
    if args.clone:
        _clone(args)
        return

    path = args.project
    logging.info('Create project in %s ...', path)

    if not os.path.exists(path):
        logging.info('Make project directory %s', path)
        os.makedirs(path)

    src = os.path.abspath(args.src)
    logging.info('Python scripts base path: %s', src)

    name = os.path.basename(os.path.abspath(path))
    project = Project(name=name, title=name, src=src, entry=args.entry)

    logging.info('Create configure file ...')
    filename = os.path.join(path, config_filename)
    project.save(path)
    logging.info('Configure file %s created', filename)

    logging.info('Create project capsule ...')
    filename = os.path.join(path, capsule_filename)
    make_capsule(filename)
    logging.info('Project capsule %s created', filename)

    logging.info('Create pyarmor command ...')
    script = make_command(plat_name, sys.executable, sys.argv[0], path)
    logging.info('Pyarmor command %s created', script)

    logging.info('Project init successfully.')
Esempio n. 8
0
def _obfuscate(args):
    '''Obfuscate scripts without project'''
    if args.src is None and args.entry is None and not args.scripts:
        raise RuntimeError('No entry script')

    entry = args.entry or args.scripts[0]
    path = os.path.abspath(
        os.path.dirname(entry) if args.src is None else args.src)
    logging.info('Obfuscate scripts in path "%s" ...', path)

    capsule = args.capsule if args.capsule else DEFAULT_CAPSULE
    if os.path.exists(capsule) and check_capsule(capsule):
        logging.info('Use cached capsule %s', capsule)
    else:
        logging.info('Generate capsule %s', capsule)
        make_capsule(capsule)

    output = args.output
    if args.recursive:
        pats = ['global-include *.py', 'prune build', 'prune dist']
        if hasattr('', 'decode'):
            pats = [p.decode() for p in pats]
        files = Project.build_manifest(pats, path)
    else:
        files = Project.build_globfiles(['*.py'], path)
    filepairs = [(os.path.join(path, x), os.path.join(output, x))
                 for x in files]

    if args.restrict:
        logging.info('Restrict mode is eanbled')
        mode = Project.map_obfuscate_mode(default_obf_module_mode,
                                          default_obf_code_mode)
    else:
        logging.info('Restrict mode is disabled')
        mode = Project.map_obfuscate_mode(default_obf_module_mode, 'wrap')

    logging.info('Obfuscate scripts with mode %s', mode)
    logging.info('Save obfuscated scripts to "%s"', output)
    for a, b in filepairs:
        logging.info('\t%s -> %s', a, b)
    obfuscate_scripts(filepairs, mode, capsule, output)

    logging.info('Make runtime files')
    make_runtime(capsule, output)
    if not args.restrict:
        licode = '*FLAGS:%c*CODE:Pyarmor-Project' % chr(1)
        licfile = os.path.join(output, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_project_license(capsule, licode, licfile)

    make_entry(os.path.basename(entry), path, output)
    for script in args.scripts[1:]:
        make_entry(os.path.basename(script), path, output)

    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 9
0
def _capsule(args):
    '''Generate the capsule explicitly.'''
    capsule = os.path.join(args.path, capsule_filename)
    if args.upgrade:
        logging.info('Preparing to upgrade the capsule %s ...', capsule)
        upgrade_capsule(capsule)
        return

    if os.path.exists(capsule):
        logging.info('Do nothing, capsule %s has been exists', capsule)
    else:
        logging.info('Generating capsule %s ...', capsule)
        make_capsule(capsule)
Esempio n. 10
0
def _capsule(args):
    '''Make capsule separately'''
    if args.upgrade:
        capsule = os.path.join(args.path, capsule_filename) if args.path \
            else DEFAULT_CAPSULE
        logging.info('Preparing to upgrade the capsule %s ...', capsule)
        upgrade_capsule(capsule)
        return

    capsule = os.path.join(args.path, capsule_filename)
    logging.info('Generating capsule %s ...', capsule)
    if os.path.exists(capsule):
        logging.info('Do nothing, capsule %s has been exists', capsule)
    else:
        make_capsule(capsule)
Esempio n. 11
0
def _obfuscate(args):
    '''Obfuscate scripts without project'''
    path = args.src
    logging.info('Obfuscate scripts in path "%s" ...', path)

    capsule = args.capsule if args.capsule else capsule_filename
    if os.path.exists(capsule):
        logging.info('Use cached capsule %s', capsule)
    else:
        logging.info('Generate capsule %s', capsule)
        make_capsule(capsule)

    output = args.output
    if args.recursive:
        pat = 'global-include *.py'.decode() if hasattr('', 'decode') \
            else 'global-include *.py'
        files = Project.build_manifest([pat], path)
    else:
        files = Project.build_globfiles(args.patterns, path)
    filepairs = [(os.path.join(path, x), os.path.join(output, x))
                 for x in files]
    if args.no_restrict:
        logging.info('Restrict mode is disabled')
        mode = Project.map_obfuscate_mode(default_obf_module_mode, 'wrap')
    else:
        mode = Project.map_obfuscate_mode(default_obf_module_mode,
                                          default_obf_code_mode)

    logging.info('Obfuscate scripts with mode %s', mode)
    logging.info('Save obfuscated scripts to "%s"', output)
    for a, b in filepairs:
        logging.info('\t%s -> %s', a, b)
    obfuscate_scripts(filepairs, mode, capsule, output)

    logging.info('Make runtime files')
    make_runtime(capsule, output)
    if args.no_restrict:
        licode = '*FLAGS:%c*CODE:Pyarmor-Project' % chr(1)
        licfile = os.path.join(output, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_project_license(capsule, licode, licfile)

    if args.entry:
        make_entry(args.entry, path, output)
    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 12
0
def main_entry():
    logging.basicConfig(
        level=logging.INFO,
        format='%(levelname)-8s %(message)s',
    )
    try:
        if 'download' not in sys.argv[1:2]:
            pytransform_bootstrap()
            capsule = DEFAULT_CAPSULE
            if not (os.path.exists(capsule) and check_capsule(capsule)):
                logging.info('Generate global capsule %s', capsule)
                make_capsule(capsule)
        main(sys.argv[1:])
    except Exception as e:
        if sys.flags.debug:
            raise
        logging.error('%s', e)
        sys.exit(1)
Esempio n. 13
0
def _licenses(args):
    '''Generate licenses for obfuscated scripts.

Examples,

* Expired license for global capsule

    pyarmor licenses --expired=2018-05-12 Customer-Jordan

* Bind license to fixed harddisk and expired someday for project

    cd projects/myproject
    ./pyarmor licenses -e 2018-05-12 \\
              --bind-disk '100304PBN2081SF3NJ5T' Customer-Tom
    '''
    if os.path.exists(os.path.join(args.project, config_filename)):
        logging.info('Generate licenses for project %s ...', args.project)
        project = Project()
        project.open(args.project)
        capsule = build_path(project.capsule, args.project) \
            if args.capsule is None else args.capsule
    else:
        if args.project != '':
            logging.warning('Ignore option --project, no project in %s',
                            args.project)
        capsule = DEFAULT_CAPSULE if args.capsule is None else args.capsule
        if not (os.path.exists(capsule) and check_capsule(capsule)):
            logging.info('Generate capsule %s', capsule)
            make_capsule(capsule)
        logging.info('Generate licenses with capsule %s ...', capsule)
        project = {
            'disable_restrict_mode': 0 if args.restrict else 1,
        }

    licpath = os.path.join(
        args.project if args.output is None else args.output, 'licenses')
    if os.path.exists(licpath):
        logging.info('Output path of licenses: %s', licpath)
    else:
        logging.info('Make output path of licenses: %s', licpath)
        os.mkdir(licpath)

    if args.expired is None:
        fmt = ''
    else:
        fmt = '*TIME:%.0f\n' % \
              time.mktime(time.strptime(args.expired, '%Y-%m-%d'))

    if project.get('disable_restrict_mode'):
        logging.info('The license files generated is in disable restrict mode')
        fmt = '%s*FLAGS:%c' % (fmt, 1)
    else:
        logging.info('The license files generated is in restrict mode')

    if args.bind_disk:
        fmt = '%s*HARDDISK:%s' % (fmt, args.bind_disk)

    if args.bind_mac:
        fmt = '%s*IFMAC:%s' % (fmt, args.bind_mac)

    if args.bind_ipv4:
        fmt = '%s*IFIPV4:%s' % (fmt, args.bind_ipv4)

    # if args.bind_ipv6:
    #     fmt = '%s*IFIPV6:%s' % (fmt, args.bind_ipv6)

    if args.bind_domain:
        fmt = '%s*DOMAIN:%s' % (fmt, args.bind_domain)

    if args.bind_file:
        bind_file, bind_key = args.bind_file.split(';', 2)
        if os.path.exists(bind_file):
            f = open(bind_file, 'rb')
            s = f.read()
            f.close()
            if sys.version_info[0] == 3:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s.decode())
            else:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s)
        else:
            raise RuntimeError('Bind file %s not found' % bindfile)

    # Prefix of registration code
    fmt = fmt + '*CODE:'

    for rcode in args.codes:
        output = os.path.join(licpath, rcode)
        if not os.path.exists(output):
            logging.info('Make path: %s', output)
            os.mkdir(output)

        licfile = os.path.join(output, license_filename)
        licode = fmt + rcode
        txtinfo = licode.replace('\n', r'\n')
        if args.expired:
            txtinfo = '"Expired:%s%s"' % (args.expired,
                                          txtinfo[txtinfo.find(r'\n') + 2:])
        logging.info('Generate license: %s', txtinfo)
        make_project_license(capsule, licode, licfile)
        logging.info('Write license file: %s', licfile)

        logging.info('Write information to %s.txt', licfile)
        with open(os.path.join(licfile + '.txt'), 'w') as f:
            f.write(txtinfo)

    logging.info('Generate %d licenses OK.', len(args.codes))
Esempio n. 14
0
def _init(args):
    '''Create an empty project or reinitialize an existing one

This command creates an empty project in the specified path -
basically a configure file .pyarmor_config, a project capsule
.pyarmor_capsule.zip, and a shell script "pyarmor" will be created (in
windows, it called "pyarmor.bat").

Option --src specifies where to find python source files. By default,
all .py files in this directory will be included in this project.

Option --entry specifies main script, which could be run directly
after obfuscated.

Option --capsule specifies project capsule file which has been
created. If it is set, no new project capsule is generated, just link
to this capsule.

EXAMPLES

    python pyarmor.py init --src=examples --entry=queens.py project1
    cd project1/
    ./pyarmor info

    '''
    if args.clone:
        logging.info(
            'Warning: option --clone is deprecated, use --capsule instead ')
        _clone(args)
        return

    path = args.project
    logging.info('Create project in %s ...', path)

    if not os.path.exists(path):
        logging.info('Make project directory %s', path)
        os.makedirs(path)

    src = os.path.abspath(args.src)
    logging.info('Python scripts base path: %s', src)

    name = os.path.basename(os.path.abspath(path))
    if (args.type == 'package') or (args.type == 'pkg') or \
       (args.type == 'auto' and os.path.exists(os.path.join(src, '__init__.py'))):
        logging.info('Project is configured as package')
        project = Project(name=name,
                          title=name,
                          src=src,
                          entry=args.entry,
                          is_package=1,
                          obf_code_mode='wrap',
                          disable_restrict_mode=1)
    else:
        logging.info('Project is configured as standalone application.')
        project = Project(name=name, title=name, src=src, entry=args.entry)

    if args.capsule:
        capsule = os.path.abspath(args.capsule)
        logging.info('Share capsule with %s', capsule)
        project._update(dict(capsule=capsule))
    else:
        logging.info('Create project capsule ...')
        filename = os.path.join(path, capsule_filename)
        make_capsule(filename)
        logging.info('Project capsule %s created', filename)

    logging.info('Create configure file ...')
    filename = os.path.join(path, config_filename)
    project.save(path)
    logging.info('Configure file %s created', filename)

    logging.info('Create pyarmor command ...')
    script = make_command(plat_name, sys.executable, sys.argv[0], path)
    logging.info('Pyarmor command %s created', script)

    logging.info('Project init successfully.')
Esempio n. 15
0
def _obfuscate(args):
    '''Obfuscate scripts without project.'''
    platforms = compatible_platform_names(args.platforms)
    if platforms:
        logging.info('Target platforms: %s', platforms)
        if check_cross_platform(platforms) is not False:
            return

    for x in ('entry', 'cross-protection'):
        if getattr(args, x.replace('-', '_')) is not None:
            logging.warning('Option --%s has been deprecated', x)

    if args.src is None:
        if args.scripts[0].lower().endswith('.py'):
            path = os.path.abspath(os.path.dirname(args.scripts[0]))
        else:
            path = os.path.abspath(args.scripts[0])
            args.src = path
            if len(args.scripts) > 1:
                raise RuntimeError('Only one path is allowed')
            args.scripts = []
    else:
        for s in args.scripts:
            if not s.lower().endswith('.py'):
                raise RuntimeError('Only one path is allowed')
        path = os.path.abspath(args.src)
    if not args.exact and len(args.scripts) > 1:
        raise RuntimeError('Two many entry scripts, only one is allowed')
    if not os.path.exists(path):
        raise RuntimeError('Not found source path: %s' % path)
    logging.info('Source path is "%s"', path)

    entries = [args.entry] if args.entry else args.scripts
    logging.info('Entry scripts are %s', entries)

    capsule = args.capsule if args.capsule else DEFAULT_CAPSULE
    if os.path.exists(capsule):
        logging.info('Use cached capsule %s', capsule)
    else:
        logging.info('Generate capsule %s', capsule)
        make_capsule(capsule)

    output = args.output
    if os.path.abspath(output) == path:
        raise RuntimeError('Output path can not be same as src')

    suffix = get_name_suffix() if args.enable_suffix else ''

    if args.recursive:
        logging.info('Recursive mode is on')
        pats = ['global-include *.py']

        if args.exclude:
            for item in args.exclude:
                for x in item.split(','):
                    if x.endswith('.py'):
                        logging.info('Exclude pattern "%s"', x)
                        pats.append('exclude %s' % x)
                    else:
                        logging.info('Exclude path "%s"', x)
                        pats.append('prune %s' % x)

        if os.path.abspath(output).startswith(path):
            x = os.path.abspath(output)[len(path):].strip('/\\')
            pats.append('prune %s' % x)
            logging.info('Auto exclude output path "%s"', x)

        if hasattr('', 'decode'):
            pats = [p.decode() for p in pats]

        files = Project.build_manifest(pats, path)

    elif args.exact:
        logging.info('Exact mode is on')
        files = [os.path.abspath(x) for x in args.scripts]

    else:
        logging.info('Normal mode is on')
        files = Project.build_globfiles(['*.py'], path)

    logging.info('Save obfuscated scripts to "%s"', output)
    if not os.path.exists(output):
        os.makedirs(output)

    logging.info('Read public key from capsule')
    prokey = get_product_key(capsule)

    logging.info('Obfuscate scripts with default mode')
    cross_protection = 0 if args.no_cross_protection else \
        1 if args.cross_protection is None else args.cross_protection

    advanced = 1 if args.advanced else 0
    logging.info('Advanced mode is %d', advanced)

    restrict = args.restrict
    logging.info('Restrict mode is %d', restrict)

    n = args.bootstrap_code
    relative = True if n == 3 else False if n == 2 else None
    bootstrap = (not args.no_bootstrap) and n
    elist = [os.path.abspath(x) for x in entries]
    for x in sorted(files):
        if os.path.isabs(x):
            a, b = x, os.path.join(output, os.path.basename(x))
        else:
            a, b = os.path.join(path, x), os.path.join(output, x)
        logging.info('\t%s -> %s', x, relpath(b))
        is_entry = os.path.abspath(a) in elist
        protection = is_entry and cross_protection
        plugins = search_plugins(args.plugins)

        d = os.path.dirname(b)
        if not os.path.exists(d):
            os.makedirs(d)

        vmode = advanced | (8 if is_entry else 0)
        encrypt_script(prokey, a, b, adv_mode=vmode, rest_mode=restrict,
                       protection=protection, platforms=platforms,
                       plugins=plugins, suffix=suffix)

        if is_entry and bootstrap:
            name = os.path.abspath(a)[len(path)+1:]
            make_entry(name, path, output, relative=relative, suffix=suffix)

    logging.info('%d scripts have been obfuscated', len(files))

    if args.no_runtime:
        logging.info('Obfuscate %d scripts OK.', len(files))
        return

    package = args.package_runtime
    make_runtime(capsule, output, platforms=platforms,
                 package=package, suffix=suffix)

    logging.info('Obfuscate scripts with restrict mode %s',
                 'on' if args.restrict else 'off')
    if not args.restrict:
        licode = '*FLAGS:%c*CODE:PyArmor-Project' % chr(1)
        licpath = (os.path.join(output, 'pytransform' + suffix) if package
                   else output)
        licfile = os.path.join(licpath, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_license_key(capsule, licode, licfile)

    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 16
0
def _licenses(args):
    '''Generate licenses for obfuscated scripts.'''
    for x in ('bind-file',):
        if getattr(args, x.replace('-', '_')) is not None:
            logging.warning('Option --%s has been deprecated', x)

    if os.path.exists(os.path.join(args.project, config_filename)):
        logging.info('Generate licenses for project %s ...', args.project)
        project = Project()
        project.open(args.project)
        capsule = build_path(project.capsule, args.project) \
            if args.capsule is None else args.capsule
    else:
        if args.project != '':
            logging.warning('Ignore option --project, there is no project')
        capsule = DEFAULT_CAPSULE if args.capsule is None else args.capsule
        if not os.path.exists(capsule):
            logging.info('Generating public capsule ...')
            make_capsule(capsule)
        logging.info('Generate licenses with capsule %s ...', capsule)
        project = dict(restrict_mode=args.restrict)
    restrict_mode = 0 if args.disable_restrict_mode else args.restrict

    licpath = os.path.join(
        args.project if args.output is None else args.output,
        'licenses')
    if os.path.exists(licpath):
        logging.info('Output path of licenses: %s', licpath)
    else:
        logging.info('Make output path of licenses: %s', licpath)
        os.mkdir(licpath)

    if args.expired is None:
        fmt = ''
    else:
        fmt = '*TIME:%.0f\n' % \
              time.mktime(time.strptime(args.expired, '%Y-%m-%d'))

    if not restrict_mode:
        logging.info('The license file generated is in disable restrict mode')
        fmt = '%s*FLAGS:%c' % (fmt, 1)
    else:
        logging.info('The license file generated is in restrict mode')

    if args.bind_disk:
        fmt = '%s*HARDDISK:%s' % (fmt, args.bind_disk)

    if args.bind_mac:
        fmt = '%s*IFMAC:%s' % (fmt, args.bind_mac)

    if args.bind_ipv4:
        fmt = '%s*IFIPV4:%s' % (fmt, args.bind_ipv4)

    # if args.bind_ipv6:
    #     fmt = '%s*IFIPV6:%s' % (fmt, args.bind_ipv6)

    if args.bind_domain:
        fmt = '%s*DOMAIN:%s' % (fmt, args.bind_domain)

    if args.bind_file:
        bind_file, bind_key = args.bind_file.split(';', 2)
        if os.path.exists(bind_file):
            f = open(bind_file, 'rb')
            s = f.read()
            f.close()
            if sys.version_info[0] == 3:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s.decode())
            else:
                fmt = '%s*FIXKEY:%s;%s' % (fmt, bind_key, s)
        else:
            raise RuntimeError('Bind file %s not found' % bind_file)

    # Prefix of registration code
    fmt = fmt + '*CODE:'
    extra_data = '' if args.bind_data is None else (';' + args.bind_data)

    for rcode in args.codes:
        output = os.path.join(licpath, rcode)
        if not os.path.exists(output):
            logging.info('Make path: %s', output)
            os.mkdir(output)

        licfile = os.path.join(output, license_filename)
        licode = fmt + rcode + extra_data
        txtinfo = licode.replace('\n', r'\n')
        if args.expired:
            txtinfo = '"Expired:%s%s"' % (args.expired,
                                          txtinfo[txtinfo.find(r'\n')+2:])
        logging.info('Generate license: %s', txtinfo)
        make_project_license(capsule, licode, licfile)
        logging.info('Write license file: %s', licfile)

        logging.info('Write information to %s.txt', licfile)
        with open(os.path.join(licfile + '.txt'), 'w') as f:
            f.write(txtinfo)

    logging.info('Generate %d licenses OK.', len(args.codes))
Esempio n. 17
0
def _obfuscate(args):
    '''Obfuscate scripts without project'''
    if args.src is None and args.entry is None and not args.scripts:
        raise RuntimeError('No entry script')

    entry = args.entry or (args.scripts and args.scripts[0])
    path = os.path.abspath(
        os.path.dirname(entry) if args.src is None else args.src)
    logging.info('Obfuscate scripts in path "%s"', path)

    capsule = args.capsule if args.capsule else DEFAULT_CAPSULE
    if os.path.exists(capsule) and check_capsule(capsule):
        logging.info('Use cached capsule %s', capsule)
    else:
        logging.info('Generate capsule %s', capsule)
        make_capsule(capsule)

    output = args.output
    if os.path.abspath(output) == path:
        raise RuntimeError('Output path can not be same as src')
    if args.recursive:
        pats = ['global-include *.py', 'prune build', 'prune dist']
        if os.path.abspath(output).startswith(path):
            x = os.path.abspath(output)[len(path):].strip('/\\')
            pats.append('prune %s' % x)
        if hasattr('', 'decode'):
            pats = [p.decode() for p in pats]
        files = Project.build_manifest(pats, path)
    else:
        files = Project.build_globfiles(['*.py'], path)

    logging.info('Save obfuscated scripts to "%s"', output)
    if not os.path.exists(output):
        os.makedirs(output)

    logging.info('Read public key from capsule')
    prokey = get_product_key(capsule)

    logging.info('Obfuscate scripts with default mode')
    for x in files:
        a, b = os.path.join(path, x), os.path.join(output, x)
        logging.info('\t%s -> %s', x, b)
        protection = args.cross_protection and entry \
            and (os.path.abspath(a) == os.path.abspath(entry))

        d = os.path.dirname(b)
        if not os.path.exists(d):
            os.makedirs(d)

        encrypt_script(prokey, a, b, protection=protection)
    logging.info('%d scripts have been obfuscated', len(files))

    make_runtime(capsule, output)

    if entry and entry.endswith('__init__.py') and args.restrict is None:
        logging.info('Disable restrict mode for package by default')
        restrict = 0
    else:
        restrict = 1 if args.restrict is None else args.restrict
        logging.info('Obfuscate scripts with restrict mode %s',
                     'on' if restrict else 'off')
    if not restrict:
        licode = '*FLAGS:%c*CODE:PyArmor-Project' % chr(1)
        licfile = os.path.join(output, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_project_license(capsule, licode, licfile)

    if entry:
        make_entry(os.path.basename(entry), path, output)
    for script in args.scripts[1:]:
        make_entry(os.path.basename(script), path, output)

    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 18
0
def _obfuscate(args):
    '''Obfuscate scripts without project.'''
    check_cross_platform(args.platform)

    for x in ('entry', 'cross-protection'):
        if getattr(args, x.replace('-', '_')) is not None:
            logging.warning('Option --%s has been deprecated', x)

    if args.src is None and not args.scripts:
        args.src = '.'

    if args.src is None:
        if args.scripts[0].lower().endswith('.py'):
            path = os.path.abspath(os.path.dirname(args.scripts[0]))
        else:
            path = os.path.abspath(args.scripts[0])
            args.src = path
            if len(args.scripts) > 1:
                raise RuntimeError('Only one path is allowed')
            args.scripts = []
    else:
        path = os.path.abspath(args.src)
    if not os.path.exists(path):
        raise RuntimeError('Not found source path: %s' % path)
    logging.info('Source path is "%s"', path)

    entry = args.entry or (args.scripts and args.scripts[0])
    logging.info('Entry script is %s', entry)

    capsule = args.capsule if args.capsule else DEFAULT_CAPSULE
    if os.path.exists(capsule):
        logging.info('Use cached capsule %s', capsule)
    else:
        logging.info('Generate capsule %s', capsule)
        make_capsule(capsule)

    output = args.output
    if os.path.abspath(output) == path:
        raise RuntimeError('Output path can not be same as src')

    if args.recursive:
        logging.info('Recursive mode is on')
        pats = ['global-include *.py']

        if args.exclude:
            for item in args.exclude:
                for x in item.split(','):
                    logging.info('Exclude path "%s"', x)
                    pats.append('prune %s' % x)

        if os.path.abspath(output).startswith(path):
            x = os.path.abspath(output)[len(path):].strip('/\\')
            pats.append('prune %s' % x)
            logging.info('Auto exclude output path "%s"', x)

        if hasattr('', 'decode'):
            pats = [p.decode() for p in pats]

        files = Project.build_manifest(pats, path)

    elif args.exact:
        logging.info('Exact mode is on')
        files = [os.path.abspath(x) for x in args.scripts]

    else:
        logging.info('Normal mode is on')
        files = Project.build_globfiles(['*.py'], path)

    logging.info('Save obfuscated scripts to "%s"', output)
    if not os.path.exists(output):
        os.makedirs(output)

    logging.info('Read public key from capsule')
    prokey = get_product_key(capsule)

    logging.info('Obfuscate scripts with default mode')
    cross_protection = 0 if args.no_cross_protection else \
        1 if args.cross_protection is None else args.cross_protection
    if args.platform:
        logging.info('Target platform is %s', args.platform)
        if cross_protection == 1:
            cross_protection = args.platform
        elif isinstance(cross_protection, str):
            cross_protection = ','.join([cross_protection, args.platform])

    advanced = 1 if args.advanced else 0
    logging.info('Advanced mode is %d', advanced)

    restrict = args.restrict
    logging.info('Restrict mode is %d', restrict)

    for x in files:
        if os.path.isabs(x):
            a, b = x, os.path.join(output, os.path.basename(x))
        else:
            a, b = os.path.join(path, x), os.path.join(output, x)
        logging.info('\t%s -> %s', x, b)
        is_entry = entry and (os.path.abspath(a) == os.path.abspath(entry))
        protection = is_entry and cross_protection
        plugins = protection and args.plugins

        d = os.path.dirname(b)
        if not os.path.exists(d):
            os.makedirs(d)

        vmode = advanced | (8 if is_entry else 0)
        encrypt_script(prokey, a, b, adv_mode=vmode, rest_mode=restrict,
                       protection=protection, plugins=plugins)
    logging.info('%d scripts have been obfuscated', len(files))

    if (not args.no_bootstrap) and entry and os.path.exists(entry):
        inner = args.package_runtime != 2
        entryname = entry if args.src else os.path.basename(entry)
        if os.path.exists(os.path.join(output, entryname)):
            make_entry(entryname, path, output, inner=inner)
        else:
            logging.info('Use outer entry script "%s"', entry)
            make_entry(entry, path, output, inner=inner)

    if args.no_runtime:
        logging.info('Obfuscate %d scripts OK.', len(files))
        return

    make_runtime(capsule, output, platform=args.platform,
                 package=args.package_runtime)

    logging.info('Obfuscate scripts with restrict mode %s',
                 'on' if args.restrict else 'off')
    if not args.restrict:
        licode = '*FLAGS:%c*CODE:PyArmor-Project' % chr(1)
        licpath = os.path.join(output, 'pytransform') if args.package_runtime \
            else output
        licfile = os.path.join(licpath, license_filename)
        logging.info('Generate no restrict mode license file: %s', licfile)
        make_project_license(capsule, licode, licfile)

    logging.info('Obfuscate %d scripts OK.', len(files))
Esempio n. 19
0
def main(args):
    parser = argparse.ArgumentParser(
        prog='pyarmor',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description='PyArmor is a command line tool used to obfuscate '
        'python scripts, bind obfuscated scripts to fixed '
        'machine or expire obfuscated scripts.',
        epilog=__doc__,
    )
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=_version_info())
    parser.add_argument('-q',
                        '--silent',
                        action='store_true',
                        help='Suppress all normal output')

    subparsers = parser.add_subparsers(
        title='The most commonly used pyarmor commands are',
        metavar='<command>')

    #
    # Command: capsule
    #
    cparser = subparsers.add_parser(
        'capsule',
        epilog=_capsule.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Generate or upgrade the capsule explicitly ')
    cparser.add_argument('--upgrade',
                         action='store_true',
                         help='Upgrade the capsule to latest version')
    cparser.add_argument('path',
                         nargs='?',
                         default=os.path.expanduser('~'),
                         help='Path to save capsule, default is home path')
    cparser.set_defaults(func=_capsule)

    #
    # Command: obfuscate
    #
    cparser = subparsers.add_parser(
        'obfuscate',
        epilog=_obfuscate.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Obfuscate python scripts')
    cparser.add_argument('-O', '--output', default='dist', metavar='PATH')
    cparser.add_argument('-e',
                         '--entry',
                         metavar='SCRIPT',
                         help='Entry script [DEPRECATED]')
    cparser.add_argument('-r',
                         '--recursive',
                         action='store_true',
                         help='Match files recursively')
    cparser.add_argument('-s',
                         '--src',
                         metavar='PATH',
                         help='Base path for search python scripts')
    cparser.add_argument('--restrict',
                         type=int,
                         choices=(0, 1),
                         help='Set restrict mode')
    cparser.add_argument('--cross-protection',
                         type=int,
                         choices=(0, 1),
                         default=1,
                         help='Enable/disable to insert protection code')
    cparser.add_argument('--capsule',
                         help='Use this capsule other than global capsule')
    cparser.add_argument('scripts',
                         metavar='SCRIPT',
                         nargs='*',
                         help='Scripts to obfuscted')
    cparser.set_defaults(func=_obfuscate)

    #
    # Command: init
    #
    cparser = subparsers.add_parser(
        'init',
        epilog=_init.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Create a project to manage obfuscated scripts')
    cparser.add_argument('-t',
                         '--type',
                         default='auto',
                         choices=('auto', 'app', 'pkg'))
    cparser.add_argument('-e', '--entry', help='Entry script of this project')
    cparser.add_argument('-s',
                         '--src',
                         required=True,
                         help='Base path of python scripts')
    cparser.add_argument('--capsule',
                         help='Use this capsule other than global capsule')
    cparser.add_argument('project', nargs='?', help='Project path')
    cparser.set_defaults(func=_init)

    #
    # Command: config
    #
    cparser = subparsers.add_parser(
        'config',
        epilog=_update.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Update project settings')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.add_argument('--name')
    cparser.add_argument('--title')
    cparser.add_argument('--src')
    cparser.add_argument('--output')
    cparser.add_argument('--capsule', help='Project capsule')
    cparser.add_argument('--manifest',
                         metavar='TEMPLATE',
                         help='Manifest template string')
    cparser.add_argument('--entry',
                         metavar='SCRIPT',
                         help='Entry script of this project')
    cparser.add_argument('--is-package', type=int, choices=(0, 1))
    cparser.add_argument('--disable-restrict-mode', type=int, choices=(0, 1))
    cparser.add_argument('--obf-module-mode',
                         choices=Project.OBF_MODULE_MODE,
                         help='[DEPRECATED] Use --obf-mod instead')
    cparser.add_argument('--obf-code-mode',
                         choices=Project.OBF_CODE_MODE,
                         help='[DEPRECATED] Use --obf-code and --wrap-mode'
                         ' instead')
    cparser.add_argument('--obf-mod', type=int, choices=(0, 1))
    cparser.add_argument('--obf-code', type=int, choices=(0, 1))
    cparser.add_argument('--wrap-mode', type=int, choices=(0, 1))
    cparser.add_argument('--cross-protection', type=int, choices=(0, 1))
    cparser.add_argument('--runtime-path', metavar="RPATH")
    cparser.set_defaults(func=_update)

    #
    # Command: info
    #
    cparser = subparsers.add_parser(
        'info',
        epilog=_info.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Show project information')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.set_defaults(func=_info)

    #
    # Command: check
    #
    cparser = subparsers.add_parser(
        'check',
        epilog=_check.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Check consistency of project')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.set_defaults(func=_check)

    #
    # Command: build
    #
    cparser = subparsers.add_parser(
        'build',
        epilog=_build.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Obfuscate all the scripts in the project')
    cparser.add_argument('project',
                         nargs='?',
                         metavar='PATH',
                         default='',
                         help='Project path')
    cparser.add_argument(
        '-B',
        '--force',
        action='store_true',
        help='Obfuscate all scripts even if it\'s not updated')
    cparser.add_argument('-r',
                         '--only-runtime',
                         action='store_true',
                         help='Generate extra runtime files only')
    cparser.add_argument('-n',
                         '--no-runtime',
                         action='store_true',
                         help='DO NOT generate extra runtime files')
    cparser.add_argument('-O',
                         '--output',
                         help='Output path, override project configuration')
    cparser.set_defaults(func=_build)

    #
    # Command: target
    #
    # cparser = subparsers.add_parser('target', help='Manage target for project')
    # cparser.add_argument('name', metavar='NAME', nargs=1,
    #                      help='Target name')
    # group = cparser.add_argument_group('Target definition')
    # group.add_argument('-p', '--platform', metavar='PLATFORM',
    #                    help='Target platform to run obfuscated scripts')
    # group.add_argument('-c', '--license', metavar='CODE',
    #                    help='License code for this target')
    # cparser.add_argument('--remove', action='store_true',
    #                      help='Remove target from project')
    # cparser.add_argument('-P', '--project', required=True, default='',
    #                      help='Project path or configure file')
    # cparser.set_defaults(func=_target)

    #
    # Command: license
    #
    cparser = subparsers.add_parser(
        'licenses',
        epilog=_licenses.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Generate new licenses for obfuscated scripts')
    cparser.add_argument('codes',
                         nargs='+',
                         metavar='CODE',
                         help='Registration code for this license')
    group = cparser.add_argument_group('Bind license to hardware')
    group.add_argument('-e',
                       '--expired',
                       metavar='YYYY-MM-DD',
                       help='Expired date for this license')
    group.add_argument('-d',
                       '--bind-disk',
                       metavar='SN',
                       help='Bind license to serial number of harddisk')
    group.add_argument('-4',
                       '--bind-ipv4',
                       metavar='a.b.c.d',
                       help='Bind license to ipv4 addr')
    # group.add_argument('-6', '--bind-ipv6', metavar='a:b:c:d',
    #                    help='Bind license to ipv6 addr')
    group.add_argument('-m',
                       '--bind-mac',
                       metavar='x:x:x:x',
                       help='Bind license to mac addr')
    group.add_argument('--bind-domain',
                       metavar='DOMAIN',
                       help='Bind license to domain name')
    group.add_argument('--bind-file',
                       metavar='filename;target_filename',
                       help='Bind license to fixed file')
    cparser.add_argument('-P', '--project', default='', help='Project path')
    cparser.add_argument('-C', '--capsule', help='Project capsule')
    cparser.add_argument('-O', '--output', help='Output path')
    cparser.add_argument('--restrict',
                         type=int,
                         default=1,
                         choices=(0, 1),
                         help='Generate license for restrict mode')

    cparser.set_defaults(func=_licenses)

    #
    # Command: hdinfo
    #
    cparser = subparsers.add_parser(
        'hdinfo',
        epilog=_hdinfo.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Show hardware information')
    cparser.set_defaults(func=_hdinfo)

    #
    # Command: benchmark
    #
    cparser = subparsers.add_parser(
        'benchmark',
        epilog=_benchmark.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Run benchmark test in current machine')
    cparser.add_argument('-m',
                         '--obf-mod',
                         choices=(0, 1),
                         default=1,
                         type=int)
    cparser.add_argument('-c',
                         '--obf-code',
                         choices=(0, 1),
                         default=1,
                         type=int)
    cparser.add_argument('-w',
                         '--wrap-mode',
                         choices=(0, 1),
                         default=1,
                         type=int)
    cparser.set_defaults(func=_benchmark)

    #
    # Command: pack
    #
    cparser = subparsers.add_parser(
        'pack',
        epilog=packer.__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        help='Pack obfuscated scripts to one bundle')
    packer.add_arguments(cparser)
    cparser.set_defaults(func=packer.packer)

    args = parser.parse_args(args)
    if args.silent:
        logging.getLogger().setLevel(100)

    if not hasattr(args, 'func'):
        parser.print_help()
        return

    logging.info(_version_info(short=True))
    logging.debug('PyArmor install path: %s', PYARMOR_PATH)

    capsule = DEFAULT_CAPSULE
    if not (os.path.exists(capsule) and check_capsule(capsule)):
        logging.info('Generate global capsule %s', capsule)
        make_capsule(capsule)

    args.func(args)