Tuesday, September 21, 2010

BreakOnDllLoad

In this post i will discuss the "BreakOnDllLoad" registry value found under the "Image File Execution Options" registry key a.k.a  IFEO.

Consider the following 2 figures:_


 
As we can see from the reversed code, the "IsDebuggerPresent" field ("BeingDebugged") in PEB is queried. If set, the "LdrQueryImageFileExecutionOptions" function is called to query for the "BreakOnDllLoad" registry value for the DLL that is being loaded. Also, the "ImageFileExecutionOptionsSpec" field ("ReadImageFileExecOptions") in PEB is queried. If set, the "LdrQueryImageFileExecutionOptions" function is called.

If the "LdrQueryImageFileExecutionOptions" function call succeeds, the "DbgBreakPoint" function is called. The "DbgBreakPoint" function is simply an int3 instruction. So, setting this registry value for a specific DLL gives you the chance to check the code of the "DllMain" function whenever you debug an application that loads this DLL, no matter what debugger you use.

Conclusion:
The "BreakOnDllLoad" registry value can be used to insert a breakpoint whenever a specific DLL loads into the address space of any process under any debugger.

You can follow me on Twitter @waleedassar 

Friday, September 17, 2010

A Walk To Design An Anti-Debug Technique

In this post, i will try to design an anti-debug technique targeting the debugged process heap behavior. Most of us know that process heaps under debuggers are different from those under normal execution.

For example:
1) Debugged heaps are filled with byte patterns like 0xbaadf00d and 0xfeeefeee, especially those allocated by the "RtlAllocateHeap" function variations e.g. the "LocalAlloc" and "HeapAlloc" functions.

N.B. Memory allocated by the "malloc" function is, in most cases, filled with 0xCDCDCDCD even under normal execution.

2) The Lookaside Lists. For more info about the Lookaside lists, i advise you to read this paper (Practical Windows XP/2003 Heap Exploitation by John McDonald and Chris Valasek).

The Lookaside lists don't exist for the debugged heap when:
1) The "_NO_DEBUG_HEAP" environment variable is not present or not set to 1.
2) The "DisableHeapLookAside" registry value found under "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\xxx.exe" is set to 1, where xxx.exe is the executable file name.

So, if my code traverses all heaps under the current process and for each heap, the code traverses the lookaside lists to determine the number of free blocks, the total number of free blocks can indicate the presence of a debugger.

If the total number of free blocks is zero, then the process is being debugged or the registry value is "DisableHeapLookAside" set. and here is the code
  • struct LOOKASIDE
  • {
  •     LOOKASIDE* pNext;
  •     unsigned long* A,B,C,D,E,F,G,H,I,J,K;
  • };
  • unsigned long* GetHeaps(unsigned long* pNum)
  • {
  • unsigned long* x;
  •          __asm
  •         {
  •                  mov eax,dword ptr fs:[0x30]
  •                  mov x,eax
  •         }
  •         *pNum=*(x+0x22);
  •         return (unsigned long*)*(x+0x24);
  • }
  • LOOKASIDE* GetLookaside(unsigned long* HeapBase)
  • {
  •     return (LOOKASIDE*)(*(unsigned long*)((unsigned char*)HeapBase+0x580));
  • }
  • //return no. of blocks in lookaside lists of all process heaps
  • int calc_lookaside()
  • {
  •     unsigned long c;
  •     unsigned long* p=GetHeaps(&c);
  •     LOOKASIDE* px;
  •     int total=0;
  •     while(c--)
  •     {
  •         if(px=GetLookaside((unsigned long*)*p++))
  •         {
  •             px+=2;
  •             for(int i=2;i<128;i++)
  •             {
  •                 int tot=0;
  •                 LOOKASIDE* pxx=px;
  •                 while(pxx->pNext)
  •                 {
  •                     tot++;
  •                     pxx=pxx->pNext;
  •                 }
  •                 total+=(tot*i);
  •                 px++;
  •             }
  •         }
  •     }
  •     return total;
  • }
  • void main()
  • {
  •     if(!calc_lookaside())
  •     {
  •         MessageBox(0,"Debugger present",0,0);
  •         goto end;
  •     }
  •     MessageBox(0,"No Debugger",0,0);
  • end:
  •     Sleep(10000);
  • }
  •  
