}
+#if 0
+
/**
* RtlpDispatchException:
* @ExceptionRecord: Ignored by libcaptive.
g_return_val_if_reached(0);
}
+#endif
+
/* =='KeGetCurrentKPCR()->ExceptionList';
* libcaptive has reduced KPCR (named 'captive_KPCR') which
* does not contain this field
*/
-static greg_t fs_KPCR_ExceptionList=(greg_t)-1;
+greg_t fs_KPCR_ExceptionList=(greg_t)-1;
+
+/* FIXME */
+static greg_t fs_KPCR_Unknown638=0;
+
static gboolean instr_mov_greg_to_fsmem(int greg,const void *fsmem,struct ucontext *ucontext)
{
g_return_val_if_reached(FALSE);
}
+static gboolean instr_mov_immed_to_fsmem(greg_t immed,const void *fsmem,struct ucontext *ucontext)
+{
+ if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */
+ fs_KPCR_ExceptionList=immed;
+ return TRUE;
+ }
+ g_return_val_if_reached(FALSE);
+}
+
static gboolean instr_mov_fsmem_to_greg(const void *fsmem,int greg,struct ucontext *ucontext)
{
if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */
g_return_val_if_reached(FALSE);
}
+static gboolean instr_push_fsmem(const void *fsmem,struct ucontext *ucontext)
+{
+ if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */
+ ucontext->uc_mcontext.gregs[REG_ESP]-=4;
+ *(greg_t *)ucontext->uc_mcontext.gregs[REG_ESP]=fs_KPCR_ExceptionList;
+ return TRUE;
+ }
+ g_return_val_if_reached(FALSE);
+}
+
+static gboolean instr_pop_fsmem(const void *fsmem,struct ucontext *ucontext)
+{
+ if (fsmem==(const void *)0x00000000) { /* exception stack top pointer */
+ fs_KPCR_ExceptionList=*(greg_t *)ucontext->uc_mcontext.gregs[REG_ESP];
+ ucontext->uc_mcontext.gregs[REG_ESP]+=4;
+ return TRUE;
+ }
+ g_return_val_if_reached(FALSE);
+}
+
+static gboolean instr_incl_fsmem(const void *fsmem,struct ucontext *ucontext)
+{
+ if (fsmem==(const void *)0x00000638) { /* Unknown638 */
+ fs_KPCR_Unknown638++;
+ return TRUE;
+ }
+ g_return_val_if_reached(FALSE);
+}
+
static int op_regcode_to_greg(guint8 regcode)
{
switch (regcode) {
}
if (*reg_eip==0x8B) { /* prefix 0x8B */
reg_eip++;
- if ((*reg_eip & ~0x38)==0x05) { /* 'mov %fs:{reg_eip[1..4]},%{op_regcode_to_greg(*reg_eip[b3..b5])} */
+ if ((*reg_eip & ~0x38)==0x05) { /* 'mov %fs:{reg_eip[1..4]},%{op_regcode_to_greg(*reg_eip[b3..b5])}' */
reg_eip++;
if (instr_mov_fsmem_to_greg(*(const void **)reg_eip,op_regcode_to_greg(reg_eip[-1]>>3U),ucontext)) {
reg_eip+=4;
}
g_assert_not_reached();
}
+ if (*reg_eip==0xFF) { /* prefix 0xFF */
+ reg_eip++;
+ if (*reg_eip==0x05) { /* 'incl %fs:{reg_eip[1..4]}' */
+ reg_eip++;
+ if (instr_incl_fsmem(*(const void **)reg_eip,ucontext)) {
+ reg_eip+=4;
+ goto ok;
+ }
+ g_assert_not_reached();
+ }
+ if (*reg_eip==0x35) { /* 'pushl %fs:{reg_eip[1..4]}' */
+ reg_eip++;
+ if (instr_push_fsmem(*(const void **)reg_eip,ucontext)) {
+ reg_eip+=4;
+ goto ok;
+ }
+ g_assert_not_reached();
+ }
+ g_assert_not_reached();
+ }
+ if (*reg_eip==0x8F) { /* prefix 0x0F */
+ reg_eip++;
+ if (*reg_eip==0x05) { /* 'popl %fs:{reg_eip[1..4]}' */
+ reg_eip++;
+ if (instr_pop_fsmem(*(const void **)reg_eip,ucontext)) {
+ reg_eip+=4;
+ goto ok;
+ }
+ g_assert_not_reached();
+ }
+ g_assert_not_reached();
+ }
+ if (*reg_eip==0xC7) { /* prefix 0xC7 */
+ reg_eip++;
+ if (*reg_eip==0x05) { /* 'movl ${reg_eip[5..8]},%fs:{reg_eip[1..4]}' */
+ reg_eip++;
+ if (instr_mov_immed_to_fsmem(((greg_t *)reg_eip)[1],*(const void **)reg_eip,ucontext)) {
+ reg_eip+=4+4;
+ goto ok;
+ }
+ g_assert_not_reached();
+ }
+ g_assert_not_reached();
+ }
+ g_assert_not_reached();
+ }
+
+ /* all instruction notation comments are written in AT&T 'instr src,dest' syntax! */
+ if (*reg_eip==0x66) { /* prefix '%fs:' */
+ reg_eip++;
+ /* TODO:thread; %fs: is CPU-dependent */
+ if (*reg_eip==0x8E) { /* two-byte opcode */
+ reg_eip++;
+ if (*reg_eip==0xE3) { /* 'mov %bx,%fs' */
+ reg_eip++;
+ g_assert(0x30==(0xFFFF&ucontext->uc_mcontext.gregs[REG_EBX]));
+ /* 'reload' of %fs can be ignored */
+ goto ok;
+ }
+ g_assert_not_reached();
+ }
g_assert_not_reached();
}
goto ok;
}
+ if (*reg_eip==0xFB) { /* sti */
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: reg_eip=%p; STI neutralized",G_STRLOC,reg_eip);
+ *reg_eip=0x90; /* nop */
+ goto ok;
+ }
+
g_assert_not_reached();
ok: