Describes process to compile python into c code and package it for different platforms
You can see the session video in youtube: https://www.youtube.com/watch?v=CoxAowBDDyE
5. Motivation
• Python was not
designed
to be obfuscated
!
• That's against the
language's philosophy
!
• Everything in Python
is open
Python is
not the tool
you need
Even compiled programs
can be reverse-engineered
Obfuscation
is really
hard
Code
protection is
overrated
Having a
legal
requirement
is a good way
to go
They hack
windows all
the time
Quit your
job
6. Crazy,
Over the rainbow, I am crazy,
Bars in the window.
There must have been a door there in the wall
When I came in.
Crazy, over the rainbow, he is crazy.
8. Process
How to
CYTHONIZE
Convert to .c Compile native
extensions
Create executable For different
platforms
1. 2. 3. 4.
SETUP PyInstall PAckage
9. 9
Process
Cythonize
c_files = []
for dir_ in included_dirs:
for dirname, dirnames, filenames in os.walk(dir_):
if 'test' in dirnames:
dirnames.remove('test')
for filename in filenames:
file_ = os.path.join(dirname, filename)
stripped_name = os.path.relpath(file_, biicode_python_path)
file_name, extension = os.path.splitext(stripped_name)
if extension == '.py':
target_file = os.path.join(src_dir, file_name + '.c')
if filename not in ignored_files:
c_files.append(stripped_name.replace('.py', '.c'))
file_dir = os.path.dirname(target_file)
if not os.path.exists(file_dir):
os.makedirs(file_dir)
extension = cythonize(stripped_name,
force=force_compile,
build_dir=src_dir)
return c_files
10. 10
Process
setup
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
modules = []
for c_file in abs_path_c_files:
relfile = os.path.relpath(c_file, src_dir)
filename = os.path.splitext(relfile)[0]
extName = filename.replace(os.path.sep, ".")
extension = Extension(extName,sources=[c_file],
define_macros=[('PYREX_WITHOUT_ASSERTIONS',None)])
modules.append(extension)
if platform.system() != 'Windows':
cflags = sysconfig.get_config_var('CFLAGS')
opt = sysconfig.get_config_var('OPT')
sysconfig._config_vars['CFLAGS'] = cflags.replace(' -g ', ' ')
sysconfig._config_vars['OPT'] = opt.replace(' -g ', ' ')
if platform.system() == 'Linux':
ldshared = sysconfig.get_config_var('LDSHARED')
sysconfig._config_vars['LDSHARED'] = ldshared.replace(' -g ', ' ')
elif platform.system() == 'Darwin':
for key in ['CONFIG_ARGS', 'LIBTOOL', 'PY_CFLAGS', 'CFLAGS']:
value = sysconfig.get_config_var(key)
if value:
sysconfig._config_vars[key] = value.replace('-mno-fused-madd', '')
sysconfig._config_vars[key] = value.replace('-DENABLE_DTRACE', '')
12. Process
PyInstall: Fake main
import biicode.client.shell.bii
import biicode.client
if False:
# Third party imports
biicode.client.shell.bii.main(sys.argv[1:])
13. Process
PyInstall: spec
a.datas += Tree('BII_SRC_PATH/biicode/client/setups/images',
prefix = 'images')
dict_tree = Tree('MIMER_PATH', prefix = 'mimer',
excludes=["*.pyc"])
# This package is a gittler non pypip dependency
# It contains dynamically loadable resources that are not
# automatically included by pyinstaller
a.datas += dict_tree
a.datas += Tree('CRYPTO_PATH', prefix='Crypto', excludes=["*.pyc"])
a.binaries += Tree('BII_COMPILED_PATH/biicode', prefix='biicode')
14. Security
Can they know it is python?
Yes as is not packaged as a simple executable
and you can see the all the files in there.
!
But even if it was (much slower) widely available
tools will tell you
15. Security
What can they see?
They can import your native extensions (even if you
packaged as single file), so they can reverse engineer
them.
!
They can see all method names and, if you din’t tell
Cython not to include them, your docstrings.
17. Read More
• Compiling your python application with Cython!
• Packaging a compiled app with PyInstaller!
• Automating DEB pkg generation!
• Automating MacOS pkg generation!
• How to do your own Windows Installer!
• C vs Python
Blog posts