def cleanup(self): """ Cleans up any old services or payloads that may have been left behind on a previous failure. This will search C:\\Windows for any files starting with PAExec-*.exe and delete them. It will also stop and remove any services that start with PAExec-* if they exist. Before calling this function, the connect() function must have already been called. """ scmr = self._service._scmr services = scmr.enum_services_status_w( self._service._scmr_handle, ServiceType.SERVICE_WIN32_OWN_PROCESS, EnumServiceState.SERVICE_STATE_ALL) for service in services: if service['service_name'].lower().startswith("paexec"): svc = Service(service['service_name'], self.session) svc.open() svc.delete() smb_tree = TreeConnect(self.session, r"\\%s\ADMIN$" % self.connection.server_name) smb_tree.connect() share = Open(smb_tree, "") query_msgs = [ share.create(ImpersonationLevel.Impersonation, DirectoryAccessMask.FILE_READ_ATTRIBUTES | DirectoryAccessMask.SYNCHRONIZE | DirectoryAccessMask.FILE_LIST_DIRECTORY, FileAttributes.FILE_ATTRIBUTE_DIRECTORY, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE | ShareAccess.FILE_SHARE_DELETE, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, send=False), share.query_directory("PAExec-*.exe", FileInformationClass.FILE_NAMES_INFORMATION, send=False), share.close(False, send=False) ] query_reqs = self.connection.send_compound([x[0] for x in query_msgs], self.session.session_id, smb_tree.tree_connect_id, related=True) # receive response for open and close query_msgs[0][1](query_reqs[0]) query_msgs[2][1](query_reqs[2]) try: # receive the response for query_directory files = query_msgs[1][1](query_reqs[1]) except SMBResponseException as exc: if exc.status != NtStatus.STATUS_NO_SUCH_FILE: raise exc files = [] for file in files: file_name = file['file_name'].get_value().decode('utf-16-le') self._delete_file(smb_tree, file_name)
def _get_paexec_files_and_services(self, client): server = os.environ['PYPSEXEC_SERVER'] username = os.environ.get('PYPSEXEC_USERNAME', None) password = os.environ.get('PYPSEXEC_PASSWORD', None) paexec_services = [] # need to close and reopen the connection to ensure deletes are # processed client.disconnect() client = Client(server, username=username, password=password) client.connect() scmr = client._service._scmr scmr_handle = client._service._scmr_handle services = scmr.enum_services_status_w(scmr_handle, ServiceType. SERVICE_WIN32_OWN_PROCESS, EnumServiceState. SERVICE_STATE_ALL) for service in services: if service['service_name'].lower().startswith("paexec"): paexec_services.append(service['service_name']) smb_tree = TreeConnect(client.session, r"\\%s\ADMIN$" % client.connection.server_name) smb_tree.connect() share = Open(smb_tree, "") share.create(ImpersonationLevel.Impersonation, DirectoryAccessMask.FILE_READ_ATTRIBUTES | DirectoryAccessMask.SYNCHRONIZE | DirectoryAccessMask.FILE_LIST_DIRECTORY, FileAttributes.FILE_ATTRIBUTE_DIRECTORY, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE | ShareAccess.FILE_SHARE_DELETE, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE) try: paexec_files = share.query_directory("PAExec-*.exe", FileInformationClass. FILE_NAMES_INFORMATION) except SMBResponseException as exc: if exc.status != NtStatus.STATUS_NO_SUCH_FILE: raise exc paexec_files = [] return client, paexec_services, paexec_files
# create some files in dir and query the contents as part of a compound # request directory_file = Open(tree, r"%s\file.txt" % dir_name) directory_file.create( ImpersonationLevel.Impersonation, FilePipePrinterAccessMask.GENERIC_WRITE | FilePipePrinterAccessMask.DELETE, FileAttributes.FILE_ATTRIBUTE_NORMAL, ShareAccess.FILE_SHARE_READ, CreateDisposition.FILE_OVERWRITE_IF, CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_DELETE_ON_CLOSE) compound_messages = [ directory_file.write("Hello World".encode('utf-8'), 0, send=False), dir_open.query_directory("*", FileInformationClass.FILE_NAMES_INFORMATION, send=False), directory_file.close(False, send=False), dir_open.close(False, send=False) ] requests = connection.send_compound([x[0] for x in compound_messages], session.session_id, tree.tree_connect_id) responses = [] for i, request in enumerate(requests): response = compound_messages[i][1](request) responses.append(response) dir_files = [] for dir_file in responses[1]: dir_files.append(dir_file['file_name'].get_value().decode('utf-16-le'))