In this article we continue investigation in the field of hiding application in the system. This theme was started by Ivan Romanenko and Sergey Popenko in the article “Driver to Hide Processes and Files”. Our aim is to discover the ways of application hiding in the system for the wide audience. The approaches described can be used in the Corporate Security systems development – to hide system agents and prevent switching them off by users. Information can be also useful for those who research harmful software - to build the adequate answer for the threats.
- List of services
- Structure of SERVICE_RECORD
- Life After The Windows Vista
- Search of signatures
- Service hiding
- Correct restoration
- Structure of the project files
This article will tell where Windows OS stores the services and how uses them. We’ll discuss how this knowledge can be applied to finding our custom service and hiding it.
So let’s start our research.
2. List of services
At the first step of my research I thought that if there were services then somewhere their manager had to be. And it discovered to be true – such manager is in the file named services.exe.
The process services.exe deals with all operations associated with services, service manager – which is familiar to many developers by the ::OpenSCManager function, and obviously with the service storing too.
So my first task is to find where the service database is stored.
My analysis showed that we need ScInitDatabase function and it includes such assembler instructions:
ScInitDatabase proc near xor eax, eax push esi mov g_uScTotalNumServiceRecs, eax mov g_ImageDatabase, eax ; _IMAGE_RECORD ImageDatabase mov g_pImageDatabase, eax ; Pointer to first _IMAGE_RECORD mov g_ServiceDatabase, eax ; _SERVICE_RECORD ServiceDatabase mov g_pServiceDatabase, eax ; Pointer to first _SERVICE_RECORD call [email protected]@YGXXZ ; ScInitGroupDatabase(void) mov esi, ds:[email protected] ; RtlInitializeResource(x) push offset [email protected]@[email protected]@A ; CServiceRecordLock ScServiceRecordLock mov [email protected]@3KA, 1 ; ulong ResumeNumber call esi ; RtlInitializeResource(x) ; RtlInitializeResource(x) push offset [email protected]@[email protected]@A ; CServiceListLock ScServiceListLock call esi ; RtlInitializeResource(x) ; RtlInitializeResource(x) push offset [email protected]@[email protected]@A ; CGroupListLock ScGroupListLock call esi ; RtlInitializeResource(x) ; RtlInitializeResource(x) call [email protected]@YGHXZ ; ScGenerateServiceDB(void) neg eax sbb eax, eax neg eax pop esi retn ScInitDatabase end
The third, sixth and seventh lines are suspected to store the data we need – service database g_pServiceDatabase. On the basis of the places where ScCreateServiceRecord and ScGetNamedServiceRecord variables are used we can say that it is exactly what we are looking for – service database and the pointer to its beginning.
Without second thought we take this method as a basis as it is called only once at the program start, and choose signature to search pointer to the beginning of the list of services in the process memory.
Let’s consider the first variant
A3 9C A0 01 01 A3 98 A0 01 01 E8 B5 08 00 00, which is just the assembler code of the three mentioned lines:
mov g_ServiceDatabase, eax ; _SERVICE_RECORD ServiceDatabase mov g_pServiceDatabase, eax ; Pointer to first _SERVICE_RECORD call [email protected]@YGXXZ ; ScInitGroupDatabase(void)
To use this signature we should guarantee that:
- All versions of services.exe have the same signature in the proper place
- All versions of services.exe have only one such signature
I developed the simple utility based on the code of FindSignature function (plServicesSiganture.cpp):
I started with services.exe for Windows XP and then checked all mentioned requirements for the signature for the rest of the services.exe versions for other OS versions. That gave me the final variant of the signature, which suited all versions and requirements:
68 XX XX XX XX C7 XX XX XX XX XX 01 00 00 00
XX is any value that means that we should search the signature by mask.
This signature is pointing to the execution of the following commands from ScInitDatabase function:
2.3.Structure of SERVICE_RECORD
Service database it’s the list of structures
SERVICE_RECORD, which contain necessary description of each service for the system. Here we won’t discuss the complete structure
SERVICE_RECORD as far as it’s not necessary for us.
My further research discovered three fields:
Prev – pointer to the previous list element
Next – pointer to the next list element
ServiceName – pointer to the string with the service name
The offsets of these fields relative to the SERVICE_RECORD structure beginning are:
Prev – 0x00
Next – 0x04
ServiceName – 0x08
2.4. Life After The Windows Vista
Windows Vista release “changed the world” – and it affected services.exe also.
The search for the list beginning changed and so do the structure of
SERVICE_RECORD. Now dereferencing should be applied to the pointer to the service list beginning (it must be the common improved protection of the pointers in the process memory) and also I had to look for the new offsets of
Here are these offsets:
Prev – 0x00
Next – 0x60
ServiceName – 0x04
Changes in the logic of the database beginning search are reflected in the functions
SearchForServicesDbOffset_Vista (in the file plServicesSignature.cpp).
Below we’ll discuss the difficulties of the practical implementation.
3.1 Search of the signatures
To search for the signatures we should look through the memory of the “services.exe” process and detect a signature. So we examine all memory allocated by this process using
After that we find the beginning of the service list by the signature.
3.2. Service hiding
Now we should only find our record in the list and redefine the
Next pointer of the previous record to the record which is next to our one, and correspondingly the
Prev pointer of the next to our record should be redefined to the record which is previous to our one:
After these manipulations our service disappears.
3.3 Correct restoration
Hiding is good but I should tell about restoration too to complete the story.
Why restore? To delete service correctly by means of corresponding DeleteService function.
My proposition is to create callback function that returns the address of the hided service in the memory of the “services.exe” process after the hiding. Then we will be able to easily restore the services sequence when we need it.
We should remember that the system is permanently changing and Prev and Next pointers of the hided record can not be the “live” records in the service list already.
That’s why while restoring we should make such steps:
- Search the record which corresponds to the
Prevaddress; if there is such a record then add element to the list after the specified element (
- If the record is not found then search the record by the corresponding
Nextaddress. If it is found then add element to the list before the specified element (
- If the record is not found by Next pointer then simply add the service to the end of the service list (
4. Structure of the project files
The source code of the usermode application which illustrates everything told here is in the archive attached.
Jeffrey Richter, Christophe Nasarre. Windows via C/C++. Especially the chapter devoted to the Virtual memory research.