国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

創(chuàng)建SvcHost.exe調(diào)用的服務(wù)原理與實踐創(chuàng)建SvcHost.exe調(diào)用的服務(wù)原理與實踐

2019-11-17 05:51:38
字體:
供稿:網(wǎng)友
創(chuàng)建SvcHost.exe調(diào)用的服務(wù)原理與實踐
1. 多個服務(wù)共享一個Svchost.exe進程利與弊windows 系統(tǒng)服務(wù)分為獨立進程和共享進程兩種,在windows NT時只有服務(wù)器治理器SCM(Services.exe)有多個共享服務(wù),隨著系統(tǒng)內(nèi)置服務(wù)的增加,在windows 2000中ms又把很多服務(wù)做成共享方式,由svchost.exe啟動。windows 2000一般有2個svchost進程,一個是RPCSS(Remote PRocedure Call)服務(wù)進程,另外一個則是由很多服務(wù)共享的一個svchost.exe。而在Windows xp中,則一般有4個以上的svchost.exe服務(wù)進程,windows 2003 server中則更多,可以看出把更多的系統(tǒng)內(nèi)置服務(wù)以共享進程方式由svchost啟動是ms的一個趨勢。這樣做在一定程度上減少了系統(tǒng)資源的消耗,不過也帶來一定的不穩(wěn)定因素,因為任何一個共享進程的服務(wù)因為錯誤退出進程就會導(dǎo)致整個進程中的所有服務(wù)都退出。另外就是有一點安全隱患,首先要介紹一下svchost.exe的實現(xiàn)機制。
2. Svchost原理Svchost本身只是作為服務(wù)宿主,并不實現(xiàn)任何服務(wù)功能,需要Svchost啟動的服務(wù)以動態(tài)鏈接庫形式實現(xiàn),在安裝這些服務(wù)時,把服務(wù)的可執(zhí)行程序指向svchost,啟動這些服務(wù)時由svchost調(diào)用相應(yīng)服務(wù)的動態(tài)鏈接庫來啟動服務(wù)。那么svchost如何知道某一服務(wù)是由哪個動態(tài)鏈接庫負(fù)責(zé)呢?這不是由服務(wù)的可執(zhí)行程序路徑中的參數(shù)部分提供的,而是服務(wù)在注冊表中的參數(shù)設(shè)置的,注冊表中服務(wù)下邊有一個Parameters子鍵其中的ServiceDll表明該服務(wù)由哪個動態(tài)鏈接庫負(fù)責(zé)。并且所有這些服務(wù)動態(tài)鏈接庫都必須要導(dǎo)出一個ServiceMain()函數(shù),用來處理服務(wù)任務(wù)。例如rpcss(Remote Procedure Call)在注冊表中的位置是 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/RpcSs,它的參數(shù)子鍵Parameters里有這樣一項:
"ServiceDll"=REG_EXPAND_SZ:"%SystemRoot%/system32/rpcss.dll"
當(dāng)啟動rpcss服務(wù)時,svchost就會調(diào)用rpcss.dll,并且執(zhí)行其ServiceMain()函數(shù)執(zhí)行具體服務(wù)。既然這些服務(wù)是使用共享進程方式由svchost啟動的,為什么系統(tǒng)中會有多個svchost進程呢?ms把這些服務(wù)分為幾組,同組服務(wù)共享一個svchost進程,不同組服務(wù)使用多個svchost進程,組的區(qū)別是由服務(wù)的可執(zhí)行程序后邊的參數(shù)決定的。例如rpcss在注冊表中 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/RpcSs 有這樣一項:
"ImagePath"=REG_EXPAND_SZ:"%SystemRoot%/system32/svchost -k rpcss"
因此rpcss就屬于rpcss組,這在服務(wù)治理控制臺也可以看到。svchost的所有組和組內(nèi)的所有服務(wù)都在注冊表的如下位置: HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Svchost,例如windows 2000共有4組rpcss、netsvcs、wugroup、BITSgroup,其中最多的就是netsvcs=REG_MULTI_SZ:EventSystem.Ias.iprip.Irmon.Netman.Nwsapagent.Rasauto.Rasman.Remoteaccess.SENS.Sharedaccess.Tapisrv.Ntmssvc.wzcsvc..在啟動一個svchost.exe負(fù)責(zé)的服務(wù)時,服務(wù)治理器假如碰到可執(zhí)行程序內(nèi)容ImagePath已經(jīng)存在于服務(wù)治理器的映象庫中,就不在啟動第2個進程svchost,而是直接啟動服務(wù)。這樣就實現(xiàn)了多個服務(wù)共享一個svchost進程。
3. Svchost代碼現(xiàn)在我們基本清楚svchost的原理了,但是要自己寫一個DLL形式的服務(wù),由svchost來啟動,僅有上邊的信息還有些問題不是很清楚。比如我們在導(dǎo)出的ServiceMain()函數(shù)中接收的參數(shù)是ANSI還是Unicode?我們是否需要調(diào)用RegisterServiceCtrlHandler和StartServiceCtrlDispatcher來注冊服務(wù)控制及調(diào)度函數(shù)?這些問題要通過查看svchost代碼獲得。下邊的代碼是windows 2000+ service pack 4 的svchost反匯編片段,可以看出svchost程序還是很簡單的。主函數(shù)首先調(diào)用ProcCommandLine()對命令行進行分析,獲得要啟動的服務(wù)組,然后調(diào)用SvcHostOptions()查詢該服務(wù)組的選項和服務(wù)組的所有服務(wù),并使用一個數(shù)據(jù)結(jié)構(gòu) svcTable 來保存這些服務(wù)及其服務(wù)的DLL,然后調(diào)用PrepareSvcTable() 函數(shù)創(chuàng)建SERVICE_TABLE_ENTRY 結(jié)構(gòu),把所有處理函數(shù)SERVICE_MAIN_FUNCTION 指向自己的一個函數(shù)FuncServiceMain(),最后調(diào)用API StartServiceCtrlDispatcher() 注冊這些服務(wù)的調(diào)度函數(shù)。; =============================== Main Funcion ===========================================
.text:010010B8 public start
.text:010010B8 start proc near
.text:010010B8 push esi
.text:010010B9 push edi
.text:010010BA push offset sub_1001EBA ; lpTopLevelExceptionFilter
.text:010010BF xor edi, edi
.text:010010C1 call ds:SetUnhandledExceptionFilter
.text:010010C7 push 1 ; uMode
.text:010010C9 call ds:SetErrorMode
.text:010010CF call ds:GetProcessHeap
.text:010010D5 push eax
.text:010010D6 call sub_1001142
.text:010010DB mov eax, offset dWord_1003018
.text:010010E0 push offset unk_1003000 ; lpCriticalSection
.text:010010E5 mov dword_100301C, eax
.text:010010EA mov dword_1003018, eax
.text:010010EF call ds:InitializeCriticalSection
.text:010010F5 call ds:GetCommandLineW
.text:010010FB push eax ; lpString
.text:010010FC call ProcCommandLine
.text:01001101 mov esi, eax
.text:01001103 test esi, esi
.text:01001105 jz short lab_doservice
.text:01001107 push esi
.text:01001108 call SvcHostOptions
.text:0100110D call PrepareSvcTable
.text:01001112 mov edi, eax ; SERVICE_TABLE_ENTRY returned
.text:01001114 test edi, edi
.text:01001116 jz short loc_1001128
.text:01001118 mov eax, [esi+10h]
.text:0100111B test eax, eax
.text:0100111D jz short loc_1001128
.text:0100111F push dword ptr [esi+14h] ; dwCapabilities
.text:01001122 push eax ; int
.text:01001123 call InitializeSecurity
.text:01001128
.text:01001128 loc_1001128: ; CODE XREF: start+5Ej
.text:01001128 ; start+65j
.text:01001128 push esi ; lpMem
.text:01001129 call HeapFreeMem
.text:0100112E
.text:0100112E lab_doservice: ; CODE XREF: start+4Dj
.text:0100112E test edi, edi
.text:01001130 jz ExitProgram
.text:01001136 push edi ; lpServiceStartTable
.text:01001137 call ds:StartServiceCtrlDispatcherW
.text:0100113D jmp ExitProgram
.text:0100113D start endp
; =============================== Main Funcion end ===========================================
由于svchost為該組的所有服務(wù)都注冊了svchost中的一個處理函數(shù),因此每次啟動任何一個服務(wù)時,服務(wù)治理器SCM都會調(diào)用FuncServiceMain() 這個函數(shù)。這個函數(shù)使用 svcTable 查詢要啟動的服務(wù)使用的DLL,調(diào)用DLL導(dǎo)出的ServiceMain()函數(shù)來啟動服務(wù),然后返回。; ============================== FuncServiceMain() ===========================================
.text:01001504 FuncServiceMain proc near ; DATA XREF: PrepareSvcTable+44o
.text:01001504
.text:01001504 arg_0 = dword ptr 8
.text:01001504 arg_4 = dword ptr 0Ch
.text:01001504
.text:01001504 push ecx
.text:01001505 mov eax, [esp+arg_4]
.text:01001509 push ebx
.text:0100150A push ebp
.text:0100150B push esi
.text:0100150C mov ebx, offset unk_1003000
.text:01001511 push edi
.text:01001512 mov edi, [eax]
.text:01001514 push ebx
.text:01001515 xor ebp, ebp
.text:01001517 call ds:EnterCriticalSection
.text:0100151D xor esi, esi
.text:0100151F cmp dwGroupSize, esi
.text:01001525 jbe short loc_1001566
.text:01001527 and [esp+10h], esi
.text:0100152B
.text:0100152B loc_100152B: ; CODE XREF: FuncServiceMain+4Aj
.text:0100152B mov eax, svcTable
.text:01001530 mov ecx, [esp+10h]
.text:01001534 push dword ptr [eax+ecx]
.text:01001537 push edi
.text:01001538 call ds:lstrcmpiW
.text:0100153E test eax, eax
.text:01001540 jz short StartThis
.text:01001542 add dword ptr [esp+10h], 0Ch
.text:01001547 inc esi
.text:01001548 cmp esi, dwGroupSize
.text:0100154E jb short loc_100152B
.text:01001550 jmp short loc_1001566
.text:01001552 ; =================================================
.text:01001552
.text:01001552 StartThis: ; CODE XREF: FuncServiceMain+3Cj
.text:01001552 mov ecx, svcTable
.text:01001558 lea eax, [esi+esi*2]
.text:0100155B lea eax, [ecx+eax*4]
.text:0100155E push eax
.text:0100155F call GetDLLServiceMain
.text:01001564 mov ebp, eax ; dll ServiceMain Function address
.text:01001566
.text:01001566 loc_1001566: ; CODE XREF: FuncServiceMain+21j
.text:01001566 ; FuncServiceMain+4Cj
.text:01001566 push ebx
.text:01001567 call ds:LeaveCriticalSection
.text:0100156D test ebp, ebp
.text:0100156F jz short loc_100157B
.text:01001571 push [esp+10h+arg_4]
.text:01001575 push [esp+14h+arg_0]
.text:01001579 call ebp
.text:0100157B
.text:0100157B loc_100157B: ; CODE XREF: FuncServiceMain+6Bj
.text:0100157B pop edi
.text:0100157C pop esi
.text:0100157D pop ebp
.text:0100157E pop ebx
.text:0100157F pop ecx
.text:01001580 retn 8
.text:01001580 FuncServiceMain endp ; sp = -8
; ============================== FuncServiceMain() end ========================================
由于svchost已經(jīng)調(diào)用了StartServiceCtrlDispatcher來服務(wù)調(diào)度函數(shù),因此我們在實現(xiàn)DLL實現(xiàn)時就不用了,這主要是因為一個進程只能調(diào)用一次StartServiceCtrlDispatcher API。但是需要用 RegisterServiceCtrlHandler 來注冊響應(yīng)控制請求的函數(shù)。最后我們的DLL接收的都是unicode字符串。由于這種服務(wù)啟動后由svchost加載,不增加新的進程,只是svchost的一個DLL,而且一般進行審計時都不會去HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Svchost 檢查服務(wù)組是否變化,就算去檢查,也不一定能發(fā)現(xiàn)異常,因此假如添加一個這樣的DLL后門,偽裝的好,是比較隱蔽的。
4. 安裝服務(wù)與設(shè)置
要通過svchost調(diào)用來啟動的服務(wù),就一定要在HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Svchost下有該服務(wù)名,這可以通過如下方式來實現(xiàn):
1) 添加一個新的服務(wù)組,在組里添加服務(wù)名
2) 在現(xiàn)有組里添加服務(wù)名
3) 直接使用現(xiàn)有服務(wù)組里的一個服務(wù)名,但本機沒有安裝的服務(wù)
4) 修改現(xiàn)有服務(wù)組里的現(xiàn)有服務(wù),把它的ServiceDll指向自己其中前兩種可以被正常服務(wù)使用,如使用第1種方式,啟動其服務(wù)要創(chuàng)建新的svchost進程;第2種方式假如該組服務(wù)已經(jīng)運行,安裝后不能馬上啟動服務(wù),因為svchost啟動后已經(jīng)把該組信息保存在內(nèi)存里,并調(diào)用API StartServiceCtrlDispatcher() 為該組所有服務(wù)注冊了調(diào)度處理函數(shù),新增加的服務(wù)不能再注冊調(diào)度處理函數(shù),需要重起計算機或者該組的svchost進程。而后兩種可能被后門使用,尤其是最后一種,沒有添加服務(wù),只是改了注冊表里一項設(shè)置,從服務(wù)治理控制臺又看不出來,假如作為后門還是很隱蔽的。比如EventSystem服務(wù),缺省是指向es.dll,假如把ServiceDll改為EventSystem.dll就很難發(fā)現(xiàn)。因此服務(wù)的安裝除了調(diào)用CreateService()創(chuàng)建服務(wù)之外,還需要設(shè)置服務(wù)的ServiceDll,假如使用前2種還要設(shè)置svchost的注冊表選項,在卸載時也最好刪除增加的部分。具體代碼參見后邊的附例(使用的是方法3)。注: ImagePath 和ServiceDll 是ExpandString不是普通字符串。因此假如使用.reg文件安裝時要注重。
5. DLL服務(wù)實現(xiàn)
DLL程序的編寫比較簡單,只要實現(xiàn)一個ServiceMain()函數(shù)和一個服務(wù)控制程序,在ServiceMain()函數(shù)里用RegisterServiceCtrlHandler()注冊服務(wù)控制程序,并設(shè)置服務(wù)的運行狀態(tài)就可以了。另外,因為此種服務(wù)的安裝除了正常的CreateService()之外,還要進行其他設(shè)置,因此最好實現(xiàn)安裝和卸載函數(shù)。 為了方便安裝,實現(xiàn)的代碼提供了InstallService()函數(shù)進行安裝,這個函數(shù)可以接收服務(wù)名作為參數(shù)(假如不提供參數(shù),就使用缺省的iprip),假如要安裝的服務(wù)不在svchost的netsvcs組里安裝就會失敗;假如要安裝的服務(wù)已經(jīng)存在,安裝也會失敗;安裝成功后程序會配置服務(wù)的ServiceDll為當(dāng)前Dll。提供的UninstallService()函數(shù),可以刪除任何函數(shù)而沒有進行任何檢查。為了方便使用rundll32.exe進行安裝,還提供了RundllInstallA()和RundllUninstallA()分別調(diào)用InstallService()及UninstallService()。因為rundll32.exe使用的函數(shù)原型是:
void CALLBACK FunctionName(
HWND hwnd, // handle to owner window
HINSTANCE hinst, // instance handle for the DLL
LPTSTR lpCmdLine, // string the DLL will parse
int nCmdShow // show state
);
對應(yīng)的命令行是rundll32 DllName,FunctionName [Arguments] DLL服務(wù)本身只是創(chuàng)建一個進程,該程序命令行就是啟動服務(wù)時提供的第一個參數(shù),假如未指定就使用缺省的svchostdll.exe。啟動服務(wù)時假如提供第二個參數(shù),創(chuàng)建的進程就是和桌面交互的。具體代碼參見后邊的附例8,源代碼和DLL文件請到http://www.binglesite.net下載。//main service process function
void __stdcall ServiceMain( int argc, wchar_t* argv[] );
//report service stat to the service control manager
int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress );
//service control handler, call back by service control manager
void __stdcall ServiceHandler( DWORD dwCommand );
//RealService just create a process
int RealService(char *cmd, int bInteract);//Install this dll as a Service host by svchost.exe, service name is given by caller
int InstallService(char *name);
//unInstall a Service, be CARE FOR call this to delete a service
int UninstallService(char *name);
//Install this dll as a Service host by svchost.exe, used by RUNDLL32.EXE to call
void CALLBACK RundllInstallA(HWND hwnd, HINSTANCE hinst, char *param, int nCmdShow);
//unInstall a Service used by RUNDLL32.EXE to call, be CARE FOR call this to delete a service
void CALLBACK RundllUninstallA(HWND hwnd, HINSTANCE hinst, char *param, int nCmdShow);//output the debug infor into log file(or stderr if a console program call me) & DbgPrint
void OutputString( char *lpFmt, ... );
6. 代碼使用
C:/>tlist -s
0 System Process
8 System
240 services.exe Svcs: Browser,Dhcp,dmserver,Dnscache,Eventlog,lanmanserver,lanmanworkstation, LmHosts,PlugPlay,ProtectedStorage,TrkWks,Wmi
504 svchost.exe Svcs: RpcSs
1360 svchost.exe Svcs: EventSystem,Netman,RasMan,SENS,TapiSrvC:/>rundll32 svchostdll.dll,RundllInstall abcd
SvcHostDLL: DllMain called DLL_PROCESS_ATTACH
you specify service name not in Svchost/netsvcs, must be one of following:
- EventSystem
- Ias
- Iprip
- Irmon
- Netman
- Nwsapagent
- Rasauto
- Rasman
- Remoteaccess
- SENS
- Sharedaccess
- Tapisrv
- Ntmssvc
- wzcsvcC:/>rundll32 svchostdll.dll,RundllInstall IPRIP
SvcHostDLL: DllMain called DLL_PROCESS_ATTACH
CreateService(IPRIP) SUCCESS. Config it
Config service IPRIP ok.C:/>sc start iprip "cmd /k whoami" 1
NT AUTHORITY/SYSTEMSvcHostDLL: ServiceMain(3, IPRIP) called
SvcHostDLL: RealService called 'cmd /k whoami' Interact
SvcHostDLL: CreateProcess(cmd /k whoami) to 640C:/>tlist -s
0 System Process
8 System
240 services.exe Svcs: Browser,Dhcp,dmserver,Dnscache,Eventlog,lanmanserver,lanmanworkstation, LmHosts,PlugPlay,ProtectedStorage,TrkWks,Wmi
504 svchost.exe Svcs: RpcSs
640 cmd.exe Title: C:/WINNT/System32/cmd.exe
1360 svchost.exe Svcs: EventSystem,Netman,RasMan,SENS,TapiSrv,IPRIPC:/>net stop iprip
The IPRIP service was stopped successfully.C:/>rundll32 svchostdll.dll,RundllUninstall iprip
DeleteService(IPRIP) SUCCESS.
7. 參考Platform SDK: Tools - Rundll32
1) Inside Win32 Services, Part 2 by: Mark Russinovich, at: http://www.winnetmag.com/Articles/Index.cfm?ArticleID=8943&pg=3
2) Platform SDK: Tools - Rundll32, at: http://msdn.microsoft.com/library/en-us/tools/tools/rundll32.asp2003/8
8. 代碼
// SvcHostDLL.cpp : Demo for a service dll used by svchost.exe to host it.
//
// for detail comment see articles.
// by bingle_at_email.com.cn
// www.BingleSite.net
//
/* save following as a .def file to export function, only ServiceMain is needed.
other used to install & uninstall service.
or use /EXPORT: link option to export them.EXPORTS
ServiceMain
InstallService
UninstallService
RundllUninstallA
RundllInstallA
*/
/*
To compile & link:
cl /MD /GX /LD svchostdll.cpp /link advapi32.lib /DLL /base:0x71000000 /export:ServiceMain /EXPORT:RundllUninstallA /EXPORT:RundllInstallA /EXPORT:InstallService /EXPORT:UninstallService
*///
// Articles:
// 1. HOWTO Create a service dll used by svchost.exe by bingle, at: http://www.BingleSite.net/article/svchost-dll-service.html
// 2. Inside Win32 Services, Part 2 by: Mark Russinovich, at: http://www.winnetmag.com/Articles/Index.cfm?ArticleID=8943&pg=3
// 3. Platform SDK: Tools - Rundll32, at: http://msdn.microsoft.com/library/en-us/tools/tools/rundll32.asp#include <stdio.h>
#include <time.h>
#include <assert.h>
#include <windows.h>#define DEFAULT_SERVICE "IPRIP"
#define MY_EXECUTE_NAME "SvcHostDLL.exe"http://main service process function
void __stdcall ServiceMain( int argc, wchar_t* argv[] );
//report service stat to the service control manager
int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress );
//service control handler, call back by service control manager
void __stdcall ServiceHandler( DWORD dwCommand );
//RealService just create a process
int RealService(char *cmd, int bInteract);//Install this dll as a Service host by svchost.exe, service name is given by caller
int InstallService(char *name);
//unInstall a Service, be CARE FOR call this to delete a service
int UninstallService(char *name);
//Install this dll as a Service host by svchost.exe, used by RUNDLL32.EXE to call
void CALLBACK RundllInstallA(HWND hwnd, HINSTANCE hinst, char *param, int nCmdShow);
//unInstall a Service used by RUNDLL32.EXE to call, be CARE FOR call this to delete a service
void CALLBACK RundllUninstallA(HWND hwnd, HINSTANCE hinst, char *param, int nCmdShow);//output the debug infor into log file(or stderr if a console program call me) & DbgPrint
void OutputString( char *lpFmt, ... );
//dll module handle used to get dll path in InstallService
HANDLE hDll = NULL;
//Service HANDLE & STATUS used to get service state
SERVICE_STATUS_HANDLE hSrv;
DWORD dwCurrState;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hDll = hModule;
#ifdef _DEBUG
AllocConsole();
OutputString("SvcHostDLL: DllMain called DLL_PROCESS_ATTACH");
break;case DLL_THREAD_ATTACH:
OutputString("SvcHostDLL: DllMain called DLL_THREAD_ATTACH");
case DLL_THREAD_DETACH:
OutputString("SvcHostDLL: DllMain called DLL_THREAD_DETACH");
case DLL_PROCESS_DETACH:
TellSCM( SERVICE_STOP_PENDING, 0, 0 );
Sleep(1500);
TellSCM( SERVICE_STOPPED, 0, 0 );
OutputString("SvcHostDLL: DllMain called DLL_PROCESS_DETACH");
#endif
break;
}return TRUE;
}
void __stdcall ServiceMain( int argc, wchar_t* argv[] )
{
// DebugBreak();
char svcname[256];
strncpy(svcname, (char*)argv[0], sizeof svcname); //it's should be unicode, but if it's ansi we do it well
wcstombs(svcname, argv[0], sizeof svcname);
OutputString("SvcHostDLL: ServiceMain(%d, %s) called", argc, svcname);hSrv = RegisterServiceCtrlHandler( svcname, (LPHANDLER_FUNCTION)ServiceHandler );
if( hSrv == NULL )
{
OutputString("SvcHostDLL: RegisterServiceCtrlHandler %S failed", argv[0]);
return;
}else FreeConsole();TellSCM( SERVICE_START_PENDING, 0, 1 );
TellSCM( SERVICE_RUNNING, 0, 0 );// call Real Service function noew
if(argc > 1)
strncpy(svcname, (char*)argv[1], sizeof svcname),
wcstombs(svcname, argv[1], sizeof svcname);
RealService(argc > 1 ? svcname : MY_EXECUTE_NAME, argc > 2 ? 1 : 0);do{
Sleep(10);//not quit until receive stop command, otherwise the service will stop
}while(dwCurrState != SERVICE_STOP_PENDING && dwCurrState != SERVICE_STOPPED);OutputString("SvcHostDLL: ServiceMain done");
return;
}int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress )
{
SERVICE_STATUS srvStatus;
srvStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
srvStatus.dwCurrentState = dwCurrState = dwState;
srvStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
srvStatus.dwWin32ExitCode = dwExitCode;
srvStatus.dwServiceSpecificExitCode = 0;
srvStatus.dwCheckPoint = dwProgress;
srvStatus.dwWaitHint = 3000;
return SetServiceStatus( hSrv, &srvStatus );
}void __stdcall ServiceHandler( DWORD dwCommand )
{
// not really necessary because the service stops quickly
switch( dwCommand )
{
case SERVICE_CONTROL_STOP:
TellSCM( SERVICE_STOP_PENDING, 0, 1 );
OutputString("SvcHostDLL: ServiceHandler called SERVICE_CONTROL_STOP");
Sleep(10);
TellSCM( SERVICE_STOPPED, 0, 0 );
break;
case SERVICE_CONTROL_PAUSE:
TellSCM( SERVICE_PAUSE_PENDING, 0, 1 );
OutputString("SvcHostDLL: ServiceHandler called SERVICE_CONTROL_PAUSE");
TellSCM( SERVICE_PAUSED, 0, 0 );
break;
case SERVICE_CONTROL_CONTINUE:
TellSCM( SERVICE_CONTINUE_PENDING, 0, 1 );
OutputString("SvcHostDLL: ServiceHandler called SERVICE_CONTROL_CONTINUE");
TellSCM( SERVICE_RUNNING, 0, 0 );
break;
case SERVICE_CONTROL_INTERROGATE:
OutputString("SvcHostDLL: ServiceHandler called SERVICE_CONTROL_INTERROGATE");
TellSCM( dwCurrState, 0, 0 );
break;
case SERVICE_CONTROL_SHUTDOWN:
OutputString("SvcHostDLL: ServiceHandler called SERVICE_CONTROL_SHUTDOWN");
TellSCM( SERVICE_STOPPED, 0, 0 );
break;
}
}
//RealService just create a process
int RealService(char *cmd, int bInteract)
{
OutputString("SvcHostDLL: RealService called '%s' %s", cmd, bInteract ? "Interact" : "");
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof si;
if(bInteract) si.lpDesktop = "WinSta0//Default";
if(!CreateProcess(NULL, cmd, NULL, NULL, false, 0, NULL, NULL, &si, &pi))
OutputString("SvcHostDLL: CreateProcess(%s) error:%d", cmd, GetLastError());
else OutputString("SvcHostDLL: CreateProcess(%s) to %d", cmd, pi.dwProcessId);return 0;
}
int InstallService(char *name)
{
// Open a handle to the SC Manager database.
int rc = 0;
HKEY hkRoot = HKEY_LOCAL_MACHINE, hkParam = 0;
SC_HANDLE hscm = NULL, schService = NULL;try{
char buff[500];
char *svcname = DEFAULT_SERVICE;
if(name && name[0]) svcname = name;//query svchost setting
char *ptr, *pSvchost = "SOFTWARE//Microsoft//Windows NT//CurrentVersion//Svchost";
rc = RegOpenKeyEx(hkRoot, pSvchost, 0, KEY_QUERY_VALUE, &hkRoot);
if(ERROR_SUCCESS != rc)
{
OutputString("RegOpenKeyEx(%s) KEY_QUERY_VALUE error %d.", pSvchost, rc);
throw "";
}DWORD type, size = sizeof buff;
rc = RegQueryValueEx(hkRoot, "netsvcs", 0, &type, (unsigned char*)buff, &size);
RegCloseKey(hkRoot);
SetLastError(rc);
if(ERROR_SUCCESS != rc)
throw "RegQueryValueEx(Svchost//netsvcs)";for(ptr = buff; *ptr; ptr = strchr(ptr, 0)+1)
if(stricmp(ptr, svcname) == 0) break;if(*ptr == 0)
{
OutputString("you specify service name not in Svchost//netsvcs, must be one of following:");
for(ptr = buff; *ptr; ptr = strchr(ptr, 0)+1)
OutputString(" - %s", ptr);
throw "";
}//install service
hscm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hscm == NULL)
throw "OpenSCManager()";char *bin = "%SystemRoot%//System32//svchost.exe -k netsvcs";schService = CreateService(
hscm, // SCManager database
svcname, // name of service
NULL, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_SHARE_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
bin, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password if (schService == NULL)
{
OutputString("CreateService(%s) error %d", svcname, rc = GetLastError());
throw "";
}
OutputString("CreateService(%s) SUCCESS. Config it", svcname); CloseServiceHandle(schService);
CloseServiceHandle(hscm); //config service
hkRoot = HKEY_LOCAL_MACHINE;
strncpy(buff, "SYSTEM//CurrentControlSet//Services//", sizeof buff);
strncat(buff, svcname, 100);
rc = RegOpenKeyEx(hkRoot, buff, 0, KEY_ALL_ACCESS, &hkRoot);
if(ERROR_SUCCESS != rc)
{
OutputString("RegOpenKeyEx(%s) KEY_SET_VALUE error %d.", svcname, rc);
throw "";
}rc = RegCreateKey(hkRoot, "Parameters", &hkParam);
SetLastError(rc);
if(ERROR_SUCCESS != rc)
throw "RegCreateKey(Parameters)";if(!GetModuleFileName(HMODULE(hDll), buff, sizeof buff))
throw "GetModuleFileName() get dll path";rc = RegSetValueEx(hkParam, "ServiceDll", 0, REG_EXPAND_SZ, (unsigned char*)buff, strlen(buff)+1);
SetLastError(rc);
if(ERROR_SUCCESS != rc)
throw "RegSetValueEx(ServiceDll)";OutputString("Config service %s ok.", svcname);
}catch(char *str)
{
if(str && str[0])
{
rc = GetLastError();
OutputString("%s error %d", str, rc);
}
}RegCloseKey(hkRoot);
RegCloseKey(hkParam);
CloseServiceHandle(schService);
CloseServiceHandle(hscm); return rc;
}/*
used to install by rundll32.exe
Platform SDK: Tools - Rundll32
The Run DLL utility (Rundll32.exe) included in Windows enables you to call functions exported from a 32-bit DLL. These functions must have the following syntax:
*/
void CALLBACK RundllInstallA(
HWND hwnd, // handle to owner window
HINSTANCE hinst, // instance handle for the DLL
char *param, // string the DLL will parse
int nCmdShow // show state
)
{
InstallService(param);
}
int UninstallService(char *name)
{
int rc = 0;
SC_HANDLE schService;
SC_HANDLE hscm;__try{
hscm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hscm == NULL)
{
OutputString("OpenSCManager() error %d", rc = GetLastError() );
return rc;
}char *svcname = DEFAULT_SERVICE;
if(name && name[0]) svcname = name;schService = OpenService(hscm, svcname, DELETE);
if (schService == NULL)
{
OutputString("OpenService(%s) error %d", svcname, rc = GetLastError() );
return rc;
}if (!DeleteService(schService) )
{
OutputString("OpenService(%s) error %d", svcname, rc = GetLastError() );
return rc;
}OutputString("DeleteService(%s) SUCCESS.", svcname);
}__except(1)
{
OutputString("Exception Catched 0x%X", GetExceptionCode());
}CloseServiceHandle(schService);
CloseServiceHandle(hscm);
return rc;
}/*
used to uninstall by rundll32.exe
Platform SDK: Tools - Rundll32
The Run DLL utility (Rundll32.exe) included in Windows enables you to call functions exported from a 32-bit DLL. These functions must have the following syntax:
*/
void CALLBACK RundllUninstallA(
HWND hwnd, // handle to owner window
HINSTANCE hinst, // instance handle for the DLL
char *param, // string the DLL will parse
int nCmdShow // show state
)
{
UninstallService(param);
}//output the debug infor into log file & DbgPrint
void OutputString( char *lpFmt, ... )
{
char buff[1024];
va_list arglist;
va_start( arglist, lpFmt );
_vsnprintf( buff, sizeof buff, lpFmt, arglist );
va_end( arglist );DWORD len;
HANDLE herr = GetStdHandle(STD_OUTPUT_HANDLE);
if(herr != INVALID_HANDLE_VALUE)
{
WriteFile(herr, buff, strlen(buff), &len, NULL);
WriteFile(herr, "/r/n", 2, &len, NULL);
}else
{
FILE *fp = fopen("SvcHost.DLL.log", "a");
if(fp)
{
char date[20], time[20];
fprintf(fp, "%s %s - %s/n", _strdate(date), _strtime(time), buff);
if(!stderr) fclose(fp);
}
}OutputDebugString(buff);
}
---  


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 阿拉善左旗| 大关县| 西丰县| 江都市| 久治县| 大余县| 洞口县| 涡阳县| 格尔木市| 宜春市| 浦县| 贵州省| 万安县| 堆龙德庆县| 舟曲县| 通化市| 江西省| 金秀| 疏勒县| 玉溪市| 南通市| 汤阴县| 平安县| 周至县| 巴塘县| 杨浦区| 泗阳县| 临沭县| 长泰县| 盐津县| 江安县| 潞西市| 格尔木市| 柏乡县| 兴安盟| 江西省| 长武县| 威远县| 门头沟区| 石城县| 峡江县|