python-obfuscation-framework 1.10.0__tar.gz → 1.11.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_obfuscation_framework-1.10.0/python_obfuscation_framework.egg-info → python_obfuscation_framework-1.11.1}/PKG-INFO +33 -4
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/README.md +32 -3
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/boolean.py +18 -6
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/esoteric/doc.py +6 -6
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/esoteric/globals.py +17 -5
- python_obfuscation_framework-1.11.1/pof/obfuscator/esoteric/imports.py +257 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/names.py +36 -3
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/print.py +1 -1
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/strings.py +101 -60
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/cipher/rc4.py +1 -1
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/stegano/ipv6encoding.py +9 -5
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/stegano/macencoding.py +9 -5
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/stegano/uuidencoding.py +15 -5
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pyproject.toml +1 -1
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1/python_obfuscation_framework.egg-info}/PKG-INFO +33 -4
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/python_obfuscation_framework.egg-info/SOURCES.txt +13 -1
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/conftest.py +35 -71
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/booleans.py +30 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/fixtures/complex.py +20 -51
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/compression.py +15 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/decorators.py +54 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/deepenc.py +14 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/docs.py +10 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/encoding.py +42 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/esoteric.py +48 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/getattr.py +27 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/import.py +21 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/lambda.py +4 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/fixtures/moderate.py +0 -27
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/numbers.py +29 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/rc4.py +36 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/fixtures/simple.py +6 -4
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/strings.py +55 -0
- python_obfuscation_framework-1.11.1/tests/obfuscator/fixtures/try.py +6 -0
- python_obfuscation_framework-1.10.0/pof/obfuscator/esoteric/imports.py +0 -71
- python_obfuscation_framework-1.10.0/tests/obfuscator/fixtures/getattr.py +0 -10
- python_obfuscation_framework-1.10.0/tests/obfuscator/fixtures/multiline_strings.py +0 -22
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/LICENSE +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/MANIFEST.in +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/__main__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/cli.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/cli_v2.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/errors.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/argv.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/base.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/cpu/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/cpu/cpu_count.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/directory_exist.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/directory_list_exist.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/directory_list_missing.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/directory_missing.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/exec_method.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/executable_path.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/file_exist.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/file_list_exist.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/file_list_missing.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/file_missing.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/fs/tmp.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/hardware/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/hardware/ram_count.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/hooks/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/hooks/debugger.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/hooks/tracemalloc.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/human/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/human/p.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/human/prompt.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/integrity.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/multi.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/os/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/os/domain.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/os/hostname.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/os/uid.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/os/username.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/processes/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/processes/proc_count.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/time/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/time/expire.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/time/uptime.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/time/utc.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/evasion/utils.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/logger.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/main.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/builtins.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/cipher/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/cipher/deep_encryption.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/cipher/rc4.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/cipher/shift.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/cipher/xor.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/compression/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/compression/bz2.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/compression/gzip.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/compression/lzma.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/compression/zlib.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/constants.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/controlflow/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/controlflow/control_flow_flatten.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/a85.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/b16.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/b32.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/b32hex.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/b64.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/b85.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/binascii.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/snt.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/encoding/whitespace.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/esoteric/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/esoteric/call.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/extract_variables.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/junk/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/junk/add_comments.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/junk/add_newlines.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/junk/dead_code.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/numbers.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/other/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/other/tokens.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/comments.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/exceptions.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/indents.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/loggings.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/loggings_old.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/remove/newline.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/restructure.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/stegano/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/stegano/docstrings.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/stegano/ipv6encoding.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/stegano/macencoding.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/stegano/uuidencoding.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/cipher/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/cipher/rc4.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/download.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/image.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/lots/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/lots/cl1pnet.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/lots/pastebin.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/lots/pasters.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/stager/quine.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/cipher/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/cipher/shift.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/compression/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/compression/bz2.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/compression/gzip.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/compression/lzma.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/compression/zlib.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/a85.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/b16.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/b3.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/b32.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/b32hex.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/b64.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/b85.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/binascii.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/snt.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/encoding/whitespace.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/entropy.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/extract_names.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/format.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/advanced.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/base.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/basic.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/comments.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/comments.txt +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/names.txt +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/generator/unicode.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/se/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/se/homoglyphs.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/se/homoglyphs.txt +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/stegano/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/utils/tokens.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/python_obfuscation_framework.egg-info/dependency_links.txt +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/python_obfuscation_framework.egg-info/entry_points.txt +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/python_obfuscation_framework.egg-info/requires.txt +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/python_obfuscation_framework.egg-info/top_level.txt +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/setup.cfg +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/fixtures/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/test_edge_cases.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/test_integration.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/obfuscator/utils.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/pyproject.toml +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/utils/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/utils/se/__init__.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/utils/se/test_homoglyphs.py +0 -0
- {python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/tests/utils/test_generator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-obfuscation-framework
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.11.1
|
|
4
4
|
Summary: Python Obfuscation Framework
|
|
5
5
|
Author-email: deoktr <35725720+deoktr@users.noreply.github.com>
|
|
6
6
|
Maintainer-email: deoktr <35725720+deoktr@users.noreply.github.com>
|
|
@@ -795,20 +795,50 @@ exec(binascii.a2b_hex("".join(['7072696e-7428-2748-656c-6c6f2c20776f','726c6427-
|
|
|
795
795
|
|
|
796
796
|
#### ImportsObfuscator
|
|
797
797
|
|
|
798
|
-
|
|
798
|
+
Remove keyword `import`.
|
|
799
799
|
|
|
800
800
|
```python
|
|
801
|
-
|
|
801
|
+
# import X
|
|
802
|
+
X = __import__("X")
|
|
803
|
+
|
|
804
|
+
# import X as Y
|
|
805
|
+
Y = __import__("X")
|
|
806
|
+
|
|
807
|
+
# import X, Y
|
|
808
|
+
X = __import__("X")
|
|
809
|
+
Y = __import__("Y")
|
|
810
|
+
|
|
811
|
+
# import X.Y
|
|
812
|
+
X = __import__("X.Y")
|
|
813
|
+
|
|
814
|
+
# from X import Y
|
|
815
|
+
Y = __import__("X", fromlist=["Y"]).Y
|
|
816
|
+
|
|
817
|
+
# from X import Y as Z
|
|
818
|
+
Z = __import__("X", fromlist=["Y"]).Y
|
|
819
|
+
|
|
820
|
+
# from X import Y, Z
|
|
821
|
+
Y = __import__("X", fromlist=["Y"]).Y
|
|
822
|
+
Z = __import__("X", fromlist=["Z"]).Z
|
|
802
823
|
```
|
|
803
824
|
|
|
825
|
+
> [!NOTE]
|
|
826
|
+
> Does not support wildcard imports `*`, or local imports `from . import`.
|
|
827
|
+
|
|
804
828
|
#### CharFromDocObfuscator
|
|
805
829
|
|
|
830
|
+
Get a single character from a documentation.
|
|
831
|
+
|
|
806
832
|
Source: `print('h')`
|
|
807
833
|
|
|
808
834
|
```python
|
|
809
835
|
print(oct.__doc__[8])
|
|
810
836
|
```
|
|
811
837
|
|
|
838
|
+
> [!WARNING]
|
|
839
|
+
> This is highly prone to error, if the documentation change between Python
|
|
840
|
+
> versions, then this may break.
|
|
841
|
+
|
|
812
842
|
#### AddCommentsObfuscator
|
|
813
843
|
|
|
814
844
|
```python
|
|
@@ -1372,7 +1402,6 @@ Other Python obfuscation projects:
|
|
|
1372
1402
|
|
|
1373
1403
|
## TODO
|
|
1374
1404
|
|
|
1375
|
-
- Fix `NamesObfuscator`.
|
|
1376
1405
|
- Add option to prepend a shebang, and add ability to customize it.
|
|
1377
1406
|
|
|
1378
1407
|
## License
|
|
@@ -750,20 +750,50 @@ exec(binascii.a2b_hex("".join(['7072696e-7428-2748-656c-6c6f2c20776f','726c6427-
|
|
|
750
750
|
|
|
751
751
|
#### ImportsObfuscator
|
|
752
752
|
|
|
753
|
-
|
|
753
|
+
Remove keyword `import`.
|
|
754
754
|
|
|
755
755
|
```python
|
|
756
|
-
|
|
756
|
+
# import X
|
|
757
|
+
X = __import__("X")
|
|
758
|
+
|
|
759
|
+
# import X as Y
|
|
760
|
+
Y = __import__("X")
|
|
761
|
+
|
|
762
|
+
# import X, Y
|
|
763
|
+
X = __import__("X")
|
|
764
|
+
Y = __import__("Y")
|
|
765
|
+
|
|
766
|
+
# import X.Y
|
|
767
|
+
X = __import__("X.Y")
|
|
768
|
+
|
|
769
|
+
# from X import Y
|
|
770
|
+
Y = __import__("X", fromlist=["Y"]).Y
|
|
771
|
+
|
|
772
|
+
# from X import Y as Z
|
|
773
|
+
Z = __import__("X", fromlist=["Y"]).Y
|
|
774
|
+
|
|
775
|
+
# from X import Y, Z
|
|
776
|
+
Y = __import__("X", fromlist=["Y"]).Y
|
|
777
|
+
Z = __import__("X", fromlist=["Z"]).Z
|
|
757
778
|
```
|
|
758
779
|
|
|
780
|
+
> [!NOTE]
|
|
781
|
+
> Does not support wildcard imports `*`, or local imports `from . import`.
|
|
782
|
+
|
|
759
783
|
#### CharFromDocObfuscator
|
|
760
784
|
|
|
785
|
+
Get a single character from a documentation.
|
|
786
|
+
|
|
761
787
|
Source: `print('h')`
|
|
762
788
|
|
|
763
789
|
```python
|
|
764
790
|
print(oct.__doc__[8])
|
|
765
791
|
```
|
|
766
792
|
|
|
793
|
+
> [!WARNING]
|
|
794
|
+
> This is highly prone to error, if the documentation change between Python
|
|
795
|
+
> versions, then this may break.
|
|
796
|
+
|
|
767
797
|
#### AddCommentsObfuscator
|
|
768
798
|
|
|
769
799
|
```python
|
|
@@ -1327,7 +1357,6 @@ Other Python obfuscation projects:
|
|
|
1327
1357
|
|
|
1328
1358
|
## TODO
|
|
1329
1359
|
|
|
1330
|
-
- Fix `NamesObfuscator`.
|
|
1331
1360
|
- Add option to prepend a shebang, and add ability to customize it.
|
|
1332
1361
|
|
|
1333
1362
|
## License
|
|
@@ -44,24 +44,30 @@ class BooleanObfuscator:
|
|
|
44
44
|
(RPAR, ")"),
|
|
45
45
|
]
|
|
46
46
|
case 3:
|
|
47
|
-
# not False
|
|
47
|
+
# (not False)
|
|
48
48
|
return [
|
|
49
|
+
(LPAR, "("),
|
|
49
50
|
(NAME, "not"),
|
|
50
51
|
(NAME, "False"),
|
|
52
|
+
(RPAR, ")"),
|
|
51
53
|
]
|
|
52
54
|
case 4:
|
|
53
|
-
# not not True
|
|
55
|
+
# (not not True)
|
|
54
56
|
return [
|
|
57
|
+
(LPAR, "("),
|
|
55
58
|
(NAME, "not"),
|
|
56
59
|
(NAME, "not"),
|
|
57
60
|
(NAME, "True"),
|
|
61
|
+
(RPAR, ")"),
|
|
58
62
|
]
|
|
59
63
|
case 5:
|
|
60
|
-
# "" in ""
|
|
64
|
+
# ("" in "")
|
|
61
65
|
return [
|
|
66
|
+
(LPAR, "("),
|
|
62
67
|
(STRING, "''"),
|
|
63
68
|
(NAME, "in"),
|
|
64
69
|
(STRING, "''"),
|
|
70
|
+
(RPAR, ")"),
|
|
65
71
|
]
|
|
66
72
|
case 6:
|
|
67
73
|
# bool(1)
|
|
@@ -97,25 +103,31 @@ class BooleanObfuscator:
|
|
|
97
103
|
(RPAR, ")"),
|
|
98
104
|
]
|
|
99
105
|
case 3:
|
|
100
|
-
# not True
|
|
106
|
+
# (not True)
|
|
101
107
|
return [
|
|
108
|
+
(LPAR, "("),
|
|
102
109
|
(NAME, "not"),
|
|
103
110
|
(NAME, "True"),
|
|
111
|
+
(RPAR, ")"),
|
|
104
112
|
]
|
|
105
113
|
case 4:
|
|
106
|
-
# not not False
|
|
114
|
+
# (not not False)
|
|
107
115
|
return [
|
|
116
|
+
(LPAR, "("),
|
|
108
117
|
(NAME, "not"),
|
|
109
118
|
(NAME, "not"),
|
|
110
119
|
(NAME, "False"),
|
|
120
|
+
(RPAR, ")"),
|
|
111
121
|
]
|
|
112
122
|
case 5:
|
|
113
|
-
# "" not in ""
|
|
123
|
+
# ("" not in "")
|
|
114
124
|
return [
|
|
125
|
+
(LPAR, "("),
|
|
115
126
|
(STRING, "''"),
|
|
116
127
|
(NAME, "not"),
|
|
117
128
|
(NAME, "in"),
|
|
118
129
|
(STRING, "''"),
|
|
130
|
+
(RPAR, ")"),
|
|
119
131
|
]
|
|
120
132
|
case 6:
|
|
121
133
|
# bool(0)
|
|
@@ -183,31 +183,31 @@ class CharFromDocObfuscator:
|
|
|
183
183
|
)
|
|
184
184
|
|
|
185
185
|
@staticmethod
|
|
186
|
-
def
|
|
186
|
+
def _get_char_indexes(string, char):
|
|
187
187
|
return [pos for pos, c in enumerate(string) if c == char]
|
|
188
188
|
|
|
189
189
|
@classmethod
|
|
190
|
-
def
|
|
190
|
+
def _try_find_doc_index(cls, char):
|
|
191
191
|
# take a random builtin doc and search for index in it
|
|
192
192
|
builtin = random.choice(cls.BUILTINS)
|
|
193
193
|
doc = __builtins__[builtin].__doc__
|
|
194
194
|
if not doc:
|
|
195
195
|
msg = f"doc for {builtin} is not a string"
|
|
196
196
|
raise PofError(msg)
|
|
197
|
-
indexes = cls.
|
|
197
|
+
indexes = cls._get_char_indexes(doc, char)
|
|
198
198
|
if len(indexes) == 0:
|
|
199
199
|
msg = "char not present"
|
|
200
200
|
raise PofError(msg)
|
|
201
201
|
index = random.choice(indexes)
|
|
202
202
|
return builtin, index
|
|
203
203
|
|
|
204
|
-
def
|
|
204
|
+
def _obfuscate_char(self, char):
|
|
205
205
|
builtin = None
|
|
206
206
|
index = None
|
|
207
207
|
retry = 3
|
|
208
208
|
for _ in range(retry):
|
|
209
209
|
try:
|
|
210
|
-
builtin, index = self.
|
|
210
|
+
builtin, index = self._try_find_doc_index(char)
|
|
211
211
|
except PofError:
|
|
212
212
|
pass
|
|
213
213
|
else:
|
|
@@ -239,7 +239,7 @@ class CharFromDocObfuscator:
|
|
|
239
239
|
string = ast.literal_eval(tokval)
|
|
240
240
|
if len(string) == 1:
|
|
241
241
|
try:
|
|
242
|
-
new_tokens = self.
|
|
242
|
+
new_tokens = self._obfuscate_char(string)
|
|
243
243
|
except PofError as e:
|
|
244
244
|
logger.debug(str(e))
|
|
245
245
|
except Exception: # noqa: BLE001
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
|
|
17
17
|
import keyword
|
|
18
|
-
from tokenize import LPAR, NAME, OP, RPAR, STRING
|
|
18
|
+
from tokenize import LPAR, NAME, NEWLINE, NL, OP, RPAR, STRING
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
# TODO (deoktr): add frequency
|
|
@@ -42,14 +42,24 @@ class GlobalsObfuscator:
|
|
|
42
42
|
def obfuscate_tokens(cls, tokens):
|
|
43
43
|
local_functions = []
|
|
44
44
|
prev_tokval = None
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
prev_col = -1
|
|
46
|
+
for toknum, tokval, *rest in tokens:
|
|
47
|
+
start = rest[0] if rest else (0, 0)
|
|
48
|
+
if prev_tokval in ["def", "class"] and toknum == NAME and prev_col == 0:
|
|
47
49
|
local_functions.append(tokval)
|
|
50
|
+
if toknum == NAME and tokval in ("def", "class"):
|
|
51
|
+
prev_col = start[1]
|
|
48
52
|
prev_tokval = tokval
|
|
49
53
|
|
|
50
|
-
result = []
|
|
54
|
+
result = []
|
|
51
55
|
prev_tokval = None
|
|
56
|
+
in_import = False
|
|
52
57
|
for index, (toknum, tokval, *_) in enumerate(tokens):
|
|
58
|
+
if tokval in ("import", "from") and toknum == NAME:
|
|
59
|
+
in_import = True
|
|
60
|
+
elif toknum in (NEWLINE, NL):
|
|
61
|
+
in_import = False
|
|
62
|
+
|
|
53
63
|
new_tokens = [(toknum, tokval)]
|
|
54
64
|
next_tokval = None
|
|
55
65
|
if len(tokens) > index + 1:
|
|
@@ -60,8 +70,10 @@ class GlobalsObfuscator:
|
|
|
60
70
|
# ensure it's not a definition
|
|
61
71
|
and prev_tokval not in ["def", "class", "."]
|
|
62
72
|
# ensure it's not an argument of a call
|
|
63
|
-
and next_tokval
|
|
73
|
+
and next_tokval != "="
|
|
64
74
|
and tokval not in cls.RESERVED
|
|
75
|
+
# ensure it's not inside an import statement
|
|
76
|
+
and not in_import
|
|
65
77
|
):
|
|
66
78
|
new_tokens = [
|
|
67
79
|
(NAME, "globals"),
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# POF, a free and open source Python obfuscation framework.
|
|
2
|
+
# Copyright (C) 2022 - 2026 Deoktr
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
from tokenize import ENDMARKER, NAME, NEWLINE, NL, OP, STRING
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ImportsObfuscator:
|
|
21
|
+
"""Obfuscate import statements using __import__().
|
|
22
|
+
|
|
23
|
+
Supported forms:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
# import X
|
|
27
|
+
X = __import__("X")
|
|
28
|
+
|
|
29
|
+
# import X as Y
|
|
30
|
+
Y = __import__("X")
|
|
31
|
+
|
|
32
|
+
# import X, Y
|
|
33
|
+
X = __import__("X")
|
|
34
|
+
Y = __import__("Y")
|
|
35
|
+
|
|
36
|
+
# import X.Y
|
|
37
|
+
X = __import__("X.Y")
|
|
38
|
+
|
|
39
|
+
# from X import Y
|
|
40
|
+
Y = __import__("X", fromlist=["Y"]).Y
|
|
41
|
+
|
|
42
|
+
# from X import Y as Z
|
|
43
|
+
Z = __import__("X", fromlist=["Y"]).Y
|
|
44
|
+
|
|
45
|
+
# from X import Y, Z
|
|
46
|
+
Y = __import__("X", fromlist=["Y"]).Y
|
|
47
|
+
Z = __import__("X", fromlist=["Z"]).Z
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Left unchanged:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
from X import *
|
|
54
|
+
from . import X
|
|
55
|
+
```
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def _is_statement_start(preceding_tokens: list) -> bool:
|
|
60
|
+
"""Check if the current position is a valid statement start."""
|
|
61
|
+
if not preceding_tokens:
|
|
62
|
+
return True
|
|
63
|
+
for toknum, _ in reversed(preceding_tokens):
|
|
64
|
+
if toknum in (NEWLINE, NL, ENDMARKER):
|
|
65
|
+
return True
|
|
66
|
+
if toknum in (NAME, OP, STRING):
|
|
67
|
+
return False
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def _transform_import(cls, stmt_tokens: list) -> list | None:
|
|
72
|
+
"""Transform collected import statement tokens into __import__() calls.
|
|
73
|
+
|
|
74
|
+
Returns None if the import should be left unchanged.
|
|
75
|
+
"""
|
|
76
|
+
body = [
|
|
77
|
+
(t, v)
|
|
78
|
+
for t, v in stmt_tokens
|
|
79
|
+
if t not in (NEWLINE, NL, ENDMARKER) and v not in ("(", ")")
|
|
80
|
+
]
|
|
81
|
+
trailing = [(t, v) for t, v in stmt_tokens if t in (NEWLINE, NL, ENDMARKER)]
|
|
82
|
+
|
|
83
|
+
if not body:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
first_val = body[0][1]
|
|
87
|
+
|
|
88
|
+
if first_val == "import":
|
|
89
|
+
return cls._transform_simple_import(body[1:]) + trailing
|
|
90
|
+
if first_val == "from":
|
|
91
|
+
t = cls._transform_from_import(body[1:])
|
|
92
|
+
if t is None:
|
|
93
|
+
return None
|
|
94
|
+
return t + trailing
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def _transform_simple_import(cls, tokens: list) -> list:
|
|
99
|
+
"""Transform: import X / import X as Y / import X, Y / import X.Y."""
|
|
100
|
+
groups = cls._split_by_comma(tokens)
|
|
101
|
+
result: list = []
|
|
102
|
+
|
|
103
|
+
for group in groups:
|
|
104
|
+
if not group:
|
|
105
|
+
continue
|
|
106
|
+
if result:
|
|
107
|
+
result.append((NEWLINE, "\n"))
|
|
108
|
+
|
|
109
|
+
names, alias = cls._extract_alias(group)
|
|
110
|
+
module_name = cls._join_dotted_name(names)
|
|
111
|
+
bind_name = alias or names[0][1]
|
|
112
|
+
|
|
113
|
+
result.extend(
|
|
114
|
+
[
|
|
115
|
+
(NAME, bind_name),
|
|
116
|
+
(OP, "="),
|
|
117
|
+
(NAME, "__import__"),
|
|
118
|
+
(OP, "("),
|
|
119
|
+
(STRING, repr(module_name)),
|
|
120
|
+
(OP, ")"),
|
|
121
|
+
],
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return result
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def _transform_from_import(cls, tokens: list) -> list | None:
|
|
128
|
+
"""Transform: from X import Y / from X import Y as Z / from X import Y, Z.
|
|
129
|
+
|
|
130
|
+
Returns None for relative imports or wildcard imports.
|
|
131
|
+
"""
|
|
132
|
+
import_idx = None
|
|
133
|
+
for idx, (_, v) in enumerate(tokens):
|
|
134
|
+
if v == "import":
|
|
135
|
+
import_idx = idx
|
|
136
|
+
break
|
|
137
|
+
|
|
138
|
+
if import_idx is None:
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
module_tokens = tokens[:import_idx]
|
|
142
|
+
name_tokens = tokens[import_idx + 1 :]
|
|
143
|
+
|
|
144
|
+
if any(v == "." for _, v in module_tokens):
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
if any(v == "*" for _, v in name_tokens):
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
module_name = cls._join_dotted_name(module_tokens)
|
|
151
|
+
|
|
152
|
+
groups = cls._split_by_comma(name_tokens)
|
|
153
|
+
result: list = []
|
|
154
|
+
|
|
155
|
+
for group in groups:
|
|
156
|
+
if not group:
|
|
157
|
+
continue
|
|
158
|
+
if result:
|
|
159
|
+
result.append((NEWLINE, "\n"))
|
|
160
|
+
|
|
161
|
+
names, alias = cls._extract_alias(group)
|
|
162
|
+
imported_name = names[0][1]
|
|
163
|
+
bind_name = alias or imported_name
|
|
164
|
+
|
|
165
|
+
result.extend(
|
|
166
|
+
[
|
|
167
|
+
(NAME, bind_name),
|
|
168
|
+
(OP, "="),
|
|
169
|
+
(NAME, "__import__"),
|
|
170
|
+
(OP, "("),
|
|
171
|
+
(STRING, repr(module_name)),
|
|
172
|
+
(OP, ","),
|
|
173
|
+
(NAME, "fromlist"),
|
|
174
|
+
(OP, "="),
|
|
175
|
+
(OP, "["),
|
|
176
|
+
(STRING, repr(imported_name)),
|
|
177
|
+
(OP, "]"),
|
|
178
|
+
(OP, ")"),
|
|
179
|
+
(OP, "."),
|
|
180
|
+
(NAME, imported_name),
|
|
181
|
+
],
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
return result
|
|
185
|
+
|
|
186
|
+
@staticmethod
|
|
187
|
+
def _split_by_comma(tokens: list) -> list[list]:
|
|
188
|
+
"""Split a token list by comma operators."""
|
|
189
|
+
groups: list[list] = [[]]
|
|
190
|
+
for toknum, tokval in tokens:
|
|
191
|
+
if toknum == OP and tokval == ",":
|
|
192
|
+
groups.append([])
|
|
193
|
+
else:
|
|
194
|
+
groups[-1].append((toknum, tokval))
|
|
195
|
+
return groups
|
|
196
|
+
|
|
197
|
+
@staticmethod
|
|
198
|
+
def _extract_alias(tokens: list) -> tuple[list, str | None]:
|
|
199
|
+
"""Extract name tokens and alias from a token group.
|
|
200
|
+
|
|
201
|
+
Returns (name_tokens, alias_string_or_None).
|
|
202
|
+
"""
|
|
203
|
+
alias = None
|
|
204
|
+
name_tokens = []
|
|
205
|
+
saw_as = False
|
|
206
|
+
for toknum, tokval in tokens:
|
|
207
|
+
if tokval == "as":
|
|
208
|
+
saw_as = True
|
|
209
|
+
elif saw_as:
|
|
210
|
+
alias = tokval
|
|
211
|
+
saw_as = False
|
|
212
|
+
else:
|
|
213
|
+
name_tokens.append((toknum, tokval))
|
|
214
|
+
return name_tokens, alias
|
|
215
|
+
|
|
216
|
+
@staticmethod
|
|
217
|
+
def _join_dotted_name(tokens: list) -> str:
|
|
218
|
+
"""Join NAME and OP('.') tokens into a dotted module name string."""
|
|
219
|
+
return "".join(v for _, v in tokens)
|
|
220
|
+
|
|
221
|
+
@classmethod
|
|
222
|
+
def obfuscate_tokens(cls, tokens: list) -> list:
|
|
223
|
+
result: list = []
|
|
224
|
+
i = 0
|
|
225
|
+
while i < len(tokens):
|
|
226
|
+
toknum, tokval, *_ = tokens[i]
|
|
227
|
+
|
|
228
|
+
if (
|
|
229
|
+
toknum == NAME
|
|
230
|
+
and tokval in ("import", "from")
|
|
231
|
+
and cls._is_statement_start(result)
|
|
232
|
+
):
|
|
233
|
+
stmt_tokens = []
|
|
234
|
+
j = i
|
|
235
|
+
paren_depth = 0
|
|
236
|
+
while j < len(tokens):
|
|
237
|
+
st, sv, *_ = tokens[j]
|
|
238
|
+
stmt_tokens.append((st, sv))
|
|
239
|
+
if sv == "(":
|
|
240
|
+
paren_depth += 1
|
|
241
|
+
elif sv == ")":
|
|
242
|
+
paren_depth -= 1
|
|
243
|
+
if st in (NEWLINE, NL, ENDMARKER) and paren_depth <= 0:
|
|
244
|
+
break
|
|
245
|
+
j += 1
|
|
246
|
+
|
|
247
|
+
replacement = cls._transform_import(stmt_tokens)
|
|
248
|
+
if replacement is not None:
|
|
249
|
+
result.extend(replacement)
|
|
250
|
+
else:
|
|
251
|
+
result.extend(stmt_tokens)
|
|
252
|
+
i = j + 1
|
|
253
|
+
continue
|
|
254
|
+
|
|
255
|
+
result.append((toknum, tokval))
|
|
256
|
+
i += 1
|
|
257
|
+
return result
|
{python_obfuscation_framework-1.10.0 → python_obfuscation_framework-1.11.1}/pof/obfuscator/names.py
RENAMED
|
@@ -50,6 +50,22 @@ class _ScopeAnalyzer(ast.NodeVisitor):
|
|
|
50
50
|
self.imported_names.add(alias.asname or alias.name)
|
|
51
51
|
self.generic_visit(node)
|
|
52
52
|
|
|
53
|
+
def visit_Assign(self, node: ast.Assign) -> None:
|
|
54
|
+
"""Detect `x = __import__(...)` and treat x as an imported name."""
|
|
55
|
+
if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name):
|
|
56
|
+
value = node.value
|
|
57
|
+
# unwrap attribute chains: x = __import__("m", fromlist=["y"]).y
|
|
58
|
+
# as they could be generated from the ImportObfuscator
|
|
59
|
+
while isinstance(value, ast.Attribute):
|
|
60
|
+
value = value.value
|
|
61
|
+
if (
|
|
62
|
+
isinstance(value, ast.Call)
|
|
63
|
+
and isinstance(value.func, ast.Name)
|
|
64
|
+
and value.func.id == "__import__"
|
|
65
|
+
):
|
|
66
|
+
self.imported_names.add(node.targets[0].id)
|
|
67
|
+
self.generic_visit(node)
|
|
68
|
+
|
|
53
69
|
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
|
54
70
|
self.class_names.add(node.name)
|
|
55
71
|
prev = self._in_class
|
|
@@ -176,14 +192,30 @@ class _StringFixer(ast.NodeTransformer):
|
|
|
176
192
|
node.args[1] = ast.Constant(value=self.mapping[node.args[1].value])
|
|
177
193
|
return node
|
|
178
194
|
|
|
195
|
+
def _is_globals_call(self, node: ast.expr) -> bool:
|
|
196
|
+
"""Check if node is a call to globals()."""
|
|
197
|
+
return (
|
|
198
|
+
isinstance(node, ast.Call)
|
|
199
|
+
and isinstance(node.func, ast.Name)
|
|
200
|
+
and node.func.id == "globals"
|
|
201
|
+
and not node.args
|
|
202
|
+
)
|
|
203
|
+
|
|
179
204
|
def visit_Subscript(self, node: ast.Subscript) -> ast.Subscript:
|
|
180
205
|
self.generic_visit(node)
|
|
181
206
|
if (
|
|
182
|
-
isinstance(node.
|
|
183
|
-
and node.value.attr == "__dict__"
|
|
184
|
-
and isinstance(node.slice, ast.Constant)
|
|
207
|
+
isinstance(node.slice, ast.Constant)
|
|
185
208
|
and isinstance(node.slice.value, str)
|
|
186
209
|
and node.slice.value in self.mapping
|
|
210
|
+
and (
|
|
211
|
+
# __dict__['name'] pattern
|
|
212
|
+
(
|
|
213
|
+
isinstance(node.value, ast.Attribute)
|
|
214
|
+
and node.value.attr == "__dict__"
|
|
215
|
+
)
|
|
216
|
+
# globals()['name'] pattern
|
|
217
|
+
or self._is_globals_call(node.value)
|
|
218
|
+
)
|
|
187
219
|
):
|
|
188
220
|
node.slice = ast.Constant(value=self.mapping[node.slice.value])
|
|
189
221
|
return node
|
|
@@ -196,6 +228,7 @@ class NamesObfuscator:
|
|
|
196
228
|
"__file__",
|
|
197
229
|
"__name__",
|
|
198
230
|
"__doc__",
|
|
231
|
+
"__builtins__",
|
|
199
232
|
"__package__",
|
|
200
233
|
"__loader__",
|
|
201
234
|
"__spec__",
|
|
@@ -53,7 +53,7 @@ class PrintObfuscator:
|
|
|
53
53
|
|
|
54
54
|
if inside_print:
|
|
55
55
|
if print_par_depth == parenthesis_depth and (
|
|
56
|
-
tokval not in ("(", "print") and prev_tokval
|
|
56
|
+
tokval not in ("(", "print") and prev_tokval not in {"print", "."}
|
|
57
57
|
): # check if still inside print
|
|
58
58
|
inside_print = False
|
|
59
59
|
else:
|