SSDT hooks for process creation XP/Vista/W7

Hi all,

I am developing a security application and am trying to accomplish a reliable DLL injection in a global system scale. The aim is to have each and every process load a custom user mode DLL that further intercepts some API calls to implement process monitoring and control when necessary. User mode code (CreateRemoteThread, LoadLibrary, SetWindowsHookEx etc) does pretty well to inject all currently running processes and at least most of the Windows GUI applications. Console applications including cmd.exe and short-lived cmd line based utilies are however ignored.

A kernel mode driver hook (largely based on http://www.codeproject.com/kb/system/hooksys.aspx ) comes to rescue with interception of NtCreateProcess, -ProcessEx, -Thread and -ThreadEx. The implementation of altering SSDT to hook these functions and to manipulate the starting address of the first thread of each process to a special thread that calls LoadLibrary before jumping to the real thread’s start address actually works. But only on XP. In XPSP3 it works even smooth and reliably, (modest) interoperability testing included.

The problems come with Vista and Windows 7 compatibility.

On Vista, apparently NtCreateProcess and -ProcessEx are abandoned. Hooking NtCreateUserProcess through the usual SSDT way works, and calls are spotted when user mode applications are started. The process handle returned by the real NtCreateUserProcess seems reasonable, 0x0900 and such. On the thread front, only NtCreateThreadEx gets hits. And the number of hits is nothing small. The function gets called pretty much constantly (not like busy loop constantly, but typically every few seconds) but the parameters (process handle etc) do not make much sense. Compared to the process handles returned by NtCreateUserProcess, the process handles passed are huge. I have not been able to spot matching process handle at the time of new application starting. It would feel logical, that a process is created first and then one or more threads spawned on it. Anyway, on Vista the hooking itself seems to work but cannot get anything done because the first thread creation cannot be detected, at least not in a reliable way.

Then on Windows 7, the story is shorter. I have tried numerous examples found plus my own code, and nothing runs. I have created free and checked versions of the drivers, signed them (with real certificate (and in Vista’s case also with self-created test certificates when Vista is in test-mode)), and who knows what other variations. W7 BSOD’s everytime when a write operation is done against the SSDT. It would seem obvious that Microsoft has decided to put a stop on the kernel mode API hooking, but have they? I have also tried reading a function address of NtCreateProcess (with the service index) from the service table and writing the exact same index back, but even that brings the BSOD up.

The service index numbers of these functions are figured out in user mode and passed to the driver over IOCTL call. Because of reasons unknown to my beginner KM skills, functions Nt/ZwCreateProcess didn’t resolve in the driver compilation. One sample was hooking ZwClose and that could be resolved in the driver code and the service index resolved there. Still, this UM->KM index number carrying works on XP and looks like it works on Vista/7 as well.

Everything described here has been in 32-bit environments. All test platforms are MSDN retail versions, would checked OS build make any difference?

I also played around with EasyHook (from CodePlex) for a while as it claimed Vista/7 compatibility and capability to provide smooth kernel mode hooking. Well, it was sort of smooth, but by the time I got till calling the LhInstallHook() function, the same BSOD kicks in from the EasyHookDrv32.sys. That one worked on XP as well so this approach didn’t seem to be any solution.

I have read a lot about why undocumented things shouldn’t be used and am aware of the downsides, but it seems like there is no other way to accomplish certain things and this is what anti-virus etc. vendors are all doing, isn’t it? If there is a better supported and clean way of doing this, then I will be super glad to learn about it.

Any comments, suggestions and insight will be appreciated.

Thanks.

KM

First go back and read the comments on this forum about hooking. Second
realize this is not going to work on x64 which is where the world is
going to. Third, realize that the sample has a lot of problems, your
security app is unsecure by using this sample. Fourth, if you had
checked the history of hooking you would have found those calls you
mention are some of the hardest to get right.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

-----Original Message-----
From: xxxxx@yahoo.com [mailto:xxxxx@yahoo.com]
Posted At: Wednesday, April 28, 2010 3:58 PM
Posted To: ntdev
Conversation: SSDT hooks for process creation XP/Vista/W7
Subject: SSDT hooks for process creation XP/Vista/W7

Hi all,

I am developing a security application and am trying to accomplish a
reliable
DLL injection in a global system scale. The aim is to have each and
every
process load a custom user mode DLL that further intercepts some API
calls to
implement process monitoring and control when necessary. User mode
code
(CreateRemoteThread, LoadLibrary, SetWindowsHookEx etc) does pretty
well to
inject all currently running processes and at least most of the
Windows GUI
applications. Console applications including cmd.exe and short-lived
cmd line
based utilies are however ignored.

A kernel mode driver hook (largely based on
http://www.codeproject.com/kb/system/hooksys.aspx ) comes to rescue
with
interception of NtCreateProcess, -ProcessEx, -Thread and -ThreadEx.
The
implementation of altering SSDT to hook these functions and to
manipulate the
starting address of the first thread of each process to a special
thread that
calls LoadLibrary before jumping to the real thread’s start address
actually
works. But only on XP. In XPSP3 it works even smooth and reliably,
(modest)
interoperability testing included.

The problems come with Vista and Windows 7 compatibility.

On Vista, apparently NtCreateProcess and -ProcessEx are abandoned.
Hooking
NtCreateUserProcess through the usual SSDT way works, and calls are
spotted
when user mode applications are started. The process handle returned
by the
real NtCreateUserProcess seems reasonable, 0x0900 and such. On the
thread
front, only NtCreateThreadEx gets hits. And the number of hits is
nothing
small. The function gets called pretty much constantly (not like busy
loop
constantly, but typically every few seconds) but the parameters
(process
handle etc) do not make much sense. Compared to the process handles
returned
by NtCreateUserProcess, the process handles passed are huge. I have
not been
able to spot matching process handle at the time of new application
starting.
It would feel logical, that a process is created first and then one or
more
threads spawned on it. Anyway, on Vista the hooking itself seems to
work but
cannot get anything done because the first thread creation cannot be
detected,
at least not in a reliable way.

Then on Windows 7, the story is shorter. I have tried numerous
examples found
plus my own code, and nothing runs. I have created free and checked
versions
of the drivers, signed them (with real certificate (and in Vista’s
case also
with self-created test certificates when Vista is in test-mode)), and
who
knows what other variations. W7 BSOD’s everytime when a write
operation is
done against the SSDT. It would seem obvious that Microsoft has
decided to put
a stop on the kernel mode API hooking, but have they? I have also
tried
reading a function address of NtCreateProcess (with the service index)
from
the service table and writing the exact same index back, but even that
brings
the BSOD up.

The service index numbers of these functions are figured out in user
mode and
passed to the driver over IOCTL call. Because of reasons unknown to my
beginner KM skills, functions Nt/ZwCreateProcess didn’t resolve in the
driver
compilation. One sample was hooking ZwClose and that could be resolved
in the
driver code and the service index resolved there. Still, this UM->KM
index
number carrying works on XP and looks like it works on Vista/7 as
well.

Everything described here has been in 32-bit environments. All test
platforms
are MSDN retail versions, would checked OS build make any difference?

I also played around with EasyHook (from CodePlex) for a while as it
claimed
Vista/7 compatibility and capability to provide smooth kernel mode
hooking.
Well, it was sort of smooth, but by the time I got till calling the
LhInstallHook() function, the same BSOD kicks in from the
EasyHookDrv32.sys.
That one worked on XP as well so this approach didn’t seem to be any
solution.

I have read a lot about why undocumented things shouldn’t be used and
am aware
of the downsides, but it seems like there is no other way to
accomplish
certain things and this is what anti-virus etc. vendors are all doing,
isn’t
it? If there is a better supported and clean way of doing this, then I
will be
super glad to learn about it.

Any comments, suggestions and insight will be appreciated.

Thanks.

KM

__________ Information from ESET Smart Security, version of virus
signature
database 5069 (20100428) __________

The message was checked by ESET Smart Security.

http://www.eset.com

Hi Don, and thanks for your reply.

Yes, as I have understood the 64-bit SSDT implementation uses offsets instead of absolute addresses. Didn’t go further there, but supposedly this is to control that the functions pointed to are actually within the kernel’s own implementation and not any 3rdparty driver.

Granted, I need to do more background checking and study the history, but discussion always helps. I am new to kernel mode stuff so it is fairly easy to get puzzled with all this, still trying to get something done here :slight_smile:

What interests me from the point of general evolution rather than my application, now that Windows kernels and OS implementation in general in the 64-bit fashion are getting more and more secure, is Microsoft exposing more documented and supported low level APIs for “trusted” software vendors to implement this sort of products. Something along the lines of the Windows Filtering Platform perhaps.

So you are saying that this is difficult to get right, but it seems to me that it is still the way to go on x86 to get this done, isn’t it? Or is there a more sane path to take? Something x64 proof? Nah?

I am sure there are threads talking about this too, hopefully it is not against the forum rules to mention things that have been mentioned before… :smiley:

KM

For 64-bit SSDT hooking does not work period. In general the
PsSetCreateProcessNotifyRotineEx will allow you to do what you want.
But this works only on Vista SP1 and later.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

-----Original Message-----
From: xxxxx@yahoo.com [mailto:xxxxx@yahoo.com]
Posted At: Wednesday, April 28, 2010 4:18 PM
Posted To: ntdev
Conversation: SSDT hooks for process creation XP/Vista/W7
Subject: RE: SSDT hooks for process creation XP/Vista/W7

Hi Don, and thanks for your reply.

Yes, as I have understood the 64-bit SSDT implementation uses offsets
instead
of absolute addresses. Didn’t go further there, but supposedly this is
to
control that the functions pointed to are actually within the kernel’s
own
implementation and not any 3rdparty driver.

Granted, I need to do more background checking and study the history,
but
discussion always helps. I am new to kernel mode stuff so it is fairly
easy to
get puzzled with all this, still trying to get something done here :slight_smile:

What interests me from the point of general evolution rather than my
application, now that Windows kernels and OS implementation in general
in the
64-bit fashion are getting more and more secure, is Microsoft exposing
more
documented and supported low level APIs for “trusted” software vendors
to
implement this sort of products. Something along the lines of the
Windows
Filtering Platform perhaps.

So you are saying that this is difficult to get right, but it seems to
me that
it is still the way to go on x86 to get this done, isn’t it? Or is
there a
more sane path to take? Something x64 proof? Nah?

I am sure there are threads talking about this too, hopefully it is
not
against the forum rules to mention things that have been mentioned
before… :smiley:

KM

__________ Information from ESET Smart Security, version of virus
signature
database 5069 (20100428) __________

The message was checked by ESET Smart Security.

http://www.eset.com

>intercepts some API calls to implement process monitoring and control when necessary. User mode

code (CreateRemoteThread, LoadLibrary, SetWindowsHookEx etc) does pretty well to inject all
currently running processes and at least most of the Windows GUI applications. Console applications
including cmd.exe and short-lived cmd line based utilies are however ignored.

Try AppInit_DLLs, this works for CMD.EXE and command-line, and for services too.

Does not work for native apps (normally it is only AUTOCHK - boot-time CHKDSK) though.

Hooking is discouraged, and MS took deliberate steps to make hooking non-working.

I think that SSDT hooks will not work on any x64 Windows.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com