home >> userland >> Hidden Service Detection

Introduction

TOP

Windows Service is a program executing in the background which is started automatically when Windows boots and runs as long as System is up and running. Service is designed to perform a specific function and generally does not interact with user.Compared to normal processes, Services normally run with 'System' privilege which allow them to perform higher privilege operations. Windows Service Manager (Services.exe) is responsible for managing all aspects of Services. Services can be managed using the built in 'Service Management Console' which can be launched through 'Administrative Tools' in Control Panel.

As services runs with highest privilege, most Rootkits implement services to keep control over the entire system.Though services operate in the background they can be seen through the 'Task Manager' or 'Service Management Console'. So it is important for the Rootkits to hide their services to prevent from being detected.

How Rootkits Hide Services

TOP

Many Rootkits such as Hacker Defender, Vanquish use the Services not only to manage its operations but to remain under the cover. As services are visible to normal user, Rootkits employ multiple methods to hide their services.

One of the common way to list services is using EnumServicesStatus API function. So Rootkits typically hook this function and return the results by filtering out its services. As a result any AntiRootkit application which uses this method will fail to discover such Rootkit services.

Another way to list all services is by enumerating 'Services' registry key. Windows keeps the database of all installed services in the registry at following location 'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services'. So application can manually enumerate through all the entries within this registry key to discover all the services. To hide from this technique, Rootkits hook the registry enumeration API functions and return the modified values thus deceiving the detection softwares.Detailed information about hiding registry entries and their detection is mentioned in the article [1]"Hidden Registry Detection".

Hidden Rootkit Services Detection Methods

TOP

Though the Rootkits use pretty good techniques to evade their detection, they can be effectively detected through advanced detection mechanisms presented below.

1. Using Hook Bypass Method through Mapped Image to Uncover Hidden Services
2. Enumerating Child Processes of Services.exe to Detect Hidden Services
3. Hidden Services Detection by Enumerating Processes with 'NtControlPipe'
4. Hidden Service Detection by Enumerating Services Registry Key

Hook Bypass Method through Mapped Image

TOP

This method rely on the fact that API hooking can be bypassed by directly mapping the DLL as an image rather than loading it through LoadLibrary function. This way any attempt by Rootkits to hook EnumServiceStatus function can be prevented by directly mapping the Advapi32.dll through CreateFileMapping API function. Then the EnumServiceStatus function within the mapped image is located and called directly thus bypassing the hooks leading to discovery of hidden Rootkit services. However this is not the new method and it was initially used in IceSword. Later it was exposed by EiNSTeiN_ in his [2]'Hidden Service Detection' article.

Here is the complete code example which illustrates this technique.


 typedef BOOL (WINAPI *LPFUN_ENUMSERVICESSTATUSEX) (
		  SC_HANDLE hSCManager,
		  SC_ENUM_TYPE InfoLevel,
		  DWORD dwServiceType,
		  DWORD dwServiceState,
		  LPBYTE lpServices,
		  DWORD cbBufSize,
		  LPDWORD pcbBytesNeeded,
		  LPDWORD lpServicesReturned,
		  LPDWORD lpResumeHandle,
		  LPCTSTR pszGroupName
		);
						
						
 BOOL DetectHiddenServicesUsingHookBypassMethod
                               (SC_HANDLE scManager)
 {
 char WinSysDir[MAX_PATH];
 char advapiPath[MAX_PATH*2];

   GetSystemDirectory(WinSysDir, MAX_PATH);
   sprintf_s(advapiPath, MAX_PATH*2, 
			 "%s\\advapi32.dll", WinSysDir);
   
   HANDLE hFile = CreateFile(advapiPath, 
   			     GENERIC_READ | GENERIC_EXECUTE , 
   			     FILE_SHARE_READ, 
   			     0, 
   			     OPEN_EXISTING, 
   			     0,
   			     0);
   
   if( hFile == INVALID_HANDLE_VALUE )
   {
   	printf("%s : Failed to open %s, Error=0x%.8x", 
	              __FUNCTION__, advapiPath, GetLastError());
   	return FALSE;
   }
   	
   HANDLE hMappedFile = CreateFileMapping(hFile, NULL, 
                  PAGE_EXECUTE_READ |SEC_IMAGE, 0, 0, NULL);
   
   if( hMappedFile == NULL )
   {
   	printf("%s : Failed to create file 
	             mapping for advapi32.dll", __FUNCTION__); 
   	CloseHandle(hFile);
   	return FALSE;
   }
   
   CloseHandle(hFile);
   
   LPVOID addrMappedDll = MapViewOfFile(hMappedFile, 
              FILE_MAP_READ | FILE_MAP_EXECUTE , 0, 0, 0);
   
   if( addrMappedDll == NULL )
   {
   	printf("%s : Failed to map view 
	             of flle advapi32.dll", __FUNCTION__);
   	CloseHandle(hMappedFile);
   	return FALSE;
   }
   
   CloseHandle(hMappedFile);

   LPFUN_ENUMSERVICESSTATUSEX MappedEnumServicesStatusEx = NULL;

   LPVOID addrDllBase = GetModuleHandle("advapi32.dll");
   MappedEnumServicesStatusEx = ( (DWORD)addrMappedDll + 
          ((DWORD)&EnumServicesStatusEx - (DWORD)addrDllBase) );
   
   printf("Org Advapi32 base address is  %p", addrDllBase);
   printf("Org EnumServiceStatus address is  %p", 
                                       &EnumServicesStatusEx);
   printf("Mapped Advapi32 address is %p", addrMappedDll);
   printf("Mapped enumservicesstatusEx address is %p", 
                                  MappedEnumServicesStatusEx);
   
   // Now enumerate services using 
   // mapped EnumServicesStatusEx function
  
   DWORD bytesNeeded ;
   DWORD countServices ;
   DWORD resumeHandle = 0;
   DWORD lastErrorCode;
   int totalCount=0;
   int curIndex=-1;
   BOOL retvalue;
   DWORD buffSize = sizeof(ENUM_SERVICE_STATUS_PROCESS) * 500;
   ENUM_SERVICE_STATUS_PROCESS *enumServices = NULL;
   
   while( 1 )
   {
       enumServices = 
	   ( ENUM_SERVICE_STATUS_PROCESS *) malloc( buffSize );
       
       if( enumServices == NULL )
       {
       	   printf("\n %s : 
		       Failed to allocated buffer", __FUNCTION__);
           break ;
       }
       
       retvalue = MappedEnumServicesStatusEx( scManager ,          
       				      SC_ENUM_PROCESS_INFO ,
       				      SERVICE_WIN32 ,     
       				      SERVICE_STATE_ALL , 
       				      enumServices ,     
       				      buffSize ,          
       				      &bytesNeeded ,      
       				      &countServices,     
       				      &resumeHandle,        
       				      NULL
       				      );
       
       
       // Error has occured ...
	   // not related to more data...so return

       lastErrorCode = GetLastError();
       if( retvalue == FALSE && lastErrorCode != ERROR_MORE_DATA )
       {
       	   free( enumServices );
       	   break;
       }
       
       for(int i = 0; i < countServices; i++ )
       {	
        // Check if this is hidden service 
		// by comparing with earlier results

        if( IsHiddenService(enumServices[i].lpServiceName) )
        {
       	 //We have found hidden service
       	 printf("\n Found hidden service %s ",
		                  enumServices[i].lpServiceName); 
        }
       }
       
       free( enumServices );
       
       // check if there are more services to be retrieved ...?
       if( (retvalue == FALSE) && 
	                   (lastErrorCode == ERROR_MORE_DATA) )
       	  buffSize = bytesNeeded ;
       else
          break; 
   }
   
   UnmapViewOfFile(addrMappedDll);
   
   return TRUE;
 }

This method can effectively detect the Rootkits such as HackerDefender which hooks EnumServiceStatus function to hide its services. Though there is no currently known Rootkits which hide against this method, it is possible to bypass this detection mechanism by hooking file mapping functions and then extending API hooks to any mapped DLL image also.

Enumerate Child Processes of Services.exe

TOP

All Windows service processes are created by 'Service Manager Process' i.e. Services.exe. This fact can be used to list all the child processes created by Services.exe, thus possibly detecting all running services. Since the normal process enumeration function can be hooked by Rootkits, the best way to implement this technique is to directly use NtQuerySystemInformation function to enumerate all processes and then separating out the child processes created by Services.exe. Then this list can be compared with the normal list to find all hidden services.

Below is the sample code which uses this technique to uncover all running services.


 BOOL IsChildProcess(int pidParent, int pidChild, HANDLE hprocess)
 {
   NTSTATUS status = STATUS_SUCCESS;
   PROCESS_BASIC_INFORMATION procInfo;
   
   status = NtQueryInformationProcess(hprocess,
   				   ProcessBasicInformation,
   				   &procInfo,
   				   sizeof(procInfo),
   				   NULL
   				   );
   
   if( status == STATUS_SUCCESS )
   {
       if( procInfo.ParentProcessId == pidParent )
   	return TRUE;
   }
   
   return FALSE;
 }


 void DetectHiddenServices(int pidService)
 {
    NTSTATUS status = STATUS_SUCCESS;
    DWORD dwSize = 800000;
    void *bufHandleTable = malloc(dwSize);;
    
    status = NtQuerySystemInformation
	   (SystemHandleInformation, bufferHandleTable, dwSize, 0);

    if( status != STATUS_SUCCESS )
    {
	//failed 
	return;
    }

   HANDLE hprocess; 
   SYSTEM_HANDLE_INFORMATION *HandleInfo = 
                   (SYSTEM_HANDLE_INFORMATION *) bufHandleTable;

   for(int i=0; i< HandleInfo->NumberOfHandles; i++)
   {
   	int pid = HandleInfo->Handles[i].UniqueProcessId;
   	
	//If this process is services.exe then ignore
	if( pidService == pid )
            continue;

	hprocess = 
	OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 
                               false,
                               pid);
		
	if( hprocess == NULL )
	    continue;

	if( IsChildProcess(pidServices, pid, hprocess) )
	{
	   printf("Found service process %d", pid);
	}

	CloseHandle(hprocess);
   }


 }

Although this technique can be easily thwarted by hooking the NtQuerySystemInformation in the Kernel, it presents simple way to detect services hidden by userland Rootkits.

Enumerating Processes with 'NtControlPipe' Handle

TOP

Every Windows service interacts with 'Service Manager Process' (services.exe) through named pipe. This named pipe has the name 'NtControlPipe**' where ** indicates the start order of that service. So by enumerating all the processes having handle 'NtControlPipe**' one can list all running services. Then this list can be compared with normal services discovered through EnumServiceStatus function to uncover the hidden service processes.

Here is the sample code below which uses this technique...


 NTSTATUS status = STATUS_SUCCESS;
 DWORD dwSize = 800000;
 void *bufHandleTable = malloc(dwSize);;

 status = NtQuerySystemInformation(SystemHandleInformation, 
			bufferHandleTable, dwSize, 0);

 if( status != STATUS_SUCCESS )
 {
 //failed 
 return;
 }

 HANDLE hprocess,hCopy; 
 IO_STATUS_BLOCK iostatus;
 int pid;
 BOOL bResult;


 SYSTEM_HANDLE_INFORMATION *HandleInfo = 
		(SYSTEM_HANDLE_INFORMATION *) bufHandleTable;

 PFILE_NAME_INFORMATION pNameInfo = 
	(PFILE_NAME_INFORMATION)malloc( MAX_PATH * 2 * 2); 

 int dwInfoSize = MAX_PATH * 2 * 2;


 for(int i=0; i< HandleInfo->NumberOfHandles; i++)
 {
 int pid = HandleInfo->Handles[i].UniqueProcessId;
 //If this process is services.exe then ignore
 if( pidService == pid )
		continue;

 //Check for only file handles
 //For XP HANDLE_TYPE_FILE is 28
 if( HandleInfo->Handles[i].ObjectTypeIndex ==  HANDLE_TYPE_FILE)
 {
	hprocess = 
	OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, 
					   false, 
					   pid
					   );

	if( hprocess == NULL )
	   continue;

	bResult = DuplicateHandle(hprocess, 
			(HANDLE)HandleInfo->Handles[i].Handle, 
			GetCurrentProcess(), 
			&hCopy, 
			MAXIMUM_ALLOWED, 
			FALSE, 
			0);
				   
   if( bResult == FALSE )
	  continue;

   status = NtQueryInformationFile(hCopy, 
			&iostatus, 
			pNameInfo, 
			dwInfoSize, 
			FileNameInformation);

   if( status == STATUS_SUCCESS )
   {
	// check if this handle is named 
	// pipe with name 'ntcontrolpipe'

	wcslwr(pNameInfo->FileName); 
	if( wcsstr( pNameInfo->FileName, L"ntcontrolpipe") )
	{
	 //Found the service, now check if its hidden service 
	 if( IsHiddenService(pid) )
	 {
		printf("Found hidden service %d", pid);
	 }
		
	}
   }
	
   CloseHandle(hCopy);
   CloseHandle(hprocess);
  }
       
} //End of for loop
		

But this code hangs when NtQueryInformationFile tries to get the name of named pipe. However it works greatly when executed inside the kernel. Even the [3]process explorer from Sysinternals uses the driver to enumerate process handles. It may be possible to successfully implement this method in the user land itself through some innovative way.

Enumerating Services Registry Key

TOP

As mentioned earlier, Windows stores all installed services under the following registry key, ' HEKY_LOCAL_MACHINE\System\CurrentControlSet\Services'. Normally Rootkits hides their service entries under this key by using variety of registry hiding technique. As a result any attempt to discover these hidden services using standard registry functions will fail. However these hidden keys can be successfully uncovered as explained in the article [1]'Hidden Registry Detection'.

Though many Rootkits uses combination of methods to hide their services, there are some (for example Vanquish Rootkit) which uses only this technique to hide its services. As a result such services are shown even in normal query through EnumServiceStatus function. So in order to effectively mark it as Rootkit, one has to use this method of detection as well.

Conclusion

TOP

This article described variety of techniques to detect the hidden Rootkit services. Even though most of the times one method is enough to uncover the hidden services, its good idea to combine multiple techniques to make the detection process more robust and successful.

EvilFingers Arsenal




Socialize with RootkitAnalytics

Twitter Feed Blogspot

Links

Rootkits & Enterprise: Enterprise is a major victim to rootkits. What could rootkits do to them?[read more]

Rootkits & Home-users: Do home-users know the seriousness of rootkits? What should a home-user know about rootkits?[read more]

Rootkits & Information Warfare: What does the silent war of intelligence and national security, got to do with rootkit analysis?[read more]

Userland Rootkits: What should one know about userland rootkits?[read more]

Kernelland Rootkits: What should one know about kernelland rootkits?[read more]

ElfStat: ElfStat is a tool designed for detecting any kernel malware that modifies the text segment of the kernel in memory...[read more]

Syscall/Kernel function interception: This is a more stealth method of syscall hijacking without having to directly modify the syscall table; instead the first several bytes of the syscall are overwritten with a jump to the new code...[read more]

Syscall Interception: What should you know about Syscall interception by directly modifying the Syscall table?[read more]

KsiD [Kernel Symbol Interception Detection]: This tool is designed to detect kernel rootkits and kernel malware which hijack syscalls and kernel functions ...[read more]

IDT /dev/kmem rootkit method: This can be done using several methods including overwriting the first several bytes of the syscall with a jump to other code, or modifying the function pointers.[read more]

Hidden Process Detection: Hidden Process Detection [HPD] using Direct NT System Call Implemenation, PIDB (Process ID Bruteforce) method, CSRSS Process Handle Enumeration and other methods...[read more]

Hidden Registry Detection: Reason for Hiding the Registry Entries, Rootkit techniques to hide, and Detecting Hidden Registry Entries Using Direct NT System Call Method and Directly Reading Hives Method...[read more]

Hidden Service Detection: Hidden Rootkit Services Detection Methods...Enumerating Processes with 'NtControlPipe', Hook Bypass Method through Mapped Image, Services Enumerating Child Processes of Services.exe, Enumerating Services Registry Key...[read more]

Syscall Handler Checker [SHC]: This tool simply verifies whether or not the system call handler system_call() has been patched to call a phony sys_call_table. If a phony sys_call_table appears to be in use, a tool like elfstat can be used for further analysis...[read more]

Firmware Rootkits: Firmware is a small static code that runs on devices ranging from consumer electronics to anything that controls heavy machinery...[read more]

Hypervisor Rootkits: This comes under both firmware and hardware rootkits. The reason being, hypervisor is a virtual environment that runs on the hardware, but basically it is a firmware. Hence, we have drawn the line and dropped this rootkit in the firmware category of rootkits...[read more]

Publications: In this section, we are planning to list all the papers that we have published so far that are rootkit related.

Backdoor Ultimate Defender: In this paper (Backdoor.Win32.UltimateDefender.gtz - Reversing) we analyze install.exe that presents the typical structure of an Medium Evoluted Malware, with basical Obfuscated-Dummy Code...[read more]

Socialize: You could socialize with us by many ways...[read more]

About: Learn about rootkit analytics here...[read more]

Contact us: How can you reach us...[read more]

Our Team: Read more about the rootkit analytics team...[read more]

dwtf v1.0: dwtf is a DLL copying engine ... [read more]

Exploring ADS: Alternate Data Stream (ADS) is the lesser known feature of Windows NTFS file system which...[read more]

Installations [from RootkitAnalytics.com]

ToolsCount
~~~~~~~~~~~~~~~~~~~
Elfstat5914
dwtf4994
KsiD4441
SHC3506

NOTE: Our tools are listed in many sites and torrents, which makes it hard for us to track all downloads. Hence, we are listing only the total installations from our website.

Socialize with EvilFingers

Twitter Feed Blogspot LinkedIn Delicious Google

Tweets