总是启动以后就立即停止 或仅仅能维持一小段时间, 无论我添加什么样的服务程序都这样
劳烦各位高手帮我看看 #include <stdafx.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <windows.h>#define DEFAULT_SERVICE "TestService"/*声明省略*/HANDLE hDll = NULL; //dll module handle used to get dll path in InstallService
SERVICE_STATUS_HANDLE hSrv; //Service HANDLE & STATUS used to get service state
DWORD dwCurrState;BOOL APIENTRY DllMain( HINSTANCE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hDll = hModule;
break;
case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:

case DLL_PROCESS_DETACH:
TellSCM( SERVICE_STOP_PENDING, 0, 0 );
Sleep(1500);
TellSCM( SERVICE_STOPPED, 0, 0 );
break;
}
return TRUE;
}__declspec(dllexport) void WINAPI ServiceMain( int argc, wchar_t* argv[] )
{
char svcname[256]=DEFAULT_SERVICE;
hSrv = RegisterServiceCtrlHandler( svcname, (LPHANDLER_FUNCTION)ServiceHandler );
if( hSrv == NULL )
{
return;
} TellSCM( SERVICE_START_PENDING, 0, 1 );
Sleep(10);
TellSCM( SERVICE_RUNNING, 0, 0 ); //Real Service    这里是服务 我没有加入服务函数 或线程 do
{
Sleep(10);//not quit until receive stop command, otherwise the service will stop
}
while(dwCurrState != SERVICE_STOP_PENDING && dwCurrState != SERVICE_STOPPED);

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 );
}
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 *pSvchost = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost";
rc = RegOpenKeyEx(hkRoot, pSvchost, 0, KEY_QUERY_VALUE, &hkRoot);
if(ERROR_SUCCESS != 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)"; //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)
{
throw "";
} 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)
{
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)"; }
catch(char *str)
{
if(str && str[0])
{
rc = GetLastError();
}
} 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 InstallA(
                             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) 
{
return rc;
} char *svcname = DEFAULT_SERVICE;
if(name && name[0]) svcname = name; schService = OpenService(hscm, svcname, DELETE);
if (schService == NULL) 
{
return rc;
} if (!DeleteService(schService) ) 
{
return rc;
} }__except(1){} 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 UninstallA(
                               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);
}void __stdcall ServiceHandler( DWORD dwCommand )
{
switch( dwCommand )
{
case SERVICE_CONTROL_STOP:
TellSCM( SERVICE_STOP_PENDING, 0, 1 );
Sleep(10);
TellSCM( SERVICE_STOPPED, 0, 0 );
break;
case SERVICE_CONTROL_PAUSE:
TellSCM( SERVICE_PAUSE_PENDING, 0, 1 );
Sleep(10);
TellSCM( SERVICE_PAUSED, 0, 0 );
break;
case SERVICE_CONTROL_CONTINUE:
TellSCM( SERVICE_CONTINUE_PENDING, 0, 1 );
Sleep(10);
TellSCM( SERVICE_RUNNING, 0, 0 );
break;
case SERVICE_CONTROL_INTERROGATE:
TellSCM( dwCurrState, 0, 0 );
break;
case SERVICE_CONTROL_SHUTDOWN:
TellSCM( SERVICE_STOPPED, 0, 0 );
break;
}
}
还有 我想在这种程序里面加入 全局Hook 行不行?

