python-obfuscation-framework 1.4.1__py3-none-any.whl

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 (147) hide show
  1. pof/__init__.py +21 -0
  2. pof/__main__.py +22 -0
  3. pof/cli.py +187 -0
  4. pof/errors.py +2 -0
  5. pof/evasion/__init__.py +57 -0
  6. pof/evasion/argv.py +44 -0
  7. pof/evasion/base.py +48 -0
  8. pof/evasion/cpu/__init__.py +0 -0
  9. pof/evasion/cpu/cpu_count.py +27 -0
  10. pof/evasion/fs/__init__.py +0 -0
  11. pof/evasion/fs/directory_exist.py +29 -0
  12. pof/evasion/fs/directory_list_exist.py +46 -0
  13. pof/evasion/fs/directory_list_missing.py +45 -0
  14. pof/evasion/fs/directory_missing.py +28 -0
  15. pof/evasion/fs/exec_method.py +51 -0
  16. pof/evasion/fs/executable_path.py +66 -0
  17. pof/evasion/fs/file_exist.py +29 -0
  18. pof/evasion/fs/file_list_exist.py +46 -0
  19. pof/evasion/fs/file_list_missing.py +45 -0
  20. pof/evasion/fs/file_missing.py +31 -0
  21. pof/evasion/fs/tmp.py +112 -0
  22. pof/evasion/hardware/__init__.py +0 -0
  23. pof/evasion/hardware/ram_count.py +50 -0
  24. pof/evasion/hooks/__init__.py +0 -0
  25. pof/evasion/hooks/debugger.py +36 -0
  26. pof/evasion/hooks/tracemalloc.py +23 -0
  27. pof/evasion/human/__init__.py +0 -0
  28. pof/evasion/human/p.py +45 -0
  29. pof/evasion/human/prompt.py +69 -0
  30. pof/evasion/integrity.py +129 -0
  31. pof/evasion/multi.py +41 -0
  32. pof/evasion/os/__init__.py +0 -0
  33. pof/evasion/os/domain.py +27 -0
  34. pof/evasion/os/hostname.py +27 -0
  35. pof/evasion/os/uid.py +28 -0
  36. pof/evasion/os/username.py +27 -0
  37. pof/evasion/processes/__init__.py +0 -0
  38. pof/evasion/processes/proc_count.py +47 -0
  39. pof/evasion/time/__init__.py +0 -0
  40. pof/evasion/time/expire.py +75 -0
  41. pof/evasion/time/uptime.py +48 -0
  42. pof/evasion/time/utc.py +26 -0
  43. pof/evasion/utils.py +198 -0
  44. pof/main.py +369 -0
  45. pof/obfuscator/__init__.py +86 -0
  46. pof/obfuscator/builtins.py +482 -0
  47. pof/obfuscator/cipher/__init__.py +0 -0
  48. pof/obfuscator/cipher/deep_encryption.py +194 -0
  49. pof/obfuscator/cipher/rc4.py +22 -0
  50. pof/obfuscator/cipher/shift.py +19 -0
  51. pof/obfuscator/cipher/xor.py +121 -0
  52. pof/obfuscator/compression/__init__.py +0 -0
  53. pof/obfuscator/compression/bz2.py +22 -0
  54. pof/obfuscator/compression/gzip.py +22 -0
  55. pof/obfuscator/compression/lzma.py +22 -0
  56. pof/obfuscator/compression/zlib.py +22 -0
  57. pof/obfuscator/constants.py +294 -0
  58. pof/obfuscator/definitions.py +341 -0
  59. pof/obfuscator/encoding/__init__.py +0 -0
  60. pof/obfuscator/encoding/a85.py +21 -0
  61. pof/obfuscator/encoding/b16.py +21 -0
  62. pof/obfuscator/encoding/b32.py +21 -0
  63. pof/obfuscator/encoding/b32hex.py +21 -0
  64. pof/obfuscator/encoding/b64.py +21 -0
  65. pof/obfuscator/encoding/b85.py +25 -0
  66. pof/obfuscator/encoding/binascii.py +22 -0
  67. pof/obfuscator/encoding/snt.py +23 -0
  68. pof/obfuscator/esoteric/__init__.py +0 -0
  69. pof/obfuscator/esoteric/call.py +49 -0
  70. pof/obfuscator/esoteric/doc.py +237 -0
  71. pof/obfuscator/esoteric/globals.py +62 -0
  72. pof/obfuscator/esoteric/imports.py +55 -0
  73. pof/obfuscator/extract_variables.py +297 -0
  74. pof/obfuscator/junk/__init__.py +0 -0
  75. pof/obfuscator/junk/add_comments.py +102 -0
  76. pof/obfuscator/junk/add_newlines.py +36 -0
  77. pof/obfuscator/names.py +474 -0
  78. pof/obfuscator/names_rope.py +375 -0
  79. pof/obfuscator/numbers.py +271 -0
  80. pof/obfuscator/other/__init__.py +0 -0
  81. pof/obfuscator/other/tokens.py +47 -0
  82. pof/obfuscator/remove/__init__.py +0 -0
  83. pof/obfuscator/remove/comments.py +36 -0
  84. pof/obfuscator/remove/exceptions.py +75 -0
  85. pof/obfuscator/remove/indents.py +28 -0
  86. pof/obfuscator/remove/loggings.py +120 -0
  87. pof/obfuscator/remove/loggings_old.py +45 -0
  88. pof/obfuscator/remove/newline.py +27 -0
  89. pof/obfuscator/remove/print.py +40 -0
  90. pof/obfuscator/restructure.py +15 -0
  91. pof/obfuscator/stegano/__init__.py +0 -0
  92. pof/obfuscator/stegano/docstrings.py +111 -0
  93. pof/obfuscator/stegano/ipv6encoding.py +21 -0
  94. pof/obfuscator/stegano/macencoding.py +21 -0
  95. pof/obfuscator/stegano/uuidencoding.py +21 -0
  96. pof/obfuscator/strings.py +359 -0
  97. pof/stager/__init__.py +17 -0
  98. pof/stager/cipher/__init__.py +0 -0
  99. pof/stager/cipher/rc4.py +36 -0
  100. pof/stager/download.py +80 -0
  101. pof/stager/image.py +374 -0
  102. pof/stager/lots/__init__.py +1 -0
  103. pof/stager/lots/cl1pnet.py +51 -0
  104. pof/stager/lots/pastebin.py +35 -0
  105. pof/stager/lots/pasters.py +30 -0
  106. pof/stager/quine.py +135 -0
  107. pof/utils/__init__.py +0 -0
  108. pof/utils/cipher/__init__.py +7 -0
  109. pof/utils/cipher/rc4.py +407 -0
  110. pof/utils/cipher/shift.py +41 -0
  111. pof/utils/compression/__init__.py +11 -0
  112. pof/utils/compression/bz2.py +38 -0
  113. pof/utils/compression/gzip.py +38 -0
  114. pof/utils/compression/lzma.py +38 -0
  115. pof/utils/compression/zlib.py +38 -0
  116. pof/utils/encoding/__init__.py +19 -0
  117. pof/utils/encoding/a85.py +35 -0
  118. pof/utils/encoding/b16.py +30 -0
  119. pof/utils/encoding/b3.py +93 -0
  120. pof/utils/encoding/b32.py +30 -0
  121. pof/utils/encoding/b32hex.py +30 -0
  122. pof/utils/encoding/b64.py +30 -0
  123. pof/utils/encoding/b85.py +35 -0
  124. pof/utils/encoding/binascii.py +38 -0
  125. pof/utils/encoding/snt.py +97 -0
  126. pof/utils/entropy.py +24 -0
  127. pof/utils/extract_names.py +204 -0
  128. pof/utils/generator/__init__.py +17 -0
  129. pof/utils/generator/advanced.py +53 -0
  130. pof/utils/generator/base.py +178 -0
  131. pof/utils/generator/basic.py +107 -0
  132. pof/utils/generator/names.txt +37241 -0
  133. pof/utils/generator/unicode.py +171 -0
  134. pof/utils/se/__init__.py +3 -0
  135. pof/utils/se/homoglyphs.py +99 -0
  136. pof/utils/se/homoglyphs.txt +96 -0
  137. pof/utils/stegano/__init__.py +5 -0
  138. pof/utils/stegano/ipv6encoding.py +97 -0
  139. pof/utils/stegano/macencoding.py +96 -0
  140. pof/utils/stegano/uuidencoding.py +102 -0
  141. pof/utils/tokens.py +68 -0
  142. python_obfuscation_framework-1.4.1.dist-info/LICENSE +674 -0
  143. python_obfuscation_framework-1.4.1.dist-info/METADATA +851 -0
  144. python_obfuscation_framework-1.4.1.dist-info/RECORD +147 -0
  145. python_obfuscation_framework-1.4.1.dist-info/WHEEL +5 -0
  146. python_obfuscation_framework-1.4.1.dist-info/entry_points.txt +2 -0
  147. python_obfuscation_framework-1.4.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,19 @@
