def first_heartbeat_result(): hosts_sorted = HeartBeat.list_hostandsession() result_history = PostModuleResultHistory.list_all() for one in result_history: for host in hosts_sorted: if one.get("hid") == host.get("id"): one["ipaddress"] = host.get("ipaddress") break Xcache.set_heartbeat_cache_result_history(result_history) notices = Notice.list_notices() jobs = Job.list_jobs() bot_wait_list = Job.list_bot_wait() # 任务队列长度 task_queue_length = Xcache.get_module_task_length() result = { 'hosts_sorted_update': True, 'hosts_sorted': hosts_sorted, 'result_history_update': True, 'result_history': result_history, 'notices_update': True, 'notices': notices, 'task_queue_length': task_queue_length, 'jobs_update': True, 'jobs': jobs, 'bot_wait_list_update': True, 'bot_wait_list': bot_wait_list } return result
def disconnect(self, close_code): try: async_to_sync(self.channel_layer.group_discard)("msfconsole", self.channel_name) Xcache.clean_msfconsoleinputcache() except Exception as E: logger.exception(E) pass
def list(loadpath=None): all_modules_config = Xcache.list_moduleconfigs() if all_modules_config is None: PostModuleConfig.load_all_modules_config() all_modules_config = Xcache.list_moduleconfigs() # 删除内部模块 for one in all_modules_config[:]: if one.get('MODULETYPE') == TAG2CH.internal: all_modules_config.remove(one) if loadpath is None: for one in all_modules_config: one['OPTIONS'] = [] context = data_return(200, CODE_MSG.get(200), all_modules_config) return context else: for one_module_config in all_modules_config: if one_module_config.get('loadpath') == loadpath: # 动态处理handler和凭证选项 new_module_config = PostModuleConfig._deal_dynamic_option( one_module_config=one_module_config) context = data_return(200, CODE_MSG.get(200), new_module_config) return context # 没有找到模块 context = data_return(200, CODE_MSG.get(200), {}) return context
def delete_job_by_uuid(self, task_uuid=None): req = Xcache.get_module_task_by_uuid(task_uuid=task_uuid) Xcache.del_module_task_by_uuid(task_uuid=task_uuid) # 清理缓存信息 # 删除后台任务 try: self.ModuleJobsScheduler.remove_job(task_uuid) except Exception as E: logger.error(E) try: module_common_instance = req.get("module") except Exception as E: logger.error(E) return False # 存储已经生成的结果 try: module_common_instance.log_status("用户手动删除任务") module_common_instance._store_result_in_history() except Exception as E: logger.error("删除多模块实例异常:{} 异常信息: {}".format(module_common_instance.NAME, E)) Notice.send_exception("模块: {} 执行异常,异常信息: {}".format(module_common_instance.NAME, E)) logger.error(E) return False # 发送通知 Notice.send_info( "模块: {} {} 手动删除".format(module_common_instance.NAME, module_common_instance.target_str)) logger.warning("多模块实例手动删除:{}".format(module_common_instance.NAME)) return True
def list_handler(): handlers = [] infos = Job.list_msfrpc_jobs() if infos is None: return handlers for key in infos.keys(): info = infos.get(key) jobid = int(key) if info.get('name') == 'Exploit: multi/handler': datastore = info.get('datastore') if datastore is not None: one_handler = {'ID': jobid, 'PAYLOAD': None} if datastore.get('PAYLOAD') is not None: one_handler['PAYLOAD'] = datastore.get('PAYLOAD') elif datastore.get('Payload') is not None: one_handler['PAYLOAD'] = datastore.get('Payload') elif datastore.get('payload') is not None: one_handler['PAYLOAD'] = datastore.get('payload') z = datastore.copy() z.update(one_handler) one_handler = z handlers.append(one_handler) Xcache.set_cache_handlers(handlers) # 获取虚拟监听 virtual_handlers = Xcache.get_virtual_handlers() handlers.extend(virtual_handlers) # 特殊参数处理 for one_handler in handlers: if one_handler.get('StageEncoder') is not None and one_handler.get('StageEncoder') != '': one_handler['EnableStageEncoding'] = True return handlers
def putin_post_python_module_queue(self, post_module_intent=None): try: # 存储uuid tmp_self_uuid = str(uuid.uuid1()) # 清空历史记录 post_module_intent.clean_log() logger.warning("模块放入列表:{} job_id: {} uuid: {}".format(post_module_intent.NAME, None, tmp_self_uuid)) post_module_intent.module_self_uuid = tmp_self_uuid self.ModuleJobsScheduler.add_job(func=post_module_intent._thread_run, max_instances=1, id=tmp_self_uuid) # 放入缓存队列,用于后续删除任务,存储结果等 req = { 'broker': post_module_intent.MODULE_BROKER, 'uuid': tmp_self_uuid, 'module': post_module_intent, 'time': int(time.time()), 'job_id': None, } Xcache.create_module_task(req) Notice.send_info( "模块: {} {} 开始执行".format(post_module_intent.NAME, post_module_intent.target_str)) return True except Exception as E: logger.error(E) return False
def write(data=None): cid = Xcache.get_console_id() if cid is None: get_active_console_result = Console.get_active_console() if get_active_console_result: cid = Xcache.get_console_id() else: return False, None params = [cid, data + "\r\n"] result = RpcClient.call(Method.ConsoleWrite, params) if result is None or result.get("result") == "failure": get_active_console_result = Console.get_active_console() if get_active_console_result: cid = Xcache.get_console_id() params = [cid, data + "\r\n"] result = RpcClient.call(Method.ConsoleWrite, params) if result is None or result.get("result") == "failure": return False, None else: return True, result else: return False, result else: return True, result
def store_result_from_sub(message=None): # 回调报文数据格式 # { # 'job_id': None, # 'uuid': '1b1a1ac0-95db-0137-5103-000c2966078a', # 'status': True, # 'message': None, # 'data': {'WHOAMI': 'nt authority\\system', 'IS_SYSTEM': True, } # } body = message.get('data') # 解析报文 try: msf_module_return_dict = json.loads(body) except Exception as E: logger.error(E) return False # 获取对应模块实例 try: req = Xcache.get_module_task_by_uuid(task_uuid=msf_module_return_dict.get("uuid")) except Exception as E: logger.error(E) return False if req is None: logger.error("未找到请求模块实例") logger.error(msf_module_return_dict) return False module_intent = req.get('module') if module_intent is None: logger.error("获取模块失败,body: {}".format(msf_module_return_dict)) return False # 调用回调函数 try: logger.warning(f"模块回调:{module_intent.NAME} " f"job_id: {msf_module_return_dict.get('job_id')} " f"uuid: {msf_module_return_dict.get('uuid')}") module_intent._clean_log() # 清理历史结果 except Exception as E: logger.error(E) return False try: module_intent.callback(status=msf_module_return_dict.get("status"), message=msf_module_return_dict.get("message"), data=msf_module_return_dict.get("data")) except Exception as E: Notice.send_error("模块 {} 的回调函数callhack运行异常".format(module_intent.NAME)) logger.error(E) try: module_intent._store_result_in_history() # 存储到历史记录 except Exception as E: logger.error(E) Xcache.del_module_task_by_uuid(task_uuid=msf_module_return_dict.get("uuid")) # 清理缓存信息 Notice.send_success("模块: {} {} 执行完成".format(module_intent.NAME, module_intent._target_str))
def list_jobs(): """获取后台任务列表,包括msf任务及本地多模块任务""" msf_jobs_dict = Job.list_msfrpc_jobs_no_cache() if msf_jobs_dict is None: # msfrpc临时异常 uncheck = True # 跳过任务检查 msf_jobs_dict = {} else: uncheck = False reqs = Xcache.list_module_tasks() reqs_temp = [] for req in reqs: # post python module if req.get("job_id") is None: req["moduleinfo"] = PostModuleSerializer(req.get("module"), many=False).data req["moduleinfo"]['_custom_param'] = Job._deal_dynamic_param( req["moduleinfo"]['_custom_param']) req.pop("module") # 弹出module实例 reqs_temp.append(req) continue # post msf module # 跳过任务检查 if uncheck: req["moduleinfo"] = PostModuleSerializer(req.get("module"), many=False).data req.pop("module") # 弹出module实例 req["moduleinfo"]['_custom_param'] = Job._deal_dynamic_param( req["moduleinfo"]['_custom_param']) reqs_temp.append(req) continue elif msf_jobs_dict.get(str(req.get("job_id"))) is not None: req["moduleinfo"] = PostModuleSerializer(req.get("module"), many=False).data req["moduleinfo"]['_custom_param'] = Job._deal_dynamic_param( req["moduleinfo"]['_custom_param']) req.pop("module") # 弹出module实例 reqs_temp.append(req) continue else: # 清除失效的任务 if int(time.time()) - req.get("time") >= 30: logger.error(f"清除失效的任务: {req.get('module').NAME}") logger.error(req) Xcache.del_module_task_by_uuid(req.get("uuid")) else: # 如果创建时间不足30秒,则等待callback处理数据 req["moduleinfo"] = PostModuleSerializer(req.get("module"), many=False).data req["moduleinfo"][ '_custom_param'] = Job._deal_dynamic_param( req["moduleinfo"]['_custom_param']) req.pop("module") reqs_temp.append(req) continue return reqs_temp
def create_bot(ipportlist=None, custom_param=None, loadpath=None): module_config = Xcache.get_moduleconfig(loadpath) # 获取模块配置 if module_config is None: context = data_return(305, PostModuleActuator_MSG.get(305), {}) return context # 处理模块参数 try: custom_param = json.loads(custom_param) except Exception as E: logger.warning(E) custom_param = {} # 获取模块实例 group_uuid = str(uuid.uuid1()).replace('-', "") class_intent = importlib.import_module(loadpath) for ipport in ipportlist: post_module_intent = class_intent.PostModule( ip=ipport.get("ip"), port=ipport.get("port"), protocol=ipport.get("protocol"), custom_param=custom_param) # 格式化固定字段 try: post_module_intent.AUTHOR = module_config.get("AUTHOR") except Exception as E: logger.warning(E) # 模块前序检查,调用check函数 try: flag, msg = post_module_intent.check() if flag is not True: # 如果检查未通过,返回未通过原因(msg) Notice.send_warning( f"模块:{post_module_intent.NAME} IP:{ipport.get('ip')} 检查未通过,原因:{msg}" ) continue except Exception as E: logger.warning(E) Notice.send_warning( f"模块:{post_module_intent.NAME} IP:{ipport.get('ip')} 检查函数执行异常" ) continue tmp_self_uuid = str(uuid.uuid1()) req = { 'uuid': tmp_self_uuid, 'group_uuid': group_uuid, 'broker': post_module_intent.MODULE_BROKER, 'module': post_module_intent, 'time': int(time.time()), } Xcache.putin_bot_wait(req) context = data_return(201, PostModuleActuator_MSG.get(201), {}) return context
def _store_result_in_history(self): """存储模块运行结果到历史记录""" if self.MODULETYPE in [TAG2CH.internal]: return None opts = {} for key in self._custom_param: for option in self.OPTIONS: if option.get("name") == key: if self._custom_param.get(key) is None: continue opts[option.get("name_tag")] = self._custom_param.get(key) # 处理凭证,监听,文件等参数 try: if key == HANDLER_OPTION.get("name"): handler_dict = json.loads( self._custom_param.get(key)) # 清理无效的参数 new_params = { "PAYLOAD": handler_dict.get("PAYLOAD"), "LPORT": handler_dict.get("LPORT") } if handler_dict.get("LHOST") is not None: new_params["LHOST"] = handler_dict.get("LHOST") if handler_dict.get("RHOST") is not None: new_params["RHOST"] = handler_dict.get("RHOST") opts[option.get("name_tag")] = json.dumps( new_params) elif key == FILE_OPTION.get("name"): file_dict = json.loads(self._custom_param.get(key)) opts[option.get("name_tag")] = json.dumps({ "name": file_dict.get("name"), }) elif key == CREDENTIAL_OPTION.get("name"): credential_dict = json.loads( self._custom_param.get(key)) opts[option.get("name_tag")] = json.dumps({ "username": credential_dict.get("username"), "password": credential_dict.get("password"), "password_type": credential_dict.get("password_type"), }) except Exception as E: logger.exception(E) module_result = Xcache.get_module_result(ipaddress=self.host_ipaddress, loadpath=self.__module__) flag = Xcache.add_module_result_history( ipaddress=self.host_ipaddress, loadpath=self.__module__, opts=opts, update_time=module_result.get("update_time"), result=module_result.get("result")) return flag
def destroy_adv_job(task_uuid=None, job_id=None, broker=None): try: if broker == BROKER.post_python_job: flag = aps_module.delete_job_by_uuid(task_uuid) if flag is not True: context = data_return(304, Job_MSG.get(304), {}) return context else: context = data_return(204, Job_MSG.get(204), { "uuid": task_uuid, "job_id": job_id }) return context elif broker == BROKER.post_msf_job: req = Xcache.get_module_task_by_uuid(task_uuid=task_uuid) common_module_instance = req.get("module") Xcache.del_module_task_by_uuid(task_uuid) params = [job_id] result = RpcClient.call(Method.JobStop, params) if result is None: context = data_return(305, Job_MSG.get(305), {}) return context if result.get('result') == 'success': # 发送通知 Notice.send_info("模块: {} {} 手动删除完成".format( common_module_instance.NAME, common_module_instance.target_str)) context = data_return(204, Job_MSG.get(204), { "uuid": task_uuid, "job_id": job_id }) return context else: context = data_return(304, Job_MSG.get(304), {}) return context elif broker == BROKER.bot_msf_job: flag = Xcache.del_bot_wait_by_group_uuid(task_uuid) if flag is not True: context = data_return(304, Job_MSG.get(304), {}) return context else: context = data_return(204, Job_MSG.get(204), {"uuid": task_uuid}) return context else: context = data_return(304, Job_MSG.get(304), {}) return context except Exception as E: logger.error(E) context = data_return(500, CODE_MSG.get(500), {}) return context
def update(sessionid=None): if sessionid is None or sessionid <= 0: context = data_return(304, Session_MSG.get(304), {}) return context Xcache.set_session_info(sessionid, None) session_lib = SessionLib(sessionid, rightinfo=True, uacinfo=True, pinfo=True) result = SessionLibSerializer(session_lib).data context = data_return(203, Session_MSG.get(203), result) return context
def list_msfrpc_jobs_no_cache(): infos = {} try: result = RpcClient.call(Method.JobList) Xcache.set_msf_job_cache(result) if result is None: infos = {} else: infos = result except Exception as E: logger.error(E) return infos
def list_all(): try: result = Xcache.list_module_result_history() for one in result: loadpath = one.get("loadpath") moduleconfig = Xcache.get_moduleconfig(loadpath) if moduleconfig is None: continue one["module_name"] = moduleconfig.get("NAME") return result except Exception as E: logger.exception(E) return []
def is_msf_job_alive(job_id): time.sleep(0.5) try: result = RpcClient.call(Method.JobList) Xcache.set_msf_job_cache(result) if result is None: return False else: if result.get(str(job_id)) is not None: return True else: return False except Exception as E: logger.error(E) return False
def create_virtual_handler(opts=None): """生成一个虚拟监听""" one_handler = opts virtual_id = Xcache.add_virtual_handler(one_handler) opts['ID'] = virtual_id return opts
def store_error_result(task_uuid=None, exception=None): req = Xcache.get_module_task_by_uuid(task_uuid=task_uuid) Xcache.del_module_task_by_uuid(task_uuid=task_uuid) # 清理缓存信息 module_common_instance = req.get("module") # 存储运行结果 try: module_common_instance.log_except(exception) module_common_instance._store_result_in_history() logger.error("多模块实例执行异常:{} 异常信息: {}".format(module_common_instance.NAME, exception)) Notice.send_exception("模块: {} 执行异常,异常信息: {}".format(module_common_instance.NAME, exception)) return True except Exception as E: logger.error("多模块实例执行异常:{} 异常信息: {}".format(module_common_instance.NAME, E)) Notice.send_exception("模块: {} 执行异常,异常信息: {}".format(module_common_instance.NAME, E)) logger.error(E) return False
def create_post(loadpath=None, sessionid=None, hid=None, custom_param=None): module_config = Xcache.get_moduleconfig(loadpath) # 获取模块配置 if module_config is None: context = data_return(305, PostModuleActuator_MSG.get(305), {}) return context # 处理模块参数 try: custom_param = json.loads(custom_param) except Exception as E: logger.warning(E) custom_param = {} # 获取模块实例 class_intent = importlib.import_module(loadpath) post_module_intent = class_intent.PostModule(sessionid, hid, custom_param) # 模块前序检查,调用check函数 try: flag, msg = post_module_intent.check() if flag is not True: # 如果检查未通过,返回未通过原因(msg) context = data_return(405, msg, {}) return context except Exception as E: logger.warning(E) context = data_return(301, PostModuleActuator_MSG.get(301), {}) return context try: broker = post_module_intent.MODULE_BROKER except Exception as E: logger.warning(E) context = data_return(305, PostModuleActuator_MSG.get(305), {}) return context if broker == BROKER.post_python_job: # 放入多模块队列 if aps_module.putin_post_python_module_queue(post_module_intent): context = data_return(201, PostModuleActuator_MSG.get(201), {}) return context else: context = data_return(306, PostModuleActuator_MSG.get(306), {}) return context elif broker == BROKER.post_msf_job: # 放入后台运行队列 if MSFModule.putin_post_msf_module_queue(post_module_intent): context = data_return(201, PostModuleActuator_MSG.get(201), {}) return context else: context = data_return(306, PostModuleActuator_MSG.get(306), {}) return context else: logger.warning("错误的broker")
def update(ipaddress=None, sessionid=None): old_result = Xcache.get_sessionio_cache(ipaddress) if sessionid is None or sessionid == -1: context = data_return(202, SessionIO_MSG.get(202), old_result) return context try: params = [sessionid] result = RpcClient.call(Method.SessionMeterpreterRead, params) if result is None or (isinstance(result, dict) is not True): context = data_return(303, SessionIO_MSG.get(303), old_result) return context new_bufer = result.get('data') result = Xcache.add_sessionio_cache(ipaddress, new_bufer) context = data_return(200, CODE_MSG.get(200), result) # code特殊处理 except Exception as E: logger.error(E) context = data_return(306, SessionIO_MSG.get(405), old_result) return context
def list(): from Msgrpc.Handle.handler import Handler data = Xcache.list_lazyloader() handlers = Handler.list_handler_config() context = data_return(200, CODE_MSG.get(200), { "lazyloaders": data, "handlers": handlers }) return context
def get_asn(ip): asn_reader = Xcache.get_asn_reader_cache(ip) if asn_reader is not None: return asn_reader asn_mmdb_dir = os.path.join(settings.BASE_DIR, 'STATICFILES', 'STATIC', 'GeoLite2-ASN.mmdb') asn_reader = geoip2.database.Reader(asn_mmdb_dir) try: response = asn_reader.asn(ip) except Exception as _: Xcache.set_asn_reader_cache(ip, "") return "" Xcache.set_asn_reader_cache(ip, response.autonomous_system_organization) return response.autonomous_system_organization
def update(loader_uuid, field, data): if field == "payload": try: data = json.loads(data) except Exception as E: logger.warning(E) context = data_return(303, LazyLoader_MSG.get(303), []) return context lazyloader = Xcache.get_lazyloader_by_uuid(loader_uuid) if lazyloader is None: context = data_return(304, LazyLoader_MSG.get(304), {}) return context else: lazyloader[field] = data Xcache.set_lazyloader_by_uuid(loader_uuid, lazyloader) context = data_return(201, LazyLoader_MSG.get(201), data) return context
def run_bot_wait_list(): # 检查当前任务数量是否大于3个 task_queue_length = Xcache.get_module_task_length() if task_queue_length >= 3: return req = Xcache.pop_one_from_bot_wait() if req is None: return broker = req.get("broker") module_intent = req.get("module") if broker == BROKER.bot_msf_job: # 放入后台运行队列 MSFModule.putin_post_msf_module_queue(module_intent) else: logger.error("unknow broker")
def putin_post_msf_module_queue(msf_module=None): """调用msgrpc生成job,放入列表""" params = [ msf_module.type, msf_module.mname, msf_module.opts, True, # 强制设置后台运行 0 # 超时时间 ] result = RpcClient.call(Method.ModuleExecute, params) if result is None: Notice.send_warning(f"渗透服务连接失败,无法执行模块 :{msf_module.NAME}") return False elif result == "license expire": Notice.send_warning(f"License 过期,无法执行模块 :{msf_module.NAME}") return False # result 数据格式 # {'job_id': 3, 'uuid': 'dbcb2530-95b1-0137-5100-000c2966078a', 'module': b'\x80\ub.'} if result.get("job_id") is None: logger.warning("模块实例:{} uuid: {} 创建后台任务失败".format( msf_module.NAME, result.get("uuid"))) Notice.send_warning("模块: {} {} 创建后台任务失败,请检查输入参数".format( msf_module.NAME, msf_module.target_str)) return False else: logger.warning("模块实例放入列表:{} job_id: {} uuid: {}".format( msf_module.NAME, result.get("job_id"), result.get("uuid"))) # 放入请求队列 req = { 'broker': msf_module.MODULE_BROKER, 'uuid': result.get("uuid"), 'module': msf_module, 'time': int(time.time()), 'job_id': result.get("job_id"), } Xcache.create_module_task(req) Notice.send_info("模块: {} {} 开始执行".format(msf_module.NAME, msf_module.target_str)) return True
def tabs(line=None): cid = Xcache.get_console_id() if cid is None: return False, {} params = [cid, line] result = RpcClient.call(Method.ConsoleTabs, params) if result is None or result.get("result") == "failure": logger.warning("Cid: {}错误".format(cid)) return False, {} else: return True, result
def init_conf_from_cache(self): conf = Xcache.get_fofa_conf() if conf is None: return False else: if conf.get("alive") is not True: return False else: self.email = conf.get("email") self.key = conf.get("key") return True
def decrypt_file_name(enfilename): key = Xcache.get_aes_key() pr = Aescrypt(key, 'ECB', '', 'utf-8') try: enfilename_url = parse.unquote(enfilename) filename = pr.aesdecrypt(enfilename_url) return filename except Exception as E: logger.exception(E) return None
def get_city(ip): result = Xcache.get_city_reader_cache(ip) if result is not None: return result city_mmdb_dir = os.path.join(settings.BASE_DIR, 'STATICFILES', 'STATIC', 'GeoLite2-City.mmdb') city_reader = geoip2.database.Reader(city_mmdb_dir) try: response = city_reader.city(ip) except Exception as _: Xcache.set_city_reader_cache(ip, "局域网") return "局域网" country = "" try: country = response.country.name country = response.country.names['zh-CN'] except Exception as E: logger.exception(E) if country is None: country = "" subdivision = "" try: subdivision = response.subdivisions.most_specific.name subdivision = response.subdivisions.most_specific.names['zh-CN'] except Exception as _: pass if subdivision is None: subdivision = "" city = "" try: city = response.city.name city = response.city.names['zh-CN'] except Exception as _: pass if city is None: city = "" result = f"{country} {subdivision} {city}" Xcache.set_city_reader_cache(ip, result) return result
def store_executed_result(task_uuid=None): req = Xcache.get_module_task_by_uuid(task_uuid=task_uuid) if req is None: logger.warning("缓存中无对应实例,可能已经模块已经中途退出") return False module_common_instance = req.get("module") # 存储运行结果 try: module_common_instance._store_result_in_history() Notice.send_success( "模块: {} {} 执行完成".format(module_common_instance.NAME, module_common_instance.target_str)) logger.warning("多模块实例执行完成:{}".format(module_common_instance.NAME)) Xcache.del_module_task_by_uuid(task_uuid=task_uuid) # 清理缓存信息 return True except Exception as E: Xcache.del_module_task_by_uuid(task_uuid=task_uuid) # 清理缓存信息 logger.error("多模块实例执行异常:{} 异常信息: {}".format(module_common_instance.NAME, E)) Notice.send_exception("模块: {} 执行异常,异常信息: {}".format(module_common_instance.NAME, E)) logger.error(E) return False