pylockware 2.2.0__tar.gz → 2.3.0__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.
Files changed (108) hide show
  1. {pylockware-2.2.0 → pylockware-2.3.0}/PKG-INFO +26 -8
  2. {pylockware-2.2.0 → pylockware-2.3.0}/README.md +24 -6
  3. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/cli/main.py +5 -0
  4. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/name_generator.py +3 -2
  5. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/obfuscator.py +14 -8
  6. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__init__.py +2 -0
  7. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/anti_tamper_builtins_module.py +0 -1
  8. pylockware-2.3.0/pylockware/modules/builtin_dispatcher_module.py +98 -0
  9. pylockware-2.3.0/pylockware/modules/expr_virtualize_module.py +57 -0
  10. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/sdk/builder.py +1 -0
  11. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/sdk/config.py +2 -0
  12. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__init__.py +3 -0
  13. pylockware-2.3.0/pylockware/transforms/builtin_dispatcher.py +355 -0
  14. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/call_obf_v2.py +11 -3
  15. pylockware-2.3.0/pylockware/transforms/expr_virtualize.py +698 -0
  16. pylockware-2.3.0/pylockware/transforms/junk_code_transformer.py +1193 -0
  17. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/num_obf.py +13 -0
  18. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/remap_transformer.py +60 -34
  19. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/str_prot.py +34 -99
  20. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware.egg-info/PKG-INFO +26 -8
  21. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware.egg-info/SOURCES.txt +2 -0
  22. {pylockware-2.2.0 → pylockware-2.3.0}/pyproject.toml +1 -1
  23. {pylockware-2.2.0 → pylockware-2.3.0}/setup.py +2 -2
  24. pylockware-2.2.0/pylockware/modules/builtin_dispatcher_module.py +0 -231
  25. pylockware-2.2.0/pylockware/transforms/builtin_dispatcher.py +0 -197
  26. pylockware-2.2.0/pylockware/transforms/junk_code_transformer.py +0 -698
  27. {pylockware-2.2.0 → pylockware-2.3.0}/.github/workflows/python-publish.yml +0 -0
  28. {pylockware-2.2.0 → pylockware-2.3.0}/.gitignore +0 -0
  29. {pylockware-2.2.0 → pylockware-2.3.0}/LICENSE +0 -0
  30. {pylockware-2.2.0 → pylockware-2.3.0}/MANIFEST.in +0 -0
  31. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/__init__.py +0 -0
  32. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/__pycache__/__init__.cpython-312.pyc +0 -0
  33. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/__pycache__/decorators.cpython-312.pyc +0 -0
  34. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/anti_debug/__init__.py +0 -0
  35. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/anti_debug/antidebug_crossplatform.py +0 -0
  36. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/anti_debug/antidebug_llvm.py +0 -0
  37. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/anti_tamper/anti_tamper_builtins.py +0 -0
  38. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/cli/__init__.py +0 -0
  39. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/cli/build.py +0 -0
  40. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/__init__.py +0 -0
  41. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/__pycache__/__init__.cpython-312.pyc +0 -0
  42. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/__pycache__/module_base.cpython-312.pyc +0 -0
  43. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/__pycache__/module_manager.cpython-312.pyc +0 -0
  44. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/__pycache__/name_generator.cpython-312.pyc +0 -0
  45. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/__pycache__/obfuscator.cpython-312.pyc +0 -0
  46. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/module_base.py +0 -0
  47. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/core/module_manager.py +0 -0
  48. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/decorators.py +0 -0
  49. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/gui/__init__.py +0 -0
  50. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/gui/main.py +0 -0
  51. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/gui/obfuscator_gui.py +0 -0
  52. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  53. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/anti_debug_module.cpython-312.pyc +0 -0
  54. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/anti_tamper_builtins_module.cpython-312.pyc +0 -0
  55. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/builtin_dispatcher_module.cpython-312.pyc +0 -0
  56. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/call_obf_module.cpython-312.pyc +0 -0
  57. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/crypt_module.cpython-312.pyc +0 -0
  58. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/decorator_obf_module.cpython-312.pyc +0 -0
  59. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/import_obf_module.cpython-312.pyc +0 -0
  60. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/junk_code_module.cpython-312.pyc +0 -0
  61. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/nuitka_builder_module.cpython-312.pyc +0 -0
  62. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/number_obf_module.cpython-312.pyc +0 -0
  63. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/remap_module.cpython-312.pyc +0 -0
  64. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/remove_annotations_module.cpython-312.pyc +0 -0
  65. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/state_machine_module.cpython-312.pyc +0 -0
  66. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/string_protect_module.cpython-312.pyc +0 -0
  67. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/__pycache__/type_annotation_obf_module.cpython-312.pyc +0 -0
  68. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/anti_debug_module.py +0 -0
  69. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/call_obf_module.py +0 -0
  70. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/crypt_module.py +0 -0
  71. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/decorator_obf_module.py +0 -0
  72. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/disable_traceback_module.py +0 -0
  73. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/import_obf_module.py +0 -0
  74. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/junk_code_module.py +0 -0
  75. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/nuitka_builder_module.py +0 -0
  76. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/number_obf_module.py +0 -0
  77. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/remap_module.py +0 -0
  78. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/remove_annotations_module.py +0 -0
  79. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/state_machine_module.py +0 -0
  80. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/string_protect_module.py +0 -0
  81. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/modules/type_annotation_obf_module.py +0 -0
  82. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/sdk/__init__.py +0 -0
  83. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/sdk/__pycache__/__init__.cpython-312.pyc +0 -0
  84. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/sdk/__pycache__/builder.cpython-312.pyc +0 -0
  85. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/sdk/__pycache__/config.cpython-312.pyc +0 -0
  86. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/__init__.cpython-312.pyc +0 -0
  87. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/builtin_dispatcher.cpython-312.pyc +0 -0
  88. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/crypter.cpython-312.pyc +0 -0
  89. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/decorator_obf.cpython-312.pyc +0 -0
  90. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/junk_code_transformer.cpython-312.pyc +0 -0
  91. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/num_obf.cpython-312.pyc +0 -0
  92. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/remap_transformer.cpython-312.pyc +0 -0
  93. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/state_machine_transformer.cpython-312.pyc +0 -0
  94. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/str_prot.cpython-312.pyc +0 -0
  95. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/__pycache__/type_annotation_obf.cpython-312.pyc +0 -0
  96. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/annotation_aware_transformer.py +0 -0
  97. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/crypter.py +0 -0
  98. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/decorator_obf.py +0 -0
  99. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/state_machine_transformer.py +0 -0
  100. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware/transforms/type_annotation_obf.py +0 -0
  101. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware.egg-info/dependency_links.txt +0 -0
  102. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware.egg-info/entry_points.txt +0 -0
  103. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware.egg-info/requires.txt +0 -0
  104. {pylockware-2.2.0 → pylockware-2.3.0}/pylockware.egg-info/top_level.txt +0 -0
  105. {pylockware-2.2.0 → pylockware-2.3.0}/requirements.txt +0 -0
  106. {pylockware-2.2.0 → pylockware-2.3.0}/setup.cfg +0 -0
  107. {pylockware-2.2.0 → pylockware-2.3.0}/test_conflict.py +0 -0
  108. {pylockware-2.2.0 → pylockware-2.3.0}/test_obf.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pylockware
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Python Code Protection SDK with obfuscation and anti-debug features
5
- Home-page: https://github.com/yourusername/pylockware
5
+ Home-page: https://github.com/amogusgggy/pylockware
6
6
  Author: PyLockWare Team
