Esempio n. 1
0
async def remove_command_parameter(request, user, cid, pid):
    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")
    try:
        query = await db_model.command_query()
        command = await db_objects.get(query, id=cid)
        query = await db_model.commandparameters_query()
        parameter = await db_objects.get(query, id=pid, command=command)
    except Exception as e:
        print(e)
        return json({
            'status': 'error',
            'error': 'failed to find command or parameter'
        })
    p_json = parameter.to_json()
    await db_objects.delete(parameter)
    # update the command since we just updated a parameter to it
    async with db_objects.atomic():
        query = await db_model.command_query()
        command = await db_objects.get(query, id=cid)
        command.version = command.version + 1
        await db_objects.update(command)
    return json({
        'status': 'success',
        **p_json, 'new_cmd_version': command.version
    })
Esempio n. 2
0
async def create_command_parameter(request, user, id):
    try:
        operator = await db_objects.get(Operator, username=user['username'])
        command = await db_objects.get(Command, id=id)
    except Exception as e:
        return json({'status': 'error', 'error': 'failed to find command'})
    data = request.json
    if "name" not in data:
        return json({'status': 'error', 'error': '"name" is required'})
    if 'type' not in data:
        return json({'status': 'error', 'error': '"type" is a required parameter'})
    if 'required' not in data:
        return json({'status': 'error', 'error': '"required" is a required parameter'})
    if data['type'] == "String" and 'hint' not in data:
        return json({'status': 'error', 'error': "\"hint\" required if type is \"String\""})
    if data['type'] == "Choice" and 'choices' not in data:
        return json({'status': 'error', 'error': "\"choices\" is required if type is \"Choice\""})
    if data['type'] == "ChoiceMultiple" and 'choices' not in data:
        return json({'status': 'error', 'error': "\"choices\" is required if type is \"ChoiceMultiple\""})
    if 'hint' not in data:
        data['hint'] = ""
    try:
        param, created = await db_objects.get_or_create(CommandParameters, **data, command=command, operator=operator)
        async with db_objects.atomic():
            command = await db_objects.get(Command, id=id)
            command.version = command.version + 1
            await db_objects.update(command)
            print("created command param")
        return json({'status': 'success', **param.to_json(), 'new_cmd_version': command.version})
    except Exception as e:
        print(e)
        return json({'status': 'error', 'error': 'failed to create parameter' + str(e)})
Esempio n. 3
0
async def download_file_to_disk_func(data):
    #  upload content blobs to be associated with filemeta id
    if 'chunk_num' not in data:
        return {'status': 'error', 'error': 'missing chunk_num'}
    if 'chunk_data' not in data:
        return {'status': 'error', 'error': 'missing chunk data'}
    try:
        query = await db_model.filemeta_query()
        file_meta = await db_objects.get(query, agent_file_id=data['file_id'])
    except Exception as e:
        print(e)
        return {'status': 'error', 'error': 'failed to get File info'}
    try:
        # print("trying to base64 decode chunk_data")
        if data['chunk_num'] <= file_meta.chunks_received:
            return {'status': 'error', 'error': 'out of order or duplicate chunk'}
        chunk_data = base64.b64decode(data['chunk_data'])
        f = open(file_meta.path, 'ab')
        f.write(chunk_data)
        f.close()
        async with db_objects.atomic():
            file_meta = await db_objects.get(query, agent_file_id=data['file_id'])
            file_meta.chunks_received = file_meta.chunks_received + 1
            # print("received chunk num {}".format(data['chunk_num']))
            if file_meta.chunks_received == file_meta.total_chunks:
                file_meta.complete = True
                contents = open(file_meta.path, 'rb').read()
                file_meta.md5 = await hash_MD5(contents)
                file_meta.sha1 = await hash_SHA1(contents)
            await db_objects.update(file_meta)
    except Exception as e:
        print("Failed to save chunk to disk: " + str(e))
        return {'status': 'error', 'error': 'failed to store chunk: ' + str(e)}
    return {'status': 'success'}
