Example #1
0
async def export_command_list(request, user, ptype):
    if user['auth'] not in ['access_token', 'apitoken']:
        abort(status_code=403,
              message=
              "Cannot access via Cookies. Use CLI or access via JS in browser")
    payload_type = unquote_plus(ptype)
    try:
        query = await db_model.payloadtype_query()
        payload_ptype = await db_objects.get(query, ptype=payload_type)
        query = await db_model.operation_query()
        operation = await db_objects.get(query, 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)
        query = await db_model.command_query()
        commands = await db_objects.execute(
            query.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']
            query = await db_model.commandparameters_query()
            params = await db_objects.execute(
                query.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
            query = await db_model.attackcommand_query()
            attacks = await db_objects.execute(
                query.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
            query = await db_model.artifacttemplate_query()
            artifacts = await db_objects.execute(
                query.where((ArtifactTemplate.command == c)
                            & (ArtifactTemplate.deleted == False)))
            artifact_list = []
            for a in artifacts:
                a_json = {
                    "command_parameter":
                    a.command_parameter.name
                    if a.command_parameter else "null",
                    "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
        query = await db_model.payloadtypec2profile_query()
        profiles = await db_objects.execute(
            query.where(PayloadTypeC2Profile.payload_type == payload_ptype))
        profiles_dict = {}
        for p in profiles:
            files = []
            for profile_file in glob.iglob("./app/c2_profiles/{}/{}/*".format(
                    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
        query = await db_model.transform_query()
        load_transforms = await db_objects.execute(
            query.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
        query = await db_model.transform_query()
        create_transforms = await db_objects.execute(
            query.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}]})
Example #2
0
async def write_payload(uuid, user):
    # for projects that need compiling, we should copy all of the necessary files to a temp location
    #  do our stamping and compiling, save off the one final file to the rightful destination
    #  then delete the temp files. They will be in a temp folder identified by the payload's UUID which should be unique
    try:
        query = await db_model.payload_query()
        payload = await db_objects.get(query, uuid=uuid)
        query = await db_model.operation_query()
        operation = await db_objects.get(query, name=user['current_operation'])
    except Exception as e:
        print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e))
        return {
            'status': 'error',
            'error': 'failed to get payload db object to write to disk'
        }
    try:
        if payload.payload_type.file_extension:
            extension = payload.payload_type.file_extension
        else:
            extension = ""
        working_path = "./app/payloads/operations/{}/{}".format(
            operation.name, payload.uuid)
        # copy the payload type's files there
        shutil.copytree(
            "./app/payloads/{}/payload/".format(payload.payload_type.ptype),
            working_path)
        # now we will work with the files from our temp directory
        # make sure the path and everything exists for where the final payload will go, create it if it doesn't exist
        payload_directory = os.path.dirname(payload.location)
        pathlib.Path(payload_directory).mkdir(parents=True, exist_ok=True)

        # wrappers won't necessarily have a c2 profile associated with them
        c2_path = './app/c2_profiles/{}/{}/{}{}'.format(
            payload.c2_profile.name, payload.payload_type.ptype,
            payload.c2_profile.name, extension)
        try:
            base_c2 = open(c2_path, 'r')
        except Exception as e:
            # if the wrapper doesn't have a c2 profile, that's ok
            if payload.payload_type.wrapper:
                pass
            # if the normal profile doesn't though, that's an issue, raise the exception
            else:
                raise e

    except Exception as e:
        print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e))
        shutil.rmtree(working_path)
        return {
            'status': 'error',
            'error': 'failed to open all needed files. ' + str(e)
        }
    # if we didn't actually find C2PROFILEHERE in the main code, we are probably looking at a multi-file project
    #   in that case, keep track so that we can copy the file over to our temp directory, fill it out, and compile
    wrote_c2_inline = False
    # we will loop over all the files in the temp directory as we attempt to write out our information
    # this will help multi file projects as well as ones where maybe code and headers need to be in different files
    for base_file in glob.iglob(working_path + "/*", recursive=False):
        base = open(base_file, 'r')
        # write to the new file, then copy it over when we're done
        custom = open(working_path + "/" + payload.uuid,
                      'w')  # make sure our temp file won't exist
        for line in base:
            if "C2PROFILE_HERE" in line and base_c2:
                # this means we need to write out the c2 profile and all parameters here
                await write_c2(custom, base_c2, payload)
                wrote_c2_inline = True
            elif 'C2PROFILE_NAME_HERE' in line:
                # optional directive to insert the name of the c2 profile
                replaced_line = line.replace("C2PROFILE_NAME_HERE",
                                             payload.c2_profile.name)
                custom.write(replaced_line)
            elif 'UUID_HERE' in line:
                replaced_line = line.replace("UUID_HERE", uuid)
                custom.write(replaced_line)
            elif 'COMMANDS_HERE' in line:
                # go through all the commands and write them to the payload
                try:
                    query = await db_model.payloadcommand_query()
                    commands = await db_objects.execute(
                        query.where(PayloadCommand.payload == payload))
                    for command in commands:
                        # try to open up the corresponding command file
                        cmd_file = open(
                            './app/payloads/{}/commands/{}'.format(
                                payload.payload_type.ptype,
                                command.command.cmd), 'r')
                        # we will write everything from the beginning to COMMAND_ENDS_HERE
                        for cmdline in cmd_file:
                            if 'COMMAND_ENDS_HERE' not in cmdline:
                                custom.write(cmdline)
                            else:
                                break  # stop once we find 'COMMAND_ENDS_HERE'
                        cmd_file.close()
                except Exception as e:
                    print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e))
                    return {
                        'status':
                        'error',
                        'error':
                        'failed to get and write commands to payload on disk'
                    }
            elif 'COMMAND_COUNT_HERE' in line:
                count = await db_objects.count(PayloadCommand.select().where(
                    PayloadCommand.payload == payload))
                replaced_line = line.replace('COMMAND_COUNT_HERE', str(count))
                custom.write(replaced_line)
            elif 'COMMAND_STRING_LIST_HERE' in line:
                query = await db_model.payloadcommand_query()
                commands = await db_objects.execute(
                    query.where(PayloadCommand.payload == payload))
                cmdlist = ','.join(
                    [str('"' + cmd.command.cmd + '"') for cmd in commands])
                replaced_line = line.replace('COMMAND_STRING_LIST_HERE',
                                             cmdlist)
                custom.write(replaced_line)
            elif 'COMMAND_RAW_LIST_HERE' in line:
                query = await db_model.payloadcommand_query()
                commands = await db_objects.execute(
                    query.where(PayloadCommand.payload == payload))
                cmdlist = ','.join([cmd.command.cmd for cmd in commands])
                replaced_line = line.replace('COMMAND_RAW_LIST_HERE', cmdlist)
                custom.write(replaced_line)
            elif 'COMMAND_HEADERS_HERE' in line:
                # go through all the commands and write them to the payload
                try:
                    query = await db_model.payloadcommand_query()
                    commands = await db_objects.execute(
                        query.where(PayloadCommand.payload == payload))
                    for command in commands:
                        # try to open up the corresponding command file
                        cmd_file = open(
                            './app/payloads/{}/commands/{}'.format(
                                payload.payload_type.ptype,
                                command.command.cmd), 'r')
                        found_headers = False
                        for cmdline in cmd_file:
                            if found_headers:
                                custom.write(cmdline)
                            elif 'COMMAND_ENDS_HERE' in cmdline:
                                found_headers = True
                        #custom.write(cmd_file.read())
                        cmd_file.close()
                except Exception as e:
                    print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e))
                    return {
                        'status':
                        'error',
                        'error':
                        'failed to get and write commands to payload on disk'
                    }
            elif 'WRAPPEDPAYLOADHERE' in line and payload.payload_type.wrapper:
                # first we need to do the proper encoding, then we write it do the appropriate spot
                wrapped_payload = open(payload.wrapped_payload.location,
                                       'rb').read()
                # eventually give a choice of how to encode, for now though, always base64 encode
                #if payload.payload_type.wrapped_encoding_type == "base64":
                wrapped_payload = base64.b64encode(wrapped_payload).decode(
                    "UTF-8")
                replaced_line = line.replace("WRAPPEDPAYLOADHERE",
                                             str(wrapped_payload))
                custom.write(replaced_line)
            else:
                custom.write(line)
        base.close()
        custom.close()
        os.remove(base_file)
        os.rename(working_path + "/" + payload.uuid, base_file)
    try:
        base_c2.close()
    except Exception as e:
        print(str(sys.exc_info()[-1].tb_lineno) + " " + str(e))
        pass
    custom.close()
    if not wrote_c2_inline:
        # we didn't write the c2 information into the main file, so it's in another file, copy it over and fill it out
        for file in glob.glob(r'./app/c2_profiles/{}/{}/*'.format(
                payload.c2_profile.name, payload.payload_type.ptype)):
            # once we copy a file over, try to replace some c2 params in it
            try:
                base_c2 = open(file, 'r')
                base_c2_new = open(
                    working_path + "/{}".format(file.split("/")[-1]), 'w')
            except Exception as e:
                shutil.rmtree(working_path)
                return {'status': 'error', 'error': 'failed to open c2 code'}
            await write_c2(base_c2_new, base_c2, payload)
            base_c2.close()
            base_c2_new.close()
    transform_request = await get_transforms_func(payload.payload_type.ptype,
                                                  "create")
    if transform_request['status'] == "success":
        transform_list = transform_request['transforms']
        # now we have a temporary location with everything we need
        # zip it all up and save it
        if not payload.payload_type.container_running:
            return {"status": "error", 'error': 'build container not running'}
        if payload.payload_type.last_heartbeat < datetime.utcnow() + timedelta(
                seconds=-30):
            query = await db_model.payloadtype_query()
            payload_type = await db_objects.get(
                query, ptype=payload.payload_type.ptype)
            payload_type.container_running = False
            await db_objects.update(payload_type)
            shutil.rmtree(working_path)
            return {
                "status":
                "error",
                'error':
                'build container not running, no heartbeat in over 30 seconds'
            }
        shutil.make_archive(
            "./app/payloads/operations/{}/{}".format(operation.name,
                                                     payload.uuid), 'zip',
            working_path)
        file_data = open(
            "./app/payloads/operations/{}/{}".format(
                operation.name, payload.uuid) + ".zip", 'rb').read()
        result = await send_pt_rabbitmq_message(
            payload.payload_type.ptype,
            "create_payload_with_code.{}".format(payload.uuid),
            base64.b64encode(
                js.dumps({
                    "zip": base64.b64encode(file_data).decode('utf-8'),
                    "transforms": transform_list,
                    "extension": payload.payload_type.file_extension
                }).encode()).decode('utf-8'))
        shutil.rmtree(working_path)
        os.remove("./app/payloads/operations/{}/{}".format(
            operation.name, payload.uuid) + ".zip")
        return {**result, "uuid": payload.uuid}
    else:
        return {'status': 'error', 'error': 'failed to query for transforms'}
