clean and fix imports
parent
13f4ebbb2b
commit
fcfebc21e2
|
@ -1,7 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import os
|
|
||||||
from os import mkdir
|
from os import mkdir
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
from os.path import join as path_join
|
from os.path import join as path_join
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import json
|
||||||
|
|
||||||
from impacket.ldap import ldapasn1 as ldapasn1_impacket
|
from impacket.ldap import ldapasn1 as ldapasn1_impacket
|
||||||
|
|
||||||
|
@ -60,7 +61,8 @@ class CMEModule:
|
||||||
}
|
}
|
||||||
if "mslaps-encryptedpassword" in values:
|
if "mslaps-encryptedpassword" in values:
|
||||||
context.log.fail(
|
context.log.fail(
|
||||||
"LAPS password is encrypted and currently CrackMapExec doesn't support the decryption..."
|
"LAPS password is encrypted and currently CrackMapExec doesn't"
|
||||||
|
" support the decryption..."
|
||||||
)
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -73,7 +75,8 @@ class CMEModule:
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
context.log.fail(
|
context.log.fail(
|
||||||
"No result found with attribute ms-MCS-AdmPwd or msLAPS-Password"
|
"No result found with attribute ms-MCS-AdmPwd or"
|
||||||
|
" msLAPS-Password"
|
||||||
)
|
)
|
||||||
|
|
||||||
laps_computers = sorted(laps_computers, key=lambda x: x[0])
|
laps_computers = sorted(laps_computers, key=lambda x: x[0])
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import socket
|
||||||
|
|
||||||
import ldap3
|
import ldap3
|
||||||
import ssl
|
import ssl
|
||||||
|
@ -75,7 +76,8 @@ class CMEModule:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
context.log.fail("\n [!] " + dcTarget + " -", str(e))
|
context.log.fail("\n [!] " + dcTarget + " -", str(e))
|
||||||
context.log.fail(
|
context.log.fail(
|
||||||
" * Ensure DNS is resolving properly, and that you can reach LDAPS on this host"
|
" * Ensure DNS is resolving properly, and that you can reach"
|
||||||
|
" LDAPS on this host"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Conduct a bind to LDAPS with channel binding supported
|
# Conduct a bind to LDAPS with channel binding supported
|
||||||
|
|
|
@ -2,19 +2,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from impacket import system_errors, version
|
from impacket import system_errors
|
||||||
from impacket.dcerpc.v5.rpcrt import DCERPCException
|
from impacket.dcerpc.v5.rpcrt import DCERPCException
|
||||||
from impacket.structure import Structure
|
from impacket.structure import Structure
|
||||||
from impacket.examples import logger
|
|
||||||
from impacket.examples.utils import parse_target
|
|
||||||
from impacket.dcerpc.v5 import transport, rprn
|
from impacket.dcerpc.v5 import transport, rprn
|
||||||
from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRSTRUCT, NDRUNION, NULL
|
from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRSTRUCT, NDRUNION, NULL
|
||||||
from impacket.dcerpc.v5.dtypes import DWORD, LPWSTR, ULONG, WSTR
|
from impacket.dcerpc.v5.dtypes import DWORD, LPWSTR, ULONG, WSTR
|
||||||
from impacket.dcerpc.v5.rprn import (
|
from impacket.dcerpc.v5.rprn import checkNullString, STRING_HANDLE, PBYTE_ARRAY
|
||||||
checkNullString,
|
|
||||||
STRING_HANDLE,
|
|
||||||
PBYTE_ARRAY,
|
|
||||||
)
|
|
||||||
|
|
||||||
KNOWN_PROTOCOLS = {
|
KNOWN_PROTOCOLS = {
|
||||||
135: {"bindstr": r"ncacn_ip_tcp:%s[135]"},
|
135: {"bindstr": r"ncacn_ip_tcp:%s[135]"},
|
||||||
|
@ -232,18 +226,12 @@ class DRIVER_INFO_2_ARRAY(Structure):
|
||||||
|
|
||||||
class DRIVER_INFO_UNION(NDRUNION):
|
class DRIVER_INFO_UNION(NDRUNION):
|
||||||
commonHdr = (("tag", ULONG),)
|
commonHdr = (("tag", ULONG),)
|
||||||
union = {
|
union = {1: ("pNotUsed", PDRIVER_INFO_1), 2: ("Level2", PDRIVER_INFO_2)}
|
||||||
1: ("pNotUsed", PDRIVER_INFO_1),
|
|
||||||
2: ("Level2", PDRIVER_INFO_2),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# MS-RPRN - 3.1.4.1.8.3
|
# MS-RPRN - 3.1.4.1.8.3
|
||||||
class DRIVER_CONTAINER(NDRSTRUCT):
|
class DRIVER_CONTAINER(NDRSTRUCT):
|
||||||
structure = (
|
structure = (("Level", DWORD), ("DriverInfo", DRIVER_INFO_UNION))
|
||||||
("Level", DWORD),
|
|
||||||
("DriverInfo", DRIVER_INFO_UNION),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
|
@ -6,9 +6,13 @@
|
||||||
# v0.4
|
# v0.4
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
from pypykatz.pypykatz import pypykatz
|
from pypykatz.pypykatz import pypykatz
|
||||||
|
|
||||||
|
from cme.helpers.bloodhound import add_user_bh
|
||||||
|
|
||||||
|
|
||||||
class CMEModule:
|
class CMEModule:
|
||||||
name = "procdump"
|
name = "procdump"
|
||||||
|
@ -69,7 +73,7 @@ class CMEModule:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
context.log.fail("Error writing file to share {}: {}".format(share, e))
|
context.log.fail(f"Error writing file to share {self.share}: {e}")
|
||||||
|
|
||||||
# get pid lsass
|
# get pid lsass
|
||||||
command = 'tasklist /v /fo csv | findstr /i "lsass"'
|
command = 'tasklist /v /fo csv | findstr /i "lsass"'
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# Credit to https://github.com/dirkjanm/adidnsdump @_dirkjan
|
# Credit to https://github.com/dirkjanm/adidnsdump @_dirkjan
|
||||||
# module by @mpgn_x64
|
# module by @mpgn_x64
|
||||||
|
|
||||||
|
from os.path import expanduser
|
||||||
import codecs
|
import codecs
|
||||||
import socket
|
import socket
|
||||||
from builtins import str
|
from builtins import str
|
||||||
|
@ -40,8 +41,9 @@ def get_dns_resolver(server, context):
|
||||||
dnsresolver.nameservers = [server]
|
dnsresolver.nameservers = [server]
|
||||||
except socket.error:
|
except socket.error:
|
||||||
context.info(
|
context.info(
|
||||||
"Using System DNS to resolve unknown entries. Make sure resolving your target domain works here or specify an IP"
|
"Using System DNS to resolve unknown entries. Make sure resolving your"
|
||||||
" as target host to use that server for queries"
|
" target domain works here or specify an IP as target host to use that"
|
||||||
|
" server for queries"
|
||||||
)
|
)
|
||||||
return dnsresolver
|
return dnsresolver
|
||||||
|
|
||||||
|
@ -137,7 +139,8 @@ class CMEModule:
|
||||||
except ldap.LDAPSearchError as e:
|
except ldap.LDAPSearchError as e:
|
||||||
if e.getErrorString().find("sizeLimitExceeded") >= 0:
|
if e.getErrorString().find("sizeLimitExceeded") >= 0:
|
||||||
context.log.debug(
|
context.log.debug(
|
||||||
"sizeLimitExceeded exception caught, giving up and processing the data received"
|
"sizeLimitExceeded exception caught, giving up and processing the"
|
||||||
|
" data received"
|
||||||
)
|
)
|
||||||
# We reached the sizeLimit, process the answers we have already and that's it. Until we implement
|
# We reached the sizeLimit, process the answers we have already and that's it. Until we implement
|
||||||
# paged queries
|
# paged queries
|
||||||
|
@ -205,7 +208,7 @@ class CMEModule:
|
||||||
)
|
)
|
||||||
|
|
||||||
context.log.highlight("Found %d records" % len(outdata))
|
context.log.highlight("Found %d records" % len(outdata))
|
||||||
path = os.path.expanduser(
|
path = expanduser(
|
||||||
"~/.cme/logs/{}_network_{}.log".format(
|
"~/.cme/logs/{}_network_{}.log".format(
|
||||||
connection.domain, datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
connection.domain, datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
||||||
)
|
)
|
||||||
|
@ -225,7 +228,8 @@ class CMEModule:
|
||||||
context.log.success("Dumped {} records to {}".format(len(outdata), path))
|
context.log.success("Dumped {} records to {}".format(len(outdata), path))
|
||||||
if not self.showall and not self.showhosts:
|
if not self.showall and not self.showhosts:
|
||||||
context.log.display(
|
context.log.display(
|
||||||
"To extract CIDR from the {} ip, run the following command: cat your_file | mapcidr -aa -silent | mapcidr -a -silent".format(
|
"To extract CIDR from the {} ip, run the following command: cat"
|
||||||
|
" your_file | mapcidr -aa -silent | mapcidr -a -silent".format(
|
||||||
len(outdata)
|
len(outdata)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -130,13 +130,10 @@ class KerberosAttacks:
|
||||||
).decode(),
|
).decode(),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logging.error(
|
cme_logger.error(
|
||||||
"Skipping %s/%s due to incompatible e-type %d"
|
"Skipping"
|
||||||
% (
|
f" {decodedTGS['ticket']['sname']['name-string'][0]}/{decodedTGS['ticket']['sname']['name-string'][1]} due"
|
||||||
decodedTGS["ticket"]["sname"]["name-string"][0],
|
f" to incompatible e-type {decodedTGS['ticket']['enc-part']['etype']:d}"
|
||||||
decodedTGS["ticket"]["sname"]["name-string"][1],
|
|
||||||
decodedTGS["ticket"]["enc-part"]["etype"],
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
|
@ -8,7 +8,6 @@ from os import getenv
|
||||||
from impacket.krb5.ccache import CCache
|
from impacket.krb5.ccache import CCache
|
||||||
from cme.connection import *
|
from cme.connection import *
|
||||||
from cme.helpers.bloodhound import add_user_bh
|
from cme.helpers.bloodhound import add_user_bh
|
||||||
from cme.helpers.logger import highlight
|
|
||||||
from cme.logger import CMEAdapter
|
from cme.logger import CMEAdapter
|
||||||
from aardwolf.connection import RDPConnection
|
from aardwolf.connection import RDPConnection
|
||||||
from aardwolf.commons.queuedata.constants import VIDEO_FORMAT
|
from aardwolf.commons.queuedata.constants import VIDEO_FORMAT
|
||||||
|
@ -96,7 +95,10 @@ class rdp(connection):
|
||||||
rdp_parser.add_argument(
|
rdp_parser.add_argument(
|
||||||
"--no-bruteforce",
|
"--no-bruteforce",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="No spray when using file for username and password (user1 => password1, user2 => password2",
|
help=(
|
||||||
|
"No spray when using file for username and password (user1 =>"
|
||||||
|
" password1, user2 => password2"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
rdp_parser.add_argument(
|
rdp_parser.add_argument(
|
||||||
"--continue-on-success",
|
"--continue-on-success",
|
||||||
|
@ -175,11 +177,13 @@ class rdp(connection):
|
||||||
def print_host_info(self):
|
def print_host_info(self):
|
||||||
if self.domain is None:
|
if self.domain is None:
|
||||||
self.logger.display(
|
self.logger.display(
|
||||||
f"Probably old, doesn't not support HYBRID or HYBRID_EX (nla:{self.nla})"
|
"Probably old, doesn't not support HYBRID or HYBRID_EX"
|
||||||
|
f" (nla:{self.nla})"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.logger.display(
|
self.logger.display(
|
||||||
f"{self.server_os} (name:{self.hostname}) (domain:{self.domain}) (nla:{self.nla})"
|
f"{self.server_os} (name:{self.hostname}) (domain:{self.domain})"
|
||||||
|
f" (nla:{self.nla})"
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -340,6 +344,7 @@ class rdp(connection):
|
||||||
"{}\\{}{} {}".format(
|
"{}\\{}{} {}".format(
|
||||||
domain,
|
domain,
|
||||||
username,
|
username,
|
||||||
|
(
|
||||||
# Show what was used between cleartext, nthash, aesKey and ccache
|
# Show what was used between cleartext, nthash, aesKey and ccache
|
||||||
" from ccache"
|
" from ccache"
|
||||||
if useCache
|
if useCache
|
||||||
|
@ -348,6 +353,7 @@ class rdp(connection):
|
||||||
kerb_pass
|
kerb_pass
|
||||||
if not self.config.get("CME", "audit_mode")
|
if not self.config.get("CME", "audit_mode")
|
||||||
else self.config.get("CME", "audit_mode") * 8
|
else self.config.get("CME", "audit_mode") * 8
|
||||||
|
)
|
||||||
),
|
),
|
||||||
self.mark_pwned(),
|
self.mark_pwned(),
|
||||||
)
|
)
|
||||||
|
@ -364,13 +370,17 @@ class rdp(connection):
|
||||||
if word in str(e):
|
if word in str(e):
|
||||||
reason = self.rdp_error_status[word]
|
reason = self.rdp_error_status[word]
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
f"{domain}\\{username}{' from ccache' if useCache else ':%s' % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode') * 8)} {f'({reason})' if reason else str(e)}",
|
(
|
||||||
color="magenta"
|
f"{domain}\\{username}{' from ccache' if useCache else ':%s' % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode') * 8)} {f'({reason})' if reason else str(e)}"
|
||||||
|
),
|
||||||
|
color=(
|
||||||
|
"magenta"
|
||||||
if (
|
if (
|
||||||
(reason or "CredSSP" in str(e))
|
(reason or "CredSSP" in str(e))
|
||||||
and reason != "KDC_ERR_C_PRINCIPAL_UNKNOWN"
|
and reason != "KDC_ERR_C_PRINCIPAL_UNKNOWN"
|
||||||
)
|
)
|
||||||
else "red",
|
else "red"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
elif "Authentication failed!" in str(e):
|
elif "Authentication failed!" in str(e):
|
||||||
self.logger.success(
|
self.logger.success(
|
||||||
|
@ -386,13 +396,17 @@ class rdp(connection):
|
||||||
if "cannot unpack non-iterable NoneType object" == str(e):
|
if "cannot unpack non-iterable NoneType object" == str(e):
|
||||||
reason = "User valid but cannot connect"
|
reason = "User valid but cannot connect"
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
f"{domain}\\{username}{' from ccache' if useCache else ':%s' % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode') * 8)} {f'({reason})' if reason else ''}",
|
(
|
||||||
color="magenta"
|
f"{domain}\\{username}{' from ccache' if useCache else ':%s' % (kerb_pass if not self.config.get('CME', 'audit_mode') else self.config.get('CME', 'audit_mode') * 8)} {f'({reason})' if reason else ''}"
|
||||||
|
),
|
||||||
|
color=(
|
||||||
|
"magenta"
|
||||||
if (
|
if (
|
||||||
(reason or "CredSSP" in str(e))
|
(reason or "CredSSP" in str(e))
|
||||||
and reason != "STATUS_LOGON_FAILURE"
|
and reason != "STATUS_LOGON_FAILURE"
|
||||||
)
|
)
|
||||||
else "red",
|
else "red"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -428,13 +442,17 @@ class rdp(connection):
|
||||||
if "cannot unpack non-iterable NoneType object" == str(e):
|
if "cannot unpack non-iterable NoneType object" == str(e):
|
||||||
reason = "User valid but cannot connect"
|
reason = "User valid but cannot connect"
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
f"{domain}\\{username}:{password} {f'({reason})' if reason else ''}",
|
(
|
||||||
color="magenta"
|
f"{domain}\\{username}:{password} {f'({reason})' if reason else ''}"
|
||||||
|
),
|
||||||
|
color=(
|
||||||
|
"magenta"
|
||||||
if (
|
if (
|
||||||
(reason or "CredSSP" in str(e))
|
(reason or "CredSSP" in str(e))
|
||||||
and reason != "STATUS_LOGON_FAILURE"
|
and reason != "STATUS_LOGON_FAILURE"
|
||||||
)
|
)
|
||||||
else "red",
|
else "red"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -473,13 +491,17 @@ class rdp(connection):
|
||||||
reason = "User valid but cannot connect"
|
reason = "User valid but cannot connect"
|
||||||
|
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
f"{domain}\\{username}:{ntlm_hash} {f'({reason})' if reason else ''}",
|
(
|
||||||
color="magenta"
|
f"{domain}\\{username}:{ntlm_hash} {f'({reason})' if reason else ''}"
|
||||||
|
),
|
||||||
|
color=(
|
||||||
|
"magenta"
|
||||||
if (
|
if (
|
||||||
(reason or "CredSSP" in str(e))
|
(reason or "CredSSP" in str(e))
|
||||||
and reason != "STATUS_LOGON_FAILURE"
|
and reason != "STATUS_LOGON_FAILURE"
|
||||||
)
|
)
|
||||||
else "red",
|
else "red"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
# Code refactored and added to by @mjhallenbeck (Marshall-Hallenbeck on GitHub)
|
# Code refactored and added to by @mjhallenbeck (Marshall-Hallenbeck on GitHub)
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from impacket.dcerpc.v5 import transport, lsat, lsad, samr
|
from impacket.dcerpc.v5 import transport, lsat, lsad, samr
|
||||||
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
|
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
|
||||||
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
|
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
|
||||||
|
from impacket.nmb import NetBIOSError
|
||||||
|
from impacket.smbconnection import SessionError
|
||||||
from cme.logger import cme_logger
|
from cme.logger import cme_logger
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,10 +152,10 @@ class SAMRQuery:
|
||||||
dce = rpc_transport.get_dce_rpc()
|
dce = rpc_transport.get_dce_rpc()
|
||||||
dce.connect()
|
dce.connect()
|
||||||
dce.bind(samr.MSRPC_UUID_SAMR)
|
dce.bind(samr.MSRPC_UUID_SAMR)
|
||||||
except impacket.nmb.NetBIOSError as e:
|
except NetBIOSError as e:
|
||||||
logging.error(f"NetBIOSError on Connection: {e}")
|
logging.error(f"NetBIOSError on Connection: {e}")
|
||||||
return
|
return
|
||||||
except impacket.smbconnection.SessionError as e:
|
except SessionError as e:
|
||||||
logging.error(f"SessionError on Connection: {e}")
|
logging.error(f"SessionError on Connection: {e}")
|
||||||
return
|
return
|
||||||
return dce
|
return dce
|
||||||
|
@ -232,6 +234,7 @@ class LSAQuery:
|
||||||
self.__kerberos = kerberos
|
self.__kerberos = kerberos
|
||||||
self.dce = self.get_dce()
|
self.dce = self.get_dce()
|
||||||
self.policy_handle = self.get_policy_handle()
|
self.policy_handle = self.get_policy_handle()
|
||||||
|
self.logger = cme_logger
|
||||||
|
|
||||||
def get_transport(self):
|
def get_transport(self):
|
||||||
string_binding = f"ncacn_np:{self.__remote_name}[\\pipe\\lsarpc]"
|
string_binding = f"ncacn_np:{self.__remote_name}[\\pipe\\lsarpc]"
|
||||||
|
@ -260,7 +263,7 @@ class LSAQuery:
|
||||||
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
|
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
|
||||||
dce.connect()
|
dce.connect()
|
||||||
dce.bind(lsat.MSRPC_UUID_LSAT)
|
dce.bind(lsat.MSRPC_UUID_LSAT)
|
||||||
except impacket.nmb.NetBIOSError as e:
|
except NetBIOSError as e:
|
||||||
self.logger.fail(f"NetBIOSError on Connection: {e}")
|
self.logger.fail(f"NetBIOSError on Connection: {e}")
|
||||||
return None
|
return None
|
||||||
return dce
|
return dce
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import sys
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
import paramiko
|
import paramiko
|
||||||
|
@ -32,12 +31,18 @@ class ssh(connection):
|
||||||
ssh_parser.add_argument(
|
ssh_parser.add_argument(
|
||||||
"--no-bruteforce",
|
"--no-bruteforce",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="No spray when using file for username and password (user1 => password1, user2 => password2",
|
help=(
|
||||||
|
"No spray when using file for username and password (user1 =>"
|
||||||
|
" password1, user2 => password2"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
ssh_parser.add_argument(
|
ssh_parser.add_argument(
|
||||||
"--key-file",
|
"--key-file",
|
||||||
type=str,
|
type=str,
|
||||||
help="Authenticate using the specified private key. Treats the password parameter as the key's passphrase.",
|
help=(
|
||||||
|
"Authenticate using the specified private key. Treats the password"
|
||||||
|
" parameter as the key's passphrase."
|
||||||
|
),
|
||||||
)
|
)
|
||||||
ssh_parser.add_argument(
|
ssh_parser.add_argument(
|
||||||
"--port", type=int, default=22, help="SSH port (default: 22)"
|
"--port", type=int, default=22, help="SSH port (default: 22)"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from cme.helpers.misc import validate_ntlm
|
|
||||||
from cme.cmedb import DatabaseNavigator, print_table, print_help
|
from cme.cmedb import DatabaseNavigator, print_table, print_help
|
||||||
|
|
||||||
|
|
||||||
|
@ -310,7 +309,8 @@ class navigator(DatabaseNavigator):
|
||||||
def do_clear_database(self, line):
|
def do_clear_database(self, line):
|
||||||
if (
|
if (
|
||||||
input(
|
input(
|
||||||
"This will destroy all data in the current database, are you SURE you want to run this? (y/n): "
|
"This will destroy all data in the current database, are you SURE you"
|
||||||
|
" want to run this? (y/n): "
|
||||||
)
|
)
|
||||||
== "y"
|
== "y"
|
||||||
):
|
):
|
||||||
|
|
|
@ -5,28 +5,15 @@ import hashlib
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
from impacket.smbconnection import SMBConnection, SessionError
|
from impacket.smbconnection import SMBConnection
|
||||||
|
|
||||||
from cme.config import process_secret
|
from cme.config import process_secret
|
||||||
from cme.connection import *
|
from cme.connection import *
|
||||||
from cme.helpers.logger import highlight
|
|
||||||
from cme.helpers.bloodhound import add_user_bh
|
from cme.helpers.bloodhound import add_user_bh
|
||||||
from cme.protocols.ldap.smbldap import LDAPConnect
|
from cme.protocols.ldap.smbldap import LDAPConnect
|
||||||
from cme.logger import CMEAdapter
|
from cme.logger import CMEAdapter
|
||||||
from pypsrp.client import Client
|
from pypsrp.client import Client
|
||||||
from impacket.examples.secretsdump import LocalOperations, LSASecrets, SAMHashes
|
from impacket.examples.secretsdump import LocalOperations, LSASecrets, SAMHashes
|
||||||
import logging
|
|
||||||
|
|
||||||
# The following disables the InsecureRequests warning and the 'Starting new HTTPS connection' log message
|
|
||||||
# from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
|
||||||
#
|
|
||||||
# requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
|
||||||
|
|
||||||
|
|
||||||
# class SuppressFilter(logging.Filter):
|
|
||||||
# # remove warning https://github.com/diyan/pywinrm/issues/269
|
|
||||||
# def filter(self, record):
|
|
||||||
# return "wsman" not in record.getMessage()
|
|
||||||
|
|
||||||
|
|
||||||
class winrm(connection):
|
class winrm(connection):
|
||||||
|
@ -59,7 +46,10 @@ class winrm(connection):
|
||||||
winrm_parser.add_argument(
|
winrm_parser.add_argument(
|
||||||
"--no-bruteforce",
|
"--no-bruteforce",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="No spray when using file for username and password (user1 => password1, user2 => password2",
|
help=(
|
||||||
|
"No spray when using file for username and password (user1 =>"
|
||||||
|
" password1, user2 => password2"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
winrm_parser.add_argument(
|
winrm_parser.add_argument(
|
||||||
"--continue-on-success",
|
"--continue-on-success",
|
||||||
|
@ -273,7 +263,8 @@ class winrm(connection):
|
||||||
}
|
}
|
||||||
if "mslaps-encryptedpassword" in values:
|
if "mslaps-encryptedpassword" in values:
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
"LAPS password is encrypted and currently CrackMapExec doesn't support the decryption..."
|
"LAPS password is encrypted and currently CrackMapExec doesn't"
|
||||||
|
" support the decryption..."
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
elif "mslaps-password" in values:
|
elif "mslaps-password" in values:
|
||||||
|
@ -286,7 +277,8 @@ class winrm(connection):
|
||||||
msMCSAdmPwd = values["ms-mcs-admpwd"]
|
msMCSAdmPwd = values["ms-mcs-admpwd"]
|
||||||
else:
|
else:
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
"No result found with attribute ms-MCS-AdmPwd or msLAPS-Password"
|
"No result found with attribute ms-MCS-AdmPwd or"
|
||||||
|
" msLAPS-Password"
|
||||||
)
|
)
|
||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
"Host: {:<20} Password: {} {}".format(
|
"Host: {:<20} Password: {} {}".format(
|
||||||
|
@ -295,9 +287,8 @@ class winrm(connection):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
"msMCSAdmPwd or msLAPS-Password is empty or account cannot read LAPS property for {}".format(
|
"msMCSAdmPwd or msLAPS-Password is empty or account cannot read LAPS"
|
||||||
self.hostname
|
" property for {}".format(self.hostname)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -306,9 +297,8 @@ class winrm(connection):
|
||||||
|
|
||||||
if msMCSAdmPwd == "":
|
if msMCSAdmPwd == "":
|
||||||
self.logger.fail(
|
self.logger.fail(
|
||||||
"msMCSAdmPwd or msLAPS-Password is empty or account cannot read LAPS property for {}".format(
|
"msMCSAdmPwd or msLAPS-Password is empty or account cannot read LAPS"
|
||||||
self.hostname
|
" property for {}".format(self.hostname)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
if ntlm_hash:
|
if ntlm_hash:
|
||||||
|
@ -347,7 +337,8 @@ class winrm(connection):
|
||||||
self.logger.debug(f"winrm create_conn_obj() - Requesting URL: {url}")
|
self.logger.debug(f"winrm create_conn_obj() - Requesting URL: {url}")
|
||||||
res = requests.post(url, verify=False, timeout=self.args.http_timeout)
|
res = requests.post(url, verify=False, timeout=self.args.http_timeout)
|
||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
f"winrm create_conn_obj() - Received response code: {res.status_code}"
|
"winrm create_conn_obj() - Received response code:"
|
||||||
|
f" {res.status_code}"
|
||||||
)
|
)
|
||||||
self.endpoint = url
|
self.endpoint = url
|
||||||
if self.endpoint.startswith("https://"):
|
if self.endpoint.startswith("https://"):
|
||||||
|
@ -526,7 +517,8 @@ class winrm(connection):
|
||||||
r = self.conn.execute_cmd(self.args.execute)
|
r = self.conn.execute_cmd(self.args.execute)
|
||||||
except:
|
except:
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
"Cannot execute command, probably because user is not local admin, but powershell command should be ok!"
|
"Cannot execute command, probably because user is not local admin, but"
|
||||||
|
" powershell command should be ok!"
|
||||||
)
|
)
|
||||||
r = self.conn.execute_ps(self.args.execute)
|
r = self.conn.execute_ps(self.args.execute)
|
||||||
self.logger.success("Executed command")
|
self.logger.success("Executed command")
|
||||||
|
@ -539,7 +531,8 @@ class winrm(connection):
|
||||||
|
|
||||||
def sam(self):
|
def sam(self):
|
||||||
self.conn.execute_cmd(
|
self.conn.execute_cmd(
|
||||||
"reg save HKLM\SAM C:\\windows\\temp\\SAM && reg save HKLM\SYSTEM C:\\windows\\temp\\SYSTEM"
|
"reg save HKLM\SAM C:\\windows\\temp\\SAM && reg save HKLM\SYSTEM"
|
||||||
|
" C:\\windows\\temp\\SYSTEM"
|
||||||
)
|
)
|
||||||
self.conn.fetch("C:\\windows\\temp\\SAM", self.output_filename + ".sam")
|
self.conn.fetch("C:\\windows\\temp\\SAM", self.output_filename + ".sam")
|
||||||
self.conn.fetch("C:\\windows\\temp\\SYSTEM", self.output_filename + ".system")
|
self.conn.fetch("C:\\windows\\temp\\SYSTEM", self.output_filename + ".system")
|
||||||
|
@ -560,7 +553,8 @@ class winrm(connection):
|
||||||
|
|
||||||
def lsa(self):
|
def lsa(self):
|
||||||
self.conn.execute_cmd(
|
self.conn.execute_cmd(
|
||||||
"reg save HKLM\SECURITY C:\\windows\\temp\\SECURITY && reg save HKLM\SYSTEM C:\\windows\\temp\\SYSTEM"
|
"reg save HKLM\SECURITY C:\\windows\\temp\\SECURITY && reg save HKLM\SYSTEM"
|
||||||
|
" C:\\windows\\temp\\SYSTEM"
|
||||||
)
|
)
|
||||||
self.conn.fetch(
|
self.conn.fetch(
|
||||||
"C:\\windows\\temp\\SECURITY", f"{self.output_filename}.security"
|
"C:\\windows\\temp\\SECURITY", f"{self.output_filename}.security"
|
||||||
|
|
Loading…
Reference in New Issue