Skip to content

Commit

Permalink
fileextractor: prepare for linux (#1787)
Browse files Browse the repository at this point in the history
  • Loading branch information
skvl authored Apr 24, 2024
1 parent 96634ef commit 643c06d
Show file tree
Hide file tree
Showing 7 changed files with 2,705 additions and 2,446 deletions.
2 changes: 2 additions & 0 deletions src/plugins/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ if PLUGIN_FILEEXTRACTOR
sources += fileextractor/fileextractor.cpp
sources += fileextractor/fileextractor.h
sources += fileextractor/private.h
sources += fileextractor/win.cpp
sources += fileextractor/win.h
endif

if PLUGIN_OBJMON
Expand Down
2,402 changes: 116 additions & 2,286 deletions src/plugins/fileextractor/fileextractor.cpp

Large diffs are not rendered by default.

165 changes: 5 additions & 160 deletions src/plugins/fileextractor/fileextractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,175 +105,20 @@
#ifndef FILEEXTRACTOR_H
#define FILEEXTRACTOR_H

#include "plugins/plugins.h"
#include "plugins/plugins_ex.h"
#include "helpers/exclude_matcher.h"
#include "private.h"
#include "win.h"

#include <map>
#include <utility>
#include <cstdint>
#include <memory>

using namespace fileextractor_ns;

struct fileextractor_config
{
uint32_t timeout;
const char* dump_folder;
uint64_t hash_size;
uint64_t extract_size;
const char* exclude_file;
};

class fileextractor: public pluginex
class fileextractor : public pluginex
{
public:
std::unique_ptr<win_fileextractor> wf;

fileextractor(drakvuf_t drakvuf, const fileextractor_config* config, output_format_t output);
fileextractor(const fileextractor&) = delete;
fileextractor& operator=(const fileextractor&) = delete;
~fileextractor() = default;

virtual bool stop_impl() override;

private:
enum class error
{
success,
none,
error,
zero_size,
};

/* Prevent injections on timeout after stop plugin begin. */
uint32_t timeout{0};
uint32_t begin_stop_at{0};
/* Internal data */
std::unordered_map<task_id, std::unique_ptr<task_t>> tasks;
bool is32bit{false};
// Maps virtual address of buffer to free flag:
// * `true` means pools is free;
// * `false` otherwise.
std::map<addr_t, bool> pools;

std::array<size_t, fileextractor_ns::__OFFSET_MAX> offsets;
size_t control_area_size = 0;
size_t mmpte_size = 0;

const char* dump_folder;
uint64_t hash_size{0};
uint64_t extract_size{0};
const exclude_matcher exclude;
output_format_t format;

int sequence_number = 0;

/* Hooks */
std::unique_ptr<libhook::SyscallHook> setinformation_hook;
std::unique_ptr<libhook::SyscallHook> writefile_hook;
std::unique_ptr<libhook::SyscallHook> close_hook;
std::unique_ptr<libhook::SyscallHook> createsection_hook;
std::unique_ptr<libhook::SyscallHook> createfile_hook;
std::unique_ptr<libhook::SyscallHook> openfile_hook;
std::map<uint64_t, std::unique_ptr<libhook::ReturnHook>> createfile_ret_hooks;
std::map<uint64_t, std::unique_ptr<libhook::ReturnHook>> writefile_ret_hooks;

/* VA of functions to be injected */
addr_t queryvolumeinfo_va = 0;
addr_t queryinfo_va = 0;
addr_t createsection_va = 0;
addr_t close_handle_va = 0;
addr_t mapview_va = 0;
addr_t unmapview_va = 0;
addr_t readfile_va = 0;
addr_t waitobject_va = 0;
addr_t exallocatepool_va = 0;
addr_t exfreepool_va = 0;
addr_t memcpy_va = 0;

/* Hook handlers */
event_response_t setinformation_cb(drakvuf_t, drakvuf_trap_info_t*);
event_response_t writefile_cb(drakvuf_t, drakvuf_trap_info_t*);
event_response_t writefile_ret_cb(drakvuf_t, drakvuf_trap_info_t*);
event_response_t close_cb(drakvuf_t, drakvuf_trap_info_t*);
event_response_t createsection_cb (drakvuf_t, drakvuf_trap_info_t*);
event_response_t createfile_cb (drakvuf_t, drakvuf_trap_info_t*);
event_response_t openfile_cb (drakvuf_t, drakvuf_trap_info_t*);
event_response_t createfile_ret_cb(drakvuf_t, drakvuf_trap_info_t*);
void createfile_cb_impl(drakvuf_t, drakvuf_trap_info_t*, addr_t handle, bool, bool);

/* Dispatchers */
// TODO Maybe remove "response" in flavor of "error"?
error dispatch_task(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_pending(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_queryvolumeinfo(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_queryinfo(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_createsection(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_mapview(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_allocate_pool(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_memcpy(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_unmapview(vmi_instance_t, drakvuf_trap_info_t*, task_t&);
error dispatch_close_handle(vmi_instance_t, drakvuf_trap_info_t*, task_t&);

/* Injection helpers */
bool inject_queryvolumeinfo(drakvuf_trap_info_t*, vmi_instance_t, task_t&);
bool inject_queryinfo(drakvuf_trap_info_t*, vmi_instance_t, task_t&);
bool inject_createsection(drakvuf_trap_info_t*, vmi_instance_t, task_t&);
bool inject_mapview(drakvuf_trap_info_t*, vmi_instance_t, task_t&);
bool inject_allocate_pool(drakvuf_trap_info_t*, vmi_instance_t, task_t&);
bool inject_memcpy(drakvuf_trap_info_t*, vmi_instance_t, task_t&);
bool inject_unmapview(drakvuf_trap_info_t*, vmi_instance_t, task_t&);
bool inject_close_handle(drakvuf_trap_info_t*, vmi_instance_t, task_t&);

/* Routines */
bool get_file_object_handle_count(drakvuf_trap_info_t*,
handle_t,
uint64_t* handle_count);

bool get_file_object_flags(drakvuf_trap_info_t*,
vmi_instance_t,
handle_t,
uint64_t* flags);
std::string get_file_name(vmi_instance_t,
drakvuf_trap_info_t*,
addr_t handle,
addr_t* out_file,
addr_t* out_filetype);
bool get_file_object_currentbyteoffset(vmi_instance_t, drakvuf_trap_info_t*, handle_t, uint64_t*);
bool get_write_offset(vmi_instance_t, drakvuf_trap_info_t*, addr_t, uint64_t*);
void calc_checksum(task_t&);
void save_file_metadata(drakvuf_trap_info_t*, addr_t control_area, task_t&);
void update_file_metadata(drakvuf_trap_info_t*, task_t&);
bool save_file_chunk(int file_sequence_number,
void* buffer,
size_t size);
bool save_file_chunk_rb(int file_sequence_number, uint64_t currentoffset,
void* buffer,
size_t size);
void dump_mem_to_file(uint64_t cr3, addr_t str, int idx, uint64_t offset, size_t size);
uint64_t make_hook_id(drakvuf_trap_info_t*);
uint64_t make_task_id(vmi_pid_t pid, handle_t handle);
uint64_t make_task_id(task_t&);
void free_pool(addr_t va);
addr_t find_pool();
void free_resources(drakvuf_trap_info_t*, task_t&);
void remove_task(drakvuf_trap_info_t*, task_t&,
const char* fail_msg = nullptr, bool restore_registers = true);
void read_vm(vmi_instance_t, drakvuf_trap_info_t*, task_t&);

bool is_handle_valid(handle_t);
void check_stack_marker(drakvuf_trap_info_t*, vmi_lock_guard&, task_t*);

void print_file_information(drakvuf_trap_info_t*, task_t&);
void print_plugin_close_information(drakvuf_trap_info_t*, task_t&);
void print_extraction_failure(drakvuf_trap_info_t* info, const std::string& filename, const std::string& message);
void print_extraction_exclusion(drakvuf_trap_info_t* info, const std::string& filename);

task_t* close_cb_get_task(drakvuf_trap_info_t*);
task_t* setinformation_cb_get_task(drakvuf_trap_info_t*);
task_t* writefile_cb_get_task(drakvuf_trap_info_t*);

void close_cb_handle_unextracted(drakvuf_trap_info_t*, task_t*);
void close_cb_handle_extracted(drakvuf_trap_info_t*, task_t*);
};

#endif
9 changes: 9 additions & 0 deletions src/plugins/fileextractor/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@

#include "../plugin_utils.h"

struct fileextractor_config
{
uint32_t timeout;
const char* dump_folder;
uint64_t hash_size;
uint64_t extract_size;
const char* exclude_file;
};

namespace fileextractor_ns
{
#define FILE_DISPOSITION_INFORMATION 13
Expand Down
Loading

0 comments on commit 643c06d

Please sign in to comment.