1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-27 19:04:15 +01:00

Added convenience functions in Windows to check "is_admin" or "is_system"

This commit is contained in:
John Hammond 2021-06-04 19:08:53 -04:00
parent 4709bfb513
commit 0b3dd372c8

View File

@ -52,7 +52,7 @@ PWNCAT_WINDOWS_C2_RELEASE_URL = "https://github.com/calebstewart/pwncat-windows-
class PowershellError(Exception): class PowershellError(Exception):
""" Executing a powershell script caused an error """ """Executing a powershell script caused an error"""
def __init__(self, errors): def __init__(self, errors):
self.errors = json.loads(errors) self.errors = json.loads(errors)
@ -92,7 +92,7 @@ class stat_result:
class WindowsFile(RawIOBase): class WindowsFile(RawIOBase):
""" Wrapper around file handles on Windows """ """Wrapper around file handles on Windows"""
def __init__(self, platform: "Windows", mode: str, handle: int, name: str = None): def __init__(self, platform: "Windows", mode: str, handle: int, name: str = None):
self.platform = platform self.platform = platform
@ -109,7 +109,7 @@ class WindowsFile(RawIOBase):
return "w" in self.mode return "w" in self.mode
def close(self): def close(self):
""" Close a file handle on the remote host """ """Close a file handle on the remote host"""
if not self.is_open: if not self.is_open:
return return
@ -121,7 +121,7 @@ class WindowsFile(RawIOBase):
return return
def readall(self): def readall(self):
""" Read until EOF """ """Read until EOF"""
data = b"" data = b""
@ -159,7 +159,7 @@ class WindowsFile(RawIOBase):
return count return count
def write(self, data: bytes): def write(self, data: bytes):
""" Write data to this file """ """Write data to this file"""
if self.eof: if self.eof:
return 0 return 0
@ -270,7 +270,7 @@ class PopenWindows(pwncat.subprocess.Popen):
self.returncode = -1 self.returncode = -1
def poll(self): def poll(self):
""" Poll if the process has completed and get return code """ """Poll if the process has completed and get return code"""
if self.returncode is not None: if self.returncode is not None:
return self.returncode return self.returncode
@ -443,7 +443,7 @@ class Windows(Platform):
self.channel.send(f"{typ}\n{method}\n".encode("utf-8")) self.channel.send(f"{typ}\n{method}\n".encode("utf-8"))
def setup_prompt(self): def setup_prompt(self):
""" Set a prompt method for powershell to ensure our prompt looks pretty :) """ """Set a prompt method for powershell to ensure our prompt looks pretty :)"""
self.powershell( self.powershell(
""" """
@ -627,7 +627,7 @@ function prompt {
self.session.log("[yellow]warning[/yellow]: failed to disable AMSI!") self.session.log("[yellow]warning[/yellow]: failed to disable AMSI!")
def get_pty(self): def get_pty(self):
""" We don't need to do this for windows """ """We don't need to do this for windows"""
def Popen( def Popen(
self, self,
@ -807,7 +807,7 @@ function prompt {
errors: str = None, errors: str = None,
newline: str = None, newline: str = None,
): ):
""" Mimick the built-in open method. """ """Mimick the built-in open method."""
# Ensure all mode properties are valid # Ensure all mode properties are valid
for char in mode: for char in mode:
@ -872,7 +872,7 @@ function prompt {
)[0] )[0]
def getuid(self): def getuid(self):
""" Retrieve the cached User ID """ """Retrieve the cached User ID"""
return self.user_info return self.user_info
@ -917,7 +917,7 @@ function prompt {
raise FileNotFoundError(path) from exc raise FileNotFoundError(path) from exc
def chdir(self, path: str): def chdir(self, path: str):
""" Change the current working directory """ """Change the current working directory"""
try: try:
result = self.powershell(f'$_ = (pwd) ; cd "{path}" ; $_ | Select Path') result = self.powershell(f'$_ = (pwd) ; cd "{path}" ; $_ | Select Path')
@ -1018,7 +1018,7 @@ function prompt {
raise PermissionError(path) raise PermissionError(path)
def lstat(self): def lstat(self):
""" Perform stat on a link instead of the target of the link. """ """Perform stat on a link instead of the target of the link."""
raise PlatformError("lstat not implemented for Windows") raise PlatformError("lstat not implemented for Windows")
@ -1036,7 +1036,7 @@ function prompt {
self.new_item(ItemType="Directory", Path=path) self.new_item(ItemType="Directory", Path=path)
def readlink(self): def readlink(self):
""" Read the target of a filesystem link """ """Read the target of a filesystem link"""
raise PlatformError("readlink not implemented for Windows") raise PlatformError("readlink not implemented for Windows")
@ -1138,7 +1138,7 @@ function prompt {
def tempfile( def tempfile(
self, mode: str, length: Optional[int] = 8, suffix: Optional[str] = None self, mode: str, length: Optional[int] = 8, suffix: Optional[str] = None
): ):
""" Create a temporary file in a safe directory. Optionally provide a suffix """ """Create a temporary file in a safe directory. Optionally provide a suffix"""
if suffix is None: if suffix is None:
suffix = "" suffix = ""
@ -1176,7 +1176,7 @@ function prompt {
raise PermissionError(path) raise PermissionError(path)
def umask(self, mask: Optional[int] = None): def umask(self, mask: Optional[int] = None):
""" Set or retrieve the current umask value """ """Set or retrieve the current umask value"""
raise NotImplementedError("windows platform does not support umask") raise NotImplementedError("windows platform does not support umask")
@ -1214,6 +1214,45 @@ function prompt {
except PowershellError as exc: except PowershellError as exc:
raise OSError from exc raise OSError from exc
def is_admin(self) -> bool:
"""
Determine if our current user is an administrator user
"""
# This is ripped from here
# https://petri.com/how-to-check-a-powershell-script-is-running-with-admin-privileges
try:
result = self.powershell(
"(New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)"
)
if not result:
raise PlatformError("failed to determine admin privileges")
return result[0]
except PowershellError as exc:
raise PlatformError(f"failed to determine admin privileges: {exc}")
def is_system(self) -> bool:
"""
Determine if our current user is SYSTEM
We might not need this, because the users name SHOULD be system...
but we implement it just in face
"""
# This is ripped from here
# https://www.optimizationcore.com/scripting/ways-get-current-logged-user-powershell/
try:
username = self.powershell("[System.Environment]::UserName")
if not username:
raise PlatformError("failed to determine username")
return username[0].strip() == "SYSTEM"
except PowershellError as exc:
raise PlatformError(f"failed to determine username: {exc}")
def powershell(self, script: Union[str, BinaryIO], depth: int = 1): def powershell(self, script: Union[str, BinaryIO], depth: int = 1):
"""Execute a powershell script in the context of the C2. The results """Execute a powershell script in the context of the C2. The results
of the command are automatically serialized with ``ConvertTo-Json``. of the command are automatically serialized with ``ConvertTo-Json``.