Пример #1
0
    def __init__(self, config: Config, instance_id: int):
        super().__init__(config)

        # Now that karton is set up we can plug in our logger
        logger = logging.getLogger("drakrun")
        for handler in self.log.handlers:
            logger.addHandler(handler)
        logger.setLevel(logging.INFO)

        self.instance_id = instance_id
        self.install_info = InstallInfo.load()
        self.default_timeout = int(
            self.config.config['drakrun'].get('analysis_timeout') or 60 * 10)
        with open(os.path.join(PROFILE_DIR, "runtime.json"), 'r') as runtime_f:
            self.runtime_info = RuntimeInfo.load(runtime_f)

        self.active_plugins = {}
        self.active_plugins["_all_"] = [
            'apimon', 'bsodmon', 'clipboardmon', 'cpuidmon', 'crashmon',
            'debugmon', 'delaymon', 'exmon', 'filedelete', 'filetracer',
            'librarymon', 'memdump', 'procdump', 'procmon', 'regmon', 'rpcmon',
            'ssdtmon', 'syscalls', 'tlsmon', 'windowmon', 'wmimon'
        ]

        for quality, list_str in self.config.config.items('drakvuf_plugins'):
            plugins = [x for x in list_str.split(',') if x.strip()]
            self.active_plugins[quality] = plugins
Пример #2
0
def create_missing_profiles():
    """
    Creates usermode profiles by restoring vm-1 and extracting the DLLs.
    Assumes that injector is configured properly, i.e. kernel and runtime
    profiles exist and that vm-1 is free to use.
    """

    # Prepare injector
    with open(os.path.join(PROFILE_DIR, "runtime.json"), "r") as runtime_f:
        runtime_info = RuntimeInfo.load(runtime_f)
    kernel_profile = os.path.join(PROFILE_DIR, "kernel.json")
    injector = Injector("vm-1", runtime_info, kernel_profile)

    # restore vm-1
    out_interface = conf["drakrun"].get("out_interface", "")
    dns_server = conf["drakrun"].get("dns_server", "")
    install_info = InstallInfo.load()
    backend = get_storage_backend(install_info)

    generate_vm_conf(install_info, 1)
    setup_vm_network(vm_id=1,
                     net_enable=False,
                     out_interface=out_interface,
                     dns_server=dns_server)
    vm = VirtualMachine(backend, 1)
    vm.restore()

    # Ensure that all declared usermode profiles exist
    # This is important when upgrade defines new entries in dll_file_list and compulsory_dll_file_list
    for profile in compulsory_dll_file_list:
        if not profiles_exist(profile.dest):
            create_rekall_profile(injector, profile, True)

    for profile in dll_file_list:
        if not profiles_exist(profile.dest):
            try:
                create_rekall_profile(injector, profile)
            except Exception:
                log.exception(
                    "Unexpected exception from create_rekall_profile!")

    build_os_info(APISCOUT_PROFILE_DIR, vmi_win_guid(vm.vm_name), backend)

    dll_basename_list = [dll.dest for dll in dll_file_list]
    static_apiscout_profile = build_static_apiscout_profile(
        APISCOUT_PROFILE_DIR, dll_basename_list)
    with open(
            Path(APISCOUT_PROFILE_DIR) / "static_apiscout_profile.json",
            "w") as f:
        json.dump(static_apiscout_profile, f)

    vm.destroy()
    delete_vm_network(vm_id=1,
                      net_enable=False,
                      out_interface=out_interface,
                      dns_server=dns_server)
Пример #3
0
def postupgrade():
    if not check_root():
        return

    with open(os.path.join(ETC_DIR, 'scripts/cfg.template'), 'r') as f:
        template = f.read()

    passwd_characters = string.ascii_letters + string.digits
    passwd = ''.join(secrets.choice(passwd_characters) for _ in range(20))
    template = template.replace('{{ VNC_PASS }}', passwd)

    with open(os.path.join(ETC_DIR, 'scripts', 'cfg.template'), 'w') as f:
        f.write(template)

    detect_defaults()

    install_info = InstallInfo.try_load()
    if not install_info:
        logging.info("Postupgrade done. DRAKVUF Sandbox not installed.")
        return

    # Prepare injector
    with open(os.path.join(PROFILE_DIR, "runtime.json"), 'r') as runtime_f:
        runtime_info = RuntimeInfo.load(runtime_f)
    kernel_profile = os.path.join(PROFILE_DIR, "kernel.json")
    injector = Injector('vm-1', runtime_info, kernel_profile)

    stop_all_drakruns()

    # Use vm-1 for generating profiles
    out_interface = conf['drakrun'].get('out_interface', '')
    dns_server = conf['drakrun'].get('dns_server', '')
    setup_vm_network(vm_id=1,
                     net_enable=False,
                     out_interface=out_interface,
                     dns_server=dns_server)
    backend = get_storage_backend(install_info)
    vm = VirtualMachine(backend, 1)
    vm.restore()

    create_missing_profiles(injector)

    vm.destroy()
    delete_vm_network(vm_id=1,
                      net_enable=False,
                      out_interface=out_interface,
                      dns_server=dns_server)
    start_enabled_drakruns()
Пример #4
0
def create_missing_profiles():
    """
    Creates usermode profiles by restoring vm-1 and extracting the DLLs.
    Assumes that injector is configured properly, i.e. kernel and runtime
    profiles exist and that vm-1 is free to use.
    """

    # Prepare injector
    with open(os.path.join(PROFILE_DIR, "runtime.json"), "r") as runtime_f:
        runtime_info = RuntimeInfo.load(runtime_f)
    kernel_profile = os.path.join(PROFILE_DIR, "kernel.json")
    injector = Injector("vm-1", runtime_info, kernel_profile)

    # restore vm-1
    out_interface = conf["drakrun"].get("out_interface", "")
    dns_server = conf["drakrun"].get("dns_server", "")
    install_info = InstallInfo.load()
    backend = get_storage_backend(install_info)

    generate_vm_conf(install_info, 1)
    setup_vm_network(vm_id=1,
                     net_enable=False,
                     out_interface=out_interface,
                     dns_server=dns_server)
    vm = VirtualMachine(backend, 1)
    vm.restore()

    # Ensure that all declared usermode profiles exist
    # This is important when upgrade defines new entries in dll_file_list and compulsory_dll_file_list
    for profile in compulsory_dll_file_list:
        if not profile_exists(profile):
            create_rekall_profile(injector, profile, True)

    for profile in dll_file_list:
        if not profile_exists(profile):
            try:
                create_rekall_profile(injector, profile)
            except Exception:
                # silence per-dll errors
                pass

    vm.destroy()
    delete_vm_network(vm_id=1,
                      net_enable=False,
                      out_interface=out_interface,
                      dns_server=dns_server)
Пример #5
0
    def __init__(self, config: Config, instance_id: int):
        super().__init__(config)

        # Now that karton is set up we can plug in our logger
        logger = logging.getLogger("drakrun")
        for handler in self.log.handlers:
            logger.addHandler(handler)
        logger.setLevel(logging.INFO)

        self.instance_id = instance_id
        self.install_info = InstallInfo.load()
        self.default_timeout = int(
            self.config.config["drakrun"].get("analysis_timeout") or 60 * 10
        )
        with open(os.path.join(PROFILE_DIR, "runtime.json"), "r") as runtime_f:
            self.runtime_info = RuntimeInfo.load(runtime_f)

        self.active_plugins = {}
        self.active_plugins["_all_"] = [
            "apimon",
            "bsodmon",
            "clipboardmon",
            "cpuidmon",
            "crashmon",
            "debugmon",
            "delaymon",
            "exmon",
            "filedelete",
            "filetracer",
            "librarymon",
            "memdump",
            "procdump",
            "procmon",
            "regmon",
            "rpcmon",
            "ssdtmon",
            "syscalls",
            "tlsmon",
            "windowmon",
            "wmimon",
        ]

        for quality, list_str in self.config.config.items("drakvuf_plugins"):
            plugins = [x for x in list_str.split(",") if x.strip()]
            self.active_plugins[quality] = plugins
Пример #6
0
    def __init__(self, vm_id: int, dns: str):
        install_info = InstallInfo.load()
        backend = get_storage_backend(install_info)

        generate_vm_conf(install_info, vm_id)
        self.vm = VirtualMachine(backend, vm_id)

        with open(Path(PROFILE_DIR) / "runtime.json", 'r') as f:
            self.runtime_info = RuntimeInfo.load(f)
        self.desktop = WinPath(r"%USERPROFILE%") / "Desktop"

        self.kernel_profile = Path(PROFILE_DIR) / "kernel.json"
        self.injector = Injector(
            self.vm.vm_name,
            self.runtime_info,
            self.kernel_profile,
        )
        setup_vm_network(vm_id, True, find_default_interface(), dns)
Пример #7
0
def postinstall(report, generate_usermode):
    if not check_root():
        return

    if os.path.exists(os.path.join(ETC_DIR, "no_usage_reports")):
        report = False

    install_info = InstallInfo.load()

    logging.info("Cleaning up leftovers(if any)")
    cleanup_postinstall_files()

    logging.info("Ejecting installation CDs")
    eject_cd("vm-0", FIRST_CDROM_DRIVE)
    if install_info.enable_unattended:
        # If unattended install is enabled, we have an additional CD-ROM drive
        eject_cd("vm-0", SECOND_CDROM_DRIVE)

    output = subprocess.check_output(['vmi-win-guid', 'name', 'vm-0'],
                                     timeout=30).decode('utf-8')

    try:
        version = re.search(r'Version: (.*)', output).group(1)
        pdb = re.search(r'PDB GUID: ([0-9a-f]+)', output).group(1)
        fn = re.search(r'Kernel filename: ([a-z]+\.[a-z]+)', output).group(1)
    except AttributeError:
        logging.error("Failed to obtain kernel PDB GUID/Kernel filename.")
        return

    logging.info("Determined PDB GUID: {}".format(pdb))
    logging.info("Determined kernel filename: {}".format(fn))

    logging.info("Fetching PDB file...")
    dest = fetch_pdb(fn, pdb, destdir=PROFILE_DIR)

    logging.info("Generating profile out of PDB file...")
    profile = make_pdb_profile(dest)

    logging.info("Saving profile...")
    kernel_profile = os.path.join(PROFILE_DIR, 'kernel.json')
    with open(kernel_profile, 'w') as f:
        f.write(profile)

    vmi_offsets = extract_vmi_offsets('vm-0', kernel_profile)
    explorer_pid = extract_explorer_pid('vm-0', kernel_profile, vmi_offsets)
    runtime_info = RuntimeInfo(vmi_offsets=vmi_offsets,
                               inject_pid=explorer_pid)

    logging.info("Saving runtime profile...")
    with open(os.path.join(PROFILE_DIR, 'runtime.json'), 'w') as f:
        f.write(runtime_info.to_json(indent=4))

    logging.info("Saving VM snapshot...")
    subprocess.check_output('xl save vm-0 ' +
                            os.path.join(VOLUME_DIR, "snapshot.sav"),
                            shell=True)

    storage_backend = get_storage_backend(install_info)
    storage_backend.snapshot_vm0_volume()
    logging.info("Snapshot was saved succesfully.")

    if generate_usermode:
        try:
            create_rekall_profiles(install_info)
        except RuntimeError as e:
            logging.warning("Generating usermode profiles failed")
            logging.exception(e)

    if report:
        send_usage_report({
            "kernel": {
                "guid": pdb,
                "filename": fn,
                "version": version
            },
            "install_iso": {
                "sha256": install_info.iso_sha256
            }
        })

    logging.info("All right, drakrun setup is done.")
    logging.info("First instance of drakrun will be enabled automatically...")
    subprocess.check_output('systemctl enable drakrun@1', shell=True)
    subprocess.check_output('systemctl start drakrun@1', shell=True)

    logging.info("If you want to have more parallel instances, execute:")
    logging.info("  # draksetup scale <number of instances>")
Пример #8
0
def test_runtime_info_load(serialized_runtime_info):
    stream = StringIO(serialized_runtime_info)
    RuntimeInfo.load(stream)
Пример #9
0
def runtime_info(vmi_offsets):
    return RuntimeInfo(vmi_offsets=vmi_offsets, inject_pid=1337)
Пример #10
0
def postinstall(report, generate_usermode):
    if not check_root():
        return

    if os.path.exists(os.path.join(ETC_DIR, "no_usage_reports")):
        report = False

    install_info = InstallInfo.load()
    storage_backend = get_storage_backend(install_info)

    vm0 = VirtualMachine(storage_backend, 0)

    if vm0.is_running is False:
        logging.exception("vm-0 is not running")
        return

    logging.info("Cleaning up leftovers(if any)")
    cleanup_postinstall_files()

    logging.info("Ejecting installation CDs")
    eject_cd("vm-0", FIRST_CDROM_DRIVE)
    if install_info.enable_unattended:
        # If unattended install is enabled, we have an additional CD-ROM drive
        eject_cd("vm-0", SECOND_CDROM_DRIVE)

    kernel_info = vmi_win_guid("vm-0")

    logging.info(f"Determined PDB GUID: {kernel_info.guid}")
    logging.info(f"Determined kernel filename: {kernel_info.filename}")

    logging.info("Fetching PDB file...")
    dest = fetch_pdb(kernel_info.filename,
                     kernel_info.guid,
                     destdir=PROFILE_DIR)

    logging.info("Generating profile out of PDB file...")
    profile = make_pdb_profile(dest)

    logging.info("Saving profile...")
    kernel_profile = os.path.join(PROFILE_DIR, "kernel.json")
    with open(kernel_profile, "w") as f:
        f.write(profile)

    safe_delete(dest)

    vmi_offsets = extract_vmi_offsets("vm-0", kernel_profile)
    explorer_pid = extract_explorer_pid("vm-0", kernel_profile, vmi_offsets)
    runtime_info = RuntimeInfo(vmi_offsets=vmi_offsets,
                               inject_pid=explorer_pid)

    logging.info("Saving runtime profile...")
    with open(os.path.join(PROFILE_DIR, "runtime.json"), "w") as f:
        f.write(runtime_info.to_json(indent=4))

    logging.info("Saving VM snapshot...")

    # Create vm-0 snapshot, and destroy it
    # WARNING: qcow2 snapshot method is a noop. fresh images are created on the fly
    # so we can't keep the vm-0 running
    vm0.save(os.path.join(VOLUME_DIR, "snapshot.sav"))
    logging.info("Snapshot was saved succesfully.")

    # Memory state is frozen, we can't do any writes to persistent storage
    logging.info("Snapshotting persistent memory...")
    storage_backend.snapshot_vm0_volume()

    if report:
        send_usage_report({
            "kernel": {
                "guid": kernel_info.guid,
                "filename": kernel_info.filename,
                "version": kernel_info.version,
            },
            "install_iso": {
                "sha256": install_info.iso_sha256
            },
        })

    if generate_usermode:
        # Restore a VM and create usermode profiles
        create_missing_profiles()

    logging.info("All right, drakrun setup is done.")
    logging.info("First instance of drakrun will be enabled automatically...")
    subprocess.check_output("systemctl enable drakrun@1", shell=True)
    subprocess.check_output("systemctl start drakrun@1", shell=True)

    logging.info("If you want to have more parallel instances, execute:")
    logging.info("  # draksetup scale <number of instances>")