visuel c ++ - Adgang nægtes, mens start eller stop vinduet service eksternt

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har designet en vinduesservice (S1) i c ++, som kan starte eller stoppe en tjeneste på afstand.
Denne tjeneste virker fint, når jeg kører dette som en proces.
Men det virker ikke, når jeg tilføjer dette til serviceadministrator og kører under den lokale systemkonto i dette tilfælde OpenSCManager returnerer 0 (adgang nægtet).


int main(int argc, char* argv[])
{
  //this is sample code not complete service code//
  char *premote\_server= "192.168.122.100";

    ImpersonateUser();

    //access service control manager
    SC\_HANDLE hSCM = ::OpenSCManager(premote\_server,
                       SERVICES\_ACTIVE\_DATABASE,
                       SC\_MANAGER\_ALL\_ACCESS);

 DWORD dwError = GetLastError(); //dwError is 5 which is Acess is denied.

    if (hSCM == 0)
    {
      printf("ERROR: UNABLE TO OPEN SERVICE MANAGER
");
      PrintError(GetLastError());
      return;
    }
  StopSvc(hSCM, 'servicename');
::CloseServiceHandle(hSCM);

  delete[] pName;

return 0;
}

void ImpersonateUser()
{
  //prepare to access remote system

  DWORD id = GetCurrentProcessId();
  HANDLE hp = OpenProcess(PROCESS\_ALL\_ACCESS, FALSE, id);

  HANDLE t;

  BOOL b = OpenProcessToken( hp,
                             TOKEN\_QUERY | TOKEN\_DUPLICATE ,
                             &t);

  if(!ImpersonateLoggedOnUser(t))
  {
    PrintError(GetLastError());
    return;
  }
 CloseHandle(hp); //close handle
 CloseHandle(t);
}
void StopSvc(SC\_HANDLE hSCM,, char *szSvcName)
{
    SC\_HANDLE hService = ::OpenService(hSCM, 
                                       szSvcName,
                                       SERVICE\_STOP);

    if (hService == NULL)
    {
        printf("ERROR: COULDN'T OPEN SERVICE
");
        return;
    }

    SERVICE\_STATUS status;
    if(!::ControlService(hService, 
                         SERVICE\_CONTROL\_STOP,
                         &status))
    printf("ERROR: COULDN'T STOP SERVICE
");


    ::CloseServiceHandle(hService);

    QuerySvc(szNetworkName, szSvcName);
}


Bemærk:
 1. Jeg har administratorrettigheder på mit lokale system samt fjernsystem.
 2. Jeg kan ikke ændre tjenesten Log On egenskaber på grund af anden funktionalitet.
3. Jeg bruger Visual Studio 2015 til udvikling.

Bedste reference



  Jeg har administratorrettigheder på fjernsystem



men hvordan fjernsystem kender dette? du skal på en eller anden måde først oprette forbindelse til IPC$ ressource på fjernmaskine med brugernavn/adgangskode. dette kan gøres for eksempel med NetUseAdd .tryk som denne: [11]


#include <Lm.h>

ULONG RemoteTest(PCWSTR lpMachineName, PCWSTR username, PCWSTR password, PCWSTR lpServiceName)
{
    USE\_INFO\_2 ui = {
        0, 0, (PWSTR)password, 0, USE\_IPC, 0, MAXDWORD, (PWSTR)username
    };

    ui.ui2\_remote = (PWSTR)alloca((wcslen(lpMachineName) + 8) *sizeof(WCHAR));

    swprintf(ui.ui2\_remote, L"\\\%s\IPC$", lpMachineName);

    ULONG ParmError, err;
    if (!(err = NetUseAdd(0, 2, (PBYTE)&ui, &ParmError)))
    {
        BOOL fOk = FALSE;

        if (SC\_HANDLE hSCM = OpenSCManager(lpMachineName, SERVICES\_ACTIVE\_DATABASE, SC\_MANAGER\_ALL\_ACCESS))
        {
            if (SC\_HANDLE hService = OpenService(hSCM, lpServiceName, SERVICE\_START|SERVICE\_STOP|SERVICE\_INTERROGATE|SERVICE\_QUERY\_STATUS ))
            {
                SERVICE\_STATUS ss;
                fOk = QueryServiceStatus(hService, &ss);
                //StartService(hService, 0, 0);
                //ControlService(hService, SERVICE\_CONTROL\_STOP, &ss);
                CloseServiceHandle(hService);
            }
            CloseServiceHandle(hSCM);
        }

        if (!fOk)
        {
            err = GetLastError();
        }

        NetUseDel(0, ui.ui2\_remote, USE\_LOTS\_OF\_FORCE);
    }

    return err;
}

// RemoteTest(L"192.168.122.100", L"Administrator", L"***", L"***");


og om din void ImpersonateUser() - i første omgang er det meningsløst (efterligner tråd med nuværende procestegn) ved anden ikke brug for åbent nuværende proceshåndtag, men kan bruge konstant pseudo-håndtag GetCurrentProcess eller NtCurrentProcess() makro. og alt dette har ingen virkning. for prepare to access remote system - du har brug for NetUseAdd opkald

Andre referencer 1


Hvis du er i et domæne-miljø, kan du ændre servicetilladelserne på målcomputeren som beskrevet i dette svar. Den korte version er, at tilladelserne skal eksplicit give adgang til at starte og stoppe tjenesten til den pågældende brugerkonto.


I dette tilfælde skal du give adgang til domænenavnet til kildecomputeren. Computerdomænekonti tager formularen COMPUTERNAME$.