2018-07-19 16:52:09 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*-coding:UTF-8 -*
|
|
|
|
"""
|
|
|
|
Decoder module
|
|
|
|
|
|
|
|
Dectect Binary and decode it
|
|
|
|
"""
|
2021-05-07 14:24:41 +02:00
|
|
|
|
|
|
|
##################################
|
|
|
|
# Import External packages
|
|
|
|
##################################
|
2018-07-19 16:52:09 +02:00
|
|
|
import os
|
|
|
|
import base64
|
|
|
|
from hashlib import sha1
|
2021-05-07 14:24:41 +02:00
|
|
|
import re
|
2021-06-02 14:42:23 +02:00
|
|
|
import sys
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-06-02 14:42:23 +02:00
|
|
|
sys.path.append(os.environ['AIL_BIN'])
|
2021-05-07 14:24:41 +02:00
|
|
|
##################################
|
|
|
|
# Import Project packages
|
|
|
|
##################################
|
2021-06-02 14:42:23 +02:00
|
|
|
from modules.abstract_module import AbstractModule
|
2022-08-19 16:53:31 +02:00
|
|
|
from lib.ConfigLoader import ConfigLoader
|
2023-01-09 16:03:06 +01:00
|
|
|
from lib.objects.Decodeds import Decoded
|
2023-05-04 16:35:56 +02:00
|
|
|
from trackers.Tracker_Term import Tracker_Term
|
|
|
|
from trackers.Tracker_Regex import Tracker_Regex
|
|
|
|
from trackers.Tracker_Yara import Tracker_Yara
|
2022-08-19 16:53:31 +02:00
|
|
|
|
|
|
|
config_loader = ConfigLoader()
|
2023-04-04 14:12:23 +02:00
|
|
|
hex_max_execution_time = config_loader.get_config_int("Decoder", "max_execution_time_hexadecimal")
|
|
|
|
binary_max_execution_time = config_loader.get_config_int("Decoder", "max_execution_time_binary")
|
|
|
|
base64_max_execution_time = config_loader.get_config_int("Decoder", "max_execution_time_base64")
|
2022-08-19 16:53:31 +02:00
|
|
|
config_loader = None
|
|
|
|
|
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
class Decoder(AbstractModule):
|
|
|
|
"""
|
|
|
|
Decoder module for AIL framework
|
|
|
|
"""
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
def hex_decoder(self, hexStr):
|
2023-01-09 16:03:06 +01:00
|
|
|
# hexStr = ''.join( hex_string.split(" ") )
|
2021-05-07 14:24:41 +02:00
|
|
|
return bytes(bytearray([int(hexStr[i:i+2], 16) for i in range(0, len(hexStr), 2)]))
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
def binary_decoder(self, binary_string):
|
|
|
|
return bytes(bytearray([int(binary_string[i:i+8], 2) for i in range(0, len(binary_string), 8)]))
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
def base64_decoder(self, base64_string):
|
|
|
|
return base64.b64decode(base64_string)
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
def __init__(self):
|
2021-05-07 14:43:25 +02:00
|
|
|
super(Decoder, self).__init__()
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2022-10-25 16:25:19 +02:00
|
|
|
regex_binary = r'[0-1]{40,}'
|
|
|
|
# regex_hex = r'(0[xX])?[A-Fa-f0-9]{40,}'
|
|
|
|
regex_hex = r'[A-Fa-f0-9]{40,}'
|
|
|
|
regex_base64 = r'(?:[A-Za-z0-9+/]{4}){2,}(?:[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=|[A-Za-z0-9+/][AQgw]==)'
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
cmp_regex_binary = re.compile(regex_binary)
|
|
|
|
cmp_regex_hex = re.compile(regex_hex)
|
|
|
|
cmp_regex_base64 = re.compile(regex_base64)
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
# map decoder function
|
2023-01-09 16:03:06 +01:00
|
|
|
self.decoder_function = {'binary': self.binary_decoder,
|
|
|
|
'hexadecimal': self.hex_decoder,
|
|
|
|
'base64': self.base64_decoder}
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
# list all decoder with regex,
|
2023-01-09 16:03:06 +01:00
|
|
|
decoder_binary = {'name': 'binary', 'regex': cmp_regex_binary,
|
|
|
|
'encoded_min_size': 300, 'max_execution_time': binary_max_execution_time}
|
|
|
|
decoder_hexadecimal = {'name': 'hexadecimal', 'regex': cmp_regex_hex,
|
|
|
|
'encoded_min_size': 300, 'max_execution_time': hex_max_execution_time}
|
|
|
|
decoder_base64 = {'name': 'base64', 'regex': cmp_regex_base64,
|
|
|
|
'encoded_min_size': 40, 'max_execution_time': base64_max_execution_time}
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2022-10-25 16:25:19 +02:00
|
|
|
self.decoder_order = [decoder_base64, decoder_binary, decoder_hexadecimal, decoder_base64]
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2022-10-25 16:25:19 +02:00
|
|
|
# Waiting time in seconds between to message processed
|
2021-05-07 14:24:41 +02:00
|
|
|
self.pending_seconds = 1
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2023-05-04 16:35:56 +02:00
|
|
|
self.tracker_term = Tracker_Term(queue=False)
|
|
|
|
self.tracker_regex = Tracker_Regex(queue=False)
|
|
|
|
self.tracker_yara = Tracker_Yara(queue=False)
|
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
# Send module state to logs
|
2023-05-12 15:29:53 +02:00
|
|
|
self.logger.info(f'Module {self.module_name} initialized')
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2021-05-07 14:24:41 +02:00
|
|
|
def compute(self, message):
|
2023-10-12 13:53:00 +02:00
|
|
|
content = self.obj.get_content()
|
|
|
|
date = self.obj.get_date()
|
2023-05-04 16:35:56 +02:00
|
|
|
new_decodeds = []
|
2018-07-19 16:52:09 +02:00
|
|
|
|
2023-01-09 16:03:06 +01:00
|
|
|
for decoder in self.decoder_order:
|
|
|
|
find = False
|
|
|
|
dname = decoder['name']
|
|
|
|
|
2023-10-12 13:53:00 +02:00
|
|
|
encodeds = self.regex_findall(decoder['regex'], self.obj.id, content)
|
|
|
|
# PERF remove encoded from obj content
|
2023-01-09 16:03:06 +01:00
|
|
|
for encoded in encodeds:
|
2021-05-07 14:24:41 +02:00
|
|
|
content = content.replace(encoded, '', 1)
|
2023-01-09 16:03:06 +01:00
|
|
|
encodeds = set(encodeds)
|
2021-05-07 14:24:41 +02:00
|
|
|
|
2023-01-09 16:03:06 +01:00
|
|
|
for encoded in encodeds:
|
|
|
|
if len(encoded) >= decoder['encoded_min_size']:
|
2023-05-04 16:35:56 +02:00
|
|
|
find = True
|
2023-01-09 16:03:06 +01:00
|
|
|
decoded_file = self.decoder_function[dname](encoded)
|
2021-05-07 14:24:41 +02:00
|
|
|
|
2023-01-09 16:03:06 +01:00
|
|
|
sha1_string = sha1(decoded_file).hexdigest()
|
|
|
|
decoded = Decoded(sha1_string)
|
2021-05-07 14:24:41 +02:00
|
|
|
|
2023-01-09 16:03:06 +01:00
|
|
|
if not decoded.exists():
|
|
|
|
mimetype = decoded.guess_mimetype(decoded_file)
|
|
|
|
if not mimetype:
|
2023-10-12 13:53:00 +02:00
|
|
|
print(sha1_string, self.obj.id)
|
|
|
|
raise Exception(f'Invalid mimetype: {decoded.id} {self.obj.id}')
|
2023-01-09 16:03:06 +01:00
|
|
|
decoded.save_file(decoded_file, mimetype)
|
2023-05-04 16:35:56 +02:00
|
|
|
new_decodeds.append(decoded.id)
|
2023-01-09 16:03:06 +01:00
|
|
|
else:
|
|
|
|
mimetype = decoded.get_mimetype()
|
2023-10-12 13:53:00 +02:00
|
|
|
decoded.add(date, self.obj, dname, mimetype=mimetype)
|
2021-05-07 14:24:41 +02:00
|
|
|
|
2023-05-12 15:29:53 +02:00
|
|
|
# new_decodeds.append(decoded.id)
|
2023-10-12 13:53:00 +02:00
|
|
|
self.logger.info(f'{self.obj.id} : {dname} - {decoded.id} - {mimetype}')
|
2022-10-25 16:25:19 +02:00
|
|
|
|
2023-01-09 16:03:06 +01:00
|
|
|
if find:
|
2023-10-12 13:53:00 +02:00
|
|
|
self.logger.info(f'{self.obj.id} - {dname}')
|
2021-06-02 14:42:23 +02:00
|
|
|
|
2023-01-09 16:03:06 +01:00
|
|
|
# Send to Tags
|
2023-06-22 15:38:04 +02:00
|
|
|
tag = f'infoleak:automatic-detection="{dname}"'
|
|
|
|
self.add_message_to_queue(message=tag, queue='Tags')
|
2023-01-09 16:03:06 +01:00
|
|
|
|
2023-05-04 16:35:56 +02:00
|
|
|
####################
|
|
|
|
# TRACKERS DECODED
|
|
|
|
for decoded_id in new_decodeds:
|
2023-10-12 13:53:00 +02:00
|
|
|
decoded = Decoded(decoded_id)
|
2023-05-12 15:29:53 +02:00
|
|
|
try:
|
2023-10-12 13:53:00 +02:00
|
|
|
self.tracker_term.compute_manual(decoded)
|
|
|
|
self.tracker_regex.compute_manual(decoded)
|
2023-05-12 15:29:53 +02:00
|
|
|
except UnicodeDecodeError:
|
|
|
|
pass
|
2023-10-12 13:53:00 +02:00
|
|
|
self.tracker_yara.compute_manual(decoded)
|
2023-05-04 16:35:56 +02:00
|
|
|
|
2023-01-09 16:03:06 +01:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2021-05-07 14:24:41 +02:00
|
|
|
module = Decoder()
|
|
|
|
module.run()
|