def _deal_powershell_json_result(result): result_without_error = re.sub('ERROR:.+\s', '', result) result_without_empty = result_without_error.replace('\r', '').replace('\n', '').replace('\t', '') try: result_json = json.loads(result_without_empty) return result_json except Exception as E: logger.warning(E) logger.warning("解析powershell结果失败") return None
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 find_local_admin_access(self): module_type = 'post' mname = 'windows/manage/powershell/exec_powershell_function_mem' opts = { 'SESSION': self._sessionid, 'SCRIPT': 'PowerView_dev.ps1', 'EXECUTE_STRING': 'Find-LocalAdminAccess -Delay 1', 'CHECK_FUNCTION': False, } result = MsfModule.run_with_output(module_type, mname, opts) try: result_json = json.loads(result.replace('\r', '').replace('\n', '').replace('\t', '')) return result_json except Exception as E: logger.warning(E) return None
def get_group_member(self, group): module_type = 'post' mname = 'windows/manage/powershell/exec_powershell_function_mem' opts = { 'SESSION': self._sessionid, 'SCRIPT': 'PowerView_dev.ps1', 'EXECUTE_STRING': ' \'{}\' | Get-DomainGroupMember'.format(group), 'CHECK_FUNCTION': False, } result = MsfModule.run_with_output(module_type, mname, opts) try: result_json = json.loads(result.replace('\r', '').replace('\n', '').replace('\t', '')) return result_json except Exception as E: logger.warning(E) return None
def param(self, name): """获取输入参数的接口""" if name in [ HANDLER_OPTION.get('name'), CREDENTIAL_OPTION.get('name'), FILE_OPTION.get('name') ]: if self._custom_param.get(name) is None: return None try: tmp_param = json.loads(self._custom_param.get(name)) return tmp_param except Exception as E: logger.warning(E) return None else: return self._custom_param.get(name)
def add_credential(username='', password='', password_type='', tag=None, source_module='', host_ipaddress='', desc=''): if tag is None: tag = {} if isinstance(tag, dict) is not True: logger.warning('数据类型检查错误,数据 {}'.format(tag)) tag = {} if password is '' or password.find('n.a.(') > 0 or len(password) > 100: return False result = postCredential.add_or_update(username, password, password_type, tag, source_module, host_ipaddress, desc) return result
def add_vulnerability(hid_or_ipaddress=None, source_module_loadpath='', extra_data=None, desc=''): if extra_data is None: extra_data = {} if isinstance(extra_data, dict) is not True: logger.warning('数据类型检查错误,数据 {}'.format(extra_data)) extra_data = {} if isinstance(hid_or_ipaddress, int): result = postVulnerability.add_or_update(hid_or_ipaddress, source_module_loadpath, extra_data, desc) return result elif isinstance(hid_or_ipaddress, str): result = postVulnerability.add_or_update( Host.get_by_ipaddress(hid_or_ipaddress).get('id'), source_module_loadpath, extra_data, desc) return result
def get_celery_result_scheduler(self): """循环调用函数,用于处理celery结果""" try: msg = self.redis_celery_result_sub.parse_response() except Exception as E: logger.warning("redis连接错误") return False try: result = json.loads(msg[2]) task_id = result.get('task_id') status = result.get('status') retval = result.get('retval') einfo = result.get('einfo') logger.info("开始存储任务结果,task_id: {}".format(task_id)) flag = Task.update_task(task_id=task_id, status=status, retval=retval, einfo=einfo) logger.info("存储任务完成,task_id: {}".format(task_id)) return True except Exception as E: logger.warning("json解析task结果失败,详细信息: {} 异常:{}".format(msg, E))
def __init__(self): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("127.0.0.1", 47200)) except socket.error: logger.warning("Monitor 已经启动") return # 初始化redis实例 self.redisHelper = RedisHelper() self.redis_celery_result_sub = self.redisHelper.subscribe( REDIS_CELERY_RESULT_CHANNEL) log = logging.getLogger('apscheduler.scheduler') log.setLevel(logging.ERROR) # 关闭apscheduler的警告 self.Scheduler = BackgroundScheduler() self.Scheduler.add_job(func=self.get_celery_result_scheduler, max_instances=1, trigger='interval', seconds=5, id='get_celery_result_scheduler') self.Scheduler.start() logger.warning("Monitor 启动完成")
def _webcheck_store(pid, retval): logger.info("wafw00f 存储结果: {} {}".format(pid, retval)) for one in retval: website = one.get('website') wid = Website.get_wid_by_website(pid, website) if wid is None: logger.warning("数据库中无法找到网站:{}".format(website)) continue else: # 更新网站存活信息 Website.update_website_alive(wid, one.get('alive')) # 更新cdn信息 WebsiteCDN.update_website_cdn(wid=wid, hascdn=one.get('hascdn'), ipaddress=one.get('ipaddress'), title=one.get('title')) # 更新techs信息 techs = one.get('techs') for tech in techs: WebsiteTech.update_website_tech(wid=wid, name=tech.get('name'), version=tech.get('version'), icon=tech.get('icon')) # 更新waf信息 waf = one.get('waf') WebsiteWaf.update_website_waf(wid=wid, hasWaf=waf.get('haswaf'), waf=waf.get('waf'), detect_tech=waf.get('detectTech')) return True
def callback(self, status, message, data): """后台运行模块回调函数""" logger.warning(self.type) logger.warning(self.mname) logger.warning(self.opts)
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 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 _deal_dynamic_option(one_module_config=None): """处理handler及凭证等动态变化参数,返回处理后参数列表""" options = one_module_config.get('OPTIONS') for option in options: # handler处理 if option.get('name') == HANDLER_OPTION.get("name"): handlers = Handler.list_handler() tmp_enum_list = [] for handler in handlers: import json lhost_str = "" rhost_srt = "" if handler.get('LHOST') is None: try: handler.pop('LHOST') except Exception as _: pass else: lhost_str = "LHOST:{} | ".format(handler.get('LHOST')) if handler.get('RHOST') is None: try: handler.pop('RHOST') except Exception as _: pass else: rhost_srt = "RHOST:{} | ".format(handler.get('RHOST')) # 虚拟监听与真实监听标签 if handler.get("ID") < 0: handlertag = "虚拟 | " else: handlertag = "" if handler.get("HandlerName") is None: name = f"{handlertag}{handler.get('PAYLOAD')} | {lhost_str}{rhost_srt} LPORT:{handler.get('LPORT')}" else: name = f"{handlertag}{handler.get('HandlerName')} | {handler.get('PAYLOAD')} | {lhost_str}{rhost_srt} LPORT:{handler.get('LPORT')}" value = json.dumps(handler) tmp_enum_list.append({'name': name, 'value': value}) option['enum_list'] = tmp_enum_list if len(tmp_enum_list) == 1: # 只有一个监听 option['default'] = tmp_enum_list[0].get("value") # 凭证处理 elif option.get('name') == CREDENTIAL_OPTION.get("name"): credentials = Credential.list_credential() tmp_enum_list = [] try: if option.get('extra_data') is None or option.get( 'extra_data').get('password_type') is None: pass else: type_list = option.get('extra_data').get( 'password_type') for credential in credentials: if credential.get('password_type') in type_list: name = "用户名:{} | 密码:{} | 标签:{} | 主机:{}".format( credential.get('username'), credential.get('password'), credential.get('tag'), credential.get('host_ipaddress')) import json value = json.dumps(credential) tmp_enum_list.append({ 'name': name, 'value': value }) option['enum_list'] = tmp_enum_list except Exception as E: logger.warning(E) # 文件处理 elif option.get('name') == FILE_OPTION.get("name"): if option.get('extra_data') is None or option.get( 'extra_data').get('file_extension') is None: file_extension_list = None else: file_extension_list = option.get('extra_data').get( 'file_extension') files = FileMsf.list_msf_files() tmp_enum_list = [] for file in files: import json # { # "filename": "test", # "filesize": 0, # "mtime": 1552273961 # }, name = file.get("name") size = FileSession.get_size_in_nice_string( file.get('size')) mtime = file.get("mtime") style_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(mtime)) show = False # 是否满足文件后缀要求 if isinstance(file_extension_list, list): for ext in file_extension_list: if name.lower().endswith(ext.lower()): show = True else: show = True if show: name = "文件: {} 大小: {} 修改时间: {}".format( name, size, style_time) value = json.dumps(file) tmp_enum_list.append({'name': name, 'value': value}) option['enum_list'] = tmp_enum_list return one_module_config