Skip to content

Commit

Permalink
Merge pull request #97 from aoshiken/windows-utils
Browse files Browse the repository at this point in the history
Added useful Windows routines...
  • Loading branch information
tklengyel committed Mar 29, 2016
2 parents 1a5168b + dc257be commit 7024c7c
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/libdrakvuf/libdrakvuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,28 @@ struct drakvuf_trap {
void *data;
};


////////////////////////////////////////////////////////////////////////////

// IMHO these definitions must be placed within another file, named
// libdrakvuf-windows.h or something similar

// For get_previous_mode...
typedef enum privilege_mode {
KERNEL_MODE,
USER_MODE,
MAXIMUM_MODE
} privilege_mode_t ;

// Confirmed only on Win7 SP1...
typedef enum object_manager_object {
OBJ_MANAGER_PROCESS_OBJECT = 7,
OBJ_MANAGER_THREAD_OBJECT = 8
} object_manager_object_t ;

////////////////////////////////////////////////////////////////////////////


bool drakvuf_init (drakvuf_t *drakvuf,
const char *domain,
const char *rekall_profile);
Expand Down Expand Up @@ -265,6 +287,38 @@ char *drakvuf_get_current_process_name(drakvuf_t drakvuf,
uint64_t vcpu_id,
x86_registers_t *regs);


bool drakvuf_get_current_thread_id( drakvuf_t drakvuf,
uint64_t vcpu_id,
x86_registers_t *regs,
uint32_t *thread_id );

// Microsoft PreviousMode KTHREAD explanation:
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff559860(v=vs.85).aspx
bool drakvuf_get_current_thread_previous_mode( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
privilege_mode_t *previous_mode );

bool drakvuf_get_thread_previous_mode( drakvuf_t drakvuf,
addr_t kthread,
privilege_mode_t *previous_mode );

bool drakvuf_is_ethread( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t ethread_addr );

bool drakvuf_is_eprocess( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t eprocess_addr );

// ObReferenceObjectByHandle
bool drakvuf_obj_ref_by_handle( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t current_eprocess,
addr_t handle,
object_manager_object_t obj_type_arg,
addr_t *obj_body_addr );

#pragma GCC visibility pop

#ifdef __cplusplus
Expand Down
14 changes: 14 additions & 0 deletions src/libdrakvuf/vmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ enum offset {
EPROCESS_TASKS,
EPROCESS_PEB,
EPROCESS_OBJECTTABLE,
EPROCESS_PCB,

KPROCESS_HEADER,

PEB_IMAGEBASADDRESS,
PEB_LDR,
Expand Down Expand Up @@ -164,6 +167,8 @@ enum offset {
KTHREAD_APCSTATE,
KTHREAD_TRAPFRAME,
KTHREAD_APCQUEUEABLE,
KTHREAD_PREVIOUSMODE,
KTHREAD_HEADER,

KTRAP_FRAME_RIP,

Expand All @@ -173,6 +178,7 @@ enum offset {
NT_TIB_STACKLIMIT,

ETHREAD_CID,
ETHREAD_TCB,
CLIENT_ID_UNIQUETHREAD,

OBJECT_HEADER_TYPEINDEX,
Expand All @@ -185,6 +191,8 @@ enum offset {
POOL_HEADER_POOLTYPE,
POOL_HEADER_POOLTAG,

DISPATCHER_TYPE,

OFFSET_MAX
};

Expand All @@ -198,6 +206,8 @@ static const char *offset_names[OFFSET_MAX][2] = {
[EPROCESS_TASKS] = { "_EPROCESS", "ActiveProcessLinks" },
[EPROCESS_PEB] = { "_EPROCESS", "Peb" },
[EPROCESS_OBJECTTABLE] = {"_EPROCESS", "ObjectTable" },
[EPROCESS_PCB] = { "_EPROCESS", "Pcb" },
[KPROCESS_HEADER] = { "_KPROCESS", "Header" },
[PEB_IMAGEBASADDRESS] = { "_PEB", "ImageBaseAddress" },
[PEB_LDR] = { "_PEB", "Ldr" },
[PEB_LDR_DATA_INLOADORDERMODULELIST] = {"_PEB_LDR_DATA", "InLoadOrderModuleList" },
Expand All @@ -219,11 +229,14 @@ static const char *offset_names[OFFSET_MAX][2] = {
[KTHREAD_TRAPFRAME] = {"_KTHREAD", "TrapFrame" },
[KTHREAD_APCSTATE] = {"_KTHREAD", "ApcState" },
[KTHREAD_APCQUEUEABLE] = {"_KTHREAD", "ApcQueueable"},
[KTHREAD_PREVIOUSMODE] = { "_KTHREAD", "PreviousMode" },
[KTHREAD_HEADER] = { "_KTHREAD", "Header" },
[KAPC_APCLISTENTRY] = {"_KAPC", "ApcListEntry" },
[KTRAP_FRAME_RIP] = {"_KTRAP_FRAME", "Rip" },
[NT_TIB_STACKBASE] = { "_NT_TIB", "StackBase" },
[NT_TIB_STACKLIMIT] = { "_NT_TIB", "StackLimit" },
[ETHREAD_CID] = {"_ETHREAD", "Cid" },
[ETHREAD_TCB] = { "_ETHREAD", "Tcb" },
[CLIENT_ID_UNIQUETHREAD] = {"_CLIENT_ID", "UniqueThread" },
[OBJECT_HEADER_TYPEINDEX] = { "_OBJECT_HEADER", "TypeIndex" },
[OBJECT_HEADER_BODY] = { "_OBJECT_HEADER", "Body" },
Expand All @@ -232,6 +245,7 @@ static const char *offset_names[OFFSET_MAX][2] = {
[POOL_HEADER_BLOCKSIZE] = {"_POOL_HEADER", "BlockSize" },
[POOL_HEADER_POOLTYPE] = {"_POOL_HEADER", "PoolType" },
[POOL_HEADER_POOLTAG] = {"_POOL_HEADER", "PoolTag" },
[DISPATCHER_TYPE] = { "_DISPATCHER_HEADER", "Type" },
};

size_t offsets[OFFSET_MAX];
Expand Down
52 changes: 52 additions & 0 deletions src/libdrakvuf/win-handles.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,55 @@ addr_t drakvuf_get_obj_by_handle(drakvuf_t drakvuf, addr_t process, uint64_t han
return handle_table_get_entry(PM2BIT(drakvuf->pm), vmi, table_base,
table_levels, table_depth, &handlecount, handle);
}


/////////////////////////////////////////////////////////////////////////////////////////////


bool drakvuf_obj_ref_by_handle( drakvuf_t drakvuf, drakvuf_trap_info_t *info, addr_t current_eprocess,
addr_t handle, object_manager_object_t obj_type_arg, addr_t *obj_body_addr )
{
bool ret = false ;
addr_t obj_addr = 0 ;

obj_addr = drakvuf_get_obj_by_handle( drakvuf, current_eprocess, handle );

if ( obj_addr )
{
uint8_t object_type ;
access_context_t ctx = {
.translate_mechanism = VMI_TM_PROCESS_DTB,
.dtb = info->regs->cr3,
};

// Get TypeIndex from _OBJ_HEADER...
ctx.addr = obj_addr + offsets[ OBJECT_HEADER_TYPEINDEX ] ;

if ( vmi_read_8( drakvuf->vmi, &ctx, &object_type ) == VMI_SUCCESS )
{
if ( object_type == obj_type_arg )
{
if ( object_type == OBJ_MANAGER_PROCESS_OBJECT )
{
// Object Body must be an _EPROCESS...
ret = drakvuf_is_eprocess( drakvuf, info, obj_addr + offsets[ OBJECT_HEADER_BODY ] );
}
else
if ( object_type == OBJ_MANAGER_THREAD_OBJECT )
{
// Object Body must be an _ETHREAD...
ret = drakvuf_is_ethread( drakvuf, info, obj_addr + offsets[ OBJECT_HEADER_BODY ] );
}
else // Other object types...
ret = true ;
}
}
}

if ( ret )
{
*obj_body_addr = obj_addr + offsets[ OBJECT_HEADER_BODY ];
}

return ret ;
}
107 changes: 107 additions & 0 deletions src/libdrakvuf/win-processes.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@

#include "vmi.h"

typedef enum dispatcher_object {
DISPATCHER_PROCESS_OBJECT = 3,
DISPATCHER_THREAD_OBJECT = 6
} dispatcher_object_t ;


addr_t drakvuf_get_current_thread(drakvuf_t drakvuf, uint64_t vcpu_id, x86_registers_t *regs){
vmi_instance_t vmi = drakvuf->vmi;
addr_t thread;
Expand Down Expand Up @@ -164,3 +170,104 @@ char *drakvuf_get_process_name(drakvuf_t drakvuf, addr_t eprocess_base) {
char *drakvuf_get_current_process_name(drakvuf_t drakvuf, uint64_t vcpu_id, x86_registers_t *regs) {
return drakvuf_get_process_name(drakvuf, drakvuf_get_current_process(drakvuf, vcpu_id, regs));
}

/////////////////////////////////////////////////////////////////////////////////////////////


bool drakvuf_get_current_thread_id( drakvuf_t drakvuf, uint64_t vcpu_id, x86_registers_t *regs,
uint32_t *thread_id )
{
addr_t p_tid ;
addr_t ethread = drakvuf_get_current_thread( drakvuf, vcpu_id, regs );

if ( ethread )
{
if ( vmi_read_addr_va( drakvuf->vmi, ethread + offsets[ ETHREAD_CID ] + offsets[ CLIENT_ID_UNIQUETHREAD ],
0,
&p_tid ) == VMI_SUCCESS )
{
*thread_id = p_tid;

return true;
}
}

return false ;
}


/////////////////////////////////////////////////////////////////////////////////////////////

// Microsoft PreviousMode KTHREAD explanation:
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff559860(v=vs.85).aspx

bool drakvuf_get_thread_previous_mode( drakvuf_t drakvuf, addr_t kthread, privilege_mode_t *previous_mode )
{
if ( kthread )
{
if ( vmi_read_8_va( drakvuf->vmi, kthread + offsets[ KTHREAD_PREVIOUSMODE ], 0,
(uint8_t *)previous_mode ) == VMI_SUCCESS )
{
if ( ( *previous_mode == KERNEL_MODE ) || ( *previous_mode == USER_MODE ) )
return true ;
}
}

return false ;
}

bool drakvuf_get_current_thread_previous_mode( drakvuf_t drakvuf, drakvuf_trap_info_t *info,
privilege_mode_t *previous_mode )
{
addr_t kthread = drakvuf_get_current_thread( drakvuf, info->vcpu, info->regs );

return drakvuf_get_thread_previous_mode( drakvuf, kthread, previous_mode );
}


/////////////////////////////////////////////////////////////////////////////////////////////


bool drakvuf_is_ethread( drakvuf_t drakvuf, drakvuf_trap_info_t *info, addr_t ethread_addr )
{
dispatcher_object_t dispatcher_type ;
access_context_t ctx = {
.translate_mechanism = VMI_TM_PROCESS_DTB,
.dtb = info->regs->cr3,
};

ctx.addr = ethread_addr + offsets[ ETHREAD_TCB ] + offsets[ KTHREAD_HEADER ]
+ offsets[ DISPATCHER_TYPE ] ;

if ( vmi_read_8( drakvuf->vmi, &ctx, (uint8_t *)&dispatcher_type ) == VMI_SUCCESS )
{
if ( dispatcher_type == DISPATCHER_THREAD_OBJECT )
return true ;
}

return false ;
}


/////////////////////////////////////////////////////////////////////////////////////////////


bool drakvuf_is_eprocess( drakvuf_t drakvuf, drakvuf_trap_info_t *info, addr_t eprocess_addr )
{
dispatcher_object_t dispatcher_type ;
access_context_t ctx = {
.translate_mechanism = VMI_TM_PROCESS_DTB,
.dtb = info->regs->cr3,
};

ctx.addr = eprocess_addr + offsets[ EPROCESS_PCB ] + offsets[ KPROCESS_HEADER ]
+ offsets[ DISPATCHER_TYPE ] ;

if ( vmi_read_8( drakvuf->vmi, &ctx, (uint8_t *)&dispatcher_type ) == VMI_SUCCESS )
{
if ( dispatcher_type == DISPATCHER_PROCESS_OBJECT )
return true ;
}

return false ;
}

0 comments on commit 7024c7c

Please sign in to comment.