forked from p34709852/monkey
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:
parent
c8a742674f
commit
ab57b5895e
|
@ -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))
|
||||||
|
|
|
@ -13,3 +13,4 @@ wmi
|
||||||
pywin32 ; sys_platform == 'win32'
|
pywin32 ; sys_platform == 'win32'
|
||||||
pymssql<3.0
|
pymssql<3.0
|
||||||
pyftpdlib
|
pyftpdlib
|
||||||
|
WinSys-3.x
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue