From: Sebastian Lackner Subject: ntoskrnl: Emulate 'mov Eb, Gb' instruction on x86 processor architecture. Message-Id: <55139ACE.9060009@fds-team.de> Date: Thu, 26 Mar 2015 06:36:14 +0100 --- dlls/ntoskrnl.exe/instr.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) From 332dcc33d8be2ab7cddeba6320bde968b5872246 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Mon, 10 Nov 2014 07:14:48 +0100 Subject: ntoskrnl: Emulate 'mov Eb, Gb' instruction on x86 processor architecture. --- dlls/ntoskrnl.exe/instr.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c index fe35686..05cd238 100644 --- a/dlls/ntoskrnl.exe/instr.c +++ b/dlls/ntoskrnl.exe/instr.c @@ -59,7 +59,7 @@ static inline struct idtr get_idtr(void) } /* store an operand into a register */ -static void store_reg( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op ) +static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op ) { switch((regmodrm >> 3) & 7) { @@ -98,6 +98,22 @@ static void store_reg( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int lo } } +/* store an operand into a byte register */ +static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr ) +{ + switch((regmodrm >> 3) & 7) + { + case 0: context->Eax = (context->Eax & 0xffffff00) | *addr; break; + case 1: context->Ecx = (context->Ecx & 0xffffff00) | *addr; break; + case 2: context->Edx = (context->Edx & 0xffffff00) | *addr; break; + case 3: context->Ebx = (context->Ebx & 0xffffff00) | *addr; break; + case 4: context->Eax = (context->Eax & 0xffff00ff) | (*addr << 8); break; + case 5: context->Ecx = (context->Ecx & 0xffff00ff) | (*addr << 8); break; + case 6: context->Edx = (context->Edx & 0xffff00ff) | (*addr << 8); break; + case 7: context->Ebx = (context->Ebx & 0xffff00ff) | (*addr << 8); break; + } +} + /*********************************************************************** * INSTR_GetOperandAddr * @@ -399,19 +415,26 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) } break; /* Unable to emulate it */ + case 0x8a: /* mov Eb, Gb */ case 0x8b: /* mov Ev, Gv */ { - BYTE *addr = INSTR_GetOperandAddr(context, instr + 1, long_addr, + BYTE *data = INSTR_GetOperandAddr(context, instr + 1, long_addr, segprefix, &len); + unsigned int data_size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1; struct idtr idtr = get_idtr(); - unsigned int offset = addr - idtr.base; + unsigned int offset = data - idtr.base; - if (offset <= idtr.limit + 1 - (long_op ? 4 : 2)) + if (offset <= idtr.limit + 1 - data_size) { idt[1].LimitLow = 0x100; /* FIXME */ idt[2].LimitLow = 0x11E; /* FIXME */ idt[3].LimitLow = 0x500; /* FIXME */ - store_reg( context, instr[1], (BYTE *)idt + offset, long_op ); + + switch (*instr) + { + case 0x8a: store_reg_byte( context, instr[1], (BYTE *)idt + offset ); break; + case 0x8b: store_reg_word( context, instr[1], (BYTE *)idt + offset, long_op ); break; + } context->Eip += prefixlen + len + 1; return ExceptionContinueExecution; } -- 2.1.3