assemblyline-v4-service 4.4.0.24__py3-none-any.whl → 4.4.0.26__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.

Potentially problematic release.


This version of assemblyline-v4-service might be problematic. Click here for more details.

Files changed (42) hide show
  1. assemblyline_v4_service/VERSION +1 -1
  2. assemblyline_v4_service/common/api.py +3 -2
  3. assemblyline_v4_service/common/base.py +3 -4
  4. assemblyline_v4_service/common/helper.py +1 -2
  5. assemblyline_v4_service/common/{extractor/ocr.py → ocr.py} +0 -1
  6. assemblyline_v4_service/common/ontology_helper.py +7 -8
  7. assemblyline_v4_service/common/request.py +4 -5
  8. assemblyline_v4_service/common/result.py +3 -3
  9. assemblyline_v4_service/common/task.py +3 -3
  10. assemblyline_v4_service/common/utils.py +2 -2
  11. assemblyline_v4_service/updater/helper.py +4 -0
  12. {assemblyline_v4_service-4.4.0.24.dist-info → assemblyline_v4_service-4.4.0.26.dist-info}/METADATA +1 -1
  13. assemblyline_v4_service-4.4.0.26.dist-info/RECORD +28 -0
  14. assemblyline_v4_service/common/balbuzard/__init__.py +0 -0
  15. assemblyline_v4_service/common/balbuzard/balbuzard.py +0 -656
  16. assemblyline_v4_service/common/balbuzard/bbcrack.py +0 -830
  17. assemblyline_v4_service/common/balbuzard/patterns.py +0 -650
  18. assemblyline_v4_service/common/dynamic_service_helper.py +0 -3631
  19. assemblyline_v4_service/common/extractor/__init__.py +0 -1
  20. assemblyline_v4_service/common/extractor/base64.py +0 -86
  21. assemblyline_v4_service/common/extractor/pe_file.py +0 -51
  22. assemblyline_v4_service/common/icap.py +0 -149
  23. assemblyline_v4_service/common/keytool_parse.py +0 -66
  24. assemblyline_v4_service/common/pestudio/__init__.py +0 -0
  25. assemblyline_v4_service/common/pestudio/xml/__init__.py +0 -0
  26. assemblyline_v4_service/common/pestudio/xml/features.xml +0 -5607
  27. assemblyline_v4_service/common/pestudio/xml/functions.xml +0 -5824
  28. assemblyline_v4_service/common/pestudio/xml/languages.xml +0 -375
  29. assemblyline_v4_service/common/pestudio/xml/resources.xml +0 -511
  30. assemblyline_v4_service/common/pestudio/xml/signatures.xml +0 -29105
  31. assemblyline_v4_service/common/pestudio/xml/strings.xml +0 -2379
  32. assemblyline_v4_service/common/safelist_helper.py +0 -73
  33. assemblyline_v4_service/common/section_reducer.py +0 -43
  34. assemblyline_v4_service/common/tag_helper.py +0 -117
  35. assemblyline_v4_service/common/tag_reducer.py +0 -242
  36. assemblyline_v4_service/testing/__init__.py +0 -0
  37. assemblyline_v4_service/testing/helper.py +0 -463
  38. assemblyline_v4_service/testing/regenerate_results.py +0 -37
  39. assemblyline_v4_service-4.4.0.24.dist-info/RECORD +0 -53
  40. {assemblyline_v4_service-4.4.0.24.dist-info → assemblyline_v4_service-4.4.0.26.dist-info}/LICENCE.md +0 -0
  41. {assemblyline_v4_service-4.4.0.24.dist-info → assemblyline_v4_service-4.4.0.26.dist-info}/WHEEL +0 -0
  42. {assemblyline_v4_service-4.4.0.24.dist-info → assemblyline_v4_service-4.4.0.26.dist-info}/top_level.txt +0 -0
@@ -1,830 +0,0 @@
1
- #! /usr/bin/env python2
2
- """
3
- 2016-10-21:
4
- Modified version of bbcrack application for AL, original code found here:
5
- https://github.com/decalage2/balbuzard
6
- """
7
- """
8
- bbcrack - v0.14 2014-05-22 Philippe Lagadec
9
-
10
- bbcrack is a tool to crack malware obfuscation such as XOR, ROL, ADD (and
11
- many combinations), by bruteforcing all possible keys and and checking for
12
- specific patterns (IP addresses, domain names, URLs, known file headers and
13
- strings, etc) using the balbuzard engine.
14
- It is part of the Balbuzard package.
15
-
16
- For more info and updates: http://www.decalage.info/balbuzard
17
- """
18
-
19
- # LICENSE:
20
- #
21
- # bbcrack is copyright (c) 2013-2014, Philippe Lagadec (http://www.decalage.info)
22
- # All rights reserved.
23
- #
24
- # Redistribution and use in source and binary forms, with or without modification,
25
- # are permitted provided that the following conditions are met:
26
- #
27
- # * Redistributions of source code must retain the above copyright notice, this
28
- # list of conditions and the following disclaimer.
29
- # * Redistributions in binary form must reproduce the above copyright notice,
30
- # this list of conditions and the following disclaimer in the documentation
31
- # and/or other materials provided with the distribution.
32
- #
33
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
34
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
37
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
42
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
-
44
-
45
- __version__ = '0.13'
46
-
47
- # --- IMPORTS ------------------------------------------------------------------
48
-
49
- from assemblyline_v4_service.common.balbuzard.balbuzard import Balbuzard
50
- from assemblyline_v4_service.common.balbuzard.patterns import PatternMatch
51
-
52
- #--- CLASSES ------------------------------------------------------------------
53
-
54
- class Transform_string (object):
55
- """
56
- Generic class to define a transform that acts on a string globally.
57
- """
58
- # generic name and id for the class:
59
- gen_name = 'Generic String Transform'
60
- gen_id = 'string'
61
-
62
- def __init__(self, params=None):
63
- """
64
- constructor for the Transform object.
65
- This method needs to be overloaded for every specific Transform.
66
- It should set name and shortname according to the provided parameters.
67
- (for example shortname="xor_17" for a XOR transform with params=17)
68
- params: single value or tuple of values, parameters for the transformation
69
- """
70
- self.name = 'Undefined String Transform'
71
- self.shortname = 'undefined_string'
72
- self.params = params
73
-
74
-
75
- def transform_string (self, data):
76
- """
77
- Method to be overloaded, only for a transform that acts on a string
78
- globally.
79
- This method should apply the transform to the data string, using params
80
- as parameters, and return the transformed data as a string.
81
- (the resulting string does not need to have the same length as data)
82
- """
83
- raise NotImplementedError
84
-
85
- @staticmethod
86
- def iter_params ():
87
- """
88
- Method to be overloaded.
89
- This static method should iterate over all possible parameters for the
90
- transform function, yielding each set of parameters as a single value
91
- or a tuple of values.
92
- (for example for a XOR transform, it should yield 1 to 255)
93
- This method should be used on the Transform class in order to
94
- instantiate a Transform object with each set of parameters.
95
- """
96
- raise NotImplementedError
97
-
98
- ## def iter_transform (self, data):
99
- ## """
100
- ## Runs the transform on data for all possible values of the parameters,
101
- ## and yields the transformed data for each possibility.
102
- ## """
103
- ## for params in self.iter_params():
104
- ## #print self.name
105
- ## yield self.transform_string(data, params)
106
-
107
-
108
- class Transform_char (Transform_string):
109
- """
110
- Generic class to define a transform that acts on each character of a string
111
- separately.
112
- """
113
- # generic name for the class:
114
- gen_name = 'Generic Character Transform'
115
- gen_id = 'char'
116
-
117
- def __init__(self, params=None):
118
- """
119
- constructor for the Transform object.
120
- This method needs to be overloaded for every specific Transform.
121
- It should set name and shortname according to the provided parameters.
122
- (for example shortname="xor_17" for a XOR transform with params=17)
123
- params: single value or tuple of values, parameters for the transformation
124
- """
125
- self.name = 'Undefined Character Transform'
126
- self.shortname = 'undefined_char'
127
- self.params = params
128
-
129
-
130
- def transform_string (self, data):
131
- """
132
- This method applies the transform to the data string, using params
133
- as parameters, and return the transformed data as a string.
134
- Here, each character is transformed separately by calling transform_char.
135
- A translation table is used to speed up the processing.
136
- (the resulting string should have the same length as data)
137
- """
138
- # for optimal speed, we build a translation table:
139
- self.trans_table = bytearray()
140
- for i in range(256):
141
- self.trans_table.append(self.transform_int(i))
142
- return data.translate(self.trans_table)
143
-
144
- def transform_char (self, char):
145
- """
146
- Method that can be overloaded, only for a transform that acts on a character.
147
- This method should apply the transform to the provided char, using params
148
- as parameters, and return the transformed data as a character.
149
- NOTE: it is usually simpler to overload transform_int and leave this one
150
- untouched.
151
- (here character = string of length 1)
152
- """
153
- # by default, call transform_int using ord(char), and convert it back
154
- # to a single character:
155
- return chr(self.transform_int(ord(char)))
156
-
157
-
158
- def transform_int (self, i):
159
- """
160
- Method to be overloaded, only for a transform that acts on a character.
161
- This method should apply the transform to the provided integer which is
162
- the ASCII code of a character (i.e. ord(c)), using params
163
- as parameters, and return the transformed data as an integer.
164
- (here character = string of length 1)
165
- """
166
- raise NotImplementedError
167
-
168
-
169
- #--- TRANSFORMS ---------------------------------------------------------------
170
-
171
- class Transform_identity (Transform_string):
172
- """
173
- Transform that does not change data.
174
- """
175
- # generic name for the class:
176
- gen_name = 'Identity Transformation, no change to data. Parameters: none.'
177
- gen_id = 'identity'
178
-
179
- def __init__(self, params=None):
180
- self.name = self.gen_name
181
- self.shortname = self.gen_id
182
- self.params = None
183
-
184
- def transform_string (self, data):
185
- return data
186
-
187
- @staticmethod
188
- def iter_params ():
189
- yield None
190
-
191
-
192
- #------------------------------------------------------------------------------
193
- class Transform_XOR (Transform_char):
194
- """
195
- XOR Transform
196
- """
197
- # generic name for the class:
198
- gen_name = 'XOR with 8 bits static key A. Parameters: A (1-FF).'
199
- gen_id = 'xor'
200
-
201
- def __init__(self, params):
202
- assert isinstance(params, int)
203
- assert params>0 and params<256
204
- self.params = params
205
- self.name = "XOR %02X" % params
206
- self.shortname = "xor%02X" % params
207
-
208
- def transform_int (self, i):
209
- # here params is an integer
210
- return i ^ self.params
211
-
212
- @staticmethod
213
- def iter_params ():
214
- # the XOR key can be 1 to 255 (0 would be identity)
215
- for key in range(1,256):
216
- yield key
217
-
218
-
219
- #------------------------------------------------------------------------------
220
- class Transform_XOR_INC (Transform_string):
221
- """
222
- XOR Transform, with incrementing key
223
- """
224
- # generic name for the class:
225
- gen_name = 'XOR with 8 bits key A incrementing after each character. Parameters: A (0-FF).'
226
- gen_id = 'xor_inc'
227
-
228
- def __init__(self, params):
229
- assert isinstance(params, int)
230
- assert params>=0 and params<256
231
- self.params = params
232
- self.name = "XOR %02X INC" % params
233
- self.shortname = "xor%02X_inc" % params
234
-
235
- def transform_string (self, data):
236
- # here params is an integer
237
- #TODO: use a list comprehension + join to get better performance
238
- # this loop is more readable, but likely to be much slower
239
- out = ''
240
- for i in range(len(data)):
241
- xor_key = (self.params + i) & 0xFF
242
- out += chr(ord(data[i]) ^ xor_key)
243
- return out
244
-
245
- @staticmethod
246
- def iter_params ():
247
- # the XOR key can be 0 to 255 (0 is not identity here)
248
- for xor_key in range(0,256):
249
- yield xor_key
250
-
251
-
252
- #------------------------------------------------------------------------------
253
- class Transform_XOR_DEC (Transform_string):
254
- """
255
- XOR Transform, with decrementing key
256
- """
257
- # generic name for the class:
258
- gen_name = 'XOR with 8 bits key A decrementing after each character. Parameters: A (0-FF).'
259
- gen_id = 'xor_dec'
260
-
261
- def __init__(self, params):
262
- assert isinstance(params, int)
263
- assert params>=0 and params<256
264
- self.params = params
265
- self.name = "XOR %02X DEC" % params
266
- self.shortname = "xor%02X_dec" % params
267
-
268
- def transform_string (self, data):
269
- # here params is an integer
270
- #TODO: use a list comprehension + join to get better performance
271
- # this loop is more readable, but likely to be much slower
272
- out = ''
273
- for i in range(len(data)):
274
- xor_key = (self.params + 0xFF - i) & 0xFF
275
- out += chr(ord(data[i]) ^ xor_key)
276
- return out
277
-
278
- @staticmethod
279
- def iter_params ():
280
- # the XOR key can be 0 to 255 (0 is not identity here)
281
- for xor_key in range(0,256):
282
- yield xor_key
283
-
284
-
285
- #------------------------------------------------------------------------------
286
- class Transform_XOR_INC_ROL (Transform_string):
287
- """
288
- XOR Transform, with incrementing key, then ROL N bits
289
- """
290
- # generic name for the class:
291
- gen_name = 'XOR with 8 bits key A incrementing after each character, then rotate B bits left. Parameters: A (0-FF), B (1-7).'
292
- gen_id = 'xor_inc_rol'
293
-
294
- def __init__(self, params):
295
- self.params = params
296
- self.name = "XOR %02X INC then ROL %d" % params
297
- self.shortname = "xor%02X_inc_rol%d" % params
298
-
299
- def transform_char (self, char):
300
- # here params is a tuple
301
- xor_key, rol_bits = self.params
302
- return chr(rol(ord(char) ^ xor_key, rol_bits))
303
-
304
- def transform_string (self, data):
305
- # here params is a tuple
306
- #TODO: use a list comprehension + join to get better performance
307
- # this loop is more readable, but likely to be much slower
308
- xor_key_init, rol_bits = self.params
309
- out = ''
310
- for i in range(len(data)):
311
- xor_key = (xor_key_init + i) & 0xFF
312
- out += chr(rol(ord(data[i]) ^ xor_key, rol_bits))
313
- return out
314
-
315
- @staticmethod
316
- def iter_params ():
317
- "return (XOR key, ROL bits)"
318
- # the XOR key can be 0 to 255 (0 is not identity here)
319
- for xor_key in range(0,256):
320
- # the ROL bits can be 1 to 7:
321
- for rol_bits in range(1,8):
322
- yield (xor_key, rol_bits)
323
-
324
-
325
- #------------------------------------------------------------------------------
326
- class Transform_SUB_INC (Transform_string):
327
- """
328
- SUB Transform, with incrementing key
329
- """
330
- # generic name for the class:
331
- gen_name = 'SUB with 8 bits key A incrementing after each character. Parameters: A (0-FF).'
332
- gen_id = 'sub_inc'
333
-
334
- def __init__(self, params):
335
- assert isinstance(params, int)
336
- assert params>=0 and params<256
337
- self.params = params
338
- self.name = "SUB %02X INC" % params
339
- self.shortname = "sub%02X_inc" % params
340
-
341
- def transform_string (self, data):
342
- # here params is an integer
343
- #TODO: use a list comprehension + join to get better performance
344
- # this loop is more readable, but likely to be much slower
345
- out = bytearray()
346
- for i in range(len(data)):
347
- key = (self.params + i) & 0xFF
348
- out.append((ord(data[i]) - key) & 0xFF)
349
- return out
350
-
351
- @staticmethod
352
- def iter_params ():
353
- # the SUB key can be 0 to 255 (0 is not identity here)
354
- for key in range(0,256):
355
- yield key
356
-
357
-
358
- def rol(byte, count):
359
- byte = (byte << count | byte >> (8-count)) & 0xFF
360
- return byte
361
-
362
- ###safety checks
363
- ##assert rol(1, 1) == 2
364
- ##assert rol(128, 1) == 1
365
- ##assert rol(1, 7) == 128
366
- ##assert rol(1, 8) == 1
367
-
368
- #------------------------------------------------------------------------------
369
- class Transform_XOR_Chained (Transform_string):
370
- """
371
- XOR Transform, chained with previous character.
372
- xor_chained(c[i], key) = c[i] xor c[i-1] xor key
373
- """
374
- # generic name for the class:
375
- gen_name = 'XOR with 8 bits key A chained with previous character. Parameters: A (1-FF).'
376
- gen_id = 'xor_chained'
377
-
378
- def __init__(self, params):
379
- assert isinstance(params, int)
380
- assert params>=0 and params<256
381
- self.params = params
382
- self.name = "XOR %02X Chained" % params
383
- self.shortname = "xor%02X_chained" % params
384
-
385
- def transform_string (self, data):
386
- # here params is an integer
387
- #TODO: it would be much faster to do the xor_chained once, then all
388
- # xor transforms using translate() only
389
- #TODO: use a list comprehension + join to get better performance
390
- # this loop is more readable, but likely to be much slower
391
- if len(data) == 0: return b''
392
- xor_key = self.params
393
- # 1st char is just xored with key:
394
- out = bytearray((ord(data[0]) ^ xor_key,))
395
- for i in range(1, len(data)):
396
- out.append(ord(data[i]) ^ xor_key ^ ord(data[i-1]))
397
- return out
398
-
399
- @staticmethod
400
- def iter_params ():
401
- # the XOR key can be 0 to 255 (0 is not identity here)
402
- for xor_key in range(0,256):
403
- yield xor_key
404
-
405
-
406
- #------------------------------------------------------------------------------
407
- class Transform_XOR_RChained (Transform_string):
408
- """
409
- XOR Transform, chained with next character. (chained on the right)
410
- xor_rchained(c[i], key) = c[i] xor c[i+1] xor key
411
- """
412
- # generic name for the class:
413
- gen_name = 'XOR with 8 bits key A chained with next character (Reverse order from end to start). Parameters: A (1-FF).'
414
- gen_id = 'xor_rchained'
415
-
416
- def __init__(self, params):
417
- assert isinstance(params, int)
418
- assert params>=0 and params<256
419
- self.params = params
420
- self.name = "XOR %02X RChained" % params
421
- self.shortname = "xor%02X_rchained" % params
422
-
423
- def transform_string (self, data):
424
- # here params is an integer
425
- #TODO: it would be much faster to do the xor_rchained once, then all
426
- # xor transforms using translate() only
427
- #TODO: use a list comprehension + join to get better performance
428
- # this loop is more readable, but likely to be much slower
429
- if len(data) == 0: return b''
430
- out = bytearray()
431
- xor_key = self.params
432
- # all chars except last one are xored with key and next char:
433
- for i in range(len(data)-1):
434
- out.append(ord(data[i]) ^ xor_key ^ ord(data[i+1]))
435
- # last char is just xored with key:
436
- out.append(ord(data[len(data)-1]) ^ xor_key)
437
- return out
438
-
439
- @staticmethod
440
- def iter_params ():
441
- # the XOR key can be 0 to 255 (0 is not identity here)
442
- for xor_key in range(0,256):
443
- yield xor_key
444
-
445
-
446
- #------------------------------------------------------------------------------
447
- class Transform_XOR_RChainedAll (Transform_string):
448
- """
449
- XOR Transform, chained from the right with all following characters.
450
- (as found in Taidoor malware)
451
- NOTE: this only works well in harvest mode, when testing all 256
452
- possibilities, because the key is position-dependent.
453
- xor_rchained_all(c[i], key) = c[i] xor key xor c[i+1] xor c[i+2]... xor c[N]
454
- """
455
- # generic name for the class:
456
- gen_name = 'XOR Transform, chained from the right with all following characters. Only works well with bbharvest.'
457
- gen_id = 'xor_rchained_all'
458
-
459
- def __init__(self, params):
460
- assert isinstance(params, int)
461
- assert params>=0 and params<256
462
- self.params = params
463
- self.name = "XOR %02X RChained All" % params
464
- self.shortname = "xor%02X_rchained_all" % params
465
-
466
- def transform_string (self, data):
467
- # here params is an integer
468
- #TODO: it would be much faster to do the xor_rchained once, then all
469
- # xor transforms using translate() only
470
- #TODO: use a list comprehension + join to get better performance
471
- # this loop is more readable, but likely to be much slower
472
- if len(data) == 0: return b''
473
- xor_key = self.params
474
- # transform data string to list of integers:
475
- l = map(ord, data)
476
- # loop from last char to 2nd one:
477
- for i in range(len(data)-1, 1, -1):
478
- l[i-1] = l[i-1] ^ xor_key ^ l[i]
479
- # last char is only xored with key:
480
- l[len(data)-1] = l[len(data)-1] ^ xor_key
481
- # convert back to list of chars:
482
- #l = map(chr, l)
483
- #out = ''.join(l)
484
- out = bytearray(l)
485
- return out
486
-
487
- @staticmethod
488
- def iter_params ():
489
- # the XOR key can be 0 to 255 (0 is not identity here)
490
- for xor_key in range(0,256):
491
- yield xor_key
492
-
493
-
494
- #------------------------------------------------------------------------------
495
- class Transform_ROL (Transform_char):
496
- """
497
- ROL Transform
498
- """
499
- # generic name for the class:
500
- gen_name = 'ROL - rotate A bits left. Parameters: A (1-7).'
501
- gen_id = 'rol'
502
-
503
- def __init__(self, params):
504
- self.params = params
505
- self.name = "ROL %d" % params
506
- self.shortname = "rol%d" % params
507
-
508
- def transform_int (self, i):
509
- # here params is an int
510
- rol_bits = self.params
511
- return rol(i, rol_bits)
512
-
513
- @staticmethod
514
- def iter_params ():
515
- "return (ROL bits)"
516
- # the ROL bits can be 1 to 7:
517
- for rol_bits in range(1,8):
518
- yield rol_bits
519
-
520
-
521
- #------------------------------------------------------------------------------
522
- class Transform_XOR_ROL (Transform_char):
523
- """
524
- XOR+ROL Transform - first XOR, then ROL
525
- """
526
- # generic name for the class:
527
- gen_name = 'XOR with static 8 bits key A, then rotate B bits left. Parameters: A (1-FF), B (1-7).'
528
- gen_id = 'xor_rol'
529
-
530
- def __init__(self, params):
531
- self.params = params
532
- self.name = "XOR %02X then ROL %d" % params
533
- self.shortname = "xor%02X_rol%d" % params
534
-
535
- def transform_int (self, i):
536
- # here params is a tuple
537
- xor_key, rol_bits = self.params
538
- return rol(i ^ xor_key, rol_bits)
539
-
540
- @staticmethod
541
- def iter_params ():
542
- "return (XOR key, ROL bits)"
543
- # the XOR key can be 1 to 255 (0 would be like ROL)
544
- for xor_key in range(1,256):
545
- # the ROL bits can be 1 to 7:
546
- for rol_bits in range(1,8):
547
- yield (xor_key, rol_bits)
548
-
549
-
550
- #------------------------------------------------------------------------------
551
- class Transform_ADD (Transform_char):
552
- """
553
- ADD Transform
554
- """
555
- # generic name for the class:
556
- gen_name = 'ADD with 8 bits static key A. Parameters: A (1-FF).'
557
- gen_id = 'add'
558
-
559
- def __init__(self, params):
560
- self.params = params
561
- self.name = "ADD %02X" % params
562
- self.shortname = "add%02X" % params
563
-
564
- def transform_int (self, i):
565
- # here params is an integer
566
- add_key = self.params
567
- return (i + add_key) & 0xFF
568
-
569
- @staticmethod
570
- def iter_params ():
571
- "return ADD key"
572
- # the ADD key can be 1 to 255 (0 would be identity):
573
- for add_key in range(1,256):
574
- yield add_key
575
-
576
-
577
- #------------------------------------------------------------------------------
578
- class Transform_ADD_ROL (Transform_char):
579
- """
580
- ADD+ROL Transform - first ADD, then ROL
581
- """
582
- # generic name for the class:
583
- gen_name = 'ADD with static 8 bits key A, then rotate B bits left. Parameters: A (1-FF), B (1-7).'
584
- gen_id = 'add_rol'
585
-
586
- def __init__(self, params):
587
- self.params = params
588
- self.name = "ADD %02X then ROL %d" % params
589
- self.shortname = "add%02X_rol%d" % params
590
-
591
- def transform_int (self, i):
592
- # here params is a tuple
593
- add_key, rol_bits = self.params
594
- return rol((i + add_key) & 0xFF, rol_bits)
595
-
596
- @staticmethod
597
- def iter_params ():
598
- "return (ADD key, ROL bits)"
599
- # the ADD key can be 1 to 255 (0 would be like ROL)
600
- for add_key in range(1,256):
601
- # the ROL bits can be 1 to 7:
602
- for rol_bits in range(1,8):
603
- yield (add_key, rol_bits)
604
-
605
-
606
- #------------------------------------------------------------------------------
607
- class Transform_ROL_ADD (Transform_char):
608
- """
609
- ROL+ADD Transform - first ROL, then ADD
610
- """
611
- # generic name for the class:
612
- gen_name = 'rotate A bits left, then ADD with static 8 bits key B. Parameters: A (1-7), B (1-FF).'
613
- gen_id = 'rol_add'
614
-
615
- def __init__(self, params):
616
- self.params = params
617
- self.name = "ROL %d then ADD %02X" % params
618
- self.shortname = "rol%d_add%02X" % params
619
-
620
- def transform_int (self, i):
621
- # here params is a tuple
622
- rol_bits, add_key = self.params
623
- return (rol(i, rol_bits) + add_key) & 0xFF
624
-
625
- @staticmethod
626
- def iter_params ():
627
- "return (ROL bits, ADD key)"
628
- # the ROL bits can be 1 to 7:
629
- for rol_bits in range(1,8):
630
- # the ADD key can be 1 to 255 (0 would be identity)
631
- for add_key in range(1,256):
632
- yield (rol_bits, add_key)
633
-
634
-
635
- #------------------------------------------------------------------------------
636
- class Transform_XOR_ADD (Transform_char):
637
- """
638
- XOR+ADD Transform - first XOR, then ADD
639
- """
640
- # generic name for the class:
641
- gen_name = 'XOR with 8 bits static key A, then ADD with 8 bits static key B. Parameters: A (1-FF), B (1-FF).'
642
- gen_id = 'xor_add'
643
-
644
- def __init__(self, params):
645
- self.params = params
646
- self.name = "XOR %02X then ADD %02X" % params
647
- self.shortname = "xor%02X_add%02X" % params
648
-
649
- def transform_int (self, i):
650
- # here params is a tuple
651
- xor_key, add_key = self.params
652
- return ((i ^ xor_key) + add_key) & 0xFF
653
-
654
- @staticmethod
655
- def iter_params ():
656
- "return (XOR key1, ADD key2)"
657
- # the XOR key can be 1 to 255 (0 would be identity)
658
- for xor_key in range(1,256):
659
- # the ADD key can be 1 to 255 (0 would be identity):
660
- for add_key in range(1,256):
661
- yield (xor_key, add_key)
662
-
663
-
664
- #------------------------------------------------------------------------------
665
- class Transform_ADD_XOR (Transform_char):
666
- """
667
- ADD+XOR Transform - first ADD, then XOR
668
- """
669
- # generic name for the class:
670
- gen_name = 'ADD with 8 bits static key A, then XOR with 8 bits static key B. Parameters: A (1-FF), B (1-FF).'
671
- gen_id = 'add_xor'
672
-
673
- def __init__(self, params):
674
- self.params = params
675
- self.name = "ADD %02X then XOR %02X" % params
676
- self.shortname = "add%02X_xor%02X" % params
677
-
678
- def transform_int (self, i):
679
- # here params is a tuple
680
- add_key, xor_key = self.params
681
- return ((i + add_key) & 0xFF) ^ xor_key
682
-
683
- @staticmethod
684
- def iter_params ():
685
- "return (ADD key1, XOR key2)"
686
- # the ADD key can be 1 to 255 (0 would be identity):
687
- for add_key in range(1,256):
688
- # the XOR key can be 1 to 255 (0 would be identity)
689
- for xor_key in range(1,256):
690
- yield (add_key, xor_key)
691
-
692
- #--- CUSTOM XOR BRUTE FORCE ---------------------------------------------------
693
-
694
- def xor_simple(a, b):
695
- out = ""
696
- for i, c in enumerate(a):
697
- out += chr(c ^ ord(b[i % len(b)]))
698
- return out
699
-
700
- def deobfuscate_simple(d, r, m):
701
- "Take mask and will create a key to unmask suspected data, then check if the xor'd data matches a regex pattern"
702
- import regex as re
703
- max_mask = m.lower()
704
- for i in range(1, len(max_mask)+1):
705
- t_mask = max_mask[:i]
706
- r_mask = xor_simple(d[:i], t_mask)
707
- de_enc = xor_simple(d, r_mask).encode()
708
- if re.match(r, de_enc):
709
- return de_enc.strip(), r_mask
710
- return None, None
711
-
712
- #--- TRANSFORM GROUPS ---------------------------------------------------------
713
-
714
- # Transforms level 1
715
- transform_classes1 = [
716
- #Transform_identity,
717
- Transform_XOR,
718
- Transform_ADD,
719
- Transform_ROL,
720
- ]
721
-
722
- # Transforms level 2
723
- transform_classes2 = [
724
- Transform_XOR_ROL,
725
- Transform_ADD_ROL,
726
- Transform_ROL_ADD,
727
- ]
728
-
729
- # Transforms level 3
730
- transform_classes3 = [
731
- Transform_XOR_ADD,
732
- Transform_ADD_XOR,
733
- Transform_XOR_INC,
734
- Transform_XOR_DEC,
735
- Transform_SUB_INC,
736
- Transform_XOR_Chained,
737
- Transform_XOR_RChained,
738
- Transform_XOR_INC_ROL,
739
- Transform_XOR_RChainedAll,
740
- ]
741
-
742
- # all transforms
743
- transform_classes_all = transform_classes1 + transform_classes2 + transform_classes3
744
-
745
-
746
- #--- PATTERNS -----------------------------------------------------------------
747
-
748
- #see balbuzard.patterns.py
749
-
750
- # === MAIN =====================================================================
751
- """
752
- 2016-10-20: Main Module modified for FrankenStrings AL service
753
- """
754
-
755
- def read_file(filename):
756
- """
757
- Open a file, read and return its data as a string.
758
- """
759
- f = open(filename, 'rb')
760
- raw_data = f.read()
761
- f.close()
762
- return raw_data
763
-
764
-
765
- def bbcrack(file_data, level=1):
766
-
767
- raw_data = file_data
768
- if level == 1 or level == 'small_string':
769
- transform_classes = transform_classes1
770
- elif level == 2:
771
- transform_classes = transform_classes1 + transform_classes2
772
- else:
773
- transform_classes = transform_classes_all
774
-
775
- results = []
776
- bbc = PatternMatch()
777
- bbcrack_patterns = bbc.bbcr(level=level)
778
-
779
- if level == 'small_string':
780
-
781
- bbz = Balbuzard(bbcrack_patterns)
782
-
783
- # Round 1
784
- for Transform_class in transform_classes:
785
- for params in Transform_class.iter_params():
786
- transform = Transform_class(params)
787
- data = transform.transform_string(raw_data)
788
- for pattern, matches in bbz.scan(data):
789
- for index, match in matches:
790
- regex = pattern.name.split("_", 1)[1]
791
- smatch = match
792
- if transform.shortname == "xor20":
793
- # for basic alpha characters, will essentially convert lower and uppercase.
794
- continue
795
- results.append((transform.shortname, regex, smatch))
796
- return results
797
-
798
- for pattern in bbz.list_patterns():
799
- pmask = pattern.name.split("_", 1)[0]
800
- sxor, smask = deobfuscate_simple(raw_data, pattern.pat, pmask)
801
- if sxor:
802
- results.append((smask, pattern.name.split("_", 1)[1], sxor))
803
- return results
804
-
805
- # Run bbcrack patterns against transforms
806
- bbz = Balbuzard(bbcrack_patterns)
807
-
808
- for Transform_class in transform_classes:
809
- for params in Transform_class.iter_params():
810
- transform = Transform_class(params)
811
- if transform.shortname == "xor20":
812
- # for basic alpha characters, will essentially convert lower and uppercase.
813
- continue
814
- data = transform.transform_string(raw_data)
815
- score = 0
816
- for pattern, matches in bbz.scan(data):
817
- for index, match in matches:
818
- regex = pattern.name
819
- smatch = match
820
- if regex == 'EXE_HEAD':
821
- if b'This program cannot be run' not in data:
822
- continue
823
- score = 100000
824
- results.append((transform.shortname, regex, index, score, data))
825
- continue
826
- score += len(match) * pattern.weight
827
- results.append((transform.shortname, regex, index, score, smatch[0:50]))
828
-
829
- return results
830
- # This was coded while listening to The Walkmen "Heaven". --Philippe Lagadec