Replaced CreateProcessAsUser with CreateProcessWithLogonW to get over the "0xc0000142" error code and added -UseBasicParsing to get over the IE Engine inconfigured error

This will be heavily documented in a tweet sometime
This commit is contained in:
Shay Nehmad 2019-12-24 19:08:52 +02:00
parent c8a742674f
commit ab57b5895e
3 changed files with 23 additions and 23 deletions

View File

@ -10,10 +10,10 @@ from infection_monkey.post_breach.pba import PBA
from infection_monkey.telemetry.post_breach_telem import PostBreachTelem from infection_monkey.telemetry.post_breach_telem import PostBreachTelem
from infection_monkey.utils.environment import is_windows_os from infection_monkey.utils.environment import is_windows_os
INFECTION_MONKEY_WEBSITE_URL = "https://infectionmonkey.com" INFECTION_MONKEY_WEBSITE_URL = "https://infectionmonkey.com/"
CREATED_PROCESS_AS_USER_SUCCESS_FORMAT = "Created process '{}' as user '{}' and the process succeeded." CREATED_PROCESS_AS_USER_SUCCESS_FORMAT = "Created process '{}' as user '{}' and the process succeeded."
CREATED_PROCESS_AS_USER_FAILED_FORMAT = "Created process '{}' as user '{}', but the process failed (exit status {})." CREATED_PROCESS_AS_USER_FAILED_FORMAT = "Created process '{}' as user '{}', but the process failed (exit status {}:{})."
USERNAME_PREFIX = "somenewuser" USERNAME_PREFIX = "somenewuser"
PASSWORD = "N3WPa55W0rD!1" PASSWORD = "N3WPa55W0rD!1"
@ -49,7 +49,7 @@ class CommunicateAsNewUser(PBA):
@staticmethod @staticmethod
def get_commandline_for_http_request(url, is_windows=is_windows_os()): def get_commandline_for_http_request(url, is_windows=is_windows_os()):
if is_windows: if is_windows:
format_string = "powershell -command \"Invoke-WebRequest {url}\"" format_string = 'powershell.exe -command "Invoke-WebRequest {url}" -UseBasicParsing'
else: else:
# true || false -> 0. false || true -> 0. false || false -> 1. So: # true || false -> 0. false || true -> 0. false || false -> 1. So:
# if curl works, we're good. # if curl works, we're good.
@ -71,4 +71,9 @@ class CommunicateAsNewUser(PBA):
CREATED_PROCESS_AS_USER_SUCCESS_FORMAT.format(commandline, username), True)).send() CREATED_PROCESS_AS_USER_SUCCESS_FORMAT.format(commandline, username), True)).send()
else: else:
PostBreachTelem(self, ( PostBreachTelem(self, (
CREATED_PROCESS_AS_USER_FAILED_FORMAT.format(commandline, username, exit_status), False)).send() CREATED_PROCESS_AS_USER_FAILED_FORMAT.format(
commandline, username, exit_status, twos_complement(exit_status)), False)).send()
def twos_complement(exit_status):
return hex(exit_status & (2 ** 32 - 1))

View File

@ -13,3 +13,4 @@ wmi
pywin32 ; sys_platform == 'win32' pywin32 ; sys_platform == 'win32'
pymssql<3.0 pymssql<3.0
pyftpdlib pyftpdlib
WinSys-3.x

View File

@ -5,7 +5,7 @@ from infection_monkey.utils.auto_new_user import AutoNewUser
from infection_monkey.utils.new_user_error import NewUserError from infection_monkey.utils.new_user_error import NewUserError
ACTIVE_NO_NET_USER = '/ACTIVE:NO' ACTIVE_NO_NET_USER = '/ACTIVE:NO'
WAIT_TIMEOUT_IN_MILLISECONDS = 20 * 1000 WAIT_TIMEOUT_IN_MILLISECONDS = 60 * 1000
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -65,8 +65,7 @@ class AutoNewWindowsUser(AutoNewUser):
self.username, self.username,
".", # Use current domain. ".", # Use current domain.
self.password, self.password,
win32con.LOGON32_LOGON_INTERACTIVE, # Logon type - interactive (normal user). win32con.LOGON32_LOGON_INTERACTIVE, # Logon type - interactive (normal user), since we're using a shell.
# using a shell.
win32con.LOGON32_PROVIDER_DEFAULT) # Which logon provider to use - whatever Windows offers. win32con.LOGON32_PROVIDER_DEFAULT) # Which logon provider to use - whatever Windows offers.
except Exception as err: except Exception as err:
raise NewUserError("Can't logon as {}. Error: {}".format(self.username, str(err))) raise NewUserError("Can't logon as {}. Error: {}".format(self.username, str(err)))
@ -78,33 +77,28 @@ class AutoNewWindowsUser(AutoNewUser):
import win32process import win32process
import win32api import win32api
import win32event import win32event
from winsys import _advapi32
exit_code = -1 exit_code = -1
process_handle = None process_handle = None
thread_handle = None thread_handle = None
try: try:
# Open process as that user: # Open process as that user
# https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera # https://github.com/tjguk/winsys/blob/master/winsys/_advapi32.py
process_handle, thread_handle, _, _ = win32process.CreateProcessAsUser( proc_info = _advapi32.CreateProcessWithLogonW(
self.get_logon_handle(), # A handle to the primary token that represents a user. username=self.username,
None, # The name of the module to be executed. domain=".",
command, # The command line to be executed. password=self.password,
None, # Process attributes command_line=command
None, # Thread attributes
True, # Should inherit handles
win32con.NORMAL_PRIORITY_CLASS, # The priority class and the creation of the process.
None, # An environment block for the new process. If this parameter is NULL, the new process
# uses the environment of the calling process.
None, # CWD. If this parameter is NULL, the new process will have the same current drive and
# directory as the calling process.
win32process.STARTUPINFO() # STARTUPINFO structure.
# https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
) )
process_handle = proc_info.hProcess
thread_handle = proc_info.hThread
logger.debug( logger.debug(
"Waiting for process to finish. Timeout: {}ms".format(WAIT_TIMEOUT_IN_MILLISECONDS)) "Waiting for process to finish. Timeout: {}ms".format(WAIT_TIMEOUT_IN_MILLISECONDS))
# https://social.msdn.microsoft.com/Forums/vstudio/en-US/b6d6a7ae-71e9-4edb-ac8f-408d2a41750d/what-events-on-a-process-handle-signal-satisify-waitforsingleobject?forum=vcgeneral
# Ignoring return code, as we'll use `GetExitCode` to determine the state of the process later. # Ignoring return code, as we'll use `GetExitCode` to determine the state of the process later.
_ = win32event.WaitForSingleObject( # Waits until the specified object is signaled, or time-out. _ = win32event.WaitForSingleObject( # Waits until the specified object is signaled, or time-out.
process_handle, # Ping process handle process_handle, # Ping process handle