7
7
  License: AGPL-3.0-or-later
8
8
  Project-URL: Homepage, https://github.com/amogus-gggy/pylockware
@@ -62,12 +62,30 @@ Dynamic: requires-python
62
62
  [![Python Version](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
63
63
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
64
64
 
65
- ## Changelog v2.2.0
66
- - stability improvements
67
- - bug fixes
68
- - improvements in crypt, call_obf modules.
69
- - Added builtin antitamper(has some bugs, dont use it please)
70
-
65
+ ## Changelog v2.3.0
66
+ **Added**
67
+ - `--expr-virtualize` — compiles expressions to custom VM bytecode with XOR-encrypted dispatch table
68
+ - Anti-dump string poisoning — 500 random garbage strings injected into junk code to pollute static analysis
69
+ - Poison variable chains self-referential dead variables that raise `NameError` if stripped by deobfuscators
70
+ - Deeply nested dead code — fake `if` chains, `try/except`, `with` blocks for maximum visual noise
71
+ - `l-i` name generator — visually ambiguous identifiers (`I`/`l`/`i`/`L`)
72
+ - Per-module embedded builtin dispatcher — no external files, each module carries its own obfuscated dispatcher
73
+
74
+ **Changed**
75
+ - Builtin dispatcher: scope-aware shadowing detection, no longer renames locally overridden builtins
76
+ - String protection: inline decode calls instead of global variables per string
77
+ - Number obfuscation: auto-injects `os`/`sys` imports when needed(bug fix)
78
+ - Remap: skips imported module attributes (fixes `datetime.datetime.hour`-style breaks)
79
+ - Call obfuscation: full frame stack walk for `_call`/`_resolve`
80
+ - Default name length: 32 → 128 chars; junk density: 0.5 → 0.8
81
+
82
+ **Fixed**
83
+ - `ExprVirtualizeModule` now runs after all AST transforms
84
+ - String protection no longer leaks undeclared globals
85
+ - Removed stale `_builtin_dispatcher.py` references
86
+
87
+ **Removed**
88
+ - Central `_builtin_dispatcher.py` — fully inlined
71
89
 
72
90
  ## 🚀 Features
73
91
 
@@ -5,12 +5,30 @@
5
5
  [![Python Version](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
6
6
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
7
 
8
- ## Changelog v2.2.0
9
- - stability improvements
10
- - bug fixes
11
- - improvements in crypt, call_obf modules.
12
- - Added builtin antitamper(has some bugs, dont use it please)
13
-
8
+ ## Changelog v2.3.0
9
+ **Added**
10
+ - `--expr-virtualize` — compiles expressions to custom VM bytecode with XOR-encrypted dispatch table
11
+ - Anti-dump string poisoning — 500 random garbage strings injected into junk code to pollute static analysis
12
+ - Poison variable chains self-referential dead variables that raise `NameError` if stripped by deobfuscators
13
+ - Deeply nested dead code — fake `if` chains, `try/except`, `with` blocks for maximum visual noise
14
+ - `l-i` name generator — visually ambiguous identifiers (`I`/`l`/`i`/`L`)
15
+ - Per-module embedded builtin dispatcher — no external files, each module carries its own obfuscated dispatcher
16
+
17
+ **Changed**
18
+ - Builtin dispatcher: scope-aware shadowing detection, no longer renames locally overridden builtins
19
+ - String protection: inline decode calls instead of global variables per string
20
+ - Number obfuscation: auto-injects `os`/`sys` imports when needed(bug fix)
21
+ - Remap: skips imported module attributes (fixes `datetime.datetime.hour`-style breaks)
22
+ - Call obfuscation: full frame stack walk for `_call`/`_resolve`
23
+ - Default name length: 32 → 128 chars; junk density: 0.5 → 0.8
24
+
25
+ **Fixed**
26
+ - `ExprVirtualizeModule` now runs after all AST transforms
27
+ - String protection no longer leaks undeclared globals
28
+ - Removed stale `_builtin_dispatcher.py` references
29
+
30
+ **Removed**
31
+ - Central `_builtin_dispatcher.py` — fully inlined
14
32
 
15
33
  ## 🚀 Features
16
34
 
@@ -38,6 +38,7 @@ def main_cli():
38
38
  parser.add_argument("--decorator-obf", action="store_true", help="Enable decorator obfuscation (converts @decorator to func = decorator(func))")
39
39
  parser.add_argument("--call-obf", action="store_true", help="Enable chained-table call obfuscation (_call/_resolve)")
40
40
  parser.add_argument("--crypt", action="store_true", help="Enable function encryption using machine fingerprinting and XOR encryption")
41
+ parser.add_argument("--expr-virtualize", action="store_true", help="Enable expression virtualization (compiles expressions to custom bytecode)")
41
42
  parser.add_argument("--anti-tamper-builtins", action=argparse.BooleanOptionalAction, default=True,
42
43
  help="Enable runtime anti-tamper guard that crashes on patched Python builtins (default: enabled)")
43
44
  parser.add_argument("--all", action="store_true", help="Enable all obfuscation options (except Nuitka)")
@@ -66,6 +67,8 @@ def main_cli():
66
67
  print(" Please use only one of these options at a time.")
67
68
  sys.exit(1)
68
69
 
70
+
71
+
69
72
  # If --all is specified, enable all obfuscation options (except Nuitka)
70
73
  if args.all:
71
74
  args.remap = False
@@ -78,6 +81,7 @@ def main_cli():
78
81
  args.disable_traceback = True
79
82
  args.decorator_obf = True
80
83
  args.call_obf = False
84
+ args.expr_virtualize = True
81
85
 
82
86
  # Determine anti_debug mode
83
87
  anti_debug_value = None
@@ -113,6 +117,7 @@ def main_cli():
113
117
  call_obf=args.call_obf,
114
118
  crypt=args.crypt,
115
119
  anti_tamper_builtins=args.anti_tamper_builtins,
120
+ expr_virtualize=args.expr_virtualize,
116
121
  enable_nuitka=args.nuitka,
117
122
  nuitka_onefile=args.nuitka_onefile,
118
123
  nuitka_standalone=args.nuitka_standalone,
@@ -20,7 +20,8 @@ class NameGenerator:
20
20
  'mixed': string.ascii_letters + string.digits + ''.join(chr(i) for i in range(0x4E00, 0x9FFF)),
21
21
  'numbers': string.digits,
22
22
  'hex': string.hexdigits,
23
- 'ascii': string.printable.strip() # All printable ASCII except whitespace
23
+ 'ascii': string.printable.strip(), # All printable ASCII except whitespace
24
+ 'l-i': "IliL"
24
25
  }
25
26
 
26
27
  self.char_set = self.char_sets.get(char_set, self.char_sets['english'])
@@ -36,7 +37,7 @@ class NameGenerator:
36
37
  Returns:
37
38
  Randomly generated name
38
39
  """
39
- length = 32 # Default length
40
+ length = 128 # Default length
40
41
 
41
42
  # If prefix is empty or doesn't start with letter/underscore, add underscore
42
43
  if not prefix or (prefix[0] not in string.ascii_letters + '_'):
@@ -28,6 +28,7 @@ from pylockware.modules.call_obf_module import CallObfModule
28
28
  from pylockware.modules.remove_annotations_module import RemoveAnnotationsModule
29
29
  from pylockware.modules.crypt_module import CryptModule
30
30
  from pylockware.modules.anti_tamper_builtins_module import AntiTamperBuiltinsModule
31
+ from pylockware.modules.expr_virtualize_module import ExprVirtualizeModule
31
32
 
32
33
 
33
34
  class PyObfuscator:
@@ -48,7 +49,8 @@ class PyObfuscator:
48
49
  nuitka_admin: bool = False, nuitka_plugins: List[str] = None, nuitka_extra_imports: List[str] = None,
49
50
  nuitka_options: List[str] = None, disable_traceback: bool = False,
50
51
  decorator_obf: bool = False, type_annotation_obf: bool = False, call_obf: bool = False,
51
- crypt: bool = False, anti_tamper_builtins: bool = True):
52
+ crypt: bool = False, anti_tamper_builtins: bool = True,
53
+ expr_virtualize: bool = False):
52
54
  self.project_path = Path(project_path)
53
55
  self.entry_point = Path(entry_point)
54
56
  self.entry_function = entry_function
@@ -71,6 +73,7 @@ class PyObfuscator:
71
73
  self.call_obf = call_obf # Enable call obfuscation using getattr pattern
72
74
  self.crypt = crypt # Enable function encryption using machine fingerprinting
73
75
  self.anti_tamper_builtins = anti_tamper_builtins # Enable runtime anti-tamper guard for builtins
76
+ self.expr_virtualize = expr_virtualize # Enable expression virtualization
74
77
 
75
78
  # Nuitka options
76
79
  self.enable_nuitka = enable_nuitka
@@ -90,7 +93,6 @@ class PyObfuscator:
90
93
 
91
94
  # Validate and adjust incompatible options
92
95
  self._validate_nuitka_compatibility()
93
-
94
96
  self.setup_modules()
95
97
 
96
98
  def _validate_nuitka_compatibility(self):
@@ -107,7 +109,7 @@ class PyObfuscator:
107
109
  if self.enable_nuitka:
108
110
  if self.anti_debug:
109
111
  self.anti_debug = None
110
-
112
+
111
113
  if self.import_obf:
112
114
  self.import_obf = False
113
115
 
@@ -160,10 +162,7 @@ class PyObfuscator:
160
162
  call_obf_config = {'name_gen': self.name_gen}
161
163
  self.module_manager.add_module(CallObfModule(call_obf_config))
162
164
 
163
- # Add modules based on configuration
164
- if self.string_prot:
165
- string_prot_config = {'name_gen': self.name_gen}
166
- self.module_manager.add_module(StringProtectModule(string_prot_config))
165
+
167
166
 
168
167
  if self.anti_debug:
169
168
  anti_debug_config = {
@@ -200,6 +199,10 @@ class PyObfuscator:
200
199
  num_obf_config = {'name_gen': self.name_gen}
201
200
  self.module_manager.add_module(NumberObfModule(num_obf_config))
202
201
 
202
+ # Add modules based on configuration
203
+ if self.string_prot:
204
+ string_prot_config = {'name_gen': self.name_gen}
205
+ self.module_manager.add_module(StringProtectModule(string_prot_config))
203
206
  # Decorator obfuscation - converts @decorator to explicit assignments
204
207
  # Module disabled due to conflict with annotations
205
208
  # if self.decorator_obf:
@@ -223,6 +226,10 @@ class PyObfuscator:
223
226
 
224
227
  # Add RemoveAnnotations module to clean up decorators
225
228
  self.module_manager.add_module(RemoveAnnotationsModule({}))
229
+
230
+ # ExprVirtualize runs AFTER all AST transforms so its output isn't corrupted
231
+ if self.expr_virtualize:
232
+ self.module_manager.add_module(ExprVirtualizeModule({}))
226
233
 
227
234
  # Add crypt module if enabled - runs after all other obfuscation
228
235
  if self.crypt:
@@ -288,7 +295,6 @@ class PyObfuscator:
288
295
  import python_minifier
289
296
 
290
297
  obfuscator_files = [
291
- "_builtin_dispatcher.py",
292
298
  "anti_tamper_builtins.py",
293
299
  "antidebug_crossplatform.py",
294
300
  "antidebug_llvm.py",
@@ -9,6 +9,7 @@ from .anti_debug_module import AntiDebugModule
9
9
  from .import_obf_module import ImportObfuscateModule
10
10
  from .state_machine_module import StateMachineModule
11
11
  from .crypt_module import CryptModule
12
+ from .expr_virtualize_module import ExprVirtualizeModule
12
13
 
13
14
  __all__ = [
14
15
  'RemapModule',
@@ -18,4 +19,5 @@ __all__ = [
18
19
  'ImportObfuscateModule',
19
20
  'StateMachineModule',
20
21
  'CryptModule',
22
+ 'ExprVirtualizeModule',
21
23
  ]
@@ -9,7 +9,6 @@ _GUARD_MARKER = "# __pylockware_anti_tamper_builtins__"
9
9
  _MODULE_NAME = "anti_tamper_builtins"
10
10
  _SKIP_FILES = {
11
11
  f"{_MODULE_NAME}.py",
12
- "_builtin_dispatcher.py",
13
12
  "antidebug_crossplatform.py",
14
13
  "antidebug_llvm.py",
15
14
  }
@@ -0,0 +1,98 @@
1
+ """
2
+ Builtin Dispatcher Module for PyLockWare
3
+ Replaces all built-in function calls with calls via a dispatcher
4
+ Встраивает dispatcher прямо в каждый модуль — без внешних файлов
5
+ """
6
+ import ast
7
+ from pathlib import Path
8
+ from typing import Dict, Any
9
+ from pylockware.core.module_base import ModuleBase
10
+ from pylockware.transforms.builtin_dispatcher import BuiltinDispatcherTransformer, BUILTIN_FUNCTIONS
11
+
12
+
13
+ class BuiltinDispatcherModule(ModuleBase):
14
+ """
15
+ Module that replaces built-in function calls with dispatcher calls
16
+ e.g., print() -> _dispatcher.ghjfkd()
17
+ Dispatcher code is embedded directly into each module - no external files needed
18
+ """
19
+
20
+ def __init__(self, config: Dict[str, Any] = None):
21
+ super().__init__(config)
22
+ self.name_gen_settings = self.config.get('name_gen', 'english')
23
+
24
+ def process(self, project_path: Path, output_path: Path) -> bool:
25
+ """
26
+ Process the project by replacing built-in calls with dispatcher calls
27
+ Dispatcher code is embedded directly into each module
28
+
29
+ Args:
30
+ project_path: Path to the original project
31
+ output_path: Path to the output directory
32
+
33
+ Returns:
34
+ True if processing was successful, False otherwise
35
+ """
36
+ try:
37
+ print("Applying builtin dispatcher obfuscation...")
38
+
39
+ # Find all Python files in the output directory
40
+ py_files = list(output_path.rglob("*.py"))
41
+
42
+ # Files that should NOT be transformed (they contain critical runtime checks)
43
+ protected_files = {
44
+ "antidebug_llvm.py",
45
+ "antidebug_crossplatform.py",
46
+ "anti_tamper_builtins.py",
47
+ }
48
+
49
+ files_modified = 0
50
+
51
+ for py_file in py_files:
52
+ if py_file.name in protected_files:
53
+ continue
54
+ try:
55
+ with open(py_file, 'r', encoding='utf-8') as f:
56
+ original_code = f.read()
57
+
58
+ tree = ast.parse(original_code)
59
+
60
+ # Create a fresh transformer for each file (unique obfuscated names)
61
+ transformer = BuiltinDispatcherTransformer(name_gen_settings=self.name_gen_settings)
62
+
63
+ # Use transform_module which embeds dispatcher directly
64
+ transformed_tree = transformer.transform_module(tree)
65
+
66
+ # Only write if changes were made
67
+ if transformer.builtins_map:
68
+ new_content = ast.unparse(transformed_tree)
69
+
70
+ with open(py_file, 'w', encoding='utf-8') as f:
71
+ f.write(new_content)
72
+ files_modified += 1
73
+ print(f" Obfuscated builtins in {py_file}")
74
+
75
+ except Exception as e:
76
+ print(f"Error processing {py_file}: {e}")
77
+ continue
78
+
79
+ if files_modified == 0:
80
+ print("No built-in functions found, skipping builtin dispatcher obfuscation.")
81
+ else:
82
+ print(f"Builtin dispatcher obfuscation complete. Modified {files_modified} files.")
83
+ return True
84
+
85
+ except Exception as e:
86
+ print(f"Error during builtin dispatcher obfuscation: {e}")
87
+ import traceback
88
+ traceback.print_exc()
89
+ return False
90
+
91
+ def validate_config(self) -> bool:
92
+ """
93
+ Validate the module's configuration
94
+
95
+ Returns:
96
+ True if configuration is valid, False otherwise
97
+ """
98
+ return True
@@ -0,0 +1,57 @@
1
+ """
2
+ Expression Virtualization Module for PyLockWare
3
+ Replaces expressions with VM-interpreted bytecode
4
+ """
5
+ import ast
6
+ from pathlib import Path
7
+ from typing import Dict, Any
8
+ from pylockware.core.module_base import ModuleBase
9
+ from pylockware.transforms.expr_virtualize import virtualize_code, VM_RUNTIME_CODE
10
+
11
+
12
+ class ExprVirtualizeModule(ModuleBase):
13
+ """
14
+ Module that virtualizes expressions by compiling them to custom bytecode
15
+ and replacing them with calls to a VM interpreter
16
+ """
17
+
18
+ def __init__(self, config: Dict[str, Any] = None):
19
+ super().__init__(config)
20
+
21
+ def process(self, project_path: Path, output_path: Path) -> bool:
22
+ try:
23
+ print("Applying expression virtualization to all Python files...")
24
+
25
+ runtime_file = output_path / "_vmentry_rt.py"
26
+ runtime_file.write_text(VM_RUNTIME_CODE, encoding='utf-8')
27
+
28
+ for py_file in output_path.rglob("*.py"):
29
+ if py_file.name in ["anti_debug_injector.py", "anti_debug_injector_normal.py",
30
+ "obfuscator.py", "num_obf.py", "antidebug_llvm.py",
31
+ "_vmentry_rt.py"]:
32
+ continue
33
+ try:
34
+ with open(py_file, 'r', encoding='utf-8') as f:
35
+ original_code = f.read()
36
+
37
+ if '_vmentry' in original_code:
38
+ continue
39
+
40
+ virtualized_code = virtualize_code(original_code)
41
+
42
+ if virtualized_code != original_code:
43
+ final_code = "from _vmentry_rt import _vmentry\n" + virtualized_code
44
+ with open(py_file, 'w', encoding='utf-8') as f:
45
+ f.write(final_code)
46
+ print(f"Virtualized expressions in {py_file}")
47
+
48
+ except Exception as e:
49
+ print(f"Error applying expression virtualization to {py_file}: {e}")
50
+
51
+ return True
52
+ except Exception as e:
53
+ print(f"Error during expression virtualization: {e}")
54
+ return False
55
+
56
+ def validate_config(self) -> bool:
57
+ return True
@@ -148,6 +148,7 @@ class Builder:
148
148
  call_obf=self.config.call_obf,
149
149
  crypt=self.config.crypt,
150
150
  anti_tamper_builtins=self.config.anti_tamper_builtins,
151
+ expr_virtualize=self.config.expr_virtualize,
151
152
  enable_nuitka=self.config.enable_nuitka,
152
153
  nuitka_onefile=self.config.nuitka_onefile,
153
154
  nuitka_standalone=self.config.nuitka_standalone,
@@ -33,6 +33,7 @@ class BuildConfig:
33
33
  crypt: bool = False
34
34
  disable_traceback: bool = True
35
35
  anti_tamper_builtins: bool = True
36
+ expr_virtualize: bool = False
36
37
 
37
38
  # Параметры обфускации
38
39
  junk_density: float = 0.5
@@ -179,6 +180,7 @@ def _save_pretty_toml(data: dict, path: Path, config: BuildConfig) -> None:
179
180
  lines.append(f"crypt = {str(config.crypt).lower()}")
180
181
  lines.append(f"disable_traceback = {str(config.disable_traceback).lower()}")
181
182
  lines.append(f"anti_tamper_builtins = {str(config.anti_tamper_builtins).lower()}")
183
+ lines.append(f"expr_virtualize = {str(config.expr_virtualize).lower()}")
182
184
  lines.append(f"anti_debug = {str(bool(config.anti_debug)).lower()}")
183
185
  lines.append("")
184
186
 
@@ -14,6 +14,7 @@ from .crypter import (
14
14
  derive_key,
15
15
  generate_seed,
16
16
  )
17
+ from .expr_virtualize import virtualize_code, VM_RUNTIME_CODE
17
18
 
18
19
  __all__ = [
19
20
  'NumberObfuscator',
@@ -27,4 +28,6 @@ __all__ = [
27
28
  'xor_encrypt',
28
29
  'derive_key',
29
30
  'generate_seed',
31
+ 'virtualize_code',
32
+ 'VM_RUNTIME_CODE',
30
33
  ]