Esempio n. 4
0
async def update_command(request, user, id):
    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")
    updated_command = False
    try:
        query = await db_model.command_query()
        command = await db_objects.get(query, id=id)
        query = await db_model.operator_query()
        operator = await db_objects.get(query, username=user['username'])
    except Exception as e:
        print(e)
        return json({'status': 'error', 'error': 'failed to get command'})
    if request.form:
        data = js.loads(request.form.get('json'))
    else:
        data = request.json
    if "description" in data and data['description'] != command.description:
        command.description = data['description']
        updated_command = True
    if "needs_admin" in data and data['needs_admin'] != command.needs_admin:
        command.needs_admin = data['needs_admin']
        updated_command = True
    if "help_cmd" in data and data['help_cmd'] != command.help_cmd:
        command.help_cmd = data['help_cmd']
        updated_command = True
    if "is_exit" in data and data['is_exit'] is True:
        query = await db_model.command_query()
        try:
            exit_commands = await db_objects.execute(
                query.where((Command.is_exit == True) & (Command.payload_type == command.payload_type)))
            # one is already set, so set it to false
            for e in exit_commands:
                e.is_exit = False
                await db_objects.update(e)
            command.is_exit = data['is_exit']
        except Exception as e:
            # one doesn't exist, so let this one be set
            print(str(e))
    if request.files:
        updated_command = True
        cmd_code = request.files['upload_file'][0].body
        cmd_file = open("./app/payloads/{}/commands/{}".format(command.payload_type.ptype, command.cmd), "wb")
        # cmd_code = base64.b64decode(data['code'])
        cmd_file.write(cmd_code)
        cmd_file.close()
    elif "code" in data:
        updated_command = True
        cmd_file = open("./app/payloads/{}/commands/{}".format(command.payload_type.ptype, command.cmd), "wb")
        cmd_code = base64.b64decode(data['code'])
        cmd_file.write(cmd_code)
        cmd_file.close()
    command.operator = operator
    await db_objects.update(command)
    if updated_command:
        async with db_objects.atomic():
            query = await db_model.command_query()
            command = await db_objects.get(query, id=command.id)
            command.version = command.version + 1
            await db_objects.update(command)
    return json({'status': 'success', **command.to_json()})
Esempio n. 5
0
async def update_command_parameter(request, user, cid, pid):
    updated_a_field = False
    try:
        query = await db_model.operator_query()
        operator = await db_objects.get(query, username=user['username'])
        query = await db_model.command_query()
        command = await db_objects.get(query, id=cid)
        query = await db_model.commandparameters_query()
        parameter = await db_objects.get(query, id=pid, command=command)
    except Exception as e:
        print(e)
        return json({
            "status": 'error',
            'error': 'failed to find command or parameter'
        })
    data = request.json
    if "name" in data and data['name'] != parameter.name:
        try:
            parameter.name = data['name']
            parameter.operator = operator
            await db_objects.update(parameter)
            updated_a_field = True
        except Exception as e:
            print(e)
            return json({
                "status":
                'error',
                'error':
                'parameter name must be unique across a command'
            })
    if "required" in data and data['required'] != parameter.required:
        parameter.required = data['required']
        updated_a_field = True
    if data['type']:
        if data['type'] != parameter.type:
            parameter.type = data['type']
            updated_a_field = True
        if data['type'] == "String" and data['hint'] != parameter.hint:
            parameter.hint = data['hint'] if 'hint' in data else ""
            updated_a_field = True
        elif data['type'] == "Choice" and data['choices'] != parameter.choices:
            parameter.choices = data['choices'] if 'choices' in data else ""
            updated_a_field = True
        elif data['type'] == "ChooseMultiple" and data[
                'choices'] != parameter.choices:
            parameter.choices = data['choices'] if 'choices' in data else ""
            updated_a_field = True
    parameter.operator = operator
    # update the command since we just updated a parameter to it
    if updated_a_field:
        async with db_objects.atomic():
            query = await db_model.command_query()
            command = await db_objects.get(query, id=cid)
            command.version = command.version + 1
            await db_objects.update(command)
        await db_objects.update(parameter)
    return json({
        'status': 'success',
        **parameter.to_json(), 'new_cmd_version': command.version
    })
Esempio n. 6
0
async def download_file_to_disk_func(data):
    #  upload content blobs to be associated with filemeta id
    if "chunk_num" not in data:
        return {"status": "error", "error": "missing chunk_num"}
    if "chunk_data" not in data:
        return {"status": "error", "error": "missing chunk data"}
    try:
        query = await db_model.filemeta_query()
        file_meta = await db_objects.get(query, agent_file_id=data["file_id"])
    except Exception as e:
        print(e)
        return {"status": "error", "error": "failed to get File info"}
    try:
        # print("trying to base64 decode chunk_data")
        if data["chunk_num"] <= file_meta.chunks_received:
            return {
                "status": "error",
                "error": "out of order or duplicate chunk"
            }
        chunk_data = base64.b64decode(data["chunk_data"])
        f = open(file_meta.path, "ab")
        f.write(chunk_data)
        f.close()
        async with db_objects.atomic():
            file_meta = await db_objects.get(query,
                                             agent_file_id=data["file_id"])
            file_meta.chunks_received = file_meta.chunks_received + 1
            if "host" in data and data[
                    "host"] is not None and data["host"] != "":
                file_meta.host = data["host"].encode("unicode-escape")
            if "full_path" in data and data[
                    "full_path"] is not None and data["full_path"] != "":
                file_meta.full_remote_path = data["full_path"].encode(
                    "unicode-escape")
                if file_meta.file_browser is None:
                    await add_upload_file_to_file_browser(
                        file_meta.operation, file_meta.task, file_meta, {
                            "host": file_meta.host,
                            "full_path": file_meta.full_remote_path
                        })
            # print("received chunk num {}".format(data['chunk_num']))
            if file_meta.chunks_received == file_meta.total_chunks:
                file_meta.complete = True
                contents = open(file_meta.path, "rb").read()
                file_meta.md5 = await hash_MD5(contents)
                file_meta.sha1 = await hash_SHA1(contents)
                if not file_meta.is_screenshot:
                    await log_to_siem(file_meta.to_json(),
                                      mythic_object="file_download")
            await db_objects.update(file_meta)
    except Exception as e:
        print("Failed to save chunk to disk: " + str(e))
        return {"status": "error", "error": "failed to store chunk: " + str(e)}
    return {"status": "success"}
Esempio n. 7
0
async def update_command(request, user, id):
    updated_command = False
    try:
        query = await db_model.command_query()
        command = await db_objects.get(query, id=id)
        query = await db_model.operator_query()
        operator = await db_objects.get(query, username=user['username'])
    except Exception as e:
        print(e)
        return json({'status': 'error', 'error': 'failed to get command'})
    if request.form:
        data = js.loads(request.form.get('json'))
    else:
        data = request.json
    if "description" in data and data['description'] != command.description:
        command.description = data['description']
        updated_command = True
    if "needs_admin" in data and data['needs_admin'] != command.needs_admin:
        command.needs_admin = data['needs_admin']
        updated_command = True
    if "help_cmd" in data and data['help_cmd'] != command.help_cmd:
        command.help_cmd = data['help_cmd']
        updated_command = True
    if request.files:
        updated_command = True
        cmd_code = request.files['upload_file'][0].body
        cmd_file = open(
            "./app/payloads/{}/commands/{}".format(command.payload_type.ptype,
                                                   command.cmd), "wb")
        # cmd_code = base64.b64decode(data['code'])
        cmd_file.write(cmd_code)
        cmd_file.close()
    elif "code" in data:
        updated_command = True
        cmd_file = open(
            "./app/payloads/{}/commands/{}".format(command.payload_type.ptype,
                                                   command.cmd), "wb")
        cmd_code = base64.b64decode(data['code'])
        cmd_file.write(cmd_code)
        cmd_file.close()
    command.operator = operator
    await db_objects.update(command)
    if updated_command:
        async with db_objects.atomic():
            query = await db_model.command_query()
            command = await db_objects.get(query, id=command.id)
            command.version = command.version + 1
            await db_objects.update(command)
    return json({'status': 'success', **command.to_json()})