N.B. The trick was designed for Windows XP (32Bit).
 
N.B. OllyAdvanced is aware of this trick.

Final word, this article is just one step towards an anti-debug technique.

Many thanks to my friend, Amr Thabet, for his note about the "malloc" function behavior.

Friday, September 10, 2010

Designing Two Svchost Services Into One DLL



While reversing the "FindDll" and "AddDll" functions of Svchost.exe , an idea came to my mind. It was to design a DLL with two Svchost services.

For this reason, i had to go deeper into the way both functions work.

Both functions are called by the "GetServiceMainFunctions" function which does the following:

1) Opens the Svchost service parameters registry key. For example, for the "DHCP" service, the registry key "HKLM\SYSTEM\CurrentControlSet\Services\Dhcp\Parameters" is opened. Under this key, a value named "ServiceDLL" is found. The value represents the DLL pathname of the Svchost service.

2) The circular doubly linked list holding information about all loaded service DLLs is searched for the node with the same DLL name and service name. If the right node isn't found in the list, another function, "AddDll", is called to create a new node. The found or the newly-created node is made to point at the corresponding _SERVICE_ARRAY_ELEMENT.
3) Under the same key is a registry value that the "GetServiceMainFunctions" function queries. Its name is "ServiceMain". It represents an alias name chosen for the "ServiceMain" function of the Svchost service.

4) The "GetServiceDllFunction" function is called to load the ServiceDll into the address space of Svchost and resolve the addresses of the "ServiceMain" and "SvchostPushServiceGlobals" functions.






Given the reversed C code in the images above, we will try to design one DLL that has two svchost services.

Hereafter, i will refer to the first service as srv1 and to the second one as srv2. srv1's job is to terminate any Taskmgr instance (just for educational purposes) and srv2's job is to terminate any Regedit instance.

Method 1
 

The ServiceMain for srv1 will be called "ServiceMain" and the ServiceMain for srv2 will be called "ServiceMain2". So, the Dll will be exporting  ServiceMain, ServiceMain2, and SvchostPushServiceGlobals. Each service will have its own handler. Both services will have the same StopCallback.
 

To install both services, you need the compiled Dll which should then be copied to the "system32" directory and a .reg file. A restart will be needed.

Reg file from here.
Source code svchost.h svc.def svc.cpp
 

Method 2
 

In this method, we will design the DLL such that only two functions, ServiceMain and SvchostPushServiceGlobals are exported. ServiceMain will act as the ServiceMain for both services.

Reg file from here
Source code svchost.h svc.def svc.cpp


Method 3

In this method, we will design the DLL such that only two functions, ServiceMain and SvchostPushServiceGlobals are exported. ServiceMain will act as the ServiceMain for srv1. SvchostPushServiceGlobals will acts as the ServiceMain for srv2 and also provide the shared globals table for both srv1 and srv2.

This method requires a little registry tweak for srv2.

Reg file from here.

Source code svchost.h svc.def svc.cpp

Thursday, September 9, 2010

Designing Simple Brute-Force Algorithm

I decided to write a brute-force algorithm and as a start, it will be a simple one. This algorithm lists all possible character combinations of all lengths starting from 4 through 22. You can also extend its functionality to include space and non-alphanumeric characters.
I also decided to give this code the ability to save its stop point and  to restore it on next start. In other words, if your program stops at the combination 002, the next time it starts it will resume at 003 and so on. This property is implemented in most of password recovery programs which use brute-force attacks.

Here is the source code

This console application runs for 20 seconds generating the in-order combinations. Just before exit, it saves its stop point.

N.B. You can freely change the code to meet your needs.

N.B. The code is only for demonstration.

Sunday, September 5, 2010

Svchost From A To Zinc - 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 Zinc - 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 Zinc - 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 Zinc - 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 Zinc - 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