Showing posts with label reversing. Show all posts
Showing posts with label reversing. Show all posts

Sunday, September 5, 2010

Svchost From A To Z - Part 5

In this post i am going talk about the "ServiceStarter" function that i consider as the backbone of svchost.exe.

First, i have to remind you with two points.

1) svchost main function (say, Main) is the entry point of svchost itself. So, it is called once per instance.
2) svchost ServiceStarter is the entry point of any svchost service running under the context of the current svchost instance. So, for every svchost service, ServiceStarter is called.

So, what does ServiceStarter do and how it looks like?

Another question...
Who pushes the arguments to the "ServiceStarter" function and how the arguments look like?

Okay, the "ServiceStarter" function is called by the SCM (Service Control Manager) not by svchost. Hence, the arguments are pushed by SCM.

The arguments are argc and argv.
Usually, argc is 1 and argv[0] is a pointer to the being-started service name. In other cases, SCM may increase argc. See the 2 figures below.

In each of the two figures above, argc is 2, argv[0] is "DHCP", and argv[1] is "walied".

Now let's go back to our main point. What does the "ServiceStarter" function do??
1) It iterates through all the ServiceArray elements comparing each _SERVICE_ARRAY_ELEMENT::srv_name with argv[0].

2) If found, it calls the "GetServiceMainFunctions" function which tries to resolve addresses of both ServiceMain (some services might choose other names by configuring their registry entries) and SvchostPushServiceGlobals after loading the corresponding ServiceDLL. It also inserts a new _SRV_DLL_INFO structure into a circular doubly linked list.

3) If the Shared globals table is not constructed yet, It calls the "_SvchostBuildSharedGlobals" function to build it.

4) It increments _SERVICE_ARRAY_ELEMENT::Count. Remember, this element is decremented by the "UnloadServiceDll" function.

5) It calls the "SvchostPushServiceGlobals" function if its address is successfully resolved.

6) It calls the "ServiceMain" function if its address is successfully resolved.

7) When the "ServiceMain" function returns, it calls the "UnloadServiceDll" function.
I leave you to look at the figure above. It is an approximate view of the "ServiceStarter" function.

Any suggestions are welcome.
waliedassar@gmail.com

Svchost From A To Z - Part 4

In the last 3 posts,We discussed the svchost functions which are called once per an svchost instance.They are BuildCommandOptions,BuildServiceArray and BuildServiceTable.
And we also discussed three important data structures .
1)INSTANCE_PARAMS
2)_SERVICE_ARRAY_ELEMENT
3)_SERVICE_TABLE_ELEMENT

if you still remember , till now no members of the structure _SERVICE_ARRAY_ELEMENT except srv_name is filled.
So what about these other members??and when do they get filled???

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

Lets take these members one by one
1)_SERVICE_ARRAY_ELEMENT::srv_name ,it is the service name in ServiceNames.
so , it is always pointing inside ServiceNames.
2)_SERVICE_ARRAY_ELEMENT::srv_dll_info
it is a pointer to another structure of different type. this structure holds info about the service DLL.
struct _SRV_DLL_INFO
{
_SRV_DLL_INFO* pNext;
_SRV_DLL_INFO* pPrev;
HMODULE hDll;
wchar_t* dllName;
_SERVICE_ARRAY_ELEMENT* pServiceArray;
};
this structure itself is a node in a "Circular Doubly linked List".
_SRV_DLL_INFO::pNext is a pointer to the next node.
_SRV_DLL_INFO::pPrev is a pointer to the previous node.
_SRV_DLL_INFO::hDll is the loaded Service DLL handle.
_SRV_DLL_INFO::dllName is the Service DLL complete filename.
_SRV_DLL_INFO::pServiceArray is pointer to the corresponding _SERVICE_ARRAY_ELEMENT.
So the final view will be like this...
In the figure above,only Audiosrv and Browser are started,So only Audiosrv and Browser have Nodes inserted into this circular doubly linked list.BITS is not started yet so it has no node.

N.B two global variables of type _SRV_DLL_INFO* exist to act as the Linked list Head and tail.
DllList acts as the head and DllList2 acts as the tail.
N.B For every Service loaded , A new node is inserted into this circular doubly linked list and its
_SERVICE_ARRAY_ELEMENT::srv_dll_info is null.
N.B If a svchost service is started,structure _SERVICE_ARRAY_ELEMENT points at structure _SRV_DLL_INFO and vice versa.
3)_SERVICE_ARRAY_ELEMENT::SvcMainName
N.B Each svchost Service DLL must export at least one function for some specific tasks.In most cases this function is exported under the name "ServiceMain".You can use other names as long as you configure the registry properly.
_SERVICE_ARRAY_ELEMENT::SvcMainName is a pointer to the name of the corresponding svchost service DLL ServiceMain.if it is zero, "ServiceMain is assumed".
it is of type char* not wchar_t* (for compatibilty with function GetProcAddress).

N.B ServiceMain is different from DllMain.
DllMain is called just after svchost calls LoadLibraryEx but ServiceMain is called by ServiceStarter(we will talk about Service Starter later,Just some patience).
N.B There is another function that many svchost service DLLs export,it is SvchostPushServiceGlobals(we will talk about its functionality later in this post).
Unlike ServiceMain ,its name cant be configured through the registry.It is always with this name.
The figure above shows the exported functions by wzcsvc "Wireless zero configuration" service.
WZCSvcMain and SvchostPushServiceGlobals.

4)_SERVICE_ARRAY_ELEMENT::Count this member is incremented,by function ServiceStarter or function _SvcRegisterStopCallback, And decremented by function UnloadServiceDLL.
5)_SERVICE_ARRAY_ELEMENT::d ,this is a pointer to the service specific stop callback function.This callback is called when a specific service object is signaled.
You may ask me how svchost knows about this callback??Is it exported by the service DLL??
No,the service Dll does not export it but it exports another function SvchostPushServiceGlobals.
This function lets svchost provide the service with some data structure called shared globals table.
struct SHARED_GLOBALS_TABLE
{
unsigned char* pNullSid;
unsigned char* pWorldSid;
unsigned char* pLocalSid;
unsigned char* pNetworkSid;
unsigned char* pLocalSystemSid;
unsigned char* pLocalServiceSid;
unsigned char* pNetworkServiceSid;
unsigned char* pBuiltinDomainSid;
unsigned char* pAuthenticatedUserSid;
unsigned char* pAnonymousLogonSid;
unsigned char* pAliasAdminsSid;
unsigned char* pAliasUsersSid;
unsigned char* pAliasGuestsSid;
unsigned char* pAliasPowerUsersSid;
unsigned char* pAliasAccountOpsSid;
unsigned char* pAliasSystemOpsSid;
unsigned char* pAliasPrintOpsSid;
unsigned char* pAliasBackupOpsSid;
//--
FPTR3 pRpcStartServer;
FPTR4 pRpcStopServer;
FPTR4 pRpcStopServerEx;
//--
FPTR5 pNetBiosOpen;
FPTR5 pNetBiosClose;
FPTR6 pNetBiosReset;
//----
FPTR7 pRegisterStopCallback;
};
//here we only care about the last member of this structure SHARED_GLOBALS_TABLE::pRegisterStopCallback.
Once SvchostPushServiceGlobals is called with this table as its argument,The service will be aware of a function in svchost that will register its own stop callback and store its address in the service _SERVICE_ARRAY_ELEMENT::d.
So here is the scenario:_
1)svchost builds the shared globals table.
2)svchost calls the service DLL function SvchostPushServiceGlobals,to provide it with this table.
3)The service calls SHARED_GLOBALS_TABLE::pRegisterStopCallback which (a)registers a wait on a service specific object.(b) increments _SERVICE_ARRAY_ELEMENT::Count (c) stores the service specific callback into _SERVICE_ARRAY_ELEMENT::d

4)Once this object (svchost knows nothing about this object except its handle) is handled,svchost function _SvchostStopCallback is called.which (a)calls the service specific callback (b)unloads yhe service DLL.
A question arises here , why all these steps for stopping an svchost service??
I asked myself this question??
The answer was simply "DllUnloadOnStop" How?
Some services need to unload its Dll on stop, the others dont.
The svchost Service which doesn't need to unload its Dll ,doesn't need to care about these steps.
The svchost service which needs to unload its Dll ,simply can't do this by itself(Cuz no DLL calls FreeLibrary to free itself from the current process Address space).
Till now ,we are still preparing for function ServiceStarter which i consider the backbone for svchost .

Any suggestions or ideas are welcome



Saturday, September 4, 2010

Svchost From A To Z - Part 3

In the beginning of this post, i want to remind you with the difference between 2 variables that you should be aware of.
1)ServiceNames is a global variable that points at the REG_MULTI_SZ extracted from the registry representing the names of the services under the current category.

2)ServiceArray which is an array to elements each of type _SERVICE_ARRAY_ELEMNT
struct _SERVICE_ARRAY_ELEMENT
{
wchar_t* srv_name;
_SRV_DLL_INFO* srv_dll_info;
char* SvcMainName;
unsigned long Count;
FUNCPTR d;
};
None of _SERVICE_ARRAY_ELEMENT memebrs except srv_name is filled till now.
As you can see in the figure above,each _SERVICE_ARRAY_ELEMENT::srv_name points at a string in ServiceNames.
///-----
Now after you became aware of the difference between ServiceNames and ServiceArray,we will now go to the Service Table and how it is constructed.
Generally,the service Table is an array of _SERVICE_TABLE_ELEMENT
struct _SERVICE_TABLE_ELEMENT
{
wchar_t* lpServiceName;
FUNCPTR2 lpFuncPtr;
};
Documented in MSDN under the name of SERVICE_TABLE_ENTRY.
First member of this structure is the service name
Second member is the service code entry point.
//-------------------------
Function BuildServiceTable has the task of constructing the service table.
It does the following
1)Given ServiceCount ,Memory for the service table is allocated.
2)Each _SERVICE_TABLE_ELEMENT::lpServiceName takes _SERVICE_ARRAY_ELEMENT::srv_name.
i.e it is also made to point at a string in ServiceNames.
3)Each _SERVICE_TABLE_ELEMENT::lpFuncPtr is made to hold the address of a function residing in svchost.exe called ServiceStarter.
And this function is the Entry point for every service ,responsible for doing some initialization tasks then calling the service specific entry point.
N.B The last Service table element must be zero.
And here is the c++ code for this function
Once the service table is constructed,it should be passed to StartServiceCtrlDispatcher.
StartServiceCtrlDispatcher connects the svchost instance main thread to the SCM(Service control manager) which decides which service of the ones in the Service table to be started.
For each service approved by the scm to be started,a new thread for this Service is created within svchost instance.
For more info about the SCM and StartServiceCtrlDispatcher ,refer to the MSDN.

In earlier posts,we categoried the functions within svchost into
1)functions running once per instance
like BuildCommandOptions,BuildServiceArray,BuildServiceTable and StartServiceCtrlDispatcher.
2)functions running per service.
like ServerStarter

we finished discussing the first category.
So in the next post we will discuss the function ServiceStarter.

Any suggestions or ideas are very welcome.

Svchost From A To Z - Part 2

In this post , i will discuss function BuildServiceArray in details.As we see in this figure ,the argument it takes is the pointer returned by function BuildCommandOptions.This pointer has the 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;
};
We can dissect this structure into two halves,the first half contains the input members, and second half which contains the output members.
i.e BuildServiceArray reads from the first half and writes to second half.

So what does this function really do???
1)The registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost" is opened.
2)A Registry value under the opened key with the same name as INSTANCE_PARAMS::svc_gp is read .It has the type REG_MULTI_SZ and contains the names of the services under this category.The value read is stored in a global variable called ServiceNames.
3)After this registry value is read successfully.A subkey with the same name as INSTANCE_PARAMS::svc_gp is opened and some values under this subkey is read into
INSTANCE_PARAMS:: CoInitia
INSTANCE_PARAMS:: Authentica
INSTANCE_PARAMS:: Impersona
INSTANCE_PARAMS:: AuthenticaCapa
INSTANCE_PARAMS:: RpcStack
then the subkey handle is closed
4)the key handle is closed
5)the REG_MULTI_SZ value is traversed for the purpose of calculating the number of services under this category then this number is stored in a global variable called ServiceCount
6)Then the service array is allocated ,A pointer to it is stored in a global variable called ServiceArray
,Each element of the service array has the the structure
struct _SERVICE_ARRAY_ELEMENT
{
wchar_t* srv_name;
_SRV_DLL_INFO* srv_dll_info;
char* SvcMainName;
unsigned long Count;
FUNCPTR d;
};
7)Each _SERVICE_ARRAY_ELEMENT::srv_name is made to point at the corresponding Service name in the REG_MULTI_SZ string.

Till now we have only the ServiceNames array and the ServiceArray array.
And they both look like this
Only _SERVICE_ARRAY_ELEMENT::srv_name is filled ,the other members of the structure are null.

The service Table is not constructed yet.
And this what we will see in the Next post.

Any ideas or suggestions are welcome.

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