青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

tqsheng

go.....
隨筆 - 366, 文章 - 18, 評論 - 101, 引用 - 0
數據加載中……

創建SvcHost.exe調用的服務原理與實踐

創建SvcHost.exe調用的服務原理與實踐
1. 多個服務共享一個Svchost.exe進程利與弊

       windows 系統服務分為獨立進程和共享進程兩種,在windows NT時只有服務器管理器SCM(Services.exe)有多個共享服務,隨著系統內置服務的增加,在windows 2000中ms又把很多服務做成共享方式,由svchost.exe啟動。windows 2000一般有2個svchost進程,一個是RPCSS(Remote Procedure Call)服務進程,另外一個則是由很多服務共享的一個svchost.exe。而在windows XP中,則一般有4個以上的svchost.exe服務進程,windows 2003 server中則更多,可以看出把更多的系統內置服務以共享進程方式由svchost啟動是ms的一個趨勢。這樣做在一定程度上減少了系統資源的消耗,不過也帶來一定的不穩定因素,因為任何一個共享進程的服務因為錯誤退出進程就會導致整個進程中的所有服務都退出。另外就是有一點安全隱患,首先要介紹一下svchost.exe的實現機制。


2. Svchost原理

      Svchost本身只是作為服務宿主,并不實現任何服務功能,需要Svchost啟動的服務以動態鏈接庫形式實現,在安裝這些服務時,把服務的可執行程序指向svchost,啟動這些服務時由svchost調用相應服務的動態鏈接庫來啟動服務。

       那么svchost如何知道某一服務是由哪個動態鏈接庫負責呢?這不是由服務的可執行程序路徑中的參數部分提供的,而是服務在注冊表中的參數設置的,注冊表中服務下邊有一個Parameters子鍵其中的ServiceDll表明該服務由哪個動態鏈接庫負責。并且所有這些服務動態鏈接庫都必須要導出一個ServiceMain()函數,用來處理服務任務。

例如rpcss(Remote Procedure Call)在注冊表中的位置是  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcSs,它的參數子鍵Parameters里有這樣一項:
"ServiceDll"=REG_EXPAND_SZ:"%SystemRoot%\system32\rpcss.dll"
當啟動rpcss服務時,svchost就會調用rpcss.dll,并且執行其ServiceMain()函數執行具體服務。

       既然這些服務是使用共享進程方式由svchost啟動的,為什么系統中會有多個svchost進程呢?ms把這些服務分為幾組,同組服務共享一個svchost進程,不同組服務使用多個svchost進程,組的區別是由服務的可執行程序后邊的參數決定的。

例如rpcss在注冊表中 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcSs 有這樣一項:
"ImagePath"=REG_EXPAND_SZ:"%SystemRoot%\system32\svchost -k rpcss"
因此rpcss就屬于rpcss組,這在服務管理控制臺也可以看到。

svchost的所有組和組內的所有服務都在注冊表的如下位置: 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負責的服務時,服務管理器如果遇到可執行程序內容ImagePath已經存在于服務管理器的映象庫中,就不在啟動第2個進程svchost,而是直接啟動服務。這樣就實現了多個服務共享一個svchost進程。


3. Svchost代碼

        現在我們基本清楚svchost的原理了,但是要自己寫一個DLL形式的服務,由svchost來啟動,僅有上邊的信息還有些問題不是很清楚。比如我們在導出的ServiceMain()函數中接收的參數是ANSI還是Unicode?我們是否需要調用RegisterServiceCtrlHandler和StartServiceCtrlDispatcher來注冊服務控制及調度函數?

        這些問題要通過查看svchost代碼獲得。下邊的代碼是windows 2000+ service pack 4 的svchost反匯編片段,可以看出svchost程序還是很簡單的。

        主函數首先調用ProcCommandLine()對命令行進行分析,獲得要啟動的服務組,然后調用SvcHostOptions()查詢該服務組的選項和服務組的所有服務,并使用一個數據結構 svcTable 來保存這些服務及其服務的DLL,然后調用PrepareSvcTable() 函數創建SERVICE_TABLE_ENTRY 結構,把所有處理函數SERVICE_MAIN_FUNCTION 指向自己的一個函數FuncServiceMain(),最后調用API StartServiceCtrlDispatcher() 注冊這些服務的調度函數。

; =============================== 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為該組的所有服務都注冊了svchost中的一個處理函數,因此每次啟動任何一個服務時,服務管理器SCM都會調用FuncServiceMain() 這個函數。這個函數使用 svcTable 查詢要啟動的服務使用的DLL,調用DLL導出的ServiceMain()函數來啟動服務,然后返回。

; ============================== 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已經調用了StartServiceCtrlDispatcher來服務調度函數,因此我們在實現DLL實現時就不用了,這主要是因為一個進程只能調用一次StartServiceCtrlDispatcher API。但是需要用 RegisterServiceCtrlHandler 來注冊響應控制請求的函數。最后我們的DLL接收的都是unicode字符串。

       由于這種服務啟動后由svchost加載,不增加新的進程,只是svchost的一個DLL,而且一般進行審計時都不會去HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost 檢查服務組是否變化,就算去檢查,也不一定能發現異常,因此如果添加一個這樣的DLL后門,偽裝的好,是比較隱蔽的。


4. 安裝服務與設置
       要通過svchost調用來啟動的服務,就一定要在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost下有該服務名,這可以通過如下方式來實現:
1) 添加一個新的服務組,在組里添加服務名
2) 在現有組里添加服務名
3) 直接使用現有服務組里的一個服務名,但本機沒有安裝的服務
4) 修改現有服務組里的現有服務,把它的ServiceDll指向自己

        其中前兩種可以被正常服務使用,如使用第1種方式,啟動其服務要創建新的svchost進程;第2種方式如果該組服務已經運行,安裝后不能立刻啟動服務,因為svchost啟動后已經把該組信息保存在內存里,并調用API StartServiceCtrlDispatcher() 為該組所有服務注冊了調度處理函數,新增加的服務不能再注冊調度處理函數,需要重起計算機或者該組的svchost進程。而后兩種可能被后門使用,尤其是最后一種,沒有添加服務,只是改了注冊表里一項設置,從服務管理控制臺又看不出來,如果作為后門還是很隱蔽的。比如EventSystem服務,缺省是指向es.dll,如果把ServiceDll改為EventSystem.dll就很難發現。

         因此服務的安裝除了調用CreateService()創建服務之外,還需要設置服務的ServiceDll,如果使用前2種還要設置svchost的注冊表選項,在卸載時也最好刪除增加的部分。

具體代碼參見后邊的附例(使用的是方法3)。

注: ImagePath 和ServiceDll 是ExpandString不是普通字符串。因此如果使用.reg文件安裝時要注意。


5. DLL服務實現
         DLL程序的編寫比較簡單,只要實現一個ServiceMain()函數和一個服務控制程序,在ServiceMain()函數里用RegisterServiceCtrlHandler()注冊服務控制程序,并設置服務的運行狀態就可以了。

          另外,因為此種服務的安裝除了正常的CreateService()之外,還要進行其他設置,因此最好實現安裝和卸載函數。

          為了方便安裝,實現的代碼提供了InstallService()函數進行安裝,這個函數可以接收服務名作為參數(如果不提供參數,就使用缺省的iprip),如果要安裝的服務不在svchost的netsvcs組里安裝就會失敗;如果要安裝的服務已經存在,安裝也會失敗;安裝成功后程序會配置服務的ServiceDll為當前Dll。提供的UninstallService()函數,可以刪除任何函數而沒有進行任何檢查。

         為了方便使用rundll32.exe進行安裝,還提供了RundllInstallA()和RundllUninstallA()分別調用InstallService()及UninstallService()。因為rundll32.exe使用的函數原型是:
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
);
對應的命令行是rundll32 DllName,FunctionName [Arguments]

         DLL服務本身只是創建一個進程,該程序命令行就是啟動服務時提供的第一個參數,如果未指定就使用缺省的svchostdll.exe。啟動服務時如果提供第二個參數,創建的進程就是和桌面交互的。

具體代碼參見后邊的附例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,TapiSrv

C:\>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
- wzcsvc

C:\>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\SYSTEM

SvcHostDLL: ServiceMain(3, IPRIP) called
SvcHostDLL: RealService called 'cmd /k whoami' Interact
SvcHostDLL: CreateProcess(cmd /k whoami) to 640

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
640 cmd.exe         Title: C:\WINNT\System32\cmd.exe
1360 svchost.exe     Svcs:  EventSystem,Netman,RasMan,SENS,TapiSrv,IPRIP

C:\>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.asp


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"

//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);
}

posted on 2005-11-30 18:18 tqsheng 閱讀(644) 評論(0)  編輯 收藏 引用

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99在线视频精品| 亚洲一区日本| 欧美另类一区| 中文av一区二区| 午夜精彩视频在线观看不卡 | 亚洲午夜精品视频| 国产精品一区二区女厕厕| 久久久九九九九| 女主播福利一区| 亚洲欧美视频在线观看| 欧美一区二区在线播放| 亚洲国产一区二区三区青草影视| 亚洲国产精品视频| 欧美午夜欧美| 久久久久久久久久久久久女国产乱| 久久裸体艺术| 亚洲手机成人高清视频| 久久成人资源| 亚洲一区二区三区四区五区午夜| 欧美亚洲视频一区二区| 亚洲欧洲日韩综合二区| 亚洲综合国产激情另类一区| 亚洲国产成人高清精品| 亚洲午夜高清视频| 亚洲激情网站| 欧美一区=区| 在线一区二区三区四区| 久久免费观看视频| 亚洲欧美不卡| 欧美精品色一区二区三区| 久久久www成人免费毛片麻豆| 免费久久精品视频| 久久精品九九| 欧美亚洲不卡| 91久久精品国产91久久| 国产亚洲精品自拍| 一区二区三区波多野结衣在线观看| 国产一区二区三区免费观看| 艳女tv在线观看国产一区| 一区二区三区在线视频播放| 在线一区视频| 中文欧美字幕免费| 欧美大片va欧美在线播放| 久久久久久久久久久一区 | 香蕉久久夜色精品| 亚洲视频 欧洲视频| 欧美a级一区| 农村妇女精品| 精品福利免费观看| 性欧美xxxx大乳国产app| 亚洲综合社区| 欧美视频你懂的| 亚洲精品社区| 亚洲狼人综合| 欧美国产日本韩| 欧美激情精品久久久久| 精品91免费| 久久久久久69| 男人的天堂亚洲| 1024成人| 欧美暴力喷水在线| 欧美国产免费| 亚洲缚视频在线观看| 久久九九精品| 欧美高清在线播放| 亚洲精品一区在线观看| 欧美激情精品久久久久久黑人| 亚洲成人资源| 亚洲第一综合天堂另类专| 黄色国产精品一区二区三区| 久久国产加勒比精品无码| 久久久久久噜噜噜久久久精品 | 久久国产精品黑丝| 美女视频黄a大片欧美| 在线免费日韩片| 欧美国产欧美亚洲国产日韩mv天天看完整 | 亚洲国产小视频在线观看| 亚洲美女av网站| 欧美日韩免费高清一区色橹橹| 日韩视频第一页| 午夜久久资源| 精品成人一区二区| 欧美精品123区| 亚洲午夜精品| 麻豆成人av| 在线视频日韩| 国产一区二区三区黄视频| 老司机精品视频一区二区三区| 亚洲国产一区视频| 欧美一区二区三区另类 | 国产一区二区三区在线观看网站| 久久女同精品一区二区| 日韩天天综合| 久久免费视频在线观看| 亚洲精品国产品国语在线app | 午夜视频一区| 亚洲黄色小视频| 欧美在线地址| 一本不卡影院| 国产婷婷成人久久av免费高清| 久久在线免费| 亚洲男女自偷自拍| 亚洲福利视频专区| 欧美一区亚洲二区| 亚洲精品一区二区网址| 国产日韩精品入口| 欧美乱妇高清无乱码| 久久激情网站| 亚洲一区二区三区四区视频| 欧美激情精品久久久久久变态| 欧美一区二区三区免费观看视频| 亚洲经典视频在线观看| 国产日韩精品在线播放| 欧美日韩免费高清一区色橹橹| 久久精品一级爱片| 亚洲一区二区免费看| 亚洲国产日韩一区二区| 久久综合999| 久久精品国产999大香线蕉| 一二三区精品福利视频| 亚洲日本电影| 在线观看91精品国产入口| 国产欧美一区二区精品婷婷 | 久久综合九色综合欧美就去吻| 亚洲欧美视频在线观看视频| 一本久道久久久| 亚洲欧洲在线观看| 亚洲第一天堂av| 欧美a级在线| 免费在线观看日韩欧美| 久久精品亚洲精品国产欧美kt∨| 亚洲伊人网站| 亚洲一区三区在线观看| 99这里只有久久精品视频| 亚洲精品美女91| 亚洲人成77777在线观看网| 在线日本成人| 91久久久精品| 亚洲美女av黄| 一区二区三区国产精华| 日韩视频―中文字幕| a4yy欧美一区二区三区| 99精品国产在热久久| 日韩视频在线观看国产| 夜夜嗨av色综合久久久综合网| 亚洲免费av观看| 一本色道久久综合亚洲精品高清 | 一区电影在线观看| 中文日韩在线视频| 亚洲欧美精品在线观看| 午夜精品国产更新| 久久精品毛片| 欧美91福利在线观看| 亚洲国产福利在线| 亚洲欧洲精品一区二区| 99视频精品全国免费| 亚洲在线日韩| 久久蜜桃精品| 欧美精品久久久久久久久老牛影院| 欧美日韩国产成人| 国产精品一二一区| 在线观看不卡av| 日韩视频中文| 欧美中文在线观看| 欧美11—12娇小xxxx| 亚洲区一区二区三区| 一本色道久久88亚洲综合88| 午夜国产一区| 欧美激情偷拍| 国产精品视频导航| 91久久中文字幕| 亚洲欧美日韩国产一区| 老牛国产精品一区的观看方式| 亚洲精品日韩综合观看成人91| 亚洲一区自拍| 欧美岛国激情| 国产亚洲一区二区三区在线播放| 亚洲欧洲一区二区在线播放| 午夜精品福利在线| 欧美激情 亚洲a∨综合| 亚洲一级特黄| 欧美风情在线观看| 国内精品一区二区三区| 一区二区电影免费在线观看| 久久久伊人欧美| 一区二区不卡在线视频 午夜欧美不卡在 | 欧美日韩成人综合天天影院| 国产欧美精品日韩精品| 日韩特黄影片| 美日韩精品免费| 亚洲伊人伊色伊影伊综合网| 欧美+日本+国产+在线a∨观看| 国产精品永久入口久久久| 日韩视频免费观看| 狼人社综合社区| 欧美一级播放| 国产精品每日更新| 亚洲美女在线观看| 亚洲第一毛片| 久久综合五月天婷婷伊人|