Example #3
0
async def write_payload(uuid, user):
    # for projects that need compiling, we should copy all of the necessary files to a temp location
    #  do our stamping and compiling, save off the one final file to the rightful destination
    #  then delete the temp files. They will be in a temp folder identified by the payload's UUID which should be unique
    try:
        query = await db_model.payload_query()
        payload = await db_objects.get(query, uuid=uuid)
        query = await db_model.operation_query()
        operation = await db_objects.get(query, name=user['current_operation'])
    except Exception as e:
        print(e)
        return {
            'status': 'error',
            'error': 'failed to get payload db object to write to disk'
        }
    try:
        if payload.payload_type.file_extension:
            extension = payload.payload_type.file_extension
        else:
            extension = ""
        working_path = "./app/payloads/operations/{}/{}".format(
            operation.name, payload.uuid)
        # copy the payload type's files there
        shutil.copytree(
            "./app/payloads/{}/payload/".format(payload.payload_type.ptype),
            working_path)
        # now we will work with the files from our temp directory
        # make sure the path and everything exists for where the final payload will go, create it if it doesn't exist
        payload_directory = os.path.dirname(payload.location)
        pathlib.Path(payload_directory).mkdir(parents=True, exist_ok=True)

        # wrappers won't necessarily have a c2 profile associated with them
        c2_path = './app/c2_profiles/{}/{}/{}/{}{}'.format(
            payload.operation.name, payload.c2_profile.name,
            payload.payload_type.ptype, payload.c2_profile.name, extension)
        try:
            base_c2 = open(c2_path, 'r')
        except Exception as e:
            # if the wrapper doesn't have a c2 profile, that's ok
            if payload.payload_type.wrapper:
                pass
            # if the normal profile doesn't though, that's an issue, raise the exception
            else:
                raise e

    except Exception as e:
        print(e)
        shutil.rmtree(working_path)
        return {
            'status': 'error',
            'error': 'failed to open all needed files. ' + str(e)
        }
    # if we didn't actually find C2PROFILEHERE in the main code, we are probably looking at a multi-file project
    #   in that case, keep track so that we can copy the file over to our temp directory, fill it out, and compile
    wrote_c2_inline = False
    # we will loop over all the files in the temp directory as we attempt to write out our information
    # this will help multi file projects as well as ones where maybe code and headers need to be in different files
    for base_file in glob.iglob(working_path + "/*", recursive=False):
        base = open(base_file, 'r')
        # write to the new file, then copy it over when we're done
        custom = open(working_path + "/" + payload.uuid,
                      'w')  # make sure our temp file won't exist
        for line in base:
            if "C2PROFILE_HERE" in line and base_c2:
                # this means we need to write out the c2 profile and all parameters here
                await write_c2(custom, base_c2, payload)
                wrote_c2_inline = True
            elif 'C2PROFILE_NAME_HERE' in line:
                # optional directive to insert the name of the c2 profile
                replaced_line = line.replace("C2PROFILE_NAME_HERE",
                                             payload.c2_profile.name)
                custom.write(replaced_line)
            elif 'UUID_HERE' in line:
                replaced_line = line.replace("UUID_HERE", uuid)
                custom.write(replaced_line)
            elif 'COMMANDS_HERE' in line:
                # go through all the commands and write them to the payload
                try:
                    query = await db_model.payloadcommand_query()
                    commands = await db_objects.execute(
                        query.where(PayloadCommand.payload == payload))
                    for command in commands:
                        # try to open up the corresponding command file
                        cmd_file = open(
                            './app/payloads/{}/commands/{}'.format(
                                payload.payload_type.ptype,
                                command.command.cmd), 'r')
                        # we will write everything from the beginning to COMMAND_ENDS_HERE
                        for cmdline in cmd_file:
                            if 'COMMAND_ENDS_HERE' not in cmdline:
                                custom.write(cmdline)
                            else:
                                break  # stop once we find 'COMMAND_ENDS_HERE'
                        cmd_file.close()
                except Exception as e:
                    print(e)
                    return {
                        'status':
                        'error',
                        'error':
                        'failed to get and write commands to payload on disk'
                    }
            elif 'COMMAND_COUNT_HERE' in line:
                count = await db_objects.count(PayloadCommand.select().where(
                    PayloadCommand.payload == payload))
                replaced_line = line.replace('COMMAND_COUNT_HERE', str(count))
                custom.write(replaced_line)
            elif 'COMMAND_STRING_LIST_HERE' in line:
                query = await db_model.payloadcommand_query()
                commands = await db_objects.execute(
                    query.where(PayloadCommand.payload == payload))
                cmdlist = ','.join(
                    [str('"' + cmd.command.cmd + '"') for cmd in commands])
                replaced_line = line.replace('COMMAND_STRING_LIST_HERE',
                                             cmdlist)
                custom.write(replaced_line)
            elif 'COMMAND_RAW_LIST_HERE' in line:
                query = await db_model.payloadcommand_query()
                commands = await db_objects.execute(
                    query.where(PayloadCommand.payload == payload))
                cmdlist = ','.join([cmd.command.cmd for cmd in commands])
                replaced_line = line.replace('COMMAND_RAW_LIST_HERE', cmdlist)
                custom.write(replaced_line)
            elif 'COMMAND_HEADERS_HERE' in line:
                # go through all the commands and write them to the payload
                try:
                    query = await db_model.payloadcommand_query()
                    commands = await db_objects.execute(
                        query.where(PayloadCommand.payload == payload))
                    for command in commands:
                        # try to open up the corresponding command file
                        cmd_file = open(
                            './app/payloads/{}/commands/{}'.format(
                                payload.payload_type.ptype,
                                command.command.cmd), 'r')
                        found_headers = False
                        for cmdline in cmd_file:
                            if found_headers:
                                custom.write(cmdline)
                            elif 'COMMAND_ENDS_HERE' in cmdline:
                                found_headers = True
                        #custom.write(cmd_file.read())
                        cmd_file.close()
                except Exception as e:
                    print(e)
                    return {
                        'status':
                        'error',
                        'error':
                        'failed to get and write commands to payload on disk'
                    }
            elif 'WRAPPEDPAYLOADHERE' in line and payload.payload_type.wrapper:
                # first we need to do the proper encoding, then we write it do the appropriate spot
                wrapped_payload = open(payload.wrapped_payload.location,
                                       'rb').read()
                # eventually give a choice of how to encode, for now though, always base64 encode
                #if payload.payload_type.wrapped_encoding_type == "base64":
                wrapped_payload = base64.b64encode(wrapped_payload).decode(
                    "UTF-8")
                replaced_line = line.replace("WRAPPEDPAYLOADHERE",
                                             str(wrapped_payload))
                custom.write(replaced_line)
            else:
                custom.write(line)
        base.close()
        custom.close()
        os.remove(base_file)
        os.rename(working_path + "/" + payload.uuid, base_file)
    try:
        base_c2.close()
    except Exception as e:
        print(e)
        pass
    custom.close()
    if not wrote_c2_inline:
        # we didn't write the c2 information into the main file, so it's in another file, copy it over and fill it out
        for file in glob.glob(r'./app/c2_profiles/{}/{}/{}/*'.format(
                payload.operation.name, payload.c2_profile.name,
                payload.payload_type.ptype)):
            # once we copy a file over, try to replace some c2 params in it
            try:
                base_c2 = open(file, 'r')
                base_c2_new = open(
                    working_path + "/{}".format(file.split("/")[-1]), 'w')
            except Exception as e:
                shutil.rmtree(working_path)
                return {'status': 'error', 'error': 'failed to open c2 code'}
            await write_c2(base_c2_new, base_c2, payload)
            base_c2.close()
            base_c2_new.close()

    # now that it's written to disk, we need to potentially do some compilation or extra transforms
    try:
        import app.api.transforms.utils
        importlib.reload(sys.modules['app.api.transforms.utils'])
    except Exception as e:
        print(e)
    from app.api.transforms.utils import TransformOperation
    transform = TransformOperation(working_dir=working_path)
    transform_request = await get_transforms_func(payload.payload_type.ptype,
                                                  "create")
    if transform_request['status'] == "success":
        transform_list = transform_request['transforms']
        # do step 0, prior_output = path of our newly written file
        transform_output = os.path.abspath(working_path) + "/"
        for t in transform_list:
            try:
                transform_output = await getattr(transform,
                                                 t['name'])(payload,
                                                            transform_output,
                                                            t['parameter'])
            except Exception as e:
                print(e)
                shutil.rmtree(working_path)
                return {
                    'status':
                    'error',
                    'error':
                    'failed to apply transform {}, with message: {}'.format(
                        t['name'], str(e))
                }
        try:
            if transform_output != payload.location:
                # this means we ended up with a final file in a location other than what we specified
                if transform_output == os.path.abspath(working_path) + "/":
                    transform_output += payload.payload_type.ptype + extension
                shutil.copy(transform_output, payload.location)
            shutil.rmtree(working_path)
            return {'status': 'success', 'path': payload.location}
        except Exception as e:
            return {'status': 'error', 'error': str(e)}
    try:
        shutil.copy(working_path + "/" + payload.uuid, payload.location)
        shutil.rmtree(working_path)
        return {'status': 'success', 'path': payload.location}
    except Exception as e:
        return {'status': 'error', 'error': str(e)}