summaryrefslogtreecommitdiff
path: root/i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'i386.c')
-rw-r--r--i386.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/i386.c b/i386.c
new file mode 100644
index 0000000..1ad1ad2
--- /dev/null
+++ b/i386.c
@@ -0,0 +1,178 @@
1/*
2 * Copyright (c) 2004 Security Architects Corporation. All rights reserved.
3 *
4 * Module Name:
5 *
6 * i386.c
7 *
8 * Abstract:
9 *
10 * This module implements various x86 processor dependant routines.
11 *
12 * Author:
13 *
14 * Eugene Tsyrklevich 07-Apr-2004
15 *
16 * Revision History:
17 *
18 * None.
19 */
20
21
22#include <NTDDK.h>
23#include "hookproc.h"
24#include "i386.h"
25#include "misc.h"
26
27
28#ifdef ALLOC_PRAGMA
29#pragma alloc_text (INIT, InitI386)
30#endif
31
32
33ULONG SystemAddressStart;
34static ULONG SharedUserDataAddress, TssAddress;
35ULONG MajorVersion, MinorVersion;
36
37
38/*
39 * InitI386()
40 *
41 * Description:
42 * Verify that we are running on Win2k, XP or 2003 on x86 platform.
43 * Also initialize various i386 related variables. Since Windows Advanced & Datacenter editions
44 * support a boot-time option that allows 3-GB user address spaces we cannot rely
45 * on static addresses for predefined structures.
46 *
47 *
48 * Parameters:
49 * None.
50 *
51 * Returns:
52 * Nothing.
53 */
54
55BOOLEAN
56InitI386()
57{
58 CHAR Gdtr[6];
59 USHORT TssOffset;
60 PKGDTENTRY TssGdtEntry;
61
62
63 PsGetVersion(&MajorVersion, &MinorVersion, NULL, NULL);
64
65
66 /*
67 * Right now we only support Windows 2000 (5.0), XP (5.1), 2003 (5.2)
68 */
69
70 if (MajorVersion != 5 || MinorVersion > 2)
71 {
72 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("InitI386: Version = %d.%d\n", MajorVersion, MinorVersion));
73 return FALSE;
74 }
75
76
77 /*
78 * Find the Shared User Data address.
79 */
80
81 if (* (PULONG) MmHighestUserAddress == 0x7FFEFFFF)
82 {
83 SharedUserDataAddress = 0x7FFE0000;
84 SystemAddressStart = 0x80000000;
85 }
86 else if (* (PULONG) MmHighestUserAddress == 0xBFFEFFFF)
87 {
88 SharedUserDataAddress = 0xBFFE0000;
89 SystemAddressStart = 0xC0000000;
90 }
91 else
92 {
93 LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("InitI386: Unknown MmHighestUserAddress=%x\n", * (PULONG) MmHighestUserAddress));
94 return FALSE;
95 }
96
97
98 /*
99 * Find the TSS address.
100 *
101 * STR - Stores the segment selector from the task register (TR) in the destination operand. The
102 * destination operand can be a general-purpose register or a memory location. The segment selector
103 * stored with this instruction points to the task state segment (TSS) for the currently running task.
104 *
105 * SGDT - Stores the content of the global descriptor table register (GDTR) in the destination operand.
106 * The destination operand specifies a 6-byte memory location.
107 */
108
109 _asm
110 {
111 str TssOffset
112 sgdt Gdtr
113 }
114
115 TssGdtEntry = (PKGDTENTRY) * (PULONG) (Gdtr + 2); /* Extract the GDT address */
116 (PCHAR) TssGdtEntry += TssOffset;
117
118 TssAddress = TssGdtEntry->BaseLow | ( ((TssGdtEntry->HighWord.Bytes.BaseHi) << 24) | ((TssGdtEntry->HighWord.Bytes.BaseMid) << 16) );
119
120
121 return TRUE;
122}
123
124
125
126/*
127 * VerifyUserReturnAddress()
128 *
129 * Description:
130 * Verifies whether a specified userland return address is valid.
131 *
132 * Parameters:
133 * None.
134 *
135 * Returns:
136 * Nothing.
137 */
138
139VOID
140VerifyUserReturnAddress()
141{
142 PKTSS tss = (PKTSS) TssAddress;
143 ULONG UserEip, UserEsp;
144
145
146 /*
147 * this feature is not supported on Windows 2000 as it can make
148 * system calls from anywhere, not just ntdll.dll (it uses int 0x2e instead of sysenter)
149 */
150 if (MinorVersion == 0)
151 return;
152
153 if (KeGetPreviousMode() != UserMode)
154 return;
155
156
157 // EIP is 5 DWORDs before ESP0 on stack
158#define EIP_OFFSET 5
159
160 UserEip = * (PULONG) (tss->Esp0 - EIP_OFFSET * sizeof(DWORD));
161
162
163#define STACK_POINTER_OFFSET 2
164
165 UserEsp = * (PULONG) (tss->Esp0 - STACK_POINTER_OFFSET * sizeof(DWORD));
166 UserEsp -= 4;
167
168
169 //XXX verify that the return address is not on a writable page
170 //(might be used with Win2K which can make calls from anywhere)
171
172 if (UserEip < (ULONG) NTDLL_Base)
173 {
174 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));
175
176 LogAlert(ALERT_SS_BOPROT, OP_INVALIDCALL, ALERT_RULE_BOPROT_INVALIDCALL, ACTION_LOG, ALERT_PRIORITY_HIGH, NULL, 0, NULL);
177 }
178}