2017-01-17 4 views
0

Я разработал сервис окна (S1) на C++, который может запускать или останавливать службу удаленно. эта служба работает нормально, когда я запускаю это как процесс. Но это не работает, когда я добавляю это в диспетчер службы и запускаю под локальной системной учетной записью, в этом случае OpenSCManager возвращает 0 (доступ запрещен).Доступ запрещен при запуске или остановке окна службы удаленно

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\n"); 
     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\n"); 
     return; 
    } 

    SERVICE_STATUS status; 
    if(!::ControlService(hService, 
         SERVICE_CONTROL_STOP, 
         &status)) 
    printf("ERROR: COULDN'T STOP SERVICE\n"); 


    ::CloseServiceHandle(hService); 

    QuerySvc(szNetworkName, szSvcName); 
} 

Примечание: 1. У меня есть права администратора на моей локальной системе, а также удаленную систему. 2. Я не могу изменить свойства службы входа в систему из-за других функций. 3.Я использую Visual Studio 2015 для разработки.

+1

Вам не нужна ваша функция ImpersonateUser(), поскольку она делает то же самое, что и встроенный API ImpersonateSelf(). На самом деле вам это тоже не нужно; вы не делаете ничего, для чего полезно использовать самоликвидацию. –

+0

Привет @ Харри Джонстон спасибо. он работает, но можно ли добавить LOCALCOMPUTERNAME в группу «Администраторы удаленного компьютера»? –

ответ

1

я права администратора на удаленной системе

но как дистанционная система это знать? вам нужно как-то сначала подключиться к ресурсу \IPC$ на удаленном компьютере с именем пользователя/паролем. это может быть сделано, например, с NetUseAdd .try коды:

#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"***"); 

и о вашем void ImpersonateUser() - сначала бессмысленно (олицетворения нити с текущими маркерами процесса) на втором не нужен открыть текущий дескриптор процесса, но может использовать константу псевдо-ручка GetCurrentProcess или NtCurrentProcess() макрос. и все это не имеет никакого эффекта. для prepare to access remote system - вам нужно NetUseAdd вызов

+0

Привет RBMn спасибо, что он работает для меня. есть ли другой способ, в котором мне не нужно указывать имя пользователя, пароль. то есть автоматически обнаруживать токен пользователя, поскольку в моем случае я не разрешаю использовать обычные текстовые учетные данные. –

+0

@DineshSaini - в пользовательском токене не существует имени/пароля, а main он используется только локально. удаленная система не может получить доступ к вашему токену для проверки. если ваша система предполагает отправить токен удаленной системе - как удаленный может проверить, что эта информация верна? как я знаю, или какая-то необходимость в проверке подлинности или способ, который советует Гарри Джонстон - добавьте LOCALCOMPUTERNAME $ в группу администраторов удаленного компьютера – RbMm

+0

Решение @RbMn, предложенное Гарри Джонстоном, работает, но я не знаю, насколько это безопасно. поэтому, если любой другой способ начать или прекратить обслуживание удаленно, пожалуйста, предложите –

0

Если вы находитесь в среде домена, вы можете изменить разрешения для службы на целевом компьютере, как описано в this answer. Короткая версия, что права доступа должны явным образом предоставить доступ для запуска и остановки службы для учетной записи пользователя.

В этом случае вам необходимо предоставить доступ к учетной записи домена исходного компьютера. Учетные записи в домене домена принимают форму COMPUTERNAME$.

Смежные вопросы