+function calls of type "pass" and "wrap"
authorshort <>
Thu, 30 Jan 2003 11:33:41 +0000 (11:33 +0000)
committershort <>
Thu, 30 Jan 2003 11:33:41 +0000 (11:33 +0000)
+support of <patch>ed W32 modules (currently only ntoskrnl.exe)
+trap of all unspecified <patched>ed W32 modules exported functions
+reference %fs:[0x124] for 'captive_KeGetCurrentKPCR()->CurrentThread'
+safe patching of "cli" instructions to "nop"

src/libcaptive/ps/signal.c

index 9ced3b0..fde4354 100644 (file)
 #include "captive/mm.h"        /* for captive_mmap_map_get() */
 #include <sys/mman.h>
 #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: