Hooking StartService

In the past two days, I was looking for a way to detect when service starts and prevent it.
At first I thought it would be rather “easy”, All I need to do is to create a filter-driver and catch the request for a service creation and that’s it.

Unfortunately, It’s not that “easy”. I thought there should be a representation of services in the kernel, but as it seems, there are none!
When one calls the StartService function, All it does is to send RPC message to services.exe. Then services.exe do all what counts: checks the service’s configuration, checking the dependencies, calls CreateProcess if needed, etc.
In all this procedure, the only kernel calls are the delivery of the RPC  (which you might hook if you are very, very sadistic), and a lot of registry related functions (reading/writing configurations), and of course a call to CreateProcess if needed, with no indication that the process is a service what-so-ever (remember, not all services are hosted in a unique process, some services can share the same process).
As it seems, there is just no way to determine when a service was launched from the kernel’s point-of-view.

So what should one do?

One can inject a DLL to services.exe and make a detour to RStartService(the function that handles the StartService RPC). Why should you hook that function and not StartService(system wide)? Because a service can be launched from a remote computer, therefor StartService won’t be called on the specific computer at all (and of course, a developer can implement the StartService by himself by calling the RPC directly, so even local commands might not be detected).

Note: If you want to detect a specific service from launching (i.e. check the service name and decide whether to block that service), hooking RStartService won’t be good enough.
Because RStartService won’t be called for the dependencies of the service the user launched, only the service itself. If one would like to fully block a specific service, it would be better to hook ScStartService (which is the function that actually starts every service).