def accept_connection(self, msg, port_attr=None, port_context=None): """Accept the connection for a ``LPC_CONNECTION_REQUEST`` message. ``msg.MessageId`` must be the same as the connection requesting message. :param AlpcMessage msg: The response message. :param ALPC_PORT_ATTRIBUTES port_attr: The attributes of the port, one with default value will be used if this parameter is ``None`` :param PVOID port_context: A value that will be copied in ``ALPC_CONTEXT_ATTR.PortContext`` of every message on this connection. """ rhandle = gdef.HANDLE() if port_attr is None: port_attr = gdef.ALPC_PORT_ATTRIBUTES() port_attr.Flags = 0x80000 # port_attr.Flags = 0x80000 + 0x2000000 # port_attr.Flags = 0x2000000 port_attr.MaxMessageLength = DEFAULT_MESSAGE_SIZE port_attr.MemoryBandwidth = 0 port_attr.MaxPoolUsage = 0xffffffff port_attr.MaxSectionSize = 0xffffffff port_attr.MaxViewSize = 0xffffffff port_attr.MaxTotalSectionSize = 0xffffffff port_attr.DupObjectTypes = 0xffffffff # windows.utils.print_ctypes_struct(port_attr, " - CONN_PORT_ATTR", hexa=True) winproxy.NtAlpcAcceptConnectPort(rhandle, self.handle, 0, None, port_attr, port_context, msg.port_message, None, True) self.communication_port_list.append(rhandle.value) return msg
def create_port_section(self, Flags, SectionHandle, SectionSize): AlpcSectionHandle = gdef.HANDLE() ActualSectionSize = gdef.SIZE_T() # RPCRT4 USE FLAGS 0x40000 ALPC_VIEWFLG_NOT_SECURE ? winproxy.NtAlpcCreatePortSection(self.handle, Flags, SectionHandle, SectionSize, AlpcSectionHandle, ActualSectionSize) return AlpcSection(AlpcSectionHandle.value, ActualSectionSize.value)
def connect_to_port(self, port_name, connect_message=None, port_attr=None, port_attr_flags=0x10000, obj_attr=None, flags=gdef.ALPC_MSGFLG_SYNC_REQUEST, timeout=None): """Connect to the ALPC port ``port_name``. Most of the parameters have defauls value is ``None`` is passed. :param AlpcMessage connect_message: The message send with the connection request, if not ``None`` the function will return an :class:`AlpcMessage` :param ALPC_PORT_ATTRIBUTES port_attr: The port attributes, one with default value will be used if this parameter is ``None`` :param int port_attr_flags: ``ALPC_PORT_ATTRIBUTES.Flags`` used if ``port_attr`` is ``None`` (MUTUALY EXCLUSINVE WITH ``port_attr``) :param OBJECT_ATTRIBUTES obj_attr: The attributes of the port (can be None) :param int flags: The flags for :func:`NtAlpcConnectPort` :param int timeout: The timeout of the request """ # TODO raise on mutual exclusive parameter if self.handle is not None: raise ValueError("Client already connected") handle = gdef.HANDLE() port_name_unicode = self._alpc_port_to_unicode_string(port_name) if port_attr is None: port_attr = gdef.ALPC_PORT_ATTRIBUTES() port_attr.Flags = port_attr_flags # Flag qui fonctionne pour l'UAC port_attr.MaxMessageLength = self.DEFAULT_MAX_MESSAGE_LENGTH port_attr.MemoryBandwidth = 0 port_attr.MaxPoolUsage = 0xffffffff port_attr.MaxSectionSize = 0xffffffff port_attr.MaxViewSize = 0xffffffff port_attr.MaxTotalSectionSize = 0xffffffff port_attr.DupObjectTypes = 0xffffffff port_attr.SecurityQos.Length = ctypes.sizeof(port_attr.SecurityQos) port_attr.SecurityQos.ImpersonationLevel = gdef.SecurityImpersonation port_attr.SecurityQos.ContextTrackingMode = 0 port_attr.SecurityQos.EffectiveOnly = 0 if connect_message is None: send_msg = None send_msg_attr = None buffersize = None elif isinstance(connect_message, basestring): buffersize = gdef.DWORD(len(connect_message) + 0x1000) send_msg = AlpcMessagePort.from_buffer_size(buffersize.value) send_msg.data = connect_message send_msg_attr = MessageAttribute.with_all_attributes() elif isinstance(connect_message, AlpcMessage): send_msg = connect_message.port_message send_msg_attr = connect_message.attributes buffersize = gdef.DWORD(connect_message.port_message_buffer_size) else: raise ValueError("Don't know how to send <{0!r}> as connect message".format(connect_message)) # windows.utils.print_ctypes_struct(port_attr, "port_attr_connect", hexa=True) receive_attr = MessageAttribute.with_all_attributes() winproxy.NtAlpcConnectPort(handle, port_name_unicode, obj_attr, port_attr, flags, None, send_msg, buffersize, send_msg_attr, receive_attr, timeout) # If send_msg is not None, it contains the ClientId.UniqueProcess : PID of the server :) self.handle = handle.value self.port_name = port_name return AlpcMessage(send_msg, receive_attr) if send_msg is not None else None
def local_handle(self): """A local copy of the handle, acquired with ``DuplicateHandle`` :type: :class:`int`""" if self.dwProcessId == windows.current_process.pid: return self.wValue res = gdef.HANDLE() winproxy.DuplicateHandle(self.process.handle, self.wValue, windows.current_process.handle, ctypes.byref(res), dwOptions=gdef.DUPLICATE_SAME_ACCESS) return res.value
def get_next_resource_descriptor(self, resource, resdes=None): if resdes is None: # Using logical-conf as resdes will retrieve the first one # https://docs.microsoft.com/en-us/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_get_next_res_des#remarks resdes = self resid = None if resource == gdef.ResType_All: resid = gdef.RESOURCEID() res = gdef.HANDLE() winproxy.CM_Get_Next_Res_Des(res, resdes, resource, resid, 0) resdes_type = resid.value if resid is not None else resource return ResourceDescriptor.from_handle_and_type(res.value, resdes_type)
def _open_directory(self): path = self.fullname utf16_len = len(path) * 2 obj_attr = gdef.OBJECT_ATTRIBUTES() obj_attr.Length = ctypes.sizeof(obj_attr) obj_attr.RootDirectory = None obj_attr.ObjectName = ctypes.pointer(gdef.LSA_UNICODE_STRING.from_string(path)) obj_attr.Attributes = gdef.OBJ_CASE_INSENSITIVE obj_attr.SecurityDescriptor = 0 obj_attr.SecurityQualityOfService = 0 res = gdef.HANDLE() winproxy.NtOpenDirectoryObject(res, gdef.DIRECTORY_QUERY | gdef.READ_CONTROL , obj_attr) return res.value
def create_port(self, port_name, msglen=None, port_attr_flags=0, obj_attr=None, port_attr=None): """Create the ALPC port ``port_name``. Most of the parameters have defauls value is ``None`` is passed. :param str port_name: The port's name to create. :param int msglen: ``ALPC_PORT_ATTRIBUTES.MaxMessageLength`` used if ``port_attr`` is ``None`` (MUTUALY EXCLUSINVE WITH ``port_attr``) :param int port_attr_flags: ``ALPC_PORT_ATTRIBUTES.Flags`` used if ``port_attr`` is ``None`` (MUTUALY EXCLUSINVE WITH ``port_attr``) :param OBJECT_ATTRIBUTES obj_attr: The attributes of the port, one with default value will be used if this parameter is ``None`` :param ALPC_PORT_ATTRIBUTES port_attr: The port attributes, one with default value will be used if this parameter is ``None`` """ # TODO raise on mutual exclusive parameter (port_attr + port_attr_flags | obj_attr + msglen) handle = gdef.HANDLE() raw_name = port_name if not raw_name.startswith("\\"): raw_name = "\\" + port_name port_name = self._alpc_port_to_unicode_string(raw_name) if msglen is None: msglen = DEFAULT_MESSAGE_SIZE if obj_attr is None: obj_attr = gdef.OBJECT_ATTRIBUTES() obj_attr.Length = ctypes.sizeof(obj_attr) obj_attr.RootDirectory = None obj_attr.ObjectName = ctypes.pointer(port_name) obj_attr.Attributes = 0 obj_attr.SecurityDescriptor = None obj_attr.SecurityQualityOfService = None if port_attr is None: port_attr = gdef.ALPC_PORT_ATTRIBUTES() port_attr.Flags = port_attr_flags # port_attr.Flags = 0x2080000 # port_attr.Flags = 0x90000 port_attr.MaxMessageLength = msglen port_attr.MemoryBandwidth = 0 port_attr.MaxPoolUsage = 0xffffffff port_attr.MaxSectionSize = 0xffffffff port_attr.MaxViewSize = 0xffffffff port_attr.MaxTotalSectionSize = 0xffffffff port_attr.DupObjectTypes = 0xffffffff # windows.utils.print_ctypes_struct(port_attr, " - PORT_ATTR", hexa=True) winproxy.NtAlpcCreatePort(handle, obj_attr, port_attr) self.port_name = raw_name self.handle = handle.value
def query_link(linkpath): """Resolve the link object with path ``linkpath``""" obj_attr = gdef.OBJECT_ATTRIBUTES() obj_attr.Length = ctypes.sizeof(obj_attr) obj_attr.RootDirectory = 0 obj_attr.ObjectName = ctypes.pointer( gdef.LSA_UNICODE_STRING.from_string(linkpath)) obj_attr.Attributes = gdef.OBJ_CASE_INSENSITIVE obj_attr.SecurityDescriptor = 0 obj_attr.SecurityQualityOfService = 0 res = gdef.HANDLE() x = winproxy.NtOpenSymbolicLinkObject( res, gdef.DIRECTORY_QUERY | gdef.READ_CONTROL, obj_attr) v = gdef.LSA_UNICODE_STRING.from_string("\x00" * 1000) s = gdef.ULONG() winproxy.NtQuerySymbolicLinkObject(res, v, s) # Handle Buffer-too-small ? return v.str
def NtCreateThreadEx(ThreadHandle=None, DesiredAccess=0x1fffff, ObjectAttributes=0, ProcessHandle=NeededParameter, lpStartAddress=NeededParameter, lpParameter=NeededParameter, CreateSuspended=0, dwStackSize=0, Unknown1=0, Unknown2=0, Unknown=0): if ThreadHandle is None: ThreadHandle = ctypes.byref(gdef.HANDLE()) return NtCreateThreadEx.ctypes_function(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle, lpStartAddress, lpParameter, CreateSuspended, dwStackSize, Unknown1, Unknown2, Unknown3)
def duplicate(self, access_rigth=gdef.MAXIMUM_ALLOWED, attributes=None, type=None, impersonation_level=None): """Duplicate the token into a new :class:`Token`. :param type: The type of token: ``TokenPrimary(0x1L)`` or ``TokenImpersonation(0x2L)`` :param impersonation_level: The :class:`~windows.generated_def.winstructs.SECURITY_IMPERSONATION_LEVEL` for a ``TokenImpersonation(0x2L)``: - If ``type`` is ``TokenPrimary(0x1L)`` this parameter is ignored if ``None`` or used as-is. - If ``type`` is ``TokenImpersonation(0x2L)`` and this parameter is None, ``self.impersonation_level`` is used. - If ``type`` is ``TokenImpersonation(0x2L)`` and our Token is a ``TokenPrimary(0x1L)`` this parameter MUST be provided :returns: :class:`Token` - The duplicate token Example: >>> tok <Token TokenId=0x39d6dde5 Type=TokenPrimary(0x1L)> >>> tok.duplicate() <Token TokenId=0x39d7b206 Type=TokenPrimary(0x1L)> >>> tok.duplicate(type=gdef.TokenImpersonation) ... ValueError: Duplicating a PrimaryToken as a TokenImpersonation require explicit <impersonation_level> parameter >>> tok.duplicate(type=gdef.TokenImpersonation, impersonation_level=gdef.SecurityImpersonation) <Token TokenId=0x39dadbf8 Type=TokenImpersonation(0x2L) ImpersonationLevel=SecurityImpersonation(0x2L)> """ newtoken = gdef.HANDLE() if type is None: type = self.type if impersonation_level is None: if self.type == gdef.TokenImpersonation: impersonation_level = self.impersonation_level elif type != gdef.TokenImpersonation: impersonation_level = 0 #: ignored else: raise ValueError( "Duplicating a PrimaryToken as a TokenImpersonation require explicit <impersonation_level> parameter" ) winproxy.DuplicateTokenEx(self.handle, access_rigth, attributes, impersonation_level, type, newtoken) return bltn_type(self)(newtoken.value)
def query_link(linkpath): """Resolve the link object with path ``linkpath``""" obj_attr = gdef.OBJECT_ATTRIBUTES() obj_attr.Length = ctypes.sizeof(obj_attr) obj_attr.RootDirectory = 0 obj_attr.ObjectName = ctypes.pointer(gdef.LSA_UNICODE_STRING.from_string(linkpath)) obj_attr.Attributes = gdef.OBJ_CASE_INSENSITIVE obj_attr.SecurityDescriptor = 0 obj_attr.SecurityQualityOfService = 0 res = gdef.HANDLE() x = winproxy.NtOpenSymbolicLinkObject(res, gdef.DIRECTORY_QUERY | gdef.READ_CONTROL , obj_attr) v = gdef.LSA_UNICODE_STRING.from_size(1000) s = gdef.ULONG() try: winproxy.NtQuerySymbolicLinkObject(res, v, s) except WindowsError as e: if not (e.winerror & 0xffffffff) == gdef.STATUS_BUFFER_TOO_SMALL: raise # If our initial 1000 buffer is not enought (improbable) retry with correct size v = gdef.LSA_UNICODE_STRING.from_size(s.value) winproxy.NtQuerySymbolicLinkObject(res, v, s) return v.str
def CreatePipe(lpPipeAttributes=None, nSize=0): hReadPipe = gdef.HANDLE() hWritePipe = gdef.HANDLE() CreatePipe.ctypes_function(hReadPipe, hWritePipe, lpPipeAttributes, nSize) return hReadPipe.value, hWritePipe.value
def get_next_logical_configuration(self, logconf): res = gdef.HANDLE(0) winproxy.CM_Get_Next_Log_Conf(res, logconf) return res
def SetThreadToken(Thread, Token): if isinstance(Thread, (int, long)): Thread = gdef.HANDLE(Thread) return SetThreadToken.ctypes_function(Thread, Token)