From 799a2f051a91246f88f161849435bbe4196da019 Mon Sep 17 00:00:00 2001 From: short <> Date: Thu, 30 Jan 2003 11:33:41 +0000 Subject: [PATCH] +function calls of type "pass" and "wrap" +support of ed W32 modules (currently only ntoskrnl.exe) +trap of all unspecified ed W32 modules exported functions +reference %fs:[0x124] for 'captive_KeGetCurrentKPCR()->CurrentThread' +safe patching of "cli" instructions to "nop" --- src/libcaptive/ps/signal.c | 74 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/src/libcaptive/ps/signal.c b/src/libcaptive/ps/signal.c index 9ced3b0..fde4354 100644 --- a/src/libcaptive/ps/signal.c +++ b/src/libcaptive/ps/signal.c @@ -30,10 +30,8 @@ #include "captive/mm.h" /* for captive_mmap_map_get() */ #include #include "reactos/internal/mm.h" /* for PAGE_SIZE */ - - -static greg_t val_exceptionstack_top=0; - +#include "captive/ldr.h" /* for captive_ModuleList_patchpoint_find() */ +#include "captive/ldr_exports.h" /* for struct captive_ModuleList_patchpoint */ /** @@ -43,7 +41,7 @@ static greg_t val_exceptionstack_top=0; * * Returns whether some exception occured (FIXME: in what scope?). * Exception handlers are registered from W32 binary in stack frames stored in "fs:[0x00000000]" - * value which gets mapped by libcaptive/ps/signal.c to #val_exceptionstack_top + * value which gets mapped by libcaptive/ps/signal.c to #fs_KPCR_ExceptionList * variable. * * libcaptive currently does not raise any exceptions therefore this call always returns value %0. @@ -74,11 +72,17 @@ ULONG RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,IN PCONTEXT Con } +/* =='KeGetCurrentKPCR()->ExceptionList'; + * libcaptive has reduced KPCR (named 'captive_KPCR') which + * does not contain this field + */ +static greg_t fs_KPCR_ExceptionList=(greg_t)-1; + static gboolean instr_mov_greg_to_fsmem(int greg,const void *fsmem,struct ucontext *ucontext) { - if (fsmem==0x00000000) { /* exception stack top pointer */ + if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */ /* moving from %esp is required to pass! */ - val_exceptionstack_top=ucontext->uc_mcontext.gregs[greg]; + fs_KPCR_ExceptionList=ucontext->uc_mcontext.gregs[greg]; return TRUE; } g_return_val_if_reached(FALSE); @@ -86,9 +90,14 @@ static gboolean instr_mov_greg_to_fsmem(int greg,const void *fsmem,struct uconte static gboolean instr_mov_fsmem_to_greg(const void *fsmem,int greg,struct ucontext *ucontext) { - if (fsmem==0x00000000) { /* exception stack top pointer */ + if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */ /* moving to %esp is required to pass! */ - ucontext->uc_mcontext.gregs[greg]=val_exceptionstack_top; + ucontext->uc_mcontext.gregs[greg]=fs_KPCR_ExceptionList; + return TRUE; + } + if (fsmem==(const void *)0x00000124) { /* =='KeGetCurrentKPCR()->CurrentThread' */ + g_return_val_if_fail(greg!=REG_ESP,FALSE); + ucontext->uc_mcontext.gregs[greg]=(greg_t)captive_KeGetCurrentKPCR()->CurrentThread; return TRUE; } g_return_val_if_reached(FALSE); @@ -111,7 +120,7 @@ static int op_regcode_to_greg(guint8 regcode) static void sigaction_SIGSEGV(int signo,siginfo_t *siginfo,struct ucontext *ucontext) { -const guint8 *reg_eip; +guint8 *reg_eip; const void *reg_eip_aligned; g_return_if_fail(signo==SIGSEGV); @@ -173,6 +182,51 @@ const void *reg_eip_aligned; } g_assert_not_reached(); } + + if (*reg_eip==0xF4) { /* hlt; from captive_ModuleList_patch() */ +struct captive_ModuleList_patchpoint *patchpoint; +const gchar *funcname_disabled; + + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: reg_eip=%p; 0xF4 hit",G_STRLOC,reg_eip); + + if ((funcname_disabled=captive_ModuleList_function_disable_find( + reg_eip))) { /* ExportAddress */ + g_error("%s: Reached disabled W32 function: %s",G_STRLOC,funcname_disabled); + g_assert_not_reached(); + } + patchpoint=captive_ModuleList_patchpoint_find( + reg_eip); /* ExportAddress */ + g_assert(patchpoint!=NULL); + if (reg_eip==patchpoint->orig_w32_func) { + g_assert(0xF4 /* hlt */ ==*patchpoint->orig_w32_func); + g_assert(patchpoint->orig_w32_2ndinstr_byte ==*patchpoint->orig_w32_2ndinstr); + if (patchpoint->through_w32_func) { + *patchpoint->orig_w32_func=patchpoint->orig_w32_func_byte; + *patchpoint->orig_w32_2ndinstr=0xF4; /* hlt */ + } + else { /* !patchpoint->through_w32_func */ + reg_eip=(guint8 *)patchpoint->wrap_wrap_func; + } + goto ok; + } + if (reg_eip==patchpoint->orig_w32_2ndinstr) { + g_assert(patchpoint->orig_w32_func_byte ==*patchpoint->orig_w32_func); + g_assert(0xF4 /* hlt */ ==*patchpoint->orig_w32_2ndinstr); + g_assert(patchpoint->through_w32_func==TRUE); + *patchpoint->orig_w32_func=0xF4; /* hlt */ + *patchpoint->orig_w32_2ndinstr=patchpoint->orig_w32_2ndinstr_byte; + patchpoint->through_w32_func=FALSE; + goto ok; + } + g_assert_not_reached(); + } + + if (*reg_eip==0xFA) { /* cli */ + g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: reg_eip=%p; CLI neutralized",G_STRLOC,reg_eip); + *reg_eip=0x90; /* nop */ + goto ok; + } + g_assert_not_reached(); ok: -- 1.8.3.1