Exemplo n.º 1
0
async def ws_payloadtypec2profile(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 "newpayloadtypec2profile";')
                    # BEFORE WE START GETTING NEW THINGS, UPDATE WITH ALL OF THE OLD DATA
                    profiles = await db_objects.execute(PayloadTypeC2Profile.select())
                    for p in profiles:
                        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(PayloadTypeC2Profile, 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()
Exemplo n.º 2
0
async def delete_c2profile(request, info, user):
    try:
        info = unquote_plus(info)
        operation = await db_objects.get(Operation,
                                         name=user['current_operation'])
        profile = await db_objects.get(C2Profile,
                                       name=info,
                                       operation=operation)
        parameters = await db_objects.execute(
            C2ProfileParameters.select().where(
                C2ProfileParameters.c2_profile == profile))
        ptypec2profile = await db_objects.execute(
            PayloadTypeC2Profile.select().where(
                PayloadTypeC2Profile.c2_profile == profile))
    except Exception as e:
        print(e)
        return json({'status': 'error', 'error': 'failed to find C2 profile'})
    try:
        # we will do this recursively because there can't be payloadtypec2profile mappings if the profile doesn't exist
        for p in parameters:
            await db_objects.delete(p, recursive=True)
        for p in ptypec2profile:
            await db_objects.delete(p, recursive=True)
        await db_objects.delete(profile, recursive=True)
        # remove it from disk
        shutil.rmtree("./app/c2_profiles/{}/{}".format(operation.name, info))
        success = {'status': 'success'}
        updated_json = profile.to_json()
        return json({**success, **updated_json})
    except Exception as e:
        return json({
            'status': 'error',
            'error': 'failed to delete c2 profile'
        })
Exemplo n.º 3
0
async def get_all_c2profiles_for_current_operation(request, user):
    if user['current_operation'] != "":
        try:
            operation = await db_objects.get(Operation,
                                             name=user['current_operation'])
            all_profiles = await db_objects.execute(
                C2Profile.select().where(C2Profile.operation == operation))
            profiles = await db_objects.execute(
                PayloadTypeC2Profile.select(
                    PayloadTypeC2Profile, C2Profile,
                    PayloadType).join(C2Profile).switch(
                        PayloadTypeC2Profile).join(PayloadType))
            results = []
            inter = {}
            for p in all_profiles:
                inter[p.name] = p.to_json()
                inter[p.name]['ptype'] = [
                ]  # start to keep track of which payload types this profile supports
            for p in profiles:
                if p.c2_profile.operation == operation:
                    inter[p.c2_profile.name]['ptype'].append(
                        p.payload_type.ptype)
            for k in inter.keys():  # make an array of dictionaries
                results.append(inter[k])
            return json(results)
        except Exception as e:
            print(e)
            return json([""])
    else:
        return json([""])
Exemplo n.º 4
0
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'
        })
Exemplo n.º 5
0
async def get_c2profiles_by_type_function(ptype, user_dict):
    try:
        payload_type = await db_objects.get(PayloadType, ptype=ptype)
        profiles = await db_objects.execute(
            PayloadTypeC2Profile.select().where(
                PayloadTypeC2Profile.payload_type == payload_type))
    except Exception as e:
        print(e)
        raise Exception
    return [
        p.to_json() for p in profiles if
        p.c2_profile.operation in user_dict['operations'] or user_dict['admin']
    ]
Exemplo n.º 6
0
async def get_all_c2profiles(request, user):
    #  this syntax is atrocious for getting a pretty version of the results from a many-to-many join table)
    all_profiles = await db_objects.execute(C2Profile.select())
    profiles = await db_objects.execute(
        PayloadTypeC2Profile.select(PayloadTypeC2Profile, C2Profile,
                                    PayloadType).join(C2Profile).switch(
                                        PayloadTypeC2Profile).join(PayloadType)
    )
    results = []
    inter = {}
    for p in all_profiles:
        # only show profiles for operations the user is part of
        #   overall admins can see all operations
        if p.operation.name in user['operations'] or user['admin']:
            inter[p.name] = p.to_json()
            # create an empty array for ptypes that we'll populate in the next for loop
            inter[p.name]['ptype'] = []
    for p in profiles:
        if p.c2_profile.name in inter:
            inter[p.c2_profile.name]['ptype'].append(p.payload_type.ptype)
    for k in inter.keys():
        results.append(inter[k])
    return json(results)