解决方案 »

  1.   

    说说你是怎么启动的?另外全局Hook是肯定不行的,因为服务程序不是运行在登陆用户的身份下,hook可以挂上,但是什么也hook不住。
      

  2.   

    我启动服务就是用sc start 没有参数
    我往里面加过Hook 确实是启动以后什么都钩不住选择合适的服务组 是不是可以实现登陆用户身份运行hook?在有 我在服务子程序里面 写死循环 0仍然是运行议会就停止 自动化程度很高……
      

  3.   

    选择合适的服务组 不可以实现登陆用户身份运行hook,但是可以有其它方式实现。
    但那样和运行普通程序没什么两样了。
    可以通过遍历进程来取得登陆用户的Shell的hToken来运行进程。下面就是示例代码:BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)
    {
     if(!lpName)
     {
      return FALSE;
     }
     HANDLE         hProcessSnap = NULL; 
        BOOL           bRet      = FALSE; 
        PROCESSENTRY32 pe32      = {0}; 
     
        hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
        if (hProcessSnap == INVALID_HANDLE_VALUE) 
            return (FALSE); 
     
        pe32.dwSize = sizeof(PROCESSENTRY32); 
     
        if (Process32First(hProcessSnap, &pe32)) 
        {  
            do 
            {
       if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName)))
       {
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
         FALSE,pe32.th32ProcessID);
        bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);
        CloseHandle (hProcessSnap); 
        return (bRet);
       }
            } 
            while (Process32Next(hProcessSnap, &pe32)); 
            bRet = TRUE; 
        } 
        else 
            bRet = FALSE;
     
        CloseHandle (hProcessSnap); 
        return (bRet);
    }BOOL RunProcess(LPCSTR lpImage)
    {
     if(!lpImage)
     {
      return FALSE;
     }
     HANDLE hToken;
     if(!GetTokenByName(hToken,"EXPLORER.EXE"))
     {
      return FALSE;
     }
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
     
     ZeroMemory(&si, sizeof(STARTUPINFO));
     si.cb= sizeof(STARTUPINFO);
     si.lpDesktop = TEXT("winsta0\\default");
     
     BOOL bResult = CreateProcessAsUser(hToken,lpImage,NULL,NULL,NULL,
      FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
     CloseHandle(hToken);
     if(bResult)
     {
      OutputDebugString("CreateProcessAsUser ok!\r\n");
     }
     else
     {
      OutputDebugString("CreateProcessAsUser false!\r\n");
     }
     return bResult;
    }
      

  4.   

    hook的条件:
    1.需要消息循环。
    2.当前桌面可以有hook权限。
    3.不会出现挎桌面hook。
      

  5.   

    我不太清楚svchost调用服务。
    但是我试了一下,可以肯定用了程序中的安装服务以后,这个服务根本就没有运行。
      

  6.   

    这个程序是我根据Bingle的文章修改的 基本没有很大的改动
    其实 可以注意到 他是运行了的 只不过是运行之后马上停止
      

  7.   

    我刚找了Bingle的文章的文章看了一下,明白了。
    你改的这个服务程序其实根本就没有运行,具体的原因我解释一下。
    根据Bingle的文章,svchost调用服务可以有四种方式启动:
    1) 添加一个新的服务组,在组里添加服务名 
    2) 在现有组里添加服务名 
    3) 直接使用现有服务组里的一个服务名,但本机没有安装的服务 
    4) 修改现有服务组里的现有服务,把它的ServiceDll指向自己
    Bingle本来的例子是采用的3的启动方式,他使用了IPrip服务,该服务本来就位于netsvcs服务组中,所以在他的InstallService例程里仅仅是添加了该服务的dll路径,这就够了,所以他的服务可以运行。
    而你修改的程序中,改了服务的名称为TestService,这个服务本身并不在netsvcs服务组中,而你也没有修改他的InstallService,将TestService添加到netsvcs服务组中去(修改HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost下netsvcs的键值),所以你修改的服务程序是不会运行的。把TestService改回IPrip,那么你的服务就可以运行了。如果你坚持要用TestService作为服务名,那么你只能使用1或2两种方式,而方式2相对简单一些,因为添加一个服务组也挺麻烦的(详细操作我也没做过)。
      

  8.   

    sorry 是下边的我没有改 那个Iprip是冒名顶替的服务 忘记了
    其实 我调程序用的一直就是IPRIP
      

  9.   

    哦,我昨天晚上看到dll被加载了就以为服务一直运行了,今天看了一下,发现dll虽然被加载了,但是服务停止了。就又看了一下,发现服务被停止的原因是因为原程序中的这几句:
    case DLL_THREAD_ATTACH:

    case DLL_THREAD_DETACH:

    case DLL_PROCESS_DETACH:
    TellSCM( SERVICE_STOP_PENDING, 0, 0 );
    Sleep(1500);
    TellSCM( SERVICE_STOPPED, 0, 0 );
    break;把它们注释掉就好了。