From 2acec63b2ed75bf4b71ad257db573c4b8f9639e7 Mon Sep 17 00:00:00 2001 From: tumagonx Date: Tue, 8 Aug 2017 10:54:53 +0700 Subject: initial commit --- i386.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 i386.c (limited to 'i386.c') diff --git a/i386.c b/i386.c new file mode 100644 index 0000000..1ad1ad2 --- /dev/null +++ b/i386.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2004 Security Architects Corporation. All rights reserved. + * + * Module Name: + * + * i386.c + * + * Abstract: + * + * This module implements various x86 processor dependant routines. + * + * Author: + * + * Eugene Tsyrklevich 07-Apr-2004 + * + * Revision History: + * + * None. + */ + + +#include +#include "hookproc.h" +#include "i386.h" +#include "misc.h" + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text (INIT, InitI386) +#endif + + +ULONG SystemAddressStart; +static ULONG SharedUserDataAddress, TssAddress; +ULONG MajorVersion, MinorVersion; + + +/* + * InitI386() + * + * Description: + * Verify that we are running on Win2k, XP or 2003 on x86 platform. + * Also initialize various i386 related variables. Since Windows Advanced & Datacenter editions + * support a boot-time option that allows 3-GB user address spaces we cannot rely + * on static addresses for predefined structures. + * + * + * Parameters: + * None. + * + * Returns: + * Nothing. + */ + +BOOLEAN +InitI386() +{ + CHAR Gdtr[6]; + USHORT TssOffset; + PKGDTENTRY TssGdtEntry; + + + PsGetVersion(&MajorVersion, &MinorVersion, NULL, NULL); + + + /* + * Right now we only support Windows 2000 (5.0), XP (5.1), 2003 (5.2) + */ + + if (MajorVersion != 5 || MinorVersion > 2) + { + LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("InitI386: Version = %d.%d\n", MajorVersion, MinorVersion)); + return FALSE; + } + + + /* + * Find the Shared User Data address. + */ + + if (* (PULONG) MmHighestUserAddress == 0x7FFEFFFF) + { + SharedUserDataAddress = 0x7FFE0000; + SystemAddressStart = 0x80000000; + } + else if (* (PULONG) MmHighestUserAddress == 0xBFFEFFFF) + { + SharedUserDataAddress = 0xBFFE0000; + SystemAddressStart = 0xC0000000; + } + else + { + LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("InitI386: Unknown MmHighestUserAddress=%x\n", * (PULONG) MmHighestUserAddress)); + return FALSE; + } + + + /* + * Find the TSS address. + * + * STR - Stores the segment selector from the task register (TR) in the destination operand. The + * destination operand can be a general-purpose register or a memory location. The segment selector + * stored with this instruction points to the task state segment (TSS) for the currently running task. + * + * SGDT - Stores the content of the global descriptor table register (GDTR) in the destination operand. + * The destination operand specifies a 6-byte memory location. + */ + + _asm + { + str TssOffset + sgdt Gdtr + } + + TssGdtEntry = (PKGDTENTRY) * (PULONG) (Gdtr + 2); /* Extract the GDT address */ + (PCHAR) TssGdtEntry += TssOffset; + + TssAddress = TssGdtEntry->BaseLow | ( ((TssGdtEntry->HighWord.Bytes.BaseHi) << 24) | ((TssGdtEntry->HighWord.Bytes.BaseMid) << 16) ); + + + return TRUE; +} + + + +/* + * VerifyUserReturnAddress() + * + * Description: + * Verifies whether a specified userland return address is valid. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + */ + +VOID +VerifyUserReturnAddress() +{ + PKTSS tss = (PKTSS) TssAddress; + ULONG UserEip, UserEsp; + + + /* + * this feature is not supported on Windows 2000 as it can make + * system calls from anywhere, not just ntdll.dll (it uses int 0x2e instead of sysenter) + */ + if (MinorVersion == 0) + return; + + if (KeGetPreviousMode() != UserMode) + return; + + + // EIP is 5 DWORDs before ESP0 on stack +#define EIP_OFFSET 5 + + UserEip = * (PULONG) (tss->Esp0 - EIP_OFFSET * sizeof(DWORD)); + + +#define STACK_POINTER_OFFSET 2 + + UserEsp = * (PULONG) (tss->Esp0 - STACK_POINTER_OFFSET * sizeof(DWORD)); + UserEsp -= 4; + + + //XXX verify that the return address is not on a writable page + //(might be used with Win2K which can make calls from anywhere) + + if (UserEip < (ULONG) NTDLL_Base) + { + LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%d VerifyUserReturnAddress: Abnormal return user EIP=%x ESP0=%x (NTDLL_Base=%x)\n", (ULONG) PsGetCurrentProcessId(), UserEip, tss->Esp0, NTDLL_Base)); + + LogAlert(ALERT_SS_BOPROT, OP_INVALIDCALL, ALERT_RULE_BOPROT_INVALIDCALL, ACTION_LOG, ALERT_PRIORITY_HIGH, NULL, 0, NULL); + } +} -- cgit v1.3