Friday, September 3, 2010

Svchost From A To Z - Part 1

In the next few posts i will be discussing svchost.exe and its internals. I chose Svchost since it is responsible for surrogating alot of windows services (those of type SERVICE_WIN32_SHARE_PROCESS).

To see how many of these services exist on your system, all you have to do is hit tasklist /svc in CMD.
As you can see in the image above, there are 5 instances of svchost on my system.

N.B. It differs from one windows to another and it also depends on your system's configuration.

Each instance of Svchost surrogates one or more services. For example one of the instances in the image above (Pid 872) surrogates 2 services, DcomLaunch and TermService and instance (Pid 1096) surrogates only one service, Dnscache.

We should easily conclude that any optimization in Svchost's code will greatly influence the system performance. Also, due to the high number of instances and services, Svchost has become a target for malware hiding their code. So, a good study of this topic is necessary.

Now get ready for discussing everything about Svchost.

Svchost's internal data structures will be revealed in this series, only for the purpose of learning.

First question you may ask is "why all these instances?" simple question and the answer will be also simple "because they have common properties"

Okay, How each Svchost knows its child services.???
To simplifiy the answer let's use WMIC to see each process's commandline.

One of the Svchost instances in the image above has the following command line:
"C:\WINDOWS\system32\svchost -k netsvcs"
The "-k" parameter tells us that netsvcs refers to the name for the group of services run under this instance.

N.B. -K switch determines the service group or category that Svchost will surrogate.

Hereafter, i will be using OllyDbg for reversing Svchost.exe.

Starting with the main function, i found that it does the following:

1) Parses the commandline passed to Svchost using a function called BuildCommandOptions.
which returns a pointer to a structure of type INSTANCE_PARAMS.

struct INSTANCE_PARAMS
{
   wchar_t* cmdline;
   wchar_t* cmdline2;
  bool gpFound;
  wchar_t* svc_gp;
  unsigned long CoInitia;
  unsigned long Authentica;
  unsigned long Impersona;
  unsigned long AuthenticaCapa;
  unsigned long RpcStack;
};

2) calls the "BuildServiceArray" function which takes a pointer returned by the "BuildCommandOptions" function as argument and creates an array of structures of type _SERVICE_ARRAY_ELEMENT.

struct _SERVICE_ARRAY_ELEMENT
{
   wchar_t* srv_name;
  _SRV_DLL_INFO* srv_dll_info;
  char* SvcMainName;
  unsigned long Count;
  FUNCPTR d;
};

The address of the created array is then stored in a global variable called ServiceArray.

3) calls the "BuildServiceTable" function which returns a pointer to an array of structures, each of type _SERVICE_TABLE_ELEMENT.

struct _SERVICE_TABLE_ELEMENT
{
    wchar_t* lpServiceName;
    FUNCPTR2 lpFuncPtr;
};

The pointer returned by this function is then passed to the "advapi32!StartServiceCtrlDispatcherW" function. StartServiceCtrlDispatcherW connects the main thread of Svchost  to SCM, short for Service Control Manager. Refer to MSDN for more information about SCM.

Now back to the "_SERVICE_TABLE_ELEMENT" structure. The structure's first member is a pointer to a string for the service name. Second member is the EntryPoint of the service-specific function (yes, it should be service-specific but in case of Svchost, it is always the EntryPoint of the "ServiceStarter" function, a function residing in Svchost.exe itself).

N.B.  The "ServiceStarter" in turn calls the real service-specific function, usually residing in the service Dll.

N.B. An array of _SERVICE_TABLE_ELEMENT's with the last one initialized to zero is called the Service Table.

Using the service table, Svchost tell SCM about the services it wants to surrogate,waiting for SCM's approval for each service, this all occurs in the process's main thread.

N.B. You should be aware that later each service in each Svchost instance will have its own thread.

Conclusion:
BuildCommandOptions, BuildServiceArray, and BuildServiceTable are called once for each Svchost  instance, in the main thread, but ServiceStarter is called once for each service under the context of the service's thread.

So, functions in Svchost can categorized as follows:_

1) Functions called once (called per instance, under the main thread).
2) Functions called with each service (called per service, under the service's own thread).

Here is an excerpt from Svchost main function approximate view.


In the next post, we will dive deeper into the function the "BuildServiceArray" function.

Any suggestions or ideas are very welcome.

You can follow me on Twitter @waleedassar

2 comments:

  1. your article is so good,very helpful to me

    ReplyDelete
  2. thx for ur awesome post , I use the command
    tasklist /SVC /FI "IMAGENAME eq svchost.exe"
    to find 11 instances of svchost on my system.

    Win8.1 Pro x32 platform.

    ReplyDelete