1
+ from tokenize import LPAR, NAME, NEWLINE, RPAR
2
+
3
+ from pof.utils.cipher import ShiftCipher
4
+ from pof.utils.tokens import untokenize
5
+
6
+
7
+ class ShiftObfuscator(ShiftCipher):
8
+ """Shift cipher obfuscator."""
9
+
10
+ @classmethod
11
+ def obfuscate_tokens(cls, tokens):
12
+ code = untokenize(tokens)
13
+ return [
14
+ (NAME, "exec"),
15
+ (LPAR, "("),
16
+ *cls.decode_tokens(cls.encode_tokens(code)),
17
+ (RPAR, ")"),
18
+ (NEWLINE, "\n"),
19
+ ]
@@ -0,0 +1,121 @@
1
+ """This is not a secure encryption method!
2
+
3
+ The main purpose of xor is to produce radically different outputs when obfuscating a
4
+ file.
5
+ """
6
+
7
+ import random
8
+ from base64 import b64encode
9
+ from tokenize import DEDENT, INDENT, NAME, NEWLINE, NL, NUMBER, OP, STRING
10
+
11
+ from pof.utils.tokens import untokenize
12
+
13
+
14
+ class XORObfuscator:
15
+ """XOR obfuscator."""
16
+
17
+ # TODO (deoktr): move code to utils/encryption/xor.py
18
+ @staticmethod
19
+ def get_exec_tokens(key, ciphertext):
20
+ return [
21
+ [NAME, "from"],
22
+ [NAME, "base64"],
23
+ [NAME, "import"],
24
+ [NAME, "b64decode"],
25
+ [NEWLINE, "\n"],
26
+ [NL, "\n"],
27
+ [NAME, "def"],
28
+ [NAME, "decrypt"],
29
+ [OP, "("],
30
+ [NAME, "cipher"],
31
+ [OP, ","],
32
+ [NAME, "key"],
33
+ [OP, ")"],
34
+ [OP, ":"],
35
+ [NEWLINE, "\n"],
36
+ [INDENT, " "],
37
+ [NAME, "bcipher"],
38
+ [OP, "="],
39
+ [NAME, "bytearray"],
40
+ [OP, "("],
41
+ [NAME, "b64decode"],
42
+ [OP, "("],
43
+ [NAME, "cipher"],
44
+ [OP, ")"],
45
+ [OP, ")"],
46
+ [NEWLINE, "\n"],
47
+ [NAME, "text"],
48
+ [OP, "="],
49
+ [NAME, "bytearray"],
50
+ [OP, "("],
51
+ [OP, ")"],
52
+ [NEWLINE, "\n"],
53
+ [NAME, "ki"],
54
+ [OP, "="],
55
+ [NUMBER, "0"],
56
+ [NEWLINE, "\n"],
57
+ [NAME, "for"],
58
+ [NAME, "i"],
59
+ [NAME, "in"],
60
+ [NAME, "bcipher"],
61
+ [OP, ":"],
62
+ [NEWLINE, "\n"],
63
+ [INDENT, " "],
64
+ [NAME, "text"],
65
+ [OP, "."],
66
+ [NAME, "append"],
67
+ [OP, "("],
68
+ [NAME, "i"],
69
+ [OP, "^"],
70
+ [NAME, "key"],
71
+ [OP, "["],
72
+ [NAME, "ki"],
73
+ [OP, "%"],
74
+ [NAME, "len"],
75
+ [OP, "("],
76
+ [NAME, "key"],
77
+ [OP, ")"],
78
+ [OP, "]"],
79
+ [OP, ")"],
80
+ [NEWLINE, "\n"],
81
+ [NAME, "ki"],
82
+ [OP, "+="],
83
+ [NUMBER, "1"],
84
+ [NEWLINE, "\n"],
85
+ [DEDENT, ""],
86
+ [NAME, "return"],
87
+ [NAME, "text"],
88
+ [NEWLINE, "\n"],
89
+ [DEDENT, ""],
90
+ [NAME, "exec"],
91
+ [OP, "("],
92
+ [NAME, "decrypt"],
93
+ [OP, "("],
94
+ [STRING, repr(ciphertext)],
95
+ [OP, ","],
96
+ [STRING, repr(key)],
97
+ [OP, ")"],
98
+ [OP, "."],
99
+ [NAME, "decode"],
100
+ [OP, "("],
101
+ [OP, ")"],
102
+ [OP, ")"],
103
+ [NEWLINE, "\n"],
104
+ ]
105
+
106
+ @staticmethod
107
+ def encrypt_code(text, key):
108
+ bcipher = bytearray()
109
+ for ki, i in enumerate(text):
110
+ bcipher.append(i ^ key[ki % len(key)])
111
+ return b64encode(bcipher)
112
+
113
+ def obfuscate_tokens(self, tokens, key: str | None = None):
114
+ code = untokenize(tokens).encode()
115
+ if key is None:
116
+ key = str(random.randint(0, 100000000)).encode()
117
+ ciphertext = self.encrypt_code(code, key)
118
+ return self.get_exec_tokens(
119
+ key=key,
120
+ ciphertext=ciphertext,
121
+ )
File without changes
@@ -0,0 +1,22 @@
1
+ from tokenize import LPAR, NAME, NEWLINE, RPAR
2
+
3
+ from pof.utils.compression import Bz2Compression
4
+ from pof.utils.tokens import untokenize
5
+
6
+
7
+ class Bz2Obfuscator(Bz2Compression):
8
+ """BZ2 compression obfuscator."""
9
+
10
+ @classmethod
11
+ def obfuscate_tokens(cls, tokens):
12
+ """Generate payload to execute the bz2 encoded code."""
13
+ code = untokenize(tokens)
14
+ return [
15
+ *cls.import_tokens(),
16
+ (NEWLINE, "\n"),
17
+ (NAME, "exec"),
18
+ (LPAR, "("),
19
+ *cls.decode_tokens(cls.encode_tokens(code.encode())),
20
+ (RPAR, ")"),
21
+ (NEWLINE, "\n"),
22
+ ]
@@ -0,0 +1,22 @@
1
+ from tokenize import LPAR, NAME, NEWLINE, RPAR
2
+
3
+ from pof.utils.compression import GzipCompression
4
+ from pof.utils.tokens import untokenize
5
+
6
+
7
+ class GzipObfuscator(GzipCompression):
8
+ """GZIP compression obfuscator."""
9
+
10
+ @classmethod
11
+ def obfuscate_tokens(cls, tokens):
12
+ """Generate payload to execute the gzip encoded code."""
13
+ code = untokenize(tokens)
14
+ return [
15
+ *cls.import_tokens(),
16
+ (NEWLINE, "\n"),
17
+ (NAME, "exec"),
18
+ (LPAR, "("),
19
+ *cls.decode_tokens(cls.encode_tokens(code.encode())),
20
+ (RPAR, ")"),
21
+ (NEWLINE, "\n"),
22
+ ]
@@ -0,0 +1,22 @@
1
+ from tokenize import LPAR, NAME, NEWLINE, RPAR
2
+
3
+ from pof.utils.compression import LzmaCompression
4
+ from pof.utils.tokens import untokenize
5
+
6
+
7
+ class LzmaObfuscator(LzmaCompression):
8
+ """LZMA compression obfuscator."""
9
+
10
+ @classmethod
11
+ def obfuscate_tokens(cls, tokens):
12
+ """Generate payload to execute the lzma encoded code."""
13
+ code = untokenize(tokens)
14
+ return [
15
+ *cls.import_tokens(),
16
+ (NEWLINE, "\n"),
17
+ (NAME, "exec"),
18
+ (LPAR, "("),
19
+ *cls.decode_tokens(cls.encode_tokens(code.encode())),
20
+ (RPAR, ")"),
21
+ (NEWLINE, "\n"),
22
+ ]
@@ -0,0 +1,22 @@
1
+ from tokenize import LPAR, NAME, NEWLINE, RPAR
2
+
3
+ from pof.utils.compression import ZlibCompression
4
+ from pof.utils.tokens import untokenize
5
+
6
+
7
+ class ZlibObfuscator(ZlibCompression):
8
+ """ZLIB compression obfuscator."""
9
+
10
+ @classmethod
11
+ def obfuscate_tokens(cls, tokens):
12
+ """Generate payload to execute the zlib encoded code."""
13
+ code = untokenize(tokens)
14
+ return [
15
+ *cls.import_tokens(),
16
+ (NEWLINE, "\n"),
17
+ (NAME, "exec"),
18
+ (LPAR, "("),
19
+ *cls.decode_tokens(cls.encode_tokens(code.encode())),
20
+ (RPAR, ")"),
21
+ (NEWLINE, "\n"),
22
+ ]
@@ -0,0 +1,294 @@
1
+ """Extract constants and put them at the top of the script.
2
+
3
+ Can extract:
4
+
5
+ - string
6
+ - number (int, float...)
7
+ - builtins (str, exec, hex...)
8
+ """
9
+
10
+ #
11
+ # Add variables for certain values
12
+ # ex:
13
+ # if type(x) is int: ...
14
+ #
15
+ # u = type
16
+ # a = int
17
+ # if u(x) is a: ...
18
+ #
19
+ # TODO (deoktr): add variables under imports as an option
20
+ # TODO (deoktr): add variables inside functions
21
+ # TODO (deoktr): add exclusions for strings and numbers
22
+ #
23
+
24
+ import random
25
+ from tokenize import DEDENT, ENCODING, INDENT, NAME, NEWLINE, NUMBER, OP, STRING
26
+
27
+
28
+ class ConstantsObfuscator:
29
+ """Extract variables and put them at the top of the file.
30
+
31
+ This will thus set strings, numbers etc. has constants.
32
+ """
33
+
34
+ # list(__builtins__.__dict__.keys())
35
+ BUILTINS = (
36
+ # look like it works now ?
37
+ "__name__", # doesn't work with 'if _name_ == "_main_": ...'
38
+ "__doc__",
39
+ "__package__",
40
+ "__loader__",
41
+ "__spec__",
42
+ "__build_class__",
43
+ "__import__",
44
+ "abs",
45
+ "all",
46
+ "any",
47
+ "ascii",
48
+ "bin",
49
+ "breakpoint",
50
+ "callable",
51
+ "chr",
52
+ "compile",
53
+ "delattr",
54
+ "dir",
55
+ "divmod",
56
+ "eval",
57
+ "exec",
58
+ # used not to work but now it does I guess
59
+ "format", # try to change "{}".format('foo')
60
+ "getattr",
61
+ "globals",
62
+ "hasattr",
63
+ "hash",
64
+ "hex",
65
+ "id",
66
+ "input",
67
+ "isinstance",
68
+ "issubclass",
69
+ "iter",
70
+ "aiter",
71
+ "len",
72
+ "locals",
73
+ "max",
74
+ "min",
75
+ "next",
76
+ "anext",
77
+ "oct",
78
+ "ord",
79
+ "pow",
80
+ "print",
81
+ "repr",
82
+ "round",
83
+ "setattr",
84
+ "sorted",
85
+ "sum",
86
+ "vars",
87
+ "None",
88
+ "Ellipsis",
89
+ "NotImplemented",
90
+ "False",
91
+ "True",
92
+ "bool",
93
+ "memoryview",
94
+ "bytearray",
95
+ "bytes",
96
+ "classmethod",
97
+ "complex",
98
+ "dict",
99
+ "enumerate",
100
+ "filter",
101
+ "float",
102
+ "frozenset",
103
+ "property",
104
+ "int",
105
+ "list",
106
+ "map",
107
+ "object",
108
+ "range",
109
+ "reversed",
110
+ "set",
111
+ "slice",
112
+ "staticmethod",
113
+ "str",
114
+ # "super", # plain doesn't work
115
+ "tuple",
116
+ "type",
117
+ "zip",
118
+ "__debug__",
119
+ "BaseException",
120
+ "Exception",
121
+ "TypeError",
122
+ "StopAsyncIteration",
123
+ "StopIteration",
124
+ "GeneratorExit",
125
+ "SystemExit",
126
+ "KeyboardInterrupt",
127
+ "ImportError",
128
+ "ModuleNotFoundError",
129
+ "OSError",
130
+ "EnvironmentError",
131
+ "IOError",
132
+ "EOFError",
133
+ "RuntimeError",
134
+ "RecursionError",
135
+ "NotImplementedError",
136
+ "NameError",
137
+ "UnboundLocalError",
138
+ "AttributeError",
139
+ "SyntaxError",
140
+ "IndentationError",
141
+ "TabError",
142
+ "LookupError",
143
+ "IndexError",
144
+ "KeyError",
145
+ "ValueError",
146
+ "UnicodeError",
147
+ "UnicodeEncodeError",
148
+ "UnicodeDecodeError",
149
+ "UnicodeTranslateError",
150
+ "AssertionError",
151
+ "ArithmeticError",
152
+ "FloatingPointError",
153
+ "OverflowError",
154
+ "ZeroDivisionError",
155
+ "SystemError",
156
+ "ReferenceError",
157
+ "MemoryError",
158
+ "BufferError",
159
+ "Warning",
160
+ "UserWarning",
161
+ "EncodingWarning",
162
+ "DeprecationWarning",
163
+ "PendingDeprecationWarning",
164
+ "SyntaxWarning",
165
+ "RuntimeWarning",
166
+ "FutureWarning",
167
+ "ImportWarning",
168
+ "UnicodeWarning",
169
+ "BytesWarning",
170
+ "ResourceWarning",
171
+ "ConnectionError",
172
+ "BlockingIOError",
173
+ "BrokenPipeError",
174
+ "ChildProcessError",
175
+ "ConnectionAbortedError",
176
+ "ConnectionRefusedError",
177
+ "ConnectionResetError",
178
+ "FileExistsError",
179
+ "FileNotFoundError",
180
+ "IsADirectoryError",
181
+ "NotADirectoryError",
182
+ "InterruptedError",
183
+ "PermissionError",
184
+ "ProcessLookupError",
185
+ "TimeoutError",
186
+ "open",
187
+ "quit",
188
+ "exit",
189
+ "copyright",
190
+ "credits",
191
+ "license",
192
+ "help",
193
+ )
194
+
195
+ def __init__(
196
+ self,
197
+ generator=None,
198
+ obf_builtins_rate=1,
199
+ obf_string_rate=1,
200
+ obf_number_rate=1,
201
+ ) -> None:
202
+ if generator is None:
203
+ from pof.utils.generator import BasicGenerator
204
+
205
+ generator = BasicGenerator.alphabet_generator()
206
+
207
+ self.generator = generator
208
+
209
+ self.obf_number_rate = obf_number_rate
210
+ self.obf_builtins_rate = obf_builtins_rate
211
+ self.obf_string_rate = obf_string_rate
212
+
213
+ def obfuscate_variable(self, toknum, tokval, variables):
214
+ if tokval not in variables:
215
+ var_name = next(self.generator)
216
+ variables.update({tokval: [var_name, toknum]})
217
+ return [(NAME, variables[tokval][0])], variables
218
+
219
+ def obfuscate_tokens(self, tokens):
220
+ variables = {}
221
+ result = []
222
+ parenthesis_depth = 0 # parenthesis depth
223
+ prev_tokval = None
224
+ prev_toknum = None
225
+ for index, (toknum, tokval, *_) in enumerate(tokens):
226
+ new_tokens = [(toknum, tokval)]
227
+ next_tokval = None
228
+ next_toknum = None
229
+ if len(tokens) > index + 1:
230
+ next_toknum, next_tokval, *__ = tokens[index + 1]
231
+
232
+ # context
233
+ if toknum == OP and tokval == "(":
234
+ parenthesis_depth += 1
235
+ elif toknum == OP and tokval == ")":
236
+ parenthesis_depth -= 1
237
+
238
+ # obfuscation
239
+ if (
240
+ (
241
+ toknum == NAME
242
+ and tokval in self.BUILTINS
243
+ and prev_tokval != "." # avoid changing class/imports functions
244
+ and (
245
+ parenthesis_depth == 0
246
+ or (parenthesis_depth > 0 and next_tokval != "=")
247
+ )
248
+ and (random.randint(0, 100) / 100) <= self.obf_builtins_rate
249
+ )
250
+ or (
251
+ # don't obfuscate docstrings
252
+ toknum == STRING
253
+ and prev_toknum
254
+ not in [
255
+ NEWLINE,
256
+ DEDENT,
257
+ INDENT,
258
+ ENCODING,
259
+ ]
260
+ and (random.randint(0, 100) / 100) <= self.obf_string_rate
261
+ )
262
+ or (
263
+ toknum == NUMBER
264
+ and (random.randint(0, 100) / 100) <= self.obf_number_rate
265
+ )
266
+ ):
267
+ new_tokens, variables = self.obfuscate_variable(
268
+ toknum,
269
+ tokval,
270
+ variables,
271
+ )
272
+
273
+ if new_tokens:
274
+ result.extend(new_tokens)
275
+ prev_tokval = tokval
276
+ prev_toknum = toknum
277
+
278
+ # randomize order
279
+ variables = list(variables.items())
280
+ random.shuffle(variables)
281
+ variables = dict(variables)
282
+
283
+ var_tokens = []
284
+ for tokval, (var_name, toknum) in variables.items():
285
+ var_tokens.extend(
286
+ [
287
+ (NAME, var_name),
288
+ (OP, "="),
289
+ (toknum, tokval),
290
+ (NEWLINE, "\n"),
291
+ ],
292
+ )
293
+
294
+ return var_tokens + result