Exemplo n.º 7
0
async def upload_c2_profile_payload_type_code(request, info, user):
    c2profile = unquote_plus(info)
    # we either get a file from the browser or somebody uploads it via a base64 encoded "code" field
    if request.form:
        data = js.loads(request.form.get('json'))
    else:
        data = request.json
    try:
        operation = await db_objects.get(Operation,
                                         name=user['current_operation'])
        profile = await db_objects.get(C2Profile,
                                       name=c2profile,
                                       operation=operation)
        registered_ptypes = await db_objects.execute(
            PayloadTypeC2Profile.select().where(
                PayloadTypeC2Profile.c2_profile == profile))
        ptypes = [p.payload_type.ptype for p in registered_ptypes
                  ]  # just get an array of all the names
    except Exception as e:
        return json({
            'status': 'error',
            'error': 'failed to find profile or operation'
        })
    if "payload_type" not in data:
        return json({
            'status':
            'error',
            'error':
            'must associate this code with a specific payload type'
        })
    if data['payload_type'] not in ptypes and data['payload_type'] != "":
        return json({
            'status':
            'error',
            'error':
            'trying to upload code for a payload time not registered with this c2 profile'
        })
    try:
        if data['payload_type'] == "":
            data[
                'payload_type'] = "."  # don't change directories and we'll still be in the main c2_profile directory
        if not os.path.exists("./app/c2_profiles/{}/{}/{}".format(
                operation.name, profile.name, data['payload_type'])):
            os.mkdir("./app/c2_profiles/{}/{}/{}".format(
                operation.name, profile.name, data['payload_type']))
        if "code" in data and "file_name" in data:
            # get a base64 blob of the code and the filename to save it as in the right directory
            code = base64.b64decode(data['code'])
            code_file = open(
                "./app/c2_profiles/{}/{}/{}/{}".format(operation.name,
                                                       profile.name,
                                                       data['payload_type'],
                                                       data['file_name']),
                'wb')
            code_file.write(code)
            code_file.close()
        elif request.files:
            code = request.files['upload_file'][0].body
            code_file = open(
                "./app/c2_profiles/{}/{}/{}/{}".format(
                    operation.name, profile.name, data['payload_type'],
                    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, data['payload_type'],
                        request.files['upload_file_' + str(i)][0].name), "wb")
                code_file.write(code)
                code_file.close()
        return json({'status': 'success', **profile.to_json()})
    except Exception as e:
        print(e)
        return json({
            'status': 'error',
            'error': 'failed to write code to file: ' + str(e)
        })
Exemplo n.º 8
0
async def export_command_list(request, user, ptype):
    payload_type = unquote_plus(ptype)
    try:
        payload_ptype = await db_objects.get(PayloadType, ptype=payload_type)
        operation = await db_objects.get(Operation,
                                         name=user['current_operation'])
    except Exception as e:
        print(e)
        return json({
            'status': 'error',
            'error': 'unable to find that payload type'
        })
    cmdlist = []
    try:
        payloadtype_json = payload_ptype.to_json()
        del payloadtype_json['id']
        del payloadtype_json['operator']
        del payloadtype_json['creation_time']
        payloadtype_json['files'] = []
        for file in glob.iglob(
                "./app/payloads/{}/payload/*".format(payload_type)):
            payload_file = open(file, 'rb')
            file_dict = {
                file.split("/")[-1]:
                base64.b64encode(payload_file.read()).decode('utf-8')
            }
            payloadtype_json['files'].append(file_dict)
        commands = await db_objects.execute(
            Command.select().where(Command.payload_type == payload_ptype))
        for c in commands:
            cmd_json = c.to_json()
            del cmd_json['id']
            del cmd_json['creation_time']
            del cmd_json['operator']
            del cmd_json['payload_type']
            params = await db_objects.execute(CommandParameters.select().where(
                CommandParameters.command == c))
            params_list = []
            for p in params:
                p_json = p.to_json()
                del p_json['id']
                del p_json['command']
                del p_json['cmd']
                del p_json['operator']
                del p_json['payload_type']
                params_list.append(p_json)
            cmd_json['parameters'] = params_list
            attacks = await db_objects.execute(
                ATTACKCommand.select().where(ATTACKCommand.command == c))
            attack_list = []
            for a in attacks:
                a_json = a.to_json()
                del a_json['command']
                del a_json['command_id']
                del a_json['id']
                attack_list.append(a_json)
            cmd_json['attack'] = attack_list
            artifacts = await db_objects.execute(
                ArtifactTemplate.select().where(ArtifactTemplate.command == c))
            artifact_list = []
            for a in artifacts:
                a_json = {
                    "command_parameter": a.command_parameter,
                    "artifact": a.artifact.name,
                    "artifact_string": a.artifact_string,
                    "replace_string": a.replace_string
                }
                artifact_list.append(a_json)
            cmd_json['artifacts'] = artifact_list
            cmd_file = open(
                "./app/payloads/{}/commands/{}".format(payload_type, c.cmd),
                'rb')
            cmd_json['file'] = base64.b64encode(
                cmd_file.read()).decode('utf-8')
            cmdlist.append(cmd_json)
        # get all the c2 profiles we can that match up with this payload type for the current operation
        profiles = await db_objects.execute(
            PayloadTypeC2Profile.select().where(
                PayloadTypeC2Profile.payload_type == payload_ptype).join(
                    C2Profile).where(C2Profile.operation == operation))
        profiles_dict = {}
        for p in profiles:
            files = []
            for profile_file in glob.iglob(
                    "./app/c2_profiles/{}/{}/{}/*".format(
                        operation.name, p.c2_profile.name, payload_type)):
                file_contents = open(profile_file, 'rb')
                file_dict = {
                    profile_file.split("/")[-1]:
                    base64.b64encode(file_contents.read()).decode('utf-8')
                }
                files.append(file_dict)
            profiles_dict[p.c2_profile.name] = files
        payloadtype_json['c2_profiles'] = profiles_dict
        # get all of the module load transformations
        load_transforms = await db_objects.execute(Transform.select().where(
            (Transform.t_type == "load")
            & (Transform.payload_type == payload_ptype)))
        load_transforms_list = []
        for lt in load_transforms:
            lt_json = lt.to_json()
            del lt_json['payload_type']
            del lt_json['operator']
            del lt_json['timestamp']
            del lt_json['t_type']
            del lt_json['id']
            load_transforms_list.append(lt_json)
        payloadtype_json['load_transforms'] = load_transforms_list
        # get all of the payload creation transformations
        create_transforms = await db_objects.execute(Transform.select().where(
            (Transform.t_type == "create")
            & (Transform.payload_type == payload_ptype)))
        create_transforms_list = []
        for ct in create_transforms:
            ct_json = ct.to_json()
            del ct_json['payload_type']
            del ct_json['operator']
            del ct_json['timestamp']
            del ct_json['t_type']
            del ct_json['id']
            create_transforms_list.append(ct_json)
        payloadtype_json['create_transforms'] = create_transforms_list
    except Exception as e:
        print(e)
        return json({
            'status':
            'error',
            'error':
            'failed to get information for that payload type: ' + str(e)
        })
    return json({"payload_types": [{**payloadtype_json, "commands": cmdlist}]})