async def ws_payloadtypes(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 "newpayloadtype";') # BEFORE WE START GETTING NEW THINGS, UPDATE WITH ALL OF THE OLD DATA payloadtypes = await db_objects.execute(PayloadType.select().order_by(PayloadType.id)) for p in payloadtypes: await ws.send(js.dumps(p.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(PayloadType, 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 update_c2profile(request, info, user): name = unquote_plus(info) data = request.json payload_types = [] try: # TODO make sure the user has appropriate access to the c2_profile by checking operations scopes profile = await db_objects.get(C2Profile, name=name) except Exception as e: print(e) return json({'status': 'error', 'error': 'failed to find C2 Profile'}) try: if 'description' in data: profile.description = data['description'] if 'payload_types' in data: # We need to update the mapping in PayloadTypeC2Profile accordingly # We need to see which ones were there before, and either add or delete accordingly mapping = await db_objects.execute( PayloadTypeC2Profile.select().where( PayloadTypeC2Profile.c2_profile == profile)) # For each payload type, make sure it's real, and that it's in the mapping for m in mapping: map = await db_objects.get(PayloadType, id=m.payload_type) if map.ptype in data['payload_types']: # something we say this c2 profile supports is already listed, so remove it from our list to process del data['payload_types'][data['payload_types'].index( map.ptype)] # remove it from the array payload_types.append(map.ptype) else: # it was in our mapping, now it's not, so remove it from the database mapping await db_objects.delete(m) # if there's anyting left in data['payload_types'], it means we need to add it to the database for m in data['payload_types']: if await db_objects.count(PayloadType.select().where( PayloadType.ptype == m.strip())) != 1: return json({ 'status': 'error', 'error': m + ' is not a valid PayloadType. Perhaps you need to register it first?' }) payload = await db_objects.get(PayloadType, ptype=m.strip()) await db_objects.create(PayloadTypeC2Profile, c2_profile=profile, payload_type=payload) payload_types.append(m.strip()) success = {'status': 'success'} updated_json = profile.to_json() return json({ **success, **updated_json, 'payload_types': payload_types }) except Exception as e: print(e) return json({ 'status': 'error', 'error': 'failed to update C2 Profile' })
async def register_new_c2profile(request, user): data = request.json #print(data) data['operator'] = user['username'] if 'name' not in data or data['name'] is "": return json({'status': 'error', 'error': 'name is required'}) if 'description' not in data: data['description'] = "" if 'payload_types' not in data: return json({ 'status': 'error', 'error': 'payload_types is required information' }) # we need to 1. make sure these are all valid payload types, and 2. create payloadtypec2profile entries as well for t in data['payload_types']: # this should be an array we can iterate over if await db_objects.count(PayloadType.select().where( PayloadType.ptype == t.strip())) != 1: return json({ 'status': 'error', 'error': t + ' is not a valid PayloadType.' }) try: op = await db_objects.get(Operator, username=data['operator']) except Exception as e: print(e) return json({ 'status': 'error', 'error': 'operator could not be found' }) try: if user['current_operation'] != "": operation = await db_objects.get(Operation, name=user['current_operation']) profile = await db_objects.create(C2Profile, name=data['name'], description=data['description'], operator=op, operation=operation) # now create the payloadtypec2profile entries for t in data['payload_types']: payload_type = await db_objects.get(PayloadType, ptype=t.strip()) await db_objects.create(PayloadTypeC2Profile, payload_type=payload_type, c2_profile=profile) profile_json = profile.to_json() status = {'status': 'success'} return json({**status, **profile_json}) else: return json({ 'status': 'error', 'error': 'must be part of an active operation' }) except Exception as e: print(e) return json({'status': 'error', 'error': 'Profile name already taken'})
async def get_all_payloadtypes(request, user): payloads = await db_objects.execute(PayloadType.select()) return json([p.to_json() for p in payloads])
async def register_new_c2profile(request, user): if request.form: data = js.loads(request.form.get('json')) else: data = request.json #print(data) # also takes in an array of 'name', 'key' values to aid in payload creation, not a requirement though data['operator'] = user['username'] if 'name' not in data or data['name'] is "" or data['name'] is None: return json({'status': 'error', 'error': 'name is required'}) if 'description' not in data: data['description'] = "" if 'payload_types' not in data or data['payload_types'] is None: return json({ 'status': 'error', 'error': 'payload_types is required information' }) # we need to 1. make sure these are all valid payload types, and 2. create payloadtypec2profile entries as well for t in data['payload_types']: # this should be an array we can iterate over if await db_objects.count(PayloadType.select().where( PayloadType.ptype == t.strip())) != 1: return json({ 'status': 'error', 'error': t + ' is not a valid PayloadType.' }) try: op = await db_objects.get(Operator, username=data['operator']) except Exception as e: print(e) return json({ 'status': 'error', 'error': 'operator could not be found' }) try: if user['current_operation'] != "": operation = await db_objects.get(Operation, name=user['current_operation']) profile = await db_objects.create(C2Profile, name=data['name'], description=data['description'], operator=op, operation=operation) # make the right directory structure os.makedirs("./app/c2_profiles/{}/{}".format( operation.name, data['name']), exist_ok=True) # now create the payloadtypec2profile entries for t in data['payload_types']: try: payload_type = await db_objects.get(PayloadType, ptype=t.strip()) except Exception as e: print(e) return json({ 'status': 'error', 'error': 'failed to find payload type: ' + t }) await db_objects.create(PayloadTypeC2Profile, payload_type=payload_type, c2_profile=profile) os.makedirs("./app/c2_profiles/{}/{}/{}".format( operation.name, data['name'], payload_type.ptype), exist_ok=True) # now create the c2profileparameters entries so we can generate the right form to fill out if 'c2profileparameters' in data: for params in data['c2profileparameters']: if not 'hint' in params: params['hint'] = "" await db_objects.create(C2ProfileParameters, c2_profile=profile, key=params['key'], name=params['name'], hint=params['hint']) profile_json = profile.to_json() # Now that the profile is created and registered, write the server code files to the appropriate directory if request.files: code = request.files['upload_file'][0].body code_file = open( "./app/c2_profiles/{}/{}/{}".format( operation.name, profile.name, request.files['upload_file'][0].name), "wb") code_file.write(code) code_file.close() for i in range(1, int(request.form.get('file_length'))): code = request.files['upload_file_' + str(i)][0].body code_file = open( "./app/c2_profiles/{}/{}/{}".format( operation.name, profile.name, request.files['upload_file_' + str(i)][0].name), "wb") code_file.write(code) code_file.close() elif 'code' in data and 'file_name' in data: # if the user is doing this through the API instead of UI, they can specify a file this way code = base64.b64decode(data['code']) code_file = open( "./app/c2_profiles/{}/{}/{}".format( operation.name, profile.name, data['file_name']), 'wb') code_file.write(code) code_file.close() status = {'status': 'success'} return json({**status, **profile_json}) else: return json({ 'status': 'error', 'error': 'must be part of an active operation' }) except Exception as e: print(e) return json({'status': 'error', 'error': 'Profile name already taken'})