mauricelambert / PyObfuscator

This module obfuscates python code.
GNU General Public License v3.0
16 stars 7 forks source link

Can you support direct full obfuscation of the entire project? #16

Closed JavanTang closed 1 month ago

JavanTang commented 2 months ago

I used a script to obfuscate all the .py files in the entire project. However, I encountered errors indicating that the modules cannot be properly linked. I would appreciate your assistance in resolving this issue. Thank you.

Here's script:

import os
import subprocess

def obfuscate_directory(path):
    # 遍历目录中的所有文件和子目录
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.endswith('.py'):  # 检查文件是否为 Python 文件
                full_path = os.path.join(root, file)
                print(f"Obfuscating {full_path}...")
                # 执行混淆命令,将输出重定向到原文件,从而替换它
                subprocess.run([
                    'python3', '-m', 'PyObfuscator',
                    '-o', full_path,   # 输出文件替换原文件
                    full_path          # 指定源文件
                ], check=True)

# 直接通过传入参数的方式,选择文件夹
import sys
obfuscate_directory(sys.argv[1])
mauricelambert commented 1 month ago

Hi @JavanTang, i think is not possible to obfuscate a full project in python without configuration because relative imports will be obfuscated:

Problem

A non obfuscated code named test.py will be:

my_variable = "qwerty"
system = "linux"

In the __main__.py file you have:

from test import my_variable
from os import system

system(f"echo {my_variable}") # this code is vulnerable, don't use it in production ! It's only for the demonstration

With this configuration you have 2 solutions to obfuscate project:

  1. Obfuscate all variables, store obfuscated names for all files and obfuscate the imports:
    • So my_variable can be obfuscated as a (for example) in all files, so you import a from test and is working good
    • system can be obfuscated as b (for example) in all file, so you import b from os and here is not working
  2. Obfuscate all variables, store obfuscated names for all files but don't obfuscate imports:
    • So my_variable can be obfuscate as a (for example) in all files but you import my_variable from test and here is not working (because in test.py the my_variable will be renamed for obfuscation)
    • system can be obfuscated as b (for example) in all file but you import system from os and here is working good

So, it's very difficult to identify correctly what should be obfuscated in imports, i think the only good way to do this is to load the python project and use the python interpreter to know where are each file and which file are imported. But loading the python project will generate a python execution (if there is the if __name__ == "__main__" it's probably safe), you probably don't want an execution on your system for each obfuscation.

Fix

If you have any other idea to fix it i will be happy to implement the solution or merge a pull request !

Solution

The only solution you have today with PyObfuscator is to configure your project, you can control the obfuscated name for all file. To do this use python script or --names argument in the command line and for each imported element write the same name than imports, for example with the previous example:

With the previous example you should use the following commands:

PyObfuscator -n "my_variable:my_variable" -l 12 test.py
PyObfuscator __main__.py

Or to obfuscate the my_variable variable name, change the __main__.py:

from test import qbd45_kj
from os import system

system(f"echo {qbd45_kj}") # this code is vulnerable, don't use it in production ! It's only for the demonstration

And use:

PyObfuscator -n "my_variable:qbd45_kj" -l 12 test.py
PyObfuscator __main__.py

You can do it with command line or python script: usages.

JavanTang commented 1 month ago

These days, I have been thinking about whether there is a way to obfuscate an entire project. But I also haven’t found a good method to achieve this. I decided to use “-n” with your suggestion to set various names. I appreciate your response. Thank you.