From 07efe0ff81f5105bda489f460ee1e318edb77c40 Mon Sep 17 00:00:00 2001 From: bluepulsar Date: Sun, 4 Jan 2026 14:23:00 +0800 Subject: [PATCH] ensure obf --- build_multi_version.py | 94 +++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/build_multi_version.py b/build_multi_version.py index 75e874c..40a1a9b 100644 --- a/build_multi_version.py +++ b/build_multi_version.py @@ -105,8 +105,10 @@ def obfuscate_code(): # PyArmor 9.x generates version-independent obfuscated code # Output directly to dist_obfuscated/src (PyArmor will create orisys subdirectory) + # Use --obf-code 1 to enable code obfuscation (default is 1, but explicit is better) + # Use --exclude to exclude __init__.py files that don't need obfuscation (optional) if IS_WINDOWS: - cmd = 'pyarmor gen --output dist_obfuscated/src --recursive src/orisys' + cmd = 'pyarmor gen --output dist_obfuscated/src --recursive --obf-code 1 src/orisys' print(f"Running: {cmd}") result = subprocess.run(cmd, capture_output=True, text=True, shell=True) else: @@ -115,6 +117,7 @@ def obfuscate_code(): 'gen', '--output', 'dist_obfuscated/src', '--recursive', + '--obf-code', '1', 'src/orisys' ] print(f"Running: {' '.join(cmd)}") @@ -127,6 +130,26 @@ def obfuscate_code(): print("Code obfuscation successful!") print(result.stdout) + + # Verify obfuscation: check that obfuscated files exist and original .py files are obfuscated + obfuscated_dir = Path('dist_obfuscated/src/orisys') + if obfuscated_dir.exists(): + py_files = list(obfuscated_dir.rglob('*.py')) + print(f"Found {len(py_files)} obfuscated .py files") + # Check a sample file to verify it's obfuscated (should contain PyArmor markers) + if py_files: + sample_file = py_files[0] + try: + with open(sample_file, 'rb') as f: + content = f.read(100) # Read first 100 bytes + # PyArmor obfuscated files typically start with specific markers + if b'__pyarmor__' in content or b'pyarmor' in content.lower(): + print(f"✓ Verified: {sample_file.name} is obfuscated") + else: + print(f"⚠ Warning: {sample_file.name} may not be properly obfuscated") + except Exception as e: + print(f"Could not verify obfuscation: {e}") + return True @@ -135,24 +158,25 @@ def copy_additional_files(): print("\n=== Copying additional files ===") # Ensure configs directory exists in obfuscated output - # PyArmor should copy it, but we verify and copy if needed + # IMPORTANT: Only copy JSON files, NOT .py files (those should be obfuscated by PyArmor) configs_src = Path('src/orisys/configs') configs_dst = Path('dist_obfuscated/src/orisys/configs') if configs_src.exists(): - print(f"Ensuring configs directory is copied...") + print(f"Ensuring configs directory is copied (JSON files only)...") if not configs_dst.exists(): - print(f"Copying configs directory from {configs_src} to {configs_dst}") - shutil.copytree(configs_src, configs_dst, dirs_exist_ok=True) + configs_dst.mkdir(parents=True, exist_ok=True) + + # Only copy JSON files, not any .py files + json_files_src = list(configs_src.glob('*.json')) + json_files_dst = list(configs_dst.glob('*.json')) + + if len(json_files_dst) < len(json_files_src): + print(f"Copying JSON files from configs directory ({len(json_files_src)} files)") + for json_file in json_files_src: + shutil.copy(json_file, configs_dst / json_file.name) else: - # Verify JSON files are present - json_files_src = list(configs_src.glob('*.json')) - json_files_dst = list(configs_dst.glob('*.json')) - if len(json_files_dst) < len(json_files_src): - print(f"Updating configs directory (found {len(json_files_dst)}/{len(json_files_src)} JSON files)") - shutil.copytree(configs_src, configs_dst, dirs_exist_ok=True) - else: - print(f"Configs directory already present with {len(json_files_dst)} JSON files") + print(f"Configs directory already present with {len(json_files_dst)} JSON files") # Copy config directory (if exists at root level) if os.path.exists('config'): @@ -165,6 +189,40 @@ def copy_additional_files(): if os.path.exists(file): print(f"Copying {file}...") shutil.copy(file, f'dist_obfuscated/{file}') + + # Verify that no original .py files are in dist_obfuscated (except obfuscated ones) + print("\n=== Verifying obfuscated output ===") + obfuscated_py_files = list(Path('dist_obfuscated/src/orisys').rglob('*.py')) + print(f"Found {len(obfuscated_py_files)} .py files in obfuscated output") + + # Check if any files look like original source (not obfuscated) + original_like_files = [] + for py_file in obfuscated_py_files: + # Skip __init__.py files as they might be simple + if py_file.name == '__init__.py': + continue + try: + with open(py_file, 'rb') as f: + content = f.read(500) # Read first 500 bytes + # Check for common Python source patterns that shouldn't be in obfuscated code + if b'def ' in content and b'__pyarmor__' not in content: + # Might be original source + if b'import ' in content or b'from ' in content: + # Check if it has readable imports (obfuscated code has different structure) + text_content = content.decode('utf-8', errors='ignore') + if 'import ' in text_content and '__pyarmor__' not in text_content: + original_like_files.append(py_file) + except Exception as e: + print(f"Warning: Could not check {py_file}: {e}") + + if original_like_files: + print(f"⚠️ Warning: Found {len(original_like_files)} files that may not be obfuscated:") + for f in original_like_files[:5]: # Show first 5 + print(f" - {f}") + if len(original_like_files) > 5: + print(f" ... and {len(original_like_files) - 5} more") + else: + print("✓ All .py files appear to be obfuscated") def create_setup_for_obfuscated(python_version=None): @@ -231,6 +289,8 @@ setup( python_requires="{version_constraint}", # Include PyArmor runtime files zip_safe=False, + # Exclude original source files - only include obfuscated files from dist_obfuscated + exclude_package_data={{'': ['*.pyc', '*.pyo', '__pycache__']}}, options={{ 'bdist_wheel': {{ 'python_tag': '{py_tag}', @@ -246,7 +306,7 @@ setup( def create_manifest_in(): - """Create MANIFEST.in to ensure JSON files in configs are included.""" + """Create MANIFEST.in to ensure JSON files in configs are included and exclude original source.""" print("\n=== Creating MANIFEST.in ===") manifest_content = """# Include all JSON files in configs directory @@ -258,6 +318,12 @@ recursive-include src *.pyd recursive-include src *.so recursive-include src *.dll recursive-include src *.dylib + +# Exclude original source files (only obfuscated .py files should be included) +# The obfuscated .py files from PyArmor will be included automatically +# But we want to make sure no original source files are accidentally included +prune src/orisys +recursive-include src/orisys *.py """ manifest_path = Path('dist_obfuscated/MANIFEST.in')