Skip to main content

Advanced Python code obfuscator with machine ID binding

Project description

PyProtect - Advanced Python Code Obfuscator

PyProtect Logo Python License Buy Me A Coffee

PyProtect is a comprehensive Python code obfuscation tool with machine ID binding, designed to protect your Python applications from reverse engineering and unauthorized distribution.

๐Ÿš€ Features

Core Obfuscation

  • Variable Name Obfuscation: Transforms readable variable names into obfuscated identifiers
  • String Encryption: Encrypts string literals using base64 encoding
  • AST Transformation: Advanced Abstract Syntax Tree manipulation
  • Import Protection: Secures import statements and module loading

Machine Binding & Licensing

  • Hardware Fingerprinting: Generates unique machine identifiers based on CPU, MAC address, and disk serial
  • License Key Generation: Creates signed license keys with expiration dates
  • Runtime Verification: Validates licenses on every code execution
  • Tamper Detection: Detects attempts to modify or bypass protection

Project Protection

  • Directory Processing: Obfuscates entire Python projects recursively
  • Package Structure Preservation: Maintains original project structure
  • Unified Licensing: Single license file for entire projects
  • Cross-Platform: Works on Linux, Windows, and macOS

Command Line Interface

  • Standalone Executable: Run with pyprotect command after installation
  • Professional CLI: Standard flag-based interface (-i, -o, -d, -r, -m, -c)
  • Deploy Mode: ๐Ÿš€ Backup and replace in-place with confirmation (-d)
  • Restore Mode: ๐Ÿ”„ Easy rollback from backups with confirmation (-r)
  • Easy Installation: One-command setup with ./install.sh
  • System Integration: Available globally after installation

๐Ÿ“‹ Table of Contents

๐Ÿ› ๏ธ Installation

Choose one of the installation methods below based on your needs.

๐Ÿ“‹ Prerequisites

  • Python 3.6 or higher (3.9+ recommended for best performance)
  • pip package manager
  • Git (for cloning the repository)
  • sudo/admin privileges (for system-wide installation)

๐Ÿ’ก Windows Users: See INSTALL_WINDOWS.md for detailed Windows-specific installation instructions and troubleshooting.


๐Ÿš€ Quick Install (Recommended)

One-Command Installation

Linux/macOS

# Clone and install PyProtect with standalone command
git clone https://github.com/dynaz/PyProtect.git
cd PyProtect
./install.sh

๐Ÿ’ก Note for Ubuntu 23.04+/Debian 12+/WSL: If you see "externally-managed-environment" error, the installer will automatically handle it. The pyprotect command will work even if package installation is skipped.

Windows (PowerShell - Recommended)

# Clone and install PyProtect with standalone command
git clone https://github.com/dynaz/PyProtect.git
cd PyProtect
.\install.ps1

Windows (Command Prompt)

# Clone and install PyProtect with standalone command
git clone https://github.com/dynaz/PyProtect.git
cd PyProtect
install.bat

Verify Installation

# Linux/macOS/Windows (after restarting terminal)
pyprotect --help
# Should display: PyProtect - Python Obfuscator with Machine ID Binding

๐Ÿ“ฆ Manual Installation

Step 1: Download

# Clone the repository
git clone https://github.com/dynaz/PyProtect.git
cd PyProtect

Step 2: Make Executable (Linux/macOS only)

# Make the script executable
chmod +x pyprotect.py

Step 3: System Integration (Optional)

Linux/macOS

# Create global symlink (requires sudo)
sudo ln -sf "$(pwd)/pyprotect.py" /usr/local/bin/pyprotect

# Or add to your PATH
export PATH="$PATH:$(pwd)"

Windows (PowerShell - Run as Administrator)

# Create wrapper batch file
$scriptDir = Get-Location
$wrapperContent = "@echo off`npython `"$scriptDir\pyprotect.py`" %*"
$wrapperContent | Out-File -FilePath "$scriptDir\pyprotect.bat" -Encoding ASCII

# Add to user PATH
$currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
[Environment]::SetEnvironmentVariable("Path", "$currentPath;$scriptDir", "User")

Windows (Command Prompt - Run as Administrator)

# Create wrapper batch file
echo @echo off > pyprotect.bat
echo python "%CD%\pyprotect.py" %%* >> pyprotect.bat

# Add to PATH (restart terminal after)
setx PATH "%PATH%;%CD%"

Step 4: Verify

# Test direct execution (Linux/macOS)
./pyprotect.py --help

# Test direct execution (Windows)
python pyprotect.py --help

# Test global command (after PATH setup and terminal restart)
pyprotect --help

๐Ÿณ Docker Installation

Build Docker Image

git clone https://github.com/dynaz/PyProtect.git
cd PyProtect

# Build the image
docker build -t pyprotect .

# Run PyProtect in container
docker run -v $(pwd):/workspace pyprotect --help

Use Pre-built Image

# Pull and run
docker run -it dynaz/pyprotect --help

๐Ÿงช Development Installation

For Contributors

Linux/macOS

# Clone repository
git clone https://github.com/dynaz/PyProtect.git
cd PyProtect

# Set up virtual environment
python3 -m venv venv
source venv/bin/activate

# Install development dependencies
pip install -r requirements-dev.txt

# Run tests
python -m pytest tests/

# Make executable
chmod +x pyprotect.py

Windows (PowerShell)

# Clone repository
git clone https://github.com/dynaz/PyProtect.git
cd PyProtect

# Set up virtual environment
python -m venv venv
.\venv\Scripts\Activate.ps1

# Install development dependencies
pip install -r requirements-dev.txt

# Run tests
python -m pytest tests/

Windows (Command Prompt)

# Clone repository
git clone https://github.com/dynaz/PyProtect.git
cd PyProtect

# Set up virtual environment
python -m venv venv
venv\Scripts\activate.bat

# Install development dependencies
pip install -r requirements-dev.txt

# Run tests
python -m pytest tests/

๐Ÿ”ง Advanced Installation

Custom Installation Path

# Install to custom location
PYPROTECT_HOME="$HOME/.local/pyprotect"
mkdir -p "$PYPROTECT_HOME"
cp -r PyProtect/* "$PYPROTECT_HOME/"
chmod +x "$PYPROTECT_HOME/pyprotect.py"

# Add to PATH in your shell profile
echo "export PATH=\"\$PATH:$PYPROTECT_HOME\"" >> ~/.bashrc
source ~/.bashrc

Portable Installation (USB/External Drive)

# Copy to external drive
EXTERNAL_DRIVE="/mnt/external"
cp -r PyProtect "$EXTERNAL_DRIVE/"
cd "$EXTERNAL_DRIVE/PyProtect"

# Run directly
python3 pyprotect.py --help

โœ… Post-Installation

Test Your Installation

# Basic functionality test
pyprotect -m  # Should show your machine ID

# Obfuscation test
pyprotect -i examples/demo.py  # Should create /dist/demo.py

# License check test
pyprotect -c  # Should scan for license files

Troubleshooting Installation

"pyprotect command not found"

# Check if in PATH
which pyprotect  # Check if in PATH
ls -la /usr/local/bin/pyprotect  # Check symlink

# Test direct execution
./pyprotect.py --help

# Check permissions
ls -la pyprotect.py

"externally-managed-environment" Error (Ubuntu/Debian/WSL)

Status: โœ… HANDLED - The installer now automatically handles this!

If you see this error on Ubuntu 23.04+, Debian 12+, or WSL:

error: externally-managed-environment

What happens: The installer will:

  1. โœ… Automatically try with --break-system-packages flag
  2. โœ… If that fails, skip package installation (symlink still works!)
  3. โœ… The pyprotect command will work even without package installation

Manual alternatives (if needed):

# Option 1: Use pipx (recommended for applications)
sudo apt install pipx
pipx install -e .

# Option 2: Use virtual environment
python3 -m venv venv
source venv/bin/activate
pip install -e .

# Option 3: Skip package install (symlink is sufficient)
# The symlink created by install.sh is enough to use 'pyprotect' command

Upgrade PyProtect

cd PyProtect
git pull origin main
./install.sh  # Re-run installer

๐Ÿš€ Quick Start

โœ… NEW: PyProtect now supports Odoo and framework obfuscation! Public API names (functions and classes that don't start with _) are automatically preserved, allowing cross-module imports to work correctly.

๐Ÿš€ NEW: Deploy mode (-d) - Automatically backup and replace in-place with user confirmation!

๐Ÿ”„ NEW: Restore mode (-r) - Easily restore from backups with one command!

Protect a Single File

pyprotect -i my_script.py -b
# Output: /dist/my_script.py (machine-bound)

Protect an Entire Project

pyprotect -i my_project/ -b -e 365
# Output: /dist/my_project/ (entire project protected)
# Note: Only use for self-contained projects without explicit cross-module imports

Deploy Mode - Backup and Replace โญ

pyprotect -i /path/to/module -d -b -e 365
# Protects, asks confirmation, then backs up and replaces original

Restore from Backup โญ

pyprotect -r /path/to/module.backup_20251209_125530
# Asks confirmation, then restores original from backup

Test Protection

# Test a protected script (after running pyprotect on it)
python3 -c "import sys; sys.path.insert(0, '.'); import my_protected_script"
# Should work on licensed machine, fail on others

# Or test the examples in this repository:
cd examples
python3 -c "import demo_bound; result = demo_bound.secret_function('super_secret_key_12345'); print('Protected script result:', result)"

# Test protected project modules:
cd protected_project
python3 -c "from models.user import User; u = User('Test', 25); print('User:', u.name)"

๐Ÿ“– Usage

Basic Syntax

pyprotect -i INPUT [-o OUTPUT] [OPTIONS]

Note: After installation with ./install.sh, you can use pyprotect from anywhere. Alternatively, use python3 pyprotect.py if running directly.

โœ… Recommended Use Cases

  • Odoo Addons: Custom Odoo modules and addons (โœ… NEW: Fully supported!)
  • Django/Flask Apps: Web applications with multiple modules (โœ… NEW: Cross-module imports work!)
  • Standalone Scripts: Single-file Python applications
  • Final Applications: Complete apps with public APIs
  • Closed Systems: Scripts running in controlled environments
  • CLI Tools: Command-line utilities
  • Custom Business Logic: Proprietary algorithms and business rules
  • Framework Plugins: Plugins and extensions for existing frameworks

โš ๏ธ Use With Caution For

  • Open-source Contributions: Code that others need to read and maintain
  • Debugging Required: Code still in active development (harder to debug obfuscated code)
  • Python Libraries: Public packages on PyPI (users expect readable source code)

Input Types

  • Single File: script.py
  • Directory: myproject/ (processes all .py files recursively)

Output Types

  • Single File: protected.py (default: /dist/filename.py)
  • Directory: protected/ (default: /dist/inputname/, maintains input structure)

โš™๏ธ Command Line Options

Option Description Default
-i, --input INPUT Input file or directory Required
-o, --output OUTPUT Output file or directory /dist/
-d, --deploy ๐Ÿš€ NEW: Deploy mode - backup and replace in-place (ignores -o) Disabled
-r, --restore BACKUP ๐Ÿ”„ NEW: Restore from backup - specify backup path -
-u, --url URL ๐Ÿ”— NEW: Project URL to embed in license file (e.g., GitHub repo) -
-m, --machine-id Display current machine ID -
-c, --check-license DIR Check license validity in directory Current dir
-b, --bind-machine Bind code to current machine hardware Disabled
-e DAYS, --expiration DAYS License expiration in days 365
--no-preserve-api Obfuscate all names including public API Disabled (API preserved)

๐Ÿ†• Public API Preservation (Default)

By default, PyProtect preserves public API names to allow cross-module imports:

  • Preserved: Public functions/classes (no leading _)
  • Obfuscated: Private functions/classes (leading _)
  • Preserved: Odoo-specific attributes (_name, _inherit, create, etc.)
  • Compatible: Works with Odoo, Django, Flask, and other frameworks

Example:

# Default: Preserves public API (Odoo/Framework compatible)
pyprotect -i my_odoo_addon/

# Full obfuscation: May break imports
pyprotect -i standalone_script.py --no-preserve-api

๐Ÿ’ก Examples

Example 1: Basic File Protection

# Protect a single Python file (output to /dist/filename.py)
pyprotect -i sensitive_code.py

# Or specify custom output
pyprotect -i sensitive_code.py -o protected.py

Example 2: Machine-Bound Protection

# Protect and bind to current machine for 1 year
pyprotect -i app.py -o app_protected.py -b -e 365

Example 3: Project Protection

# Protect entire Django/Flask project (output to /dist/)
pyprotect -i my_django_project/ -b

# Or specify custom output directory
pyprotect -i my_django_project/ -o protected_project/ -b

Example 4: Check Machine ID

# Display current machine ID for licensing
pyprotect -m
# Output: Machine ID: 0a3a756bffd5fe563cb9b9ec3e5e17fb

Example 5: Check License Status

# Check license validity in current directory
pyprotect -c

# Check license in specific directory
pyprotect -c /path/to/protected/app
# Shows: โœ… VALID - License valid, โœ… Machine ID matches

Example 6: Trial Version (30 days)

# Create time-limited trial version
pyprotect -i software.py -o trial_version.py -b -e 30

Example 7: Obfuscating Odoo Addons (โœ… Now Supported!)

# โœ… NEW: Obfuscating Odoo addons now works correctly!
# Public API names are preserved, allowing cross-module imports

# Obfuscate a custom Odoo addon
pyprotect -i /path/to/custom_addon/ -o /dist/custom_addon/ -b

# Obfuscate entire Odoo server (if needed)
pyprotect -i /odoo18/odoo18-server/addons/my_custom_addon/ -b

# What gets preserved:
# โœ… Public functions: def my_function() โ†’ preserved
# โœ… Public classes: class MyClass โ†’ preserved  
# โœ… Public methods: def method() โ†’ preserved
# โœ… Odoo model attributes: _name, _inherit, create, write, etc.
# โš™๏ธ Private functions: def _helper() โ†’ obfuscated to _fn_0
# โš™๏ธ Variables: user_input โ†’ obfuscated to _obf_0

# Test after obfuscation:
cd /dist/custom_addon
python3 -m odoo  # Should work! โœ…

Example 8: Deploy Mode - Backup and Replace In-Place ๐Ÿš€ NEW

# Deploy mode: Protect and replace original (with automatic backup)
pyprotect -i /odoo18/custom/my_addon -d -b -e 365 -u https://github.com/mycompany/my_addon

# What happens:
# 1. Protects the code
# 2. Shows confirmation prompt:
#    โš ๏ธ  Proceed with backup and replacement? (y/n): 
# 3. If 'y': Creates backup (my_addon.backup_20251209_125530) and replaces original
# 4. If 'n': Keeps everything unchanged

# Result (if confirmed):
# โœ… my_addon/ - Protected code (deployed)
# ๐Ÿ“ฆ my_addon.backup_20251209_125530/ - Original backup

# Benefits:
# โœ… One-command deployment
# โœ… Automatic timestamped backup
# โœ… User confirmation before replacing
# โœ… Backup stays in same directory for easy access

Example 9: Restore from Backup ๐Ÿ”„ NEW

# Restore original code from backup
pyprotect -r /odoo18/custom/my_addon.backup_20251209_125530

# What happens:
# 1. Shows restore plan
# 2. Asks for confirmation:
#    โš ๏ธ  Proceed with restore? (y/n):
# 3. If 'y': Removes current version and restores backup
# 4. If 'n': Nothing is changed

# Benefits:
# โœ… Easy one-command restore
# โœ… Automatic path detection
# โœ… User confirmation before removing current version
# โœ… Safe rollback if protected code has issues

Example 10: Complete Deploy โ†’ Test โ†’ Restore Workflow

# Step 1: Deploy protected version
pyprotect -i /odoo18/custom/my_addon -d -b -e 365
# Answer 'y' to confirm

# Step 2: Test the protected version
# ... test your application ...

# Step 3: If issues found, restore quickly
pyprotect -r /odoo18/custom/my_addon.backup_20251209_125530
# Answer 'y' to restore

# Step 4: Fix issues in original, then re-deploy
pyprotect -i /odoo18/custom/my_addon -d -b -e 365

๐Ÿ”’ Security Features

Variable Obfuscation

# Original
def process_data(user_input, api_key="secret123"):
    secret_token = "token_abc123"
    return user_input + secret_token

# Protected
def _obf_0(_obf_1, _obf_2=_decrypt_str('0')):
    _obf_3 = _decrypt_str('1')
    return _obf_1 + _obf_3

String Encryption

# Original strings are base64 encoded
_STRINGS = ['c2VjcmV0MTIz', 'dG9rZW5fYWJjMTIz']  # Encrypted strings

Hardware Binding

  • Machine ID Generation: Combines CPU, MAC, and disk serial
  • License Validation: Runtime checks ensure code only runs on authorized machines
  • Expiration Control: Time-based license expiration

Runtime Protection

# Automatic license check on import
_check_license()  # Validates machine and expiration

๐Ÿ—๏ธ Architecture

Core Components

  1. AST Processor (Obfuscator class)

    • Parses Python code into Abstract Syntax Tree
    • Transforms variable names and string literals
    • Applies obfuscation rules
  2. License Manager

    • Generates hardware fingerprints
    • Creates signed license keys
    • Validates licenses at runtime
  3. Runtime Engine

    • Decrypts strings on-demand
    • Verifies machine authorization
    • Handles tamper detection

File Structure

PyProtect/
โ”œโ”€โ”€ pyprotect.py          # Main obfuscation tool
โ”œโ”€โ”€ README.md            # This documentation
โ”œโ”€โ”€ examples/            # Sample projects
โ”‚   โ”œโ”€โ”€ basic_script.py
โ”‚   โ””โ”€โ”€ sample_project/
โ””โ”€โ”€ tests/               # Test cases
    โ”œโ”€โ”€ test_obfuscation.py
    โ””โ”€โ”€ test_licensing.py

โš ๏ธ Limitations

Current Limitations

  • Complex Metaclasses: Advanced Python patterns may need adjustment
  • Dynamic Imports: importlib and dynamic imports may require special handling
  • Third-party Libraries: Some libraries may not work with obfuscated code

Public API Preservation (Default Behavior)

  • โœ… Framework Compatible: By default, PyProtect preserves public API names (functions/classes not starting with _)
  • โœ… Cross-Module Imports: from module import function_name works correctly after obfuscation
  • โœ… Odoo Compatible: Tested and working with Odoo's module system
  • Option: Use --no-preserve-api flag for full obfuscation (may break imports)

Known Issues

  • Very large files (>10MB) may be slow to process
  • Some debugging tools may not work with obfuscated code

๐Ÿ”ง Troubleshooting

Common Issues

"ImportError: cannot import name 'function_name' from 'module'" (FIXED!)

Status: โœ… RESOLVED - This issue is now fixed in the latest version!

Solution: PyProtect now automatically preserves public API names (functions and classes that don't start with _), so cross-module imports work correctly by default.

How it works:

# Public functions (no leading _) are preserved:
def strftime_format_to_spreadsheet_date_format(fmt):  # Name preserved โœ…
    return _internal_helper(fmt)  # Private function obfuscated โœ…

# After obfuscation, you can still import:
from module import strftime_format_to_spreadsheet_date_format  # Works! โœ…

Advanced Option: If you need full obfuscation (which may break imports), use:

pyprotect -i mycode.py --no-preserve-api

Best Practice: Keep default behavior for Odoo/framework code. Only use --no-preserve-api for standalone scripts where no imports are needed.

"SyntaxError: invalid syntax"

Cause: F-strings or advanced Python syntax not supported Solution: Convert f-strings to .format() or string concatenation

"ModuleNotFoundError"

Cause: Import paths changed after obfuscation Solution: Use absolute imports or adjust PYTHONPATH

"Unauthorized use of script"

Cause: License validation failed Solutions:

  • Verify you're on the licensed machine
  • Check license hasn't expired
  • Regenerate license if hardware changed

"ast.Unparse not available"

Cause: Python version < 3.9 Solution: Upgrade Python or use string fallback mode

Debug Mode

# Enable verbose output
pyprotect -i input.py -o output.py --verbose

Recovery

# If obfuscation fails, restore from backup
cp original_file.py obfuscated_file.py.backup

๐Ÿค Contributing

We welcome contributions! Please see our contributing guidelines:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. Submit a pull request

Development Setup

git clone https://github.com/dynaz/PyProtect
cd pyprotect
python3 -m pip install -r requirements-dev.txt
python3 -m pytest tests/

Code Standards

  • Follow PEP 8 style guidelines
  • Add docstrings to all functions
  • Include unit tests for new features
  • Update documentation for changes

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

Commercial Use

For commercial applications requiring advanced features:

  • Enterprise licensing available
  • Priority support
  • Custom feature development
  • Professional services

๐Ÿ“ž Support

Documentation

Community

  • GitHub Issues: Report bugs and request features
  • Discussions: Ask questions and share experiences
  • Wiki: Community guides and tutorials

Professional Support

For enterprise deployments and custom requirements:

Support the Project

If you find PyProtect helpful, consider supporting the development:

Buy Me A Coffee

Your support helps maintain and improve this open-source project! โ˜•


๐ŸŽฏ Quick Reference

Most Common Commands

# Quick protection (output to /dist/)
pyprotect -i file.py -b

# Project protection (output to /dist/)
pyprotect -i project/ -b

# Trial version (30 days)
pyprotect -i app.py -o trial.py -b -e 30

# Check machine ID
pyprotect -m

# Check license status
pyprotect -c

Verification

# Test protected file
python3 protected.py

# Test protected module (after creating one)
python3 -c "import my_protected_module; print('Module works!')"

# View machine ID (alternative method)
pyprotect -m

# Check license validity in current directory
pyprotect -c

# Check license in protected project
pyprotect -c /dist/base

# Test example protected scripts
cd examples
python3 -c "import demo_bound; result = demo_bound.secret_function('super_secret_key_12345'); print('Demo result:', result)"
python3 -c "import test_protected; result = test_protected.secret_function('super_secret_key_12345'); print('Test result:', result)"

PyProtect - Secure your Python code with advanced obfuscation and hardware binding! ๐Ÿ”โœจ

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyprotect_th-2.1.1-py3-none-any.whl (24.3 kB view details)

Uploaded Python 3

File details

Details for the file pyprotect_th-2.1.1-py3-none-any.whl.

File metadata

  • Download URL: pyprotect_th-2.1.1-py3-none-any.whl
  • Upload date:
  • Size: 24.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pyprotect_th-2.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0ab16549a204f70bc1dcef74570d2e5b4371d7c94d084d85b0f67d49b6f61946
MD5 229a83a5476eacce4301b16d4eb4b2fa
BLAKE2b-256 6f1ec67f81155b66f10d97f0fe28ecfd0eb646c540b516dcc8938c1a0773129c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page