async def get_all_tasks(request): callbacks = Callback.select() operators = Operator.select() tasks = Task.select() # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) full_task_data = await db_objects.prefetch(tasks, callbacks, operators) return json([c.to_json() for c in full_task_data])
async def ws_operators(request, ws): try: async with aiopg.create_pool(apfell.config['DB_POOL_CONNECT_STRING']) as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute('LISTEN "newoperator";') # BEFORE WE START GETTING NEW THINGS, UPDATE WITH ALL OF THE OLD DATA operators = await db_objects.execute(Operator.select()) for o in operators: await ws.send(js.dumps(o.to_json())) await ws.send("") # now pull off any new payloads we got queued up while processing old data while True: try: msg = conn.notifies.get_nowait() id = (msg.payload) p = await db_objects.get(Operator, id=id) await ws.send(js.dumps(p.to_json())) except asyncio.QueueEmpty as e: await asyncio.sleep(2) await ws.send("") # this is our test to see if the client is still there continue except Exception as e: print(e) return finally: pool.close()
async def ws_tasks(request, ws): try: async with aiopg.create_pool(apfell.config['DB_POOL_CONNECT_STRING']) as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute('LISTEN "newtask";') # before we start getting new things, update with all of the old data callbacks = Callback.select() operators = Operator.select() tasks = Task.select() tasks_with_all_info = await db_objects.prefetch(tasks, callbacks, operators) # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) for task in tasks_with_all_info: await ws.send(js.dumps(task.to_json())) await ws.send("") # now pull off any new tasks we got queued up while processing the old data while True: try: msg = conn.notifies.get_nowait() id = (msg.payload) tsk = await db_objects.get(Task, id=id) await ws.send(js.dumps(tsk.to_json())) except asyncio.QueueEmpty as e: await asyncio.sleep(2) await ws.send("") # this is our test to see if the client is still there continue except Exception as e: print(e) return finally: # print("closed /ws/tasks") pool.close()
async def ws_callbacks_current_operation(request, ws, user): try: async with aiopg.create_pool(apfell.config['DB_POOL_CONNECT_STRING']) as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute('LISTEN "newcallback";') if user['current_operation'] != "": # before we start getting new things, update with all of the old data operation = await db_objects.get(Operation, name=user['current_operation']) callbacks = Callback.select().where(Callback.operation == operation).order_by(Callback.id) operators = Operator.select() callbacks_with_operators = await db_objects.prefetch(callbacks, operators) for cb in callbacks_with_operators: await ws.send(js.dumps(cb.to_json())) await ws.send("") # now pull off any new callbacks we got queued up while processing the old data while True: # msg = await conn.notifies.get() try: msg = conn.notifies.get_nowait() id = (msg.payload) cb = await db_objects.get(Callback, id=id, operation=operation) await ws.send(js.dumps(cb.to_json())) except asyncio.QueueEmpty as e: await asyncio.sleep(0.5) await ws.send("") # this is our test to see if the client is still there continue except Exception as e: print(e) return finally: pool.close()
async def get_all_callbacks(request): #callbacks = await db_objects.execute(Callback.select(Callback, Operator).join(Operator)) #return json([c.to_json() for c in callbacks]) callbacks = Callback.select() operators = Operator.select() callbacks_with_operators = await db_objects.prefetch(callbacks, operators) return json([c.to_json() for c in callbacks_with_operators])
async def initial_setup(): # create apfell_admin operators = await db_objects.execute(Operator.select()) # mark all the profiles as stopped first since we just started the server await mark_profiles_as_not_running() if len(operators) != 0: print("Users already exist, exiting initial setup early") return admin, created = await db_objects.get_or_create( Operator, username="******", password= "******", admin=True, active=True) print("Created Admin") # create default operation operation, created = await db_objects.get_or_create(Operation, name='default', admin=admin, complete=False) print("Created Operation") await db_objects.get_or_create(OperatorOperation, operator=admin, operation=operation) print("Registered Admin with the default operation") print("Started parsing ATT&CK data...") file = open('./app/templates/attack.json', 'r') attack = js.load( file) # this is a lot of data and might take a hot second to load for obj in attack['techniques']: await db_objects.create(ATTACK, **obj) file.close() print("Created all ATT&CK entries") file = open("./app/templates/artifacts.json", "r") artifacts_file = js.load(file) for artifact in artifacts_file['artifacts']: await db_objects.get_or_create(Artifact, name=artifact['name'], description=artifact['description']) file.close() print("Created all base artifacts") file = open('./app/templates/apfell-jxa.json', 'r') apfell_jxa = js.load( file) # this is a lot of data and might take a hot second to load print("parsed apfell-jxa payload file") for ptype in apfell_jxa['payload_types']: await import_payload_type_func(ptype, admin, operation) file.close() print("created Apfell-jxa payload") file = open('./app/templates/linfell_c.json', 'r') linfell_c = js.load( file) # this is a lot of data and might take a hot second to load for ptype in linfell_c['payload_types']: await import_payload_type_func(ptype, admin, operation) file.close() print("created Linfell-c payload") await register_default_profile_operation(admin, operation) print("Successfully finished initial setup")
async def initial_setup(): # create mythic_admin operators = await db_objects.execute(Operator.select()) if len(operators) != 0: print("Users already exist, aborting initial install") await start_all_socks_after_restart() return password = await crypto.hash_SHA512(mythic_admin_password) admin, created = await db_objects.get_or_create(Operator, username=mythic_admin_user, password=password, admin=True, active=True) print("Created Admin") # create default operation AES_PSK = await create_key_AES256() operation, created = await db_objects.get_or_create( Operation, name=default_operation_name, admin=admin, complete=False, AESPSK=AES_PSK, ) print("Created Operation") await db_objects.get_or_create(OperatorOperation, operator=admin, operation=operation) admin.current_operation = operation await db_objects.update(admin) print("Registered Admin with the default operation") print("Started parsing ATT&CK data...") file = open("./app/default_files/other_info/attack.json", "r") attack = js.load( file) # this is a lot of data and might take a hot second to load for obj in attack["techniques"]: await db_objects.create(ATTACK, **obj) file.close() print("Created all ATT&CK entries") file = open("./app/default_files/other_info/artifacts.json", "r") artifacts_file = js.load(file) for artifact in artifacts_file["artifacts"]: await db_objects.get_or_create(Artifact, name=artifact["name"], description=artifact["description"]) file.close() print("Created all base artifacts") for base_file in glob.iglob("./app/default_files/c2_profiles/*"): file = open(base_file, "r") c2 = js.load(file) print("parsed {}".format(base_file)) # await import_c2_profile_func(c2, admin) print("Created all C2 Profiles") print("Successfully finished initial setup")
async def search(request, user): template = env.get_template('search.html') try: operator = Operator.get(Operator.username == user['username']) if use_ssl: content = template.render(links=links, name=user['username'], http="https", ws="wss") else: content = template.render(links=links, name=user['username'], http="http", ws="ws") return response.html(content) except Exception as e: print(e) return json({'status': 'error', 'error': 'Failed to find operator'})
async def get_all_tasks(request, user): callbacks = Callback.select() operators = Operator.select() tasks = Task.select() full_task_data = await db_objects.prefetch(tasks, callbacks, operators) if user['admin']: # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) return json([c.to_json() for c in full_task_data]) elif user['current_operation'] != "": operation = await db_objects.get(Operation, name=user['current_operation']) return json([c.to_json() for c in full_task_data if c.callback.operation == operation]) else: return json({'status': 'error', 'error': 'must be admin to see all tasks or part of a current operation'})
async def get_all_tasks(request, user): if user['admin']: callbacks = Callback.select() operators = Operator.select() tasks = Task.select() # callbacks_with_operators = await db_objects.prefetch(callbacks, operators) full_task_data = await db_objects.prefetch(tasks, callbacks, operators) return json([c.to_json() for c in full_task_data]) else: return json({ 'status': 'error', 'error': 'must be admin to see all tasks' })
async def settings(request, user): template = env.get_template('settings.html') try: operator = Operator.get(Operator.username == user['username']) op_json = operator.to_json() del op_json['ui_config'] if use_ssl: content = template.render(links=links, name=user['username'], http="https", ws="wss", op=op_json, config=user['ui_config']) else: content = template.render(links=links, name=user['username'], http="http", ws="ws", op=op_json, config=user['ui_config']) return response.html(content) except Exception as e: print(e) return json({'status': 'error', 'error': 'Failed to find operator'})
async def get_all_operators(request): ops = await db_objects.execute(Operator.select()) return json([p.to_json() for p in ops])
async def initial_setup(): # create apfell_admin operators = await db_objects.execute(Operator.select()) if len(operators) != 0: print("Users already exist, only handling transform updates") rsp = await write_transforms_to_file() if rsp['status'] == 'success': print("Successfully wrote transforms to file") rsp2 = await update_all_pt_transform_code() if rsp2['status'] == 'success': print("Successfully sent transforms to containers") else: print("Failed to send code to containers: " + rsp2['error']) else: print("Failed to write transforms to file: " + rsp['error']) return admin, created = await db_objects.get_or_create( Operator, username="******", password= "******", admin=True, active=True) print("Created Admin") # create default operation AES_PSK = await create_key_AES256() operation, created = await db_objects.get_or_create(Operation, name='default', admin=admin, complete=False, AESPSK=AES_PSK) print("Created Operation") await db_objects.get_or_create(OperatorOperation, operator=admin, operation=operation) print("Registered Admin with the default operation") print("Started parsing ATT&CK data...") file = open('./app/default_files/other_info/attack.json', 'r') attack = js.load( file) # this is a lot of data and might take a hot second to load for obj in attack['techniques']: await db_objects.create(ATTACK, **obj) file.close() print("Created all ATT&CK entries") file = open("./app/default_files/other_info/artifacts.json", "r") artifacts_file = js.load(file) for artifact in artifacts_file['artifacts']: await db_objects.get_or_create(Artifact, name=artifact['name'], description=artifact['description']) file.close() await register_default_profile_operation(admin) print("Created all base artifacts") for base_file in glob.iglob("./app/default_files/payload_types/*"): file = open(base_file, 'r') ptype = js.load(file) print("parsed {}".format(base_file)) for payload_type in ptype['payload_types']: await import_payload_type_func(payload_type, admin, operation) print("Created all payload types") print("registering initial browser scripts") code = open("./app/scripts/browser_scripts.json", 'r').read() code = js.loads(code) result = await import_browserscript_func(code, {"username": admin.username}) print("Generating initial transforms.py file") rsp = await write_transforms_to_file() if rsp['status'] == 'success': rsp2 = await update_all_pt_transform_code() if rsp2['status'] == 'success': print("Successfully sent transforms to containers") else: print("Failed to send code to containers: " + rsp2['error']) else: print("Failed to write transforms to file: " + rsp['error']) print("Successfully finished initial setup")
async def initial_setup(): # create apfell_admin operators = await db_objects.execute(Operator.select()) # mark all the profiles as stopped first since we just started the server await mark_profiles_as_not_running() if len(operators) != 0: print("Users already exist, exiting initial setup early") return admin, created = await db_objects.get_or_create(Operator, username="******", password="******", admin=True, active=True) print("Created Admin") # create default operation operation, created = await db_objects.get_or_create(Operation, name='default', admin=admin, complete=False) print("Created Operation") # create default payload types apfell_jxa_command_template = """exports.command_name = function(task, command, params){ //task is a dictionary of Task information //command is the single word command that caused this function to be called //params is a string of everything passed in except for the command // if you pass in a json blob on the command line, then to get json back here call JSON.parse(params); //do stuff here, with access to the following commands: does_file_exist(strPath); convert_to_nsdata(strData); write_data_to_file(data, filePath); base64_decode(data); base64_encode(data); }; """ payload_type_apfell_jxa, created = await db_objects.get_or_create(PayloadType, ptype='apfell-jxa', operator=admin, file_extension=".js", wrapper=False, command_template=apfell_jxa_command_template) #c2_profile, pt_c2_profile = await create_default_c2_for_operation(operation, admin, [payload_type_apfell_jxa]) await register_default_profile_operation({"username": "******"}, "default") # create the default transforms for apfell-jxa payloads jxa_load_transform = await db_objects.get_or_create(Transform, name="readCommands", t_type="load", order=1, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="combineAppend", t_type="load", order=2, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="convertBytesToString", t_type="load", order=3, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="removeSlashes", t_type="load", order=4, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="strToByteArray", t_type="load", order=5, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="writeFile", t_type="load", order=6, payload_type=payload_type_apfell_jxa, operator=admin) print("Created Apfell-jxa payload type") # add the apfell_admin to the default operation await db_objects.get_or_create(OperatorOperation, operator=admin, operation=operation) print("Registered Admin with the default operation") # Register commands for created payload types file = open("./app/templates/default_commands.json", "r") command_file = js.load(file) for cmd_group in command_file['payload_types']: for cmd in cmd_group['commands']: if cmd['needs_admin'] == "false": cmd['needs_admin'] = False else: cmd['needs_admin'] = True command, created = await db_objects.get_or_create(Command, cmd=cmd['cmd'], needs_admin=cmd['needs_admin'], description=cmd['description'], help_cmd=cmd['help_cmd'], payload_type=payload_type_apfell_jxa, operator=admin) for param in cmd['parameters']: try: if param['required'] == "false": param['required'] = False else: param['required'] = True await db_objects.get_or_create(CommandParameters, command=command, **param, operator=admin) except Exception as e: print(e) print("Created all commands and command parameters") file.close()
async def initial_setup(): # create apfell_admin operators = await db_objects.execute(Operator.select()) # mark all the profiles as stopped first since we just started the server await mark_profiles_as_not_running() if len(operators) != 0: print("Users already exist, exiting initial setup early") return admin, created = await db_objects.get_or_create(Operator, username="******", password="******", admin=True, active=True) print("Created Admin") # create default operation operation, created = await db_objects.get_or_create(Operation, name='default', admin=admin, complete=False) print("Created Operation") # create default payload types payload_type_apfell_jxa, created = await db_objects.get_or_create(PayloadType, ptype='apfell-jxa', operator=admin, file_extension=".js", wrapper=False) #c2_profile, pt_c2_profile = await create_default_c2_for_operation(operation, admin, [payload_type_apfell_jxa]) await register_default_profile_operation({"username": "******"}, "default") # create the default transforms for apfell-jxa payloads jxa_load_transform = await db_objects.get_or_create(Transform, name="readCommands", t_type="load", order=1, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="combineAppend", t_type="load", order=2, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="convertBytesToString", t_type="load", order=3, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="removeSlashes", t_type="load", order=4, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="strToByteArray", t_type="load", order=5, payload_type=payload_type_apfell_jxa, operator=admin) jxa_load_transform = await db_objects.get_or_create(Transform, name="writeFile", t_type="load", order=6, payload_type=payload_type_apfell_jxa, operator=admin) print("Created Apfell-jxa payload type") # add the apfell_admin to the default operation await db_objects.get_or_create(OperatorOperation, operator=admin, operation=operation) print("Registered Admin with the default operation") # Register commands for created payload types file = open("./app/templates/default_commands.json", "r") command_file = js.load(file) for cmd_group in command_file['payload_types']: for cmd in cmd_group['commands']: if cmd['needs_admin'] == "false": cmd['needs_admin'] = False else: cmd['needs_admin'] = True command, created = await db_objects.get_or_create(Command, cmd=cmd['cmd'], needs_admin=cmd['needs_admin'], description=cmd['description'], help_cmd=cmd['help_cmd'], payload_type=payload_type_apfell_jxa, operator=admin) for param in cmd['parameters']: try: if param['required'] == "false": param['required'] = False else: param['required'] = True await db_objects.get_or_create(CommandParameters, command=command, **param, operator=admin) except Exception as e: print(e) print("Created all commands and command parameters") file.close()