Esempio n. 8
0
async def remove_command_parameter(request, user, cid, pid):
    try:
        command = await db_objects.get(Command, id=cid)
        parameter = await db_objects.get(CommandParameters, id=pid, command=command)
    except Exception as e:
        print(e)
        return json({'status': 'error', 'error': 'failed to find command or parameter'})
    p_json = parameter.to_json()
    await db_objects.delete(parameter)
    # update the command since we just updated a parameter to it
    async with db_objects.atomic():
        command = await db_objects.get(Command, id=cid)
        command.version = command.version + 1
        print("deleted param")
        await db_objects.update(command)
    return json({'status': 'success', **p_json, 'new_cmd_version': command.version})
Esempio n. 9
0
async def create_command_parameter(request, user, id):
    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")
    try:
        query = await db_model.operator_query()
        operator = await db_objects.get(query, username=user['username'])
        query = await db_model.command_query()
        command = await db_objects.get(query, id=id)
    except Exception as e:
        return json({'status': 'error', 'error': 'failed to find command'})
    data = request.json
    if "name" not in data:
        return json({'status': 'error', 'error': '"name" is required'})
    if 'type' not in data:
        return json({'status': 'error', 'error': '"type" is a required parameter'})
    if 'required' not in data:
        return json({'status': 'error', 'error': '"required" is a required parameter'})
    if data['type'] == "String" and 'hint' not in data:
        return json({'status': 'error', 'error': "\"hint\" required if type is \"String\""})
    if data['type'] == "Choice" and 'choices' not in data:
        return json({'status': 'error', 'error': "\"choices\" is required if type is \"Choice\""})
    if data['type'] == "ChooseMultiple" and 'choices' not in data:
        return json({'status': 'error', 'error': "\"choices\" is required if type is \"ChooseMultiple\""})
    if 'hint' not in data:
        data['hint'] = ""
    try:
        query = await db_model.commandparameters_query()
        try:
            param = await db_objects.get(query, **data, command=command, operator=operator)
        except Exception as e:
            param = await db_objects.create(CommandParameters, **data, command=command, operator=operator)
        async with db_objects.atomic():
            query = await db_model.command_query()
            command = await db_objects.get(query, id=id)
            command.version = command.version + 1
            await db_objects.update(command)
        return json({'status': 'success', **param.to_json(), 'new_cmd_version': command.version})
    except Exception as e:
        print(e)
        return json({'status': 'error', 'error': 'failed to create parameter' + str(e)})
Esempio n. 10
0
async def download_file_to_disk_func(data):
    #  upload content blobs to be associated with filemeta id
    if 'chunk_num' not in data:
        return {'status': 'error', 'error': 'missing chunk_num'}
    if 'chunk_data' not in data:
        return {'status': 'error', 'error': 'missing chunk data'}
    try:
        query = await db_model.filemeta_query()
        file_meta = await db_objects.get(query, agent_file_id=data['file_id'])
    except Exception as e:
        print(e)
        return {'status': 'error', 'error': 'failed to get File info'}
    try:
        # print("trying to base64 decode chunk_data")
        chunk_data = base64.b64decode(data['chunk_data'])
        f = open(file_meta.path, 'ab')
        f.write(chunk_data)
        f.close()
        async with db_objects.atomic():
            file_meta = await db_objects.get(query,
                                             agent_file_id=data['file_id'])
            file_meta.chunks_received = file_meta.chunks_received + 1
            # print("received chunk num {}".format(data['chunk_num']))
            if file_meta.chunks_received == file_meta.total_chunks:
                file_meta.complete = True
            await db_objects.update(file_meta)
            # if we ended up downloading a file from mac's screencapture utility, we need to fix it a bit
        f = open(file_meta.path, 'rb').read(8)
        if f == b"'PNGf'($":
            f = open(file_meta.path, 'rb').read()
            new_file = open(file_meta.path, 'wb')
            new_file.write(unhexlify(f[8:-2]))
            new_file.close()
    except Exception as e:
        print("Failed to save chunk to disk: " + str(e))
        return {'status': 'error', 'error': 'failed to store chunk: ' + str(e)}
    return {'status': 'success'}