def first_heartbeat_result(): hosts_sorted = HostAndSession.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 = Notices.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 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 = list_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 = dict_data_return(200, CODE_MSG.get(200), new_module_config) return context # 没有找到模块 context = dict_data_return(200, CODE_MSG.get(200), {}) return context
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 store_result_in_result_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 create_bot(ipportlist=None, custom_param=None, loadpath=None): module_config = Xcache.get_moduleconfig(loadpath) # 获取模块配置 if module_config is None: context = dict_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) # 模块前序检查,调用check函数 try: flag, msg = post_module_intent.check() if flag is not True: # 如果检查未通过,返回未通过原因(msg) Notices.send_warning( f"模块:{post_module_intent.NAME} IP:{ipport.get('ip')} 检查未通过,原因:{msg}" ) continue except Exception as E: logger.warning(E) Notices.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 = dict_data_return(201, PostModuleActuator_MSG.get(201), {}) return context
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 update(): PostModuleConfig.load_all_modules_config() all_modules_config = Xcache.list_moduleconfigs() for one in all_modules_config: one['OPTIONS'] = [] context = list_data_return(201, PostModuleConfig_MSG.get(201), all_modules_config) return context
def list(hid=None, loadpath=None): host = Host.get_by_hid(hid) result = Xcache.get_module_result(ipaddress=host.get("ipaddress"), loadpath=loadpath) result_dict = { "hid": hid, "loadpath": loadpath, "update_time": result.get("update_time"), "result": result.get("result") } context = dict_data_return(200, CODE_MSG.get(200), result_dict) return context
def connect(self): """ 打开 websocket 连接 :return: """ async_to_sync(self.channel_layer.group_add)("heartbeat", self.channel_name) self.accept() query_string = self.scope.get('query_string') ssh_args = QueryDict(query_string=query_string, encoding='utf-8') token = ssh_args.get('token') if Xcache.alive_token(token): result = HeartBeat.first_heartbeat_result() self.send(json.dumps(result)) return else: self.disconnect()
def thread_run(self): t1 = ThreadWithExc(target=self.run) t1.start() while True: req = Xcache.get_module_task_by_uuid_nowait(self.module_self_uuid) if req is None: # 检查模块是否已经删除 self.exit_flag = True time.sleep(3) while t1.is_alive(): time.sleep(0.1) try: t1.raise_exc(Exception) except Exception as _: pass break elif t1.is_alive() is not True: break else: time.sleep(1)
def connect(self): """ 打开 websocket 连接 :return: """ async_to_sync(self.channel_layer.group_add)("msfconsole", self.channel_name) self.accept() query_string = self.scope.get('query_string') ssh_args = QueryDict(query_string=query_string, encoding='utf-8') token = ssh_args.get('token') if Xcache.alive_token(token): result = Console.get_active_console() if result: return else: self.disconnect(True) return else: self.disconnect(True)
def get_heartbeat_result(): result = {} # hosts_sorted hosts_sorted = HostAndSession.list_hostandsession() cache_hosts_sorted = Xcache.get_heartbeat_cache_hosts_sorted() if cache_hosts_sorted == hosts_sorted: result["hosts_sorted_update"] = False result["hosts_sorted"] = [] else: Xcache.set_heartbeat_cache_hosts_sorted(hosts_sorted) result["hosts_sorted_update"] = True result["hosts_sorted"] = hosts_sorted # result_history 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 cache_result_history = Xcache.get_heartbeat_cache_result_history() if cache_result_history == result_history: result["result_history_update"] = False result["result_history"] = [] else: Xcache.set_heartbeat_cache_result_history(result_history) result["result_history_update"] = True result["result_history"] = result_history # notices notices = Notices.list_notices() cache_notices = Xcache.get_heartbeat_cache_notices() if cache_notices == notices: result["notices_update"] = False result["notices"] = [] else: Xcache.set_heartbeat_cache_notices(notices) result["notices_update"] = True result["notices"] = notices # 任务队列长度 task_queue_length = Xcache.get_module_task_length() result["task_queue_length"] = task_queue_length # jobs 列表 jobs = Job.list_jobs() cache_jobs = Xcache.get_heartbeat_cache_jobs() if cache_jobs == jobs: result["jobs_update"] = False result["jobs"] = [] else: Xcache.set_heartbeat_cache_jobs(jobs) result["jobs_update"] = True result["jobs"] = jobs # bot_wait_list 列表 bot_wait_list = Job.list_bot_wait() cache_bot_wait_list = Xcache.get_heartbeat_cache_bot_wait_list() if cache_bot_wait_list == bot_wait_list: result["bot_wait_list_update"] = False result["bot_wait_list"] = [] else: Xcache.set_heartbeat_cache_bot_wait_list(bot_wait_list) result["bot_wait_list_update"] = True result["bot_wait_list"] = bot_wait_list return result
def create_post(loadpath=None, sessionid=None, hid=None, custom_param=None): module_config = Xcache.get_moduleconfig(loadpath) # 获取模块配置 if module_config is None: context = dict_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 = dict_data_return(405, msg, {}) return context except Exception as E: logger.warning(E) context = dict_data_return(301, PostModuleActuator_MSG.get(301), {}) return context try: broker = post_module_intent.MODULE_BROKER except Exception as E: logger.warning(E) context = dict_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 = dict_data_return(201, PostModuleActuator_MSG.get(201), {}) return context else: context = dict_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 = dict_data_return(201, PostModuleActuator_MSG.get(201), {}) return context else: context = dict_data_return(306, PostModuleActuator_MSG.get(306), {}) return context else: logger.warning("错误的broker")
def destory(): Xcache.del_module_result_history() context = dict_data_return(204, PostModuleResultHistory_MSG.get(204), {}) return context
def log_except(self, result_line): result_format = "[x] {} \n".format(result_line) Xcache.add_module_result(self.host_ipaddress, self.loadpath, result_format)
def log_raw(self, result_line): if not result_line.endswith('\n'): result_line = "{}\n".format(result_line) Xcache.add_module_result(self.host_ipaddress, self.loadpath, result_line)
def store_log(self, result_format): """API:存储结果到数据库""" result_format = result_format.strip() Xcache.set_module_result(self.host_ipaddress, self.loadpath, result_format)
def clean_log(self): flag = Xcache.set_module_result(self.host_ipaddress, self.loadpath, "") return flag
def receive(self, text_data=None, bytes_data=None): """接收前端用户输入""" message = json.loads(text_data) input_data = message.get("data") # \r \t \x7f # ctrl+c \x03 # ctrl+z \x1a cache_str = Xcache.get_msfconsoleinputcache() # 输入处理 if input_data == "\r" or input_data == "\r\n": Xcache.add_to_msfconsole_history_cache(cache_str) if cache_str.lower() == "exit -f": cache_str = "exit" elif cache_str.lower() == "viper": Console.reset_active_console() cache_str = "" Console.write(cache_str + "\r\n") Xcache.clean_msfconsoleinputcache() self.send_input_feedback("\r\n") Thread(target=self.send_msfrpc_read).start() elif input_data == "\x7f": # 删除键 return_str = Xcache.del_one_from_msfconsoleinputcache() self.send_input_feedback(return_str) elif input_data == "\t": # tab键 flag, result = Console.tabs(cache_str) if flag is not True: extra_str = "\r\nConnect Error >" self.send_input_feedback(extra_str) return tabs = result.get("tabs") if tabs == None or len(tabs) == 0: return elif len(tabs) == 1: extra_str = tabs[0][len(cache_str):] self.send_input_feedback(extra_str) Xcache.add_to_msfconsoleinputcache(extra_str) else: tmp = self.deal_tabs_options(cache_str, tabs) if tmp is None or tmp == cache_str: extra_str = "\r\n" for one in tabs: extra_str = extra_str + one + "\r\n" prompt = result.get("prompt") extra_str = extra_str + prompt + cache_str self.send_input_feedback(extra_str) else: extra_str = tmp[len(cache_str):] self.send_input_feedback(extra_str) Xcache.add_to_msfconsoleinputcache(extra_str) elif input_data == "\x1b[A": # 上键 clear_cmd = Xcache.clear_oneline_from_msfconsoleinputcache() self.send_input_feedback(clear_cmd) last = Xcache.get_last_from_msfconsole_history_cache() if last is None: pass else: Xcache.add_to_msfconsoleinputcache(last) self.send_input_feedback(last) elif input_data == "\x1b[B": # 上键 clear_cmd = Xcache.clear_oneline_from_msfconsoleinputcache() self.send_input_feedback(clear_cmd) last = Xcache.get_next_from_msfconsole_history_cache() if last is None: pass else: Xcache.add_to_msfconsoleinputcache(last) self.send_input_feedback(last) elif input_data == '\x03': # ctrl+c Console.session_kill() Xcache.clean_msfconsoleinputcache() Console.write("\r\n") self.send_input_feedback("\r\n") Thread(target=self.send_msfrpc_read).start() elif input_data == '\x1a': # ctrl+z Console.session_detach() Xcache.clean_msfconsoleinputcache() Console.write("\r\n") self.send_input_feedback("\r\n") Thread(target=self.send_msfrpc_read).start() else: Xcache.add_to_msfconsoleinputcache(input_data) self.send_input_feedback(input_data)
def load_all_modules_config(): def _sort_by_moduletype(module_config=None): return TAG2CH.get_moduletype_order(module_config.get('MODULETYPE')) all_modules_config = [] # viper 内置模块 viper_module_count = 0 modulenames = os.listdir(os.path.join(settings.BASE_DIR, 'MODULES')) for modulename in modulenames: modulename = modulename.split(".")[0] if modulename == "__init__" or modulename == "__pycache__": # __init__.py的特殊处理 continue class_intent = importlib.import_module( 'MODULES.{}'.format(modulename)) try: if isinstance(class_intent.PostModule.ATTCK, str): attck = [class_intent.PostModule.ATTCK] elif isinstance(class_intent.PostModule.ATTCK, list): attck = [class_intent.PostModule.ATTCK] else: attck = [] one_module_config = { "BROKER": class_intent.PostModule.MODULE_BROKER, # 处理器 "NAME": class_intent.PostModule.NAME, "DESC": class_intent.PostModule.DESC, "WARN": class_intent.PostModule.WARN, "AUTHOR": class_intent.PostModule.AUTHOR, "REFERENCES": class_intent.PostModule.REFERENCES, "MODULETYPE": class_intent.PostModule.MODULETYPE, "OPTIONS": class_intent.PostModule.OPTIONS, "loadpath": 'MODULES.{}'.format(modulename), # post类配置 "REQUIRE_SESSION": class_intent.PostModule.REQUIRE_SESSION, "PLATFORM": class_intent.PostModule.PLATFORM, "PERMISSIONS": class_intent.PostModule.PERMISSIONS, "ATTCK": attck, # bot类配置 "SEARCH": class_intent.PostModule.SEARCH, } all_modules_config.append(one_module_config) viper_module_count += 1 except Exception as E: logger.error(E) continue logger.warning("内置模块加载完成,加载{}个模块".format(viper_module_count)) Notices.send_success(f"内置模块加载完成,加载{viper_module_count}个模块") # 自定义模块 diy_module_count = 0 modulenames = os.listdir( os.path.join(settings.BASE_DIR, 'Docker', "module")) for modulename in modulenames: modulename = modulename.split(".")[0] if modulename == "__init__" or modulename == "__pycache__": # __init__.py的特殊处理 continue class_intent = importlib.import_module( 'Docker.module.{}'.format(modulename)) importlib.reload(class_intent) try: if isinstance(class_intent.PostModule.ATTCK, str): attck = [class_intent.PostModule.ATTCK] elif isinstance(class_intent.PostModule.ATTCK, list): attck = [class_intent.PostModule.ATTCK] else: attck = [] one_module_config = { "BROKER": class_intent.PostModule.MODULE_BROKER, # 处理器 "NAME": class_intent.PostModule.NAME, "DESC": class_intent.PostModule.DESC, "WARN": class_intent.PostModule.WARN, "AUTHOR": class_intent.PostModule.AUTHOR, "REFERENCES": class_intent.PostModule.REFERENCES, "MODULETYPE": class_intent.PostModule.MODULETYPE, "OPTIONS": class_intent.PostModule.OPTIONS, "loadpath": 'Docker.module.{}'.format(modulename), # post类配置 "REQUIRE_SESSION": class_intent.PostModule.REQUIRE_SESSION, "PLATFORM": class_intent.PostModule.PLATFORM, "PERMISSIONS": class_intent.PostModule.PERMISSIONS, "ATTCK": attck, # bot类配置 "SEARCH": class_intent.PostModule.SEARCH, } all_modules_config.append(one_module_config) diy_module_count += 1 except Exception as E: logger.error(E) continue logger.warning("自定义模块加载完成,加载{}个模块".format(diy_module_count)) Notices.send_success(f"自定义模块加载完成,加载{diy_module_count}个模块") all_modules_config.sort(key=_sort_by_moduletype) if Xcache.update_moduleconfigs(all_modules_config): return len(all_modules_config) else: return 0
def get_module_name_by_loadpath(loadpath=None): module_config = Xcache.get_moduleconfig(loadpath) if module_config is not None: return module_config.get('NAME') else: return None