Запуск службы Windows из приложения без прав администратора (c ++) - PullRequest
2 голосов
/ 05 декабря 2011

Я написал службу Windows (и она работает нормально).Теперь у меня есть отдельное приложение, из которого я хочу запустить эту службу, но кажется, что это невозможно без прав администратора.

Как будет выглядеть правильное решение, чтобы пользователь мог запустить / остановить службу (например,из трея или приложения)

ИМХО плохо, что приложение всегда должно запускаться с правами администратора.

Ответы [ 4 ]

9 голосов
/ 05 декабря 2011

Вам просто нужно изменить разрешения для объекта службы, желательно одновременно с его установкой.

wchar_t sddl[] = L"D:"
  L"(A;;CCLCSWRPWPDTLOCRRC;;;SY)"           // default permissions for local system
  L"(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)"   // default permissions for administrators
  L"(A;;CCLCSWLOCRRC;;;AU)"                 // default permissions for authenticated users
  L"(A;;CCLCSWRPWPDTLOCRRC;;;PU)"           // default permissions for power users
  L"(A;;RP;;;IU)"                           // added permission: start service for interactive users
  ;

PSECURITY_DESCRIPTOR sd;

if (!ConvertStringSecurityDescriptorToSecurityDescriptor(sddl, SDDL_REVISION_1, &sd, NULL))
{
   fail();
}

if (!SetServiceObjectSecurity(service, DACL_SECURITY_INFORMATION, sd))
{
   fail();
}

Я предполагаю, что вы уже открыли дескриптор сервиса. Вам нужно разрешение WRITE_DAC.

Если вы также хотите, чтобы пользователи без прав администратора могли останавливать службу, добавьте право WP, т.е.

L"(A;;RPWP;;;IU)"                           
  // added permissions: start service, stop service for interactive users

Коды SDDL для прав на обслуживание можно найти в записи блога Уэйна Мартина, Безопасность диспетчера управления службами для не-администраторов .

0 голосов
/ 28 августа 2017

@ У меня с Гарри Джонстоном все в порядке, если кто-то захочет сделать это на C #:

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool SetServiceObjectSecurity(SafeHandle serviceHandle,
    UInt32 secInfos,
    IntPtr lpSecDesrBuf);

[DllImport("advapi32.dll", EntryPoint = "ConvertStringSecurityDescriptorToSecurityDescriptorW", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern Boolean ConvertStringSecurityDescriptorToSecurityDescriptor(
    [MarshalAs(UnmanagedType.LPWStr)] String strSecurityDescriptor,
    UInt32 sDRevision,
    ref IntPtr securityDescriptor,
    ref UInt32 securityDescriptorSize);

public static void SetServicePermissions(string service)
{
    System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(service);
    bool ok;
    IntPtr pSD = IntPtr.Zero;
    uint securityDescriptorSize = 0;
    string secDesc = "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;RPWP;;;IU)";

    ok = ConvertStringSecurityDescriptorToSecurityDescriptor(secDesc, 1, ref pSD, ref securityDescriptorSize);
    if (!ok)
    {
        throw new ApplicationException("error calling ConvertStringSecurityDescriptorToSecurityDescriptor(): error code=" + Marshal.GetLastWin32Error());
    }

    ok = SetServiceObjectSecurity(sc.ServiceHandle, 4 , pSD);
    if (!ok)
    {
        throw new ApplicationException("error calling SetServiceObjectSecurity(); error code=" + Marshal.GetLastWin32Error());
    }
}
0 голосов
/ 15 августа 2016

@ Гарри Джонстон, в дополнение к ответу.

Вот пример конструктора c ++.

void __fastcall TService1::ServiceAfterInstall(TService *Sender)
{
 wchar_t lpBuffer[256];
 long errorCode;
 SC_HANDLE hSCManager,hService;

 hSCManager  = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
 if (hSCManager == NULL)
 {
   errorCode = GetLastError();
   FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL);
   LogMessage("OpenSCManager Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE);
   return;
 }


 hService = OpenService(hSCManager, this->Name.c_str(), READ_CONTROL | WRITE_DAC);
 if (hService == NULL)
 {
   errorCode = GetLastError();
   FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL);
   LogMessage("OpenService Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE);
   CloseServiceHandle(hSCManager);
 }

 wchar_t sddl[] = L"D:"
  L"(A;;CCLCSWRPWPDTLOCRRC;;;SY)"           // default permissions for local system
  L"(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)"   // default permissions for administrators
  L"(A;;CCLCSWLOCRRC;;;AU)"                 // default permissions for authenticated users
  L"(A;;CCLCSWRPWPDTLOCRRC;;;PU)"           // default permissions for power users
  L"(A;;RP;;;IU)"                           // added permission: start service for interactive users
  ;

  PSECURITY_DESCRIPTOR sd;
  if (!ConvertStringSecurityDescriptorToSecurityDescriptor(AnsiString(sddl).c_str(), SDDL_REVISION_1, &sd, NULL))
  {
    errorCode = GetLastError();
    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL);
    LogMessage("ConvertStringSecurityDescriptorToSecurityDescriptor Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE);
  }

  if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd))
  {
    errorCode = GetLastError();
    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL);
    LogMessage("SetServiceObjectSecurity Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE);
  }

  CloseServiceHandle(hService);
  CloseServiceHandle(hSCManager);
}
0 голосов
/ 05 декабря 2011

Запуск услуги программно осуществляется с помощью функции StartService.Существует подробный пример использования, также приведенный под заголовком запуск службы , который также показывает, как:

  • обнаружить, что служба по какой-то причине закрывается
  • ждать, пока служба не будет в стабильном состоянии (запущена / остановлена)
  • запустить службу программно

Что касается прав администратора, это необходимо, потому что если любое приложение можетЗавершение работы служб (или, что более важно, установка и запуск новых служб ), это приведет к очень реальным и очень серьезным проблемам безопасности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...