Added enum_avproducts module, fixed module logging

- Modules now do not print output of commands called from their protocol
- Added the enum_avproducts module
- Fixed the mimikatz_enum_vault_creds to not display creds with invalid
passwords
- Added an export command to the SMB protocols DB navigator (as
suggested by @hatredshapedlikeaman)
- Misc output fixes
This commit is contained in:
byt3bl33d3r
2017-05-07 21:16:18 -06:00
parent 04907ceb29
commit 4ff034f366
10 changed files with 108 additions and 4 deletions
+1 -1
View File
@@ -102,7 +102,7 @@ class CMEDatabaseNavigator(cmd.Cmd):
self.write_configfile()
self.workspace = line
self.prompt = 'cmedb ({}) >'.format(line)
self.prompt = 'cmedb ({}) > '.format(line)
def do_exit(self, line):
sys.exit(0)
+2 -2
View File
@@ -146,12 +146,12 @@ def main():
exit(1)
if getattr(module, 'opsec_safe') is False:
ans = raw_input(highlight('[!] Module is not opsec safe, are you sure you want to run this? [Y/n]', 'red'))
ans = raw_input(highlight('[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ', 'red'))
if ans.lower() not in ['y', 'yes', '']:
sys.exit(1)
if getattr(module, 'multiple_hosts') is False and len(targets) > 1:
ans = raw_input(highlight("[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n]", 'red'))
ans = raw_input(highlight("[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ", 'red'))
if ans.lower() not in ['y', 'yes', '']:
sys.exit(1)
+11
View File
@@ -1,6 +1,7 @@
import random
import string
import re
import inspect
def gen_random_string(length=10):
return ''.join(random.sample(string.ascii_letters, int(length)))
@@ -11,3 +12,13 @@ def validate_ntlm(data):
return True
else:
return False
def called_from_cmd_args():
for stack in inspect.stack():
if stack[3] == 'print_host_info':
return True
if stack[3] == 'plaintext_login' or stack[3] == 'hash_login':
return True
if stack[3] == 'call_cmd_args':
return True
return False
+19
View File
@@ -1,6 +1,7 @@
import logging
import sys
import re
from cme.helpers.misc import called_from_cmd_args
from termcolor import colored
from datetime import datetime
@@ -59,6 +60,12 @@ class CMEAdapter(logging.LoggerAdapter):
msg), kwargs
def info(self, msg, *args, **kwargs):
try:
if 'protocol' in self.extra.keys() and not called_from_cmd_args():
return
except AttributeError:
pass
msg, kwargs = self.process(u'{} {}'.format(colored("[*]", 'blue', attrs=['bold']), msg), kwargs)
self.logger.info(msg, *args, **kwargs)
@@ -70,10 +77,22 @@ class CMEAdapter(logging.LoggerAdapter):
pass
def success(self, msg, *args, **kwargs):
try:
if 'protocol' in self.extra.keys() and not called_from_cmd_args():
return
except AttributeError:
pass
msg, kwargs = self.process(u'{} {}'.format(colored("[+]", 'green', attrs=['bold']), msg), kwargs)
self.logger.info(msg, *args, **kwargs)
def highlight(self, msg, *args, **kwargs):
try:
if 'protocol' in self.extra.keys() and not called_from_cmd_args():
return
except AttributeError:
pass
msg, kwargs = self.process(u'{}'.format(colored(msg, 'yellow', attrs=['bold'])), kwargs)
self.logger.info(msg, *args, **kwargs)
+30
View File
@@ -0,0 +1,30 @@
class CMEModule:
'''
Uses WMI to gather information on all endpoint protection solutions installed on the the remote host(s)
Module by @byt3bl33d3r
'''
name = 'enum_avproducts'
description = 'Gathers information on all endpoint protection solutions installed on the the remote host(s) via WMI'
supported_protocols = ['smb']
opsec_safe= True
multiple_hosts = True
def options(self, context, module_options):
pass
def on_admin_login(self, context, connection):
output = connection.wmi('Select * From AntiSpywareProduct', 'root\\SecurityCenter2')
if output:
context.log.success('Found Anti-Spyware product:')
for entry in output:
for k,v in entry.iteritems():
context.log.highlight('{} => {}'.format(k,v['value']))
output = connection.wmi('Select * from AntiVirusProduct', 'root\\SecurityCenter2')
if output:
context.log.success('Found Anti-Virus product:')
for entry in output:
for k,v in entry.iteritems():
context.log.highlight('{} => {}'.format(k,v['value']))
+5
View File
@@ -22,9 +22,14 @@ class CMEModule:
for share in shares:
if share['name'] == 'SYSVOL' and 'READ' in share['access']:
context.log.success('Found SYSVOL share')
context.log.info('Searching for Registry.xml')
paths = connection.spider('SYSVOL', pattern=['Registry.xml'])
for path in paths:
context.log.info('Found {}'.format(path))
buf = StringIO()
connection.conn.getFile('SYSVOL', path, buf.write)
xml = ET.fromstring(buf.getvalue())
+5
View File
@@ -25,9 +25,14 @@ class CMEModule:
for share in shares:
if share['name'] == 'SYSVOL' and 'READ' in share['access']:
context.log.success('Found SYSVOL share')
context.log.info('Searching for potential XML files containing passwords')
paths = connection.spider('SYSVOL', pattern=['Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml'])
for path in paths:
context.log.info('Found {}'.format(path))
buf = StringIO()
connection.conn.getFile('SYSVOL', path, buf.write)
xml = ET.fromstring(buf.getvalue())
+2 -1
View File
@@ -76,7 +76,8 @@ class CMEModule:
user = buf[i+1].split(':', 1)[1].strip().replace('[STRING]', '')
passw = buf[i+4].split(':', 1)[1].strip().replace('[STRING]', '')
creds.append({'url': url, 'user': user, 'passw': passw})
if '[BYTE*]' not in passw:
creds.append({'url': url, 'user': user, 'passw': passw})
i += 1
except:
+1
View File
@@ -49,6 +49,7 @@ class CMEModule:
shares = connection.shares()
for share in shares:
if 'WRITE' in share['access'] and share['name'] not in ['C$', 'ADMIN$']:
context.log.success('Found writable share: {}'.format(share['name']))
if not self.cleanup:
with open(self.lnk_path, 'rb') as lnk:
try:
+32
View File
@@ -1,4 +1,5 @@
import requests
import os
from requests import ConnectionError
#The following disables the InsecureRequests warning and the 'Starting new HTTPS connection' log message
from requests.packages.urllib3.exceptions import InsecureRequestWarning
@@ -26,6 +27,28 @@ class navigator(cmd.Cmd):
def do_exit(self, line):
exit(0)
def do_export(self, line):
if not line:
return
line = line.split()
if len(line) < 3:
return
if line[0].lower() == 'creds':
if line[1].lower() == 'plaintext':
creds = self.db.get_credentials(credtype="plaintext")
elif line[1].lower()== 'hashes':
creds = self.db.get_credentials(credtype="hash")
else:
return
with open(os.path.expanduser(line[2]), 'w') as export_file:
for cred in creds:
_,_,_,password,_,_ = cred
export_file.write('{}\n'.format(password))
def do_import(self, line):
if not line:
@@ -437,3 +460,12 @@ class navigator(cmd.Cmd):
mline = line.partition(' ')[2]
offs = len(mline) - len(text)
return [s[offs:] for s in commands if s.startswith(mline)]
def complete_export(self, text, line, begidx, endidx):
"Tab-complete 'creds' commands."
commands = [ "creds"]
mline = line.partition(' ')[2]
offs = len(mline) - len(text)
return [s[offs:] for s in commands if s.startswith(mline)]