powershell-pro-obfuscator 1.0.0__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.
@@ -0,0 +1,414 @@
1
+ #!/usr/bin/env python
2
+
3
+ ###############################################################################
4
+ #
5
+ # PowerShell Pro Obfuscator is a source code obfuscator for PowerShell scripts.
6
+ # Obfuscate, virtualize and protect your PowerShell .ps1 scripts against
7
+ # analysis, reverse engineering and technology theft.
8
+ #
9
+ # PowerShell Pro Obfuscator provides advanced PowerShell source code parsing
10
+ # based on AST trees, multiple advanced obfuscation, virtualization and
11
+ # protection strategies are available.
12
+ #
13
+ # Version : Python SDK v1.0.0
14
+ # Python : Python v3
15
+ # Dependencies : requests (https://pypi.python.org/pypi/requests/)
16
+ # Author : Bartosz Wójcik (support@pelock.com)
17
+ # Project : https://www.pelock.com/products/powershell-pro-obfuscator
18
+ # Homepage : https://www.pelock.com
19
+ #
20
+ ###############################################################################
21
+
22
+ import zlib
23
+ import base64
24
+
25
+ # required external package - install with "pip install requests"
26
+ import requests
27
+
28
+
29
+ class PowerShellProObfuscator(object):
30
+ """PowerShell Pro Obfuscator module"""
31
+
32
+ #
33
+ # @var string default PowerShell Pro Obfuscator WebApi endpoint
34
+ #
35
+ API_URL = "https://www.pelock.com/api/powershell-pro-obfuscator/v1"
36
+
37
+ #
38
+ # @var string WebApi key for the service
39
+ #
40
+ _apiKey = ""
41
+
42
+ #
43
+ # @var bool should the source code be compressed
44
+ #
45
+ enableCompression = False
46
+
47
+ #
48
+ # @var bool protection against tampering with protected code (integrity verification)
49
+ #
50
+ selfDefending = True
51
+
52
+ #
53
+ # @var bool protection linker (decoy call graph)
54
+ #
55
+ protectionLinker = True
56
+
57
+ #
58
+ # @var bool rename variable names to random string values
59
+ #
60
+ renameVariables = True
61
+
62
+ #
63
+ # @var bool rename parameter names to random string values
64
+ #
65
+ renameParameters = True
66
+
67
+ #
68
+ # @var bool rename function names to random string values
69
+ #
70
+ renameFunctions = True
71
+
72
+ #
73
+ # @var bool shuffle function order in the output source
74
+ #
75
+ shuffleFunctions = True
76
+
77
+ #
78
+ # @var bool change linear code execution flow via control-flow flattening
79
+ #
80
+ controlFlowFlatten = True
81
+
82
+ #
83
+ # @var bool rewrite statement blocks into finite-state automata (state-machine obfuscation)
84
+ #
85
+ stateMachine = True
86
+
87
+ #
88
+ # @var bool lift selected statements into a VM engine (virtualized statements)
89
+ #
90
+ vmStrategy = True
91
+
92
+ #
93
+ # @var bool encrypt integers
94
+ #
95
+ encryptIntegers = True
96
+
97
+ #
98
+ # @var bool split strings into concatenated chunks
99
+ #
100
+ splitStrings = True
101
+
102
+ #
103
+ # @var bool encrypt strings using randomly generated polymorphic encryption algorithms
104
+ #
105
+ encryptStrings = True
106
+
107
+ #
108
+ # @var bool move integers to arrays
109
+ #
110
+ integersToArrays = True
111
+
112
+ #
113
+ # @var bool move floats to arrays
114
+ #
115
+ floatsToArrays = True
116
+
117
+ #
118
+ # @var bool insert dead code
119
+ #
120
+ insertDeadCode = True
121
+
122
+ #
123
+ # @var bool replace boolean conditions with equivalent complex expressions
124
+ #
125
+ complexifyBooleans = True
126
+
127
+ #
128
+ # @var bool represent integers via floating-point math
129
+ #
130
+ integersToFloating = True
131
+
132
+ #
133
+ # @var bool encrypt floating point numbers
134
+ #
135
+ encryptFloating = True
136
+
137
+ #
138
+ # @var bool insert decoy functions
139
+ #
140
+ decoyFunctions = True
141
+
142
+ #
143
+ # @var bool insert anti-debugging detections
144
+ #
145
+ detectDebugger = True
146
+
147
+ #
148
+ # @var bool insert fake dot-source comment markers
149
+ #
150
+ fakeDotSourceMarkers = True
151
+
152
+ #
153
+ # @var bool insert opaque predicate branches
154
+ #
155
+ opaqueBranches = True
156
+
157
+ #
158
+ # @var bool insert scriptblock decoys
159
+ #
160
+ scriptblockDecoys = True
161
+
162
+ #
163
+ # @var bool insert here-string padding
164
+ #
165
+ literalPadding = True
166
+
167
+ #
168
+ # @var bool use indirect command invocation
169
+ #
170
+ reflectInvokeCommands = True
171
+
172
+ #
173
+ # @var bool store string fragments in char-code array vaults
174
+ #
175
+ stringCharArrayVault = True
176
+
177
+ #
178
+ # @var bool wrap code in try/finally blocks with dead noise
179
+ #
180
+ tryFinallyNoise = True
181
+
182
+ #
183
+ # @var bool apply redundant xor / affine integer masks
184
+ #
185
+ affineIntegerMask = True
186
+
187
+ #
188
+ # @var bool insert dead event/timer stubs
189
+ #
190
+ eventStub = True
191
+
192
+ #
193
+ # @var bool strip comments from the output source
194
+ #
195
+ removeComments = True
196
+
197
+ #
198
+ # @var integer success
199
+ #
200
+ ERROR_SUCCESS = 0
201
+
202
+ #
203
+ # @var integer invalid size for source code (it's 1000 bytes max. for demo version)
204
+ #
205
+ ERROR_INPUT_SIZE = 1
206
+
207
+ #
208
+ # @var integer input source is empty
209
+ #
210
+ ERROR_INPUT = 2
211
+
212
+ #
213
+ # @var integer PowerShell source code parsing error
214
+ #
215
+ ERROR_PARSING = 3
216
+
217
+ #
218
+ # @var integer PowerShell parsed code obfuscation error
219
+ #
220
+ ERROR_OBFUSCATION = 4
221
+
222
+ #
223
+ # @var integer error while generating output code
224
+ #
225
+ ERROR_OUTPUT = 5
226
+
227
+ def __init__(self, api_key=None, enable_all_obfuscation_options=True):
228
+ """Initialize PowerShell Pro Obfuscator class
229
+
230
+ :param api_key: Activation key for the service (it can be empty for demo mode)
231
+ :param enable_all_obfuscation_options: Enable or disable all of the obfuscation options
232
+ """
233
+
234
+ self._apiKey = api_key
235
+
236
+ # compression stays disabled by default (API does not decompress today)
237
+ self.enableCompression = False
238
+
239
+ self.selfDefending = enable_all_obfuscation_options
240
+ self.protectionLinker = enable_all_obfuscation_options
241
+ self.renameVariables = enable_all_obfuscation_options
242
+ self.renameParameters = enable_all_obfuscation_options
243
+ self.renameFunctions = enable_all_obfuscation_options
244
+ self.shuffleFunctions = enable_all_obfuscation_options
245
+ self.controlFlowFlatten = enable_all_obfuscation_options
246
+ self.stateMachine = enable_all_obfuscation_options
247
+ self.vmStrategy = enable_all_obfuscation_options
248
+ self.encryptIntegers = enable_all_obfuscation_options
249
+ self.splitStrings = enable_all_obfuscation_options
250
+ self.encryptStrings = enable_all_obfuscation_options
251
+ self.integersToArrays = enable_all_obfuscation_options
252
+ self.floatsToArrays = enable_all_obfuscation_options
253
+ self.insertDeadCode = enable_all_obfuscation_options
254
+ self.complexifyBooleans = enable_all_obfuscation_options
255
+ self.integersToFloating = enable_all_obfuscation_options
256
+ self.encryptFloating = enable_all_obfuscation_options
257
+ self.decoyFunctions = enable_all_obfuscation_options
258
+ self.detectDebugger = enable_all_obfuscation_options
259
+ self.fakeDotSourceMarkers = enable_all_obfuscation_options
260
+ self.opaqueBranches = enable_all_obfuscation_options
261
+ self.scriptblockDecoys = enable_all_obfuscation_options
262
+ self.literalPadding = enable_all_obfuscation_options
263
+ self.reflectInvokeCommands = enable_all_obfuscation_options
264
+ self.stringCharArrayVault = enable_all_obfuscation_options
265
+ self.tryFinallyNoise = enable_all_obfuscation_options
266
+ self.affineIntegerMask = enable_all_obfuscation_options
267
+ self.eventStub = enable_all_obfuscation_options
268
+ self.removeComments = enable_all_obfuscation_options
269
+
270
+ def login(self):
271
+ """Login to the service and get the information about the current license limits
272
+
273
+ :return: An array with the results or False on error
274
+ :rtype: bool,dict
275
+ """
276
+
277
+ # parameters
278
+ params = {"command": "login"}
279
+
280
+ return self.post_request(params)
281
+
282
+ def obfuscate_script_file(self, script_file_path):
283
+ """Obfuscate PowerShell script source code file using provided parameters
284
+
285
+ :param script_file_path: PowerShell compatible script *.ps1 file path
286
+ :return: An array with the results or False on error
287
+ :rtype: bool,dict
288
+ """
289
+
290
+ source_file = open(script_file_path, 'r')
291
+ source = source_file.read()
292
+ source_file.close()
293
+
294
+ if not source:
295
+ return False
296
+
297
+ return self.obfuscate_script_source(source)
298
+
299
+ def obfuscate_script_source(self, script_source):
300
+ """Obfuscate PowerShell script source code using provided parameters
301
+
302
+ :param script_source: PowerShell compatible script *.ps1 source code
303
+ :return: An array with the results or False on error
304
+ :rtype: bool,dict
305
+ """
306
+
307
+ # additional parameters
308
+ params_array = {"command": "obfuscate", "source": script_source}
309
+
310
+ return self.post_request(params_array)
311
+
312
+ def post_request(self, params_array):
313
+ """Send a POST request to the server
314
+
315
+ :param params_array: An array with the parameters
316
+ :return: An array with the results or false on error
317
+ :rtype: bool,dict
318
+ """
319
+
320
+ # add activation key to the parameters array
321
+ if self._apiKey:
322
+ params_array["key"] = self._apiKey
323
+
324
+ #
325
+ # obfuscation strategies
326
+ #
327
+ if self.selfDefending:
328
+ params_array["self_defending"] = "1"
329
+ if self.protectionLinker:
330
+ params_array["protection_linker"] = "1"
331
+ if self.renameVariables:
332
+ params_array["rename_variables"] = "1"
333
+ if self.renameParameters:
334
+ params_array["rename_parameters"] = "1"
335
+ if self.renameFunctions:
336
+ params_array["rename_functions"] = "1"
337
+ if self.shuffleFunctions:
338
+ params_array["shuffle_functions"] = "1"
339
+ if self.controlFlowFlatten:
340
+ params_array["control_flow_flatten"] = "1"
341
+ if self.stateMachine:
342
+ params_array["state_machine"] = "1"
343
+ if self.vmStrategy:
344
+ params_array["vm_strategy"] = "1"
345
+ if self.encryptIntegers:
346
+ params_array["encrypt_integers"] = "1"
347
+ if self.splitStrings:
348
+ params_array["split_strings"] = "1"
349
+ if self.encryptStrings:
350
+ params_array["encrypt_strings"] = "1"
351
+ if self.integersToArrays:
352
+ params_array["integers_to_arrays"] = "1"
353
+ if self.floatsToArrays:
354
+ params_array["floats_to_arrays"] = "1"
355
+ if self.insertDeadCode:
356
+ params_array["insert_dead_code"] = "1"
357
+ if self.complexifyBooleans:
358
+ params_array["complexify_booleans"] = "1"
359
+ if self.integersToFloating:
360
+ params_array["integers_to_floating"] = "1"
361
+ if self.encryptFloating:
362
+ params_array["encrypt_floating"] = "1"
363
+ if self.decoyFunctions:
364
+ params_array["decoy_functions"] = "1"
365
+ if self.detectDebugger:
366
+ params_array["detect_debugger"] = "1"
367
+ if self.fakeDotSourceMarkers:
368
+ params_array["fake_dot_source_markers"] = "1"
369
+ if self.opaqueBranches:
370
+ params_array["opaque_branches"] = "1"
371
+ if self.scriptblockDecoys:
372
+ params_array["scriptblock_decoys"] = "1"
373
+ if self.literalPadding:
374
+ params_array["literal_padding"] = "1"
375
+ if self.reflectInvokeCommands:
376
+ params_array["reflect_invoke_commands"] = "1"
377
+ if self.stringCharArrayVault:
378
+ params_array["string_char_array_vault"] = "1"
379
+ if self.tryFinallyNoise:
380
+ params_array["try_finally_noise"] = "1"
381
+ if self.affineIntegerMask:
382
+ params_array["affine_integer_mask"] = "1"
383
+ if self.eventStub:
384
+ params_array["event_stub"] = "1"
385
+ if self.removeComments:
386
+ params_array["remove_comments"] = "1"
387
+
388
+ #
389
+ # check if compression is enabled
390
+ #
391
+ if "source" in params_array and self.enableCompression and params_array["source"]:
392
+
393
+ compressed_data = zlib.compress(bytes(params_array["source"], 'utf-8'), 9)
394
+ base64_encoded_data = base64.b64encode(compressed_data).decode()
395
+
396
+ params_array["source"] = base64_encoded_data
397
+ params_array["compression"] = "1"
398
+
399
+ response = requests.post(self.API_URL, data=params_array)
400
+
401
+ # no response at all or an invalid response code
402
+ if not response or not response.ok:
403
+ return False
404
+
405
+ # decode to json array
406
+ result = response.json()
407
+
408
+ # depack output code back into the string
409
+ if "output" in result and self.enableCompression and result["error"] == self.ERROR_SUCCESS:
410
+
411
+ result["output"] = str(zlib.decompress(base64.b64decode(result["output"])), "utf-8")
412
+
413
+ # return original JSON response code
414
+ return result