Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

obfy + PyInstaller template

A minimal, ready-to-build project that ships a Python app as a single native executable with its source obfuscated and AES-256-GCM encrypted by obfy.

The flow is two steps: obfy build turns ./src into a protected drop-in mirror (./protected), then PyInstaller bundles that mirror — never your real source — into one binary.

src/run.py ──► obfy build ──► protected/  ──► pyinstaller ──► dist/app
src/app/                      (encrypted)                     (one binary)

Layout

Path What it is
src/run.py App entry point. Edit or replace.
src/app/ Your code package — this is what gets protected.
app.spec PyInstaller spec, already pointed at the protected ./protected tree.
build.sh One-shot: obfy build + pyinstaller.
Pipfile Build-time tools (obfy, pyinstaller), managed with pipenv.
protected/, build/, dist/ Generated output (git-ignored).

Prerequisites

  • CPython 3.10–3.13. Build with the same Python version you ship for — obfy's marshalled bytecode is interpreter-version specific.
  • macOS (Apple Silicon / Intel), Linux (x86_64 / aarch64), or Windows (x64).
  • PyInstaller produces a binary for the OS and architecture you build on. Build on each target platform you want to ship (e.g. in CI).

Setup

This template uses pipenv (the Pipfile pins python_version = "3.12"). Install the build tooling into a managed virtualenv:

pip install --user pipenv          # if you don't have it
pipenv install                     # creates the venv from Pipfile

Add your app's own runtime dependencies to the Pipfile too (pipenv install <pkg>), so PyInstaller can discover and bundle them.

Prefer a plain venv + pip? That works as well:

python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install obfy pyinstaller

Build

pipenv run build                   # == pipenv run bash build.sh

That runs the two steps for you. To run them by hand (inside pipenv shell or an activated venv):

# 1. Protect ./src into ./protected (a drop-in mirror)
obfy build --src ./src --out ./protected --python python --level 5

# 2. Bundle the protected mirror into one executable
pyinstaller --noconfirm app.spec

Run the result:

./dist/app            # Windows: dist\app.exe
./dist/app Ada        # pass args through as usual

How it fits together

  • obfy build --src ./src --out ./protected discovers every .py under src/, obfuscates it (--level 5 also natively compiles eligible functions so their CPython bytecode never ships), then compiles → marshals → AES-256-GCM encrypts each module. ./protected is a 1:1 mirror of ./src: each .py becomes a tiny self-activating stub, the real code lives encrypted in protected/__obfy__/*.obfy, and obfy's native loader is bundled in.

  • app.spec points PyInstaller at protected/run.py (not src/run.py) and ships the whole ./protected/ tree as data, plus obfy_runtime as a hidden import because the loader is imported dynamically at runtime. The decryption happens in memory at import time; plaintext source is never written to disk.

Obfy level

obfy build takes --level 0–5, a sophistication dial where each level does strictly more — 1 strips docstrings, 2 adds string mangling + dead code, 3 adds function-local renames, 4 adds cross-module public-name renames, and 5 adds native function compilation: eligible functions are lowered to obfy's own bytecode VM, so their CPython bytecode never ships (a decrypted module shows only stubs, with nothing to marshal.loads + dis). Reference: obfuscation levels.

This template builds at --level 5 — the maximum. A PyInstaller binary is a self-contained app with no framework resolving names by string, so the most aggressive setting is safe here. Functions the ISA doesn't yet cover fall back to level-4 encrypted marshal automatically, so the build never breaks. If a dependency does dynamic name/attribute lookups that renaming would break, lower --level in build.sh.

Customizing

  • Your code: put it under src/app/ (or add packages alongside it) and import it from src/run.py. Keep src/ to code only — obfy build copies every non-.py file under --src into the output, so don't point it at a tree that contains .env files or keys.
  • Executable name / icon / windowed mode: edit app.spec (name=, add icon=, set console=False for a GUI app).
  • Obfuscation level: change --level in build.sh (05; higher does strictly more). See obfuscation levels.
  • Excluding files from protection (e.g. framework files read as text): use --exclude (fnmatch patterns, repeatable). See packaging.

Docs

Full obfy documentation: docs.camouflage.network/obfy.

License

MIT — see LICENSE. The code you build with this template is yours.

About

Obfy Pyinstaller template

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages