Hi!
I’ve decided to implement a driver that can call user mode functions
recently (alike to SwitchStack mentioned in the OSR “Execution Context in NT
drivers” whitepaper).
Quote from the whitepaper follows (one of the most exciting parts
):
“Given the design of NT, there is very little that the called-back user
function cannot do. It can issue Win32
function calls, pop up dialog boxes, and perform File I/O. The only
difference is that the user-application is
running in kernel mode, on the kernel stack. When an application is running
in kernel mode it is not subject
to privilege limits, quotas, or protection checking. Since all functions
executing in kernel mode have IOPL,
the user application can even issue IN and OUT instructions (on an Intel
architecture system, of course).
Your imagination (coupled with common sense) is the only limit on the types
of things you could do with
this driver.”
My implementation allows the user mode client to specify the signature of
the function to call and the driver prepares the stack for the call
appropriately.
So, control flow is:
- The user mode client sends ioctl to the driver passing: function address,
calling convention, parameters. - The driver prepares the stack, calls the function, performs stack cleanup
(if needed by calling convention).
Everything works fine, until I try to call a function initiating a ring
transition (via sysenter). In this case, the user mode application hangs.
Here goes some WinDBG output concerning the user mode thread:
THREAD 82d3f780 Cid 224.2c4 Teb: 7ffde000 Win32Thread: 00000000 WAIT:
(DelayExecution) KernelMode Non-Alertable
82d3f870 NotificationTimer
IRP List:
8305ef68: (0006,0094) Flags: 40000000 Mdl: 00000000
Not impersonating
DeviceMap e1aa9c50
Owning Process 82cce5a0
Wait Start TickCount 30034 Elapsed Ticks: 4
Context Switch Count 825 LargeStack
UserTime 00:00:00.0000
KernelTime 00:00:00.0281
Start Address 0x77e8149f
Win32 Start Address 0x01001e52
Stack Init f5a8d000 Current f5a8cbc8 Base f5a8d000 Limit f5a88000 Call 0
Priority 16 BasePriority 8 PriorityDecrement 0 DecrementCount 0
ChildEBP RetAddr
f5a8cbe0 804ebd36 nt!KiSwapContext+0x2e (FPO: [EBP 0xf5a8cc18] [0,0,4])
f5a8cbec 804ec393 nt!KiSwapThread+0x44 (FPO: [0,0,2])
f5a8cc18 8055b7b7 nt!KeDelayExecutionThread+0x1c7 (FPO: [Non-Fpo])
f5a8cc48 8058aa29 nt!IoCancelThreadIo+0x66 (FPO: [Non-Fpo])
f5a8ccf0 8059785a nt!PspExitThread+0x41e (FPO: [Non-Fpo])
f5a8ccfc 804fb64f nt!PsExitSpecialApc+0x20 (FPO: [5,0,1])
f5a8cd4c 804da970 nt!KiDeliverApc+0x1ad (FPO: [Non-Fpo])
f5a8cd4c 7ffe0304 nt!KiExceptionExit+0x39 (FPO: [0,0] TrapFrame @ f5a8cd64)
f5a8cba4 804ec6c9 SharedUserData!SystemCallStub+0x4 (FPO: [0,0,0])
f5a8cb90 00000000 nt!KiInsertTimerTable+0x1a (FPO: [Non-Fpo]
kd> .trap f5a8cd64
ErrCode = 00000005
eax=c0000005 ebx=8305ef00 ecx=f5a8cb74 edx=7ffe0304 esi=82e41508
edi=0006ff74
eip=7ffe0304 esp=f5a8cb74 ebp=f5a8cb90 iopl=0 nv up ei ng nz na po
nc
cs=001b ss=0023 ds=0023 es=0023 fs=0000 gs=0000
efl=00000286
SharedUserData!SystemCallStub+4:
001b:7ffe0304 c3 ret
As seen from the output, the ring transition fails with
STATUS_ACCESS_VIOLATION.
The questions are:
- Have I missed something (the paper says that almost anything may be
called, but I’m limited to “pure” user mode functions so far)? - Is it possible to sneak by the check which leads to
STATUS_ACCESS_VIOLATION? - Why the thread hangs?
P.S. Of course, as if I need to say this, but:
- I know that it is not a brilliant idea to call the user mode functions
from the kmode (ok, it’s really a BAD idea
). - I know this is a hack.
- I know that a lot of things (including new service pack or star
disposition on the sky) may change the system and this code won’t work any
more. - This won’t be used in production.
- This is just a research.
So, please, “Repeat after me …”, “Go and write on the nearest whiteboard
…” and “Chorus says …” answer writers: don’t bother ![]()