diff --git a/cme/config.py b/cme/config.py index eb168faf..a5ac6805 100644 --- a/cme/config.py +++ b/cme/config.py @@ -1,8 +1,14 @@ # coding=utf-8 import os +from os.path import join as path_join import configparser -from cme.paths import CME_PATH +from cme.paths import CME_PATH, DATA_PATH from cme.first_run import first_run_setup +from cme.logger import cme_logger +from ast import literal_eval + +cme_default_config = configparser.ConfigParser() +cme_default_config.read(path_join(DATA_PATH, "cme.conf")) cme_config = configparser.ConfigParser() cme_config.read(os.path.join(CME_PATH, "cme.conf")) @@ -11,12 +17,30 @@ if "CME" not in cme_config.sections(): first_run_setup() cme_config.read(os.path.join(CME_PATH, "cme.conf")) +# Check if there are any missing options in the config file +for section in cme_default_config.sections(): + for option in cme_default_config.options(section): + if not cme_config.has_option(section, option): + cme_logger.display(f"Adding missing option '{option}' in config section '{section}' to cme.conf") + cme_config.set(section, option, cme_default_config.get(section, option)) + + with open(path_join(CME_PATH, "cme.conf"), "w") as config_file: + cme_config.write(config_file) + +#!!! THESE OPTIONS HAVE TO EXIST IN THE DEFAULT CONFIG FILE !!! cme_workspace = cme_config.get("CME", "workspace", fallback="default") -config_log = cme_config.getboolean("CME", "log_mode", fallback=False) -ignore_opsec = cme_config.getboolean("CME", "ignore_opsec", fallback=False) pwned_label = cme_config.get("CME", "pwn3d_label", fallback="Pwn3d!") audit_mode = cme_config.get("CME", "audit_mode", fallback=False) reveal_chars_of_pwd = int(cme_config.get("CME", "reveal_chars_of_pwd", fallback=0)) +config_log = cme_config.getboolean("CME", "log_mode", fallback=False) +ignore_opsec = cme_config.getboolean("CME", "ignore_opsec", fallback=False) +host_info_colors = literal_eval(cme_config.get("CME", "host_info_colors", fallback=["green", "red", "yellow", "cyan"])) + + +if len(host_info_colors) != 4: + cme_logger.error("Config option host_info_colors must have 4 values! Using default values.") + host_info_colors = cme_default_config.get("CME", "host_info_colors") + # this should probably be put somewhere else, but if it's in the config helpers, there is a circular import def process_secret(text): diff --git a/cme/data/cme.conf b/cme/data/cme.conf index 264f0b72..5c4062a0 100755 --- a/cme/data/cme.conf +++ b/cme/data/cme.conf @@ -2,10 +2,11 @@ workspace = default last_used_db = smb pwn3d_label = Pwn3d! -audit_mode = +audit_mode = reveal_chars_of_pwd = 0 log_mode = False ignore_opsec = True +host_info_colors = ["green", "red", "yellow", "cyan"] [BloodHound] bh_enabled = False diff --git a/cme/first_run.py b/cme/first_run.py index 3a6267a7..a55f0746 100755 --- a/cme/first_run.py +++ b/cme/first_run.py @@ -5,8 +5,6 @@ from os import mkdir from os.path import exists from os.path import join as path_join import shutil -import configparser -from configparser import NoSectionError, NoOptionError from cme.paths import CME_PATH, CONFIG_PATH, TMP_PATH, DATA_PATH from cme.cmedb import initialize_db from cme.logger import cme_logger @@ -40,20 +38,6 @@ def first_run_setup(logger=cme_logger): logger.display("Copying default configuration file") default_path = path_join(DATA_PATH, "cme.conf") shutil.copy(default_path, CME_PATH) - else: - # This is just a quick check to make sure the config file isn't the old 3.x format - try: - config = configparser.ConfigParser() - config.read(CONFIG_PATH) - config.get("CME", "workspace") - config.get("CME", "pwn3d_label") - config.get("CME", "audit_mode") - config.get("BloodHound", "bh_enabled") - config.get("CME", "log_mode") - except (NoSectionError, NoOptionError): - logger.display("Old configuration file detected, replacing with new version") - default_path = path_join(DATA_PATH, "cme.conf") - shutil.copy(default_path, CME_PATH) # if not exists(CERT_PATH): # logger.display('Generating SSL certificate') diff --git a/cme/protocols/ldap.py b/cme/protocols/ldap.py index 49471a6a..c7826a0f 100644 --- a/cme/protocols/ldap.py +++ b/cme/protocols/ldap.py @@ -32,7 +32,7 @@ from impacket.ldap import ldapasn1 as ldapasn1_impacket from impacket.smb import SMB_DIALECT from impacket.smbconnection import SMBConnection, SessionError -from cme.config import process_secret +from cme.config import process_secret, host_info_colors from cme.connection import * from cme.helpers.bloodhound import add_user_bh from cme.logger import CMEAdapter, cme_logger @@ -305,8 +305,8 @@ class ldap(connection): else: self.logger.extra["protocol"] = "SMB" if not self.no_ntlm else "LDAP" self.logger.extra["port"] = "445" if not self.no_ntlm else "389" - signing = colored(f"signing:{self.signing}", 'green') if self.signing else colored(f"signing:{self.signing}", 'red') - smbv1 = colored(f"SMBv1:{self.smbv1}", 'yellow') if self.smbv1 else colored(f"SMBv1:{self.smbv1}", 'blue') + signing = colored(f"signing:{self.signing}", host_info_colors[0], attrs=['bold']) if self.signing else colored(f"signing:{self.signing}", host_info_colors[1], attrs=['bold']) + smbv1 = colored(f"SMBv1:{self.smbv1}", host_info_colors[2], attrs=['bold']) if self.smbv1 else colored(f"SMBv1:{self.smbv1}", host_info_colors[3], attrs=['bold']) self.logger.display(f"{self.server_os}{f' x{self.os_arch}' if self.os_arch else ''} (name:{self.hostname}) (domain:{self.domain}) ({signing}) ({smbv1})") self.logger.extra["protocol"] = "LDAP" # self.logger.display(self.endpoint) diff --git a/cme/protocols/rdp.py b/cme/protocols/rdp.py index 6a979b31..f5083ef1 100644 --- a/cme/protocols/rdp.py +++ b/cme/protocols/rdp.py @@ -12,6 +12,7 @@ from impacket.krb5.ccache import CCache from cme.connection import * from cme.helpers.bloodhound import add_user_bh from cme.logger import CMEAdapter +from cme.config import host_info_colors from aardwolf.connection import RDPConnection from aardwolf.commons.queuedata.constants import VIDEO_FORMAT @@ -103,7 +104,7 @@ class rdp(connection): ) def print_host_info(self): - nla = colored(f"nla:{self.nla}", 'blue') if self.nla else colored(f"nla:{self.nla}", 'yellow') + nla = colored(f"nla:{self.nla}", host_info_colors[3], attrs=['bold']) if self.nla else colored(f"nla:{self.nla}", host_info_colors[2], attrs=['bold']) if self.domain is None: self.logger.display("Probably old, doesn't not support HYBRID or HYBRID_EX" f" ({nla})") else: diff --git a/cme/protocols/smb.py b/cme/protocols/smb.py index 79338923..0e689669 100755 --- a/cme/protocols/smb.py +++ b/cme/protocols/smb.py @@ -27,7 +27,7 @@ from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED from impacket.krb5.kerberosv5 import SessionKeyDecryptionError from impacket.krb5.types import KerberosException -from cme.config import process_secret +from cme.config import process_secret, host_info_colors from cme.connection import * from cme.logger import CMEAdapter from cme.protocols.smb.firefox import FirefoxTriage @@ -361,8 +361,8 @@ class smb(connection): return True def print_host_info(self): - signing = colored(f"signing:{self.signing}", 'green') if self.signing else colored(f"signing:{self.signing}", 'red') - smbv1 = colored(f"SMBv1:{self.smbv1}", 'yellow') if self.smbv1 else colored(f"SMBv1:{self.smbv1}", 'blue') + signing = colored(f"signing:{self.signing}", host_info_colors[0], attrs=['bold']) if self.signing else colored(f"signing:{self.signing}", host_info_colors[1], attrs=['bold']) + smbv1 = colored(f"SMBv1:{self.smbv1}", host_info_colors[2], attrs=['bold']) if self.smbv1 else colored(f"SMBv1:{self.smbv1}", host_info_colors[3], attrs=['bold']) self.logger.display(f"{self.server_os}{f' x{self.os_arch}' if self.os_arch else ''} (name:{self.hostname}) (domain:{self.domain}) ({signing}) ({smbv1})") if self.args.laps: return self.laps_search(self.args.username, self.args.password, self.args.hash, self.domain)