Skip to content

Commit

Permalink
refactor plugin (#1734)
Browse files Browse the repository at this point in the history
* refactor plugin

* fix compilation error

* fix typo
  • Loading branch information
delvinru authored Oct 26, 2023
1 parent f4a3479 commit c932689
Show file tree
Hide file tree
Showing 12 changed files with 532 additions and 355 deletions.
6 changes: 6 additions & 0 deletions src/libdrakvuf/libdrakvuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,12 @@ bool drakvuf_get_process_dtb(drakvuf_t drakvuf,
addr_t process_base,
addr_t* dtb) NOEXCEPT;


bool drakvuf_get_process_group_id( drakvuf_t drakvuf,
addr_t process_base,
uint32_t* pgid) NOEXCEPT;


bool drakvuf_get_current_process_environ(drakvuf_t drakvuf,
drakvuf_trap_info_t* info,
GHashTable** environ) NOEXCEPT;
Expand Down
8 changes: 8 additions & 0 deletions src/libdrakvuf/linux-offsets-map.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ static const char* linux_offset_names[__LINUX_OFFSETS_MAX][2] =
[TASK_STRUCT_NSPROXY] = {"task_struct", "nsproxy"},
[TASK_STRUCT_MMSTRUCT] = {"task_struct", "mm"},
[TASK_STRUCT_ACTIVE_MMSTRUCT] = {"task_struct", "active_mm"},
[TASK_STRUCT_THREAD_PID] = {"task_struct", "thread_pid"},
[TASK_STRUCT_SIGNAL] = {"task_struct", "signal"},
[SIGNAL_STRUCT_PIDS] = {"signal_struct", "pids"},
[PID_LEVEL] = {"pid", "level"},
[PID_NUMBERS] = {"pid", "numbers"},
[PID_NAMESPACE_LEVEL] = {"pid_namespace", "level"},
[UPID_NS] = {"upid", "ns"},
[UPID_NR] = {"upid", "nr"},
[MM_STRUCT_MMAP] = {"mm_struct", "mmap"},
[MM_STRUCT_PGD] = {"mm_struct", "pgd"},
[MM_STRUCT_ARG_START] = {"mm_struct", "arg_start"},
Expand Down
8 changes: 8 additions & 0 deletions src/libdrakvuf/linux-offsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ enum linux_offsets
TASK_STRUCT_NSPROXY,
TASK_STRUCT_MMSTRUCT,
TASK_STRUCT_ACTIVE_MMSTRUCT,
TASK_STRUCT_THREAD_PID,
TASK_STRUCT_SIGNAL,
SIGNAL_STRUCT_PIDS,
PID_LEVEL,
PID_NUMBERS,
PID_NAMESPACE_LEVEL,
UPID_NS,
UPID_NR,
MM_STRUCT_MMAP,
MM_STRUCT_PGD,
MM_STRUCT_ARG_START,
Expand Down
118 changes: 118 additions & 0 deletions src/libdrakvuf/linux-processes.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@
#define PF_EXITING 0x00000004 /* Getting shut down */
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */

enum
{
PIDTYPE_PID,
PIDTYPE_TGID,
PIDTYPE_PGID,
PIDTYPE_SID,
PIDTYPE_MAX,
};

static addr_t read_process_base(drakvuf_t drakvuf, addr_t rsp, access_context_t* ctx)
{
vmi_instance_t vmi = drakvuf->vmi;
Expand Down Expand Up @@ -463,6 +472,115 @@ bool linux_get_process_tid(drakvuf_t drakvuf, addr_t process_base, uint32_t* tid
return ( VMI_SUCCESS == vmi_read_32(drakvuf->vmi, &ctx, tid) );
}

static bool linux_get_task_pid(drakvuf_t drakvuf, addr_t process_base, addr_t* thread_pid)
{
return get_kernel_struct_field_pointer(drakvuf, process_base, TASK_STRUCT_THREAD_PID, thread_pid);
}

static bool linux_get_task_pgrp(drakvuf_t drakvuf, addr_t process_base, addr_t* struct_pid)
{
addr_t signal;
if (!get_kernel_struct_field_pointer(drakvuf, process_base, TASK_STRUCT_SIGNAL, &signal))
return false;

ACCESS_CONTEXT(ctx,
.translate_mechanism = VMI_TM_PROCESS_DTB,
.dtb = drakvuf->kpgd
);

ctx.addr = signal + drakvuf->offsets[SIGNAL_STRUCT_PIDS] + sizeof(addr_t) * PIDTYPE_PGID;

if (VMI_FAILURE == vmi_read_addr(drakvuf->vmi, &ctx, struct_pid))
return false;

return true;
}

static bool linux_get_ns_of_pid(drakvuf_t drakvuf, addr_t struct_pid, addr_t* ns)
{
ACCESS_CONTEXT(ctx,
.translate_mechanism = VMI_TM_PROCESS_DTB,
.dtb = drakvuf->kpgd
);

uint32_t level;
ctx.addr = struct_pid + drakvuf->offsets[PID_LEVEL];
if (VMI_FAILURE == vmi_read_32(drakvuf->vmi, &ctx, &level))
return false;

// In the version before 4.15, the "struct upid" has a different size, but this version is not supported
// https://elixir.bootlin.com/linux/v6.5.7/source/include/linux/pid.h#L54
const uint32_t size_of_upid = 8;

ctx.addr = struct_pid + drakvuf->offsets[PID_NUMBERS] + level * size_of_upid + drakvuf->offsets[UPID_NS];
return ( VMI_SUCCESS == vmi_read_addr(drakvuf->vmi, &ctx, ns) );
}

static bool linux_get_pid_ns(drakvuf_t drakvuf, addr_t process_base, addr_t* ns)
{
addr_t thread_pid;
if (!linux_get_task_pid(drakvuf, process_base, &thread_pid))
return false;

return linux_get_ns_of_pid(drakvuf, thread_pid, ns);
}

/*
* get process group id
* by default return zero: https://elixir.bootlin.com/linux/v6.5.7/source/kernel/pid.c#L475
*/
bool linux_get_process_pgid(drakvuf_t drakvuf, addr_t process_base, uint32_t* pgid)
{
*pgid = 0;
const kernel_version_t* version = linux_get_kernel_version_from_process(drakvuf, process_base);
if (version->major <= 4 && version->minor < 19)
{
PRINT_DEBUG("Failed to extract PGID (unsupported kernel version)\n");
return false;
}

addr_t struct_pid;
if (!linux_get_task_pgrp(drakvuf, process_base, &struct_pid))
return false;

addr_t ns;
if (!linux_get_pid_ns(drakvuf, process_base, &ns))
return false;

ACCESS_CONTEXT(ctx,
.translate_mechanism = VMI_TM_PROCESS_DTB,
.dtb = drakvuf->kpgd
);

uint32_t ns_level;
ctx.addr = ns + drakvuf->offsets[PID_NAMESPACE_LEVEL];
if (VMI_FAILURE == vmi_read_32(drakvuf->vmi, &ctx, &ns_level))
return false;

uint32_t pid_level;
ctx.addr = struct_pid + drakvuf->offsets[PID_LEVEL];
if (VMI_FAILURE == vmi_read_32(drakvuf->vmi, &ctx, &pid_level))
return false;

if (ns_level <= pid_level)
{
// TODO: maybe ns_level incorrect (usually 0)
addr_t upid = struct_pid + drakvuf->offsets[PID_NUMBERS] + ns_level;

addr_t upid_ns;
ctx.addr = upid + drakvuf->offsets[UPID_NS];
if (VMI_FAILURE == vmi_read_addr(drakvuf->vmi, &ctx, &upid_ns))
return false;

ctx.addr = upid + drakvuf->offsets[UPID_NR];
if (upid_ns == ns)
return ( VMI_SUCCESS == vmi_read_32(drakvuf->vmi, &ctx, pgid) );
}

return true;
}


char* linux_get_current_process_name(drakvuf_t drakvuf, drakvuf_trap_info_t* info, bool fullpath)
{
UNUSED(fullpath);
Expand Down
52 changes: 38 additions & 14 deletions src/libdrakvuf/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,8 @@ static char* linux_get_banner(drakvuf_t drakvuf)
}
#endif

static char* linux_read_kernel_version(drakvuf_t drakvuf, drakvuf_trap_info_t* info)
static char* linux_read_kernel_version(drakvuf_t drakvuf, addr_t process_base)
{
addr_t process_base = linux_get_current_process(drakvuf, info);

ACCESS_CONTEXT(ctx,
.translate_mechanism = VMI_TM_PROCESS_DTB,
.dtb = drakvuf->kpgd);
Expand All @@ -300,28 +298,53 @@ static char* linux_read_kernel_version(drakvuf_t drakvuf, drakvuf_trap_info_t* i
return vmi_read_str(drakvuf->vmi, &ctx);
}

const kernel_version_t* linux_get_kernel_version(drakvuf_t drakvuf, drakvuf_trap_info_t* info)
static char* linux_read_kernel_version_from_current(drakvuf_t drakvuf, drakvuf_trap_info_t* info)
{
addr_t process_base = linux_get_current_process(drakvuf, info);
return linux_read_kernel_version(drakvuf, process_base);
}

static void linux_parse_kernel_version(drakvuf_t drakvuf, char* version)
{
int major, minor, patch;
int scanned = sscanf(version, "%d.%d.%d", &major, &minor, &patch);
g_free(version);

if (scanned == 3)
{
drakvuf->kernel_ver.major = major;
drakvuf->kernel_ver.minor = minor;
drakvuf->kernel_ver.patch = patch;
drakvuf->kernel_ver_initialized = true;
}
}

const kernel_version_t* linux_get_kernel_version_from_process(drakvuf_t drakvuf, addr_t process_base)
{
if (!drakvuf->kernel_ver_initialized)
{
char* version = linux_read_kernel_version(drakvuf, info);
char* version = linux_read_kernel_version(drakvuf, process_base);
if (!version)
{
PRINT_DEBUG("Failed to extract linux kernel version\n");
return NULL;
}
linux_parse_kernel_version(drakvuf, version);
}
return &drakvuf->kernel_ver;
}

int major, minor, patch;
int scanned = sscanf(version, "%d.%d.%d", &major, &minor, &patch);
g_free(version);

if (scanned == 3)
const kernel_version_t* linux_get_kernel_version(drakvuf_t drakvuf, drakvuf_trap_info_t* info)
{
if (!drakvuf->kernel_ver_initialized)
{
char* version = linux_read_kernel_version_from_current(drakvuf, info);
if (!version)
{
drakvuf->kernel_ver.major = major;
drakvuf->kernel_ver.minor = minor;
drakvuf->kernel_ver.patch = patch;
drakvuf->kernel_ver_initialized = true;
PRINT_DEBUG("Failed to extract linux kernel version\n");
return NULL;
}
linux_parse_kernel_version(drakvuf, version);
}
return &drakvuf->kernel_ver;
}
Expand Down Expand Up @@ -355,6 +378,7 @@ bool set_os_linux(drakvuf_t drakvuf)
drakvuf->osi.get_current_thread_id = linux_get_current_thread_id;
drakvuf->osi.get_process_pid = linux_get_process_pid;
drakvuf->osi.get_process_tid = linux_get_process_tid;
drakvuf->osi.get_process_pgid = linux_get_process_pgid;
drakvuf->osi.get_process_ppid = linux_get_process_ppid;
drakvuf->osi.get_process_data = linux_get_process_data;
drakvuf->osi.get_process_dtb = linux_get_process_dtb;
Expand Down
4 changes: 4 additions & 0 deletions src/libdrakvuf/linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ bool linux_get_process_pid(drakvuf_t drakvuf, addr_t process_base, vmi_pid_t* pi

bool linux_get_process_tid(drakvuf_t drakvuf, addr_t process_base, uint32_t* tid);

bool linux_get_process_pgid(drakvuf_t drakvuf, addr_t process_base, uint32_t* pgid);

char* linux_get_current_process_name(drakvuf_t drakvuf, drakvuf_trap_info_t* info, bool fullpath);

int64_t linux_get_process_userid(drakvuf_t drakvuf, addr_t process_base);
Expand Down Expand Up @@ -155,6 +157,8 @@ bool linux_get_kernel_symbol_rva(drakvuf_t drakvuf, const char* function, addr_t

bool linux_get_kernel_symbol_va(drakvuf_t drakvuf, const char* function, addr_t* va);

const kernel_version_t* linux_get_kernel_version_from_process(drakvuf_t drakvuf, addr_t process_base);

const kernel_version_t* linux_get_kernel_version(drakvuf_t drakvuf, drakvuf_trap_info_t* info);

char* linux_get_filepath_from_dentry(drakvuf_t drakvuf, addr_t dentry_addr);
Expand Down
28 changes: 28 additions & 0 deletions src/libdrakvuf/os.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,20 @@ bool drakvuf_get_process_thread_id(drakvuf_t drakvuf, addr_t process_base, uint3
return ret;
}

bool drakvuf_get_process_group_id(drakvuf_t drakvuf, addr_t process_base, uint32_t* pgid)
{
bool ret = false;

if ( drakvuf->osi.get_process_pgid )
{
drakvuf_lock_and_get_vmi(drakvuf);
ret = drakvuf->osi.get_process_pgid(drakvuf, process_base, pgid);
drakvuf_release_vmi(drakvuf);
}

return ret;
}

char* drakvuf_get_current_process_name(drakvuf_t drakvuf, drakvuf_trap_info_t* info, bool fullpath)
{
char* ret = NULL;
Expand Down Expand Up @@ -453,6 +467,20 @@ bool drakvuf_get_process_dtb(drakvuf_t drakvuf, addr_t process_base, addr_t* dtb
return ret;
}

bool drakvuf_get_process_arguments(drakvuf_t drakvuf, addr_t process_base, addr_t* argv)
{
bool ret = false;

if ( drakvuf->osi.get_process_arguments )
{
drakvuf_lock_and_get_vmi(drakvuf);
ret = drakvuf->osi.get_process_arguments(drakvuf, process_base, argv);
drakvuf_release_vmi(drakvuf);
}

return ret;
}

bool drakvuf_get_current_process_environ(drakvuf_t drakvuf, drakvuf_trap_info_t* info, GHashTable** environ)
{
bool ret = false;
Expand Down
3 changes: 3 additions & 0 deletions src/libdrakvuf/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ typedef struct os_interface
bool (*get_process_tid)
(drakvuf_t drakvuf, addr_t process_base, uint32_t* tid);

bool (*get_process_pgid)
(drakvuf_t drakvuf, addr_t process_base, uint32_t* pgid);

int64_t (*get_current_process_userid)
(drakvuf_t drakvuf, drakvuf_trap_info_t* info);

Expand Down
12 changes: 12 additions & 0 deletions src/plugins/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,17 @@ if get_option('plugin-hidevm')
config_h.set('ENABLE_PLUGIN_HIDEVM', 1)
endif

if get_option('plugin-procmon')
plugin_sources += 'procmon/procmon.cpp'
plugin_sources += 'procmon/linux.cpp'
plugin_sources += 'procmon/linux_utils.cpp'
plugin_sources += 'procmon/win.cpp'
plugin_sources += 'procmon/winnt.cpp'
plugin_sources += 'procmon/privileges.cpp'

config_h.set('ENABLE_PLUGIN_PROCMON', 1)
endif

if get_option('plugin-ptracemon')
plugin_sources += 'ptracemon/ptracemon.cpp'

Expand Down Expand Up @@ -257,6 +268,7 @@ summary({
'objmon': get_option('plugin-objmon'),
'rootkitmon': get_option('plugin-rootkitmon'),
'spraymon': get_option('plugin-spraymon'),
'procmon': get_option('plugin-procmon'),
'hidevm': get_option('plugin-hidevm'),
'ptracemon': get_option('plugin-ptracemon'),
'ebpfmon' : get_option('plugin-ebpfmon'),
Expand Down
Loading

0 comments on commit c932689

Please sign in to comment.