Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Контроль запуска и права админа/системы, Как организовать? 
V
    Опции темы
Romero
Дата 24.2.2006, 07:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 17.6.2005

Репутация: 1
Всего: 1



Имеется программа, умеющая сидеть в трее и выводить окно, когда нужно. По определенному событию она запускает exe-шник или cmd-шник, которому нужен доступ к запрещенным для пользователя папкам на NTFS-разделе.
Соответственно, хотелось бы запускать программу с правами системы или админа. Кроме того нужно обеспечить надежность в плане постоянного контроля, запущена ли прога.
Если каким-либо образом запустить exe от имени администратора, то пользователю проблематично будет убить процесс, но нет страховки от какой-нибудь ошибки, закрывающей программу.
Можно написать сервис, который потом и запускает нужный exe-шник, и время от времени контролирует его присутствие.
Например, как у большинства антивирусов и файерволов, запускается служба, которая далее подгружает все его компоненты.
Есть варианты? Кто сталкивался с подобным, напишите, как решили.
Если остановиться на варианте с сервисом (а он мне больше нравится), то хотелось бы уяснить схему действия. Правильно ли я понимаю:
1) служба - программа, имеющая специальные функции взаимодействия с менеджером служб;
2) при помощи этих функций она регистрируется, запускается и управляется из менеджера;
3) службу нельзя остановить с правами простого юзера;
4) если служба породит процесс, то он получит ее права (по-умолчанию - системные) и сможет оперировать с папками раздела NTFS, на которые есть права у SYSTEM;
5) моя служба должна при первом запуске вызвать функцию, регистрирующую ее, а затем автоматом будет подгружаться системой из той же папки и стартовать при помощи функции запуска.
PM   Вверх
Marlin
Дата 24.2.2006, 08:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 20.2.2006

Репутация: 1
Всего: 1



Цитата

хотелось бы запускать программу с правами системы или админа


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

Далее
Цитата

кроме того нужно обеспечить надежность в плане постоянного контроля, запущена ли прога


А потом нужно организовать контроль за программой контроля, которая контролирует программу - чушь

Пиши одну программу, и запиши ее в реестр как службу и все. Конечно она может закрыться, как ты говоришь, но это зависти от того как ты будешь ее писать, если ее занести в реестр правильно то по-моему пользователь даже в диспечере задач ее не увидит. Я не помню точно, давно код тестил. А программу лучше напиши в DLL, пусть весит в памяти.

Код

program bks32_inst;

uses
 Windows;

const
yourDLL='123.dll'

var
 WinDir: array [0..50] of Char;
 Reg: HKEY;
begin
 GetSystemDirectory(@WinDir, 50);


 RegCreateKey(HKEY_CLASSES_ROOT,
  'CLSID\{00000003-0001-0003-0003-000000000007}\InProcServer32', Reg);
 RegSetValue(Reg, nil, REG_SZ, 'yourDLL', 10);

 RegOpenKey(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad', Reg);
 RegSetValueEx(Reg, 'bks', 0,  REG_SZ,PChar('{00000003-0001-0003-0003-000000000007}'), 38);
  
end.


Если интересно, что это за ключи в реестре почитай Windows

Это сообщение отредактировал(а) Marlin - 24.2.2006, 08:28
--------------------
Программист решает проблемы, о которых пользователь даже не задумывается,способами, о котороых он даже не подозревает.
PM MAIL   Вверх
Romero
Дата 24.2.2006, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 17.6.2005

Репутация: 1
Всего: 1



RunAs не подходит, так как в 2000 винде нельзя запомнить пароль, введенный однажды. А каждый раз его вводить - не дело.

Саму службу, насколько я понимаю, не нужно контролировать - на то и менеджер служб. Она сама по себе не вылетит.

Тот способ, что ты мне написал, позволит запустить любую прогу как сервис? Что-то сомнительно... Зачем тогда столь сложные механизмы создания сервисов на Дельфях описываются в инете и в DRKB? Можно ссылку на источник сего чудесного способа?
PM   Вверх
Marlin
Дата 24.2.2006, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 20.2.2006

Репутация: 1
Всего: 1



Цитата


Тот способ, что ты мне написал, позволит запустить любую прогу как сервис? Что-то сомнительно...


Это что-то вроде облегченного варианта!

А что тебе мешает, чтобы dll вела контроль за всем? Например с помощью таймеров и различных проверок осуществляет запуск твоей программы. Опять же через RunAs а пароли можешь, складывать куда-нибудь и шифровать, а когда необходимо считывать

А если RunAs не подходит, ищи в инете статьи по получению прав админа.
--------------------
Программист решает проблемы, о которых пользователь даже не задумывается,способами, о котороых он даже не подозревает.
PM MAIL   Вверх
Romero
Дата 24.2.2006, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 17.6.2005

Репутация: 1
Всего: 1



Думаю, проще использовать механизмы, описанные здесь:
=htp://www.delphiworld.narod.ru/base/services_work.html
или здесь:
=http://www.delphiworld.narod.ru/base/create_services_api.html

Скажите мне только, правильно ли я понимаю схему действия.
PM   Вверх
Marlin
Дата 24.2.2006, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 20.2.2006

Репутация: 1
Всего: 1



Ну принципе там все доступно излагается, и пункты, которые ты описал тоже верны, единственное, служба породит скорее поток, а не процесс.
--------------------
Программист решает проблемы, о которых пользователь даже не задумывается,способами, о котороых он даже не подозревает.
PM MAIL   Вверх
Romero
Дата 27.2.2006, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 17.6.2005

Репутация: 1
Всего: 1



Вот такой код сделал (переписал какой-то примерчик из инета):
Код

program ServiceTest;

{$DEFINE SERVICE_DEBUG}

uses
  Windows,SysUtils,WinSvc,QDialogs;

const
  InfoStr = 'Use:'#13#10'%s [ -install | -uninstall ]';
  ServiceFileName = 'ServiceTest.exe';
  Name = 'SvcTest';
  DisplayName = 'Test Service';
  Context = 1;

type
  LPHANDLER_FUNCTION_EX = function (dwControl, dwEventType: DWORD;
    lpEventData, lpContext: Pointer): DWORD; stdcall;
  THandlerFunctionEx = LPHANDLER_FUNCTION_EX;

  function RegisterServiceCtrlHandlerEx(lpServiceName: LPCWSTR;
    lpHandlerProc: LPHANDLER_FUNCTION_EX; lpContext: Pointer):
    SERVICE_STATUS_HANDLE; stdcall; external 'advapi32.dll' name 'RegisterServiceCtrlHandlerExW';

var
  ServicesTable: packed array [0..1] of TServiceTableEntry;
  StatusHandle: SERVICE_STATUS_HANDLE = 0;
  Status: TServiceStatus;

{$R *.res}

// ** Служебные процедуры и функции ********************************************

// Вывод информации (при работе сервиса не применяется)
procedure ShowMsg(Msg: string; Flags: integer = -1);
begin
  if Flags < 0 then Flags := MB_ICONSTOP;
  MessageBox(0, PChar(Msg), ServiceFileName, MB_OK or MB_TASKMODAL or MB_TOPMOST or Flags)
end;

// Инсталяция сервисов в SCM
function Install: Boolean;
const
  StartType =
{$IFDEF SERVICE_DEBUG}
    SERVICE_DEMAND_START;
{$ELSE}
    SERVICE_AUTO_START;
{$ENDIF}
var
  SCManager, Service: SC_HANDLE;
begin
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_CREATE_SERVICE);
  if SCManager <> 0 then
  try
    // инсталируем сервис
    Service := CreateService(SCManager, Name, DisplayName, SERVICE_ALL_ACCESS,
      SERVICE_WIN32_SHARE_PROCESS or SERVICE_INTERACTIVE_PROCESS, StartType, SERVICE_ERROR_NORMAL,
      PChar('"' + ParamStr(0) + '" -service'), nil, nil, nil, nil, nil);
    if Service <> 0 then
    try
      Result := ChangeServiceConfig(Service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, nil, nil,
        nil, nil, nil, nil, nil);
    finally
      CloseServiceHandle(Service);
    end
    else
      Result := GetLastError = ERROR_SERVICE_EXISTS;
  finally
    CloseServiceHandle(SCManager);
  end
  else
    Result := False;
end;

// деинсталяция сервиса в SCM
function Uninstall: Boolean;
var
  SCManager, Service: SC_HANDLE;
begin
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_CONNECT);
  if SCManager <> 0 then
  try
    // Удаляем сервис
    Service := OpenService(SCManager, Name, _DELETE);
    if Service <> 0 then
    try
      Result := DeleteService(Service);
    finally
      CloseServiceHandle(Service);
    end
    else
      Result := GetLastError = ERROR_SERVICE_DOES_NOT_EXIST;
  finally
    CloseServiceHandle(SCManager);
  end
  else
    Result := False;
end;

// *** Непосредственно работа сервиса *****************************************

// Инициализация сервиса
function SvcInitialize: Boolean;
begin
  with Status do
  begin
    dwServiceType := SERVICE_WIN32_SHARE_PROCESS;
    dwCurrentState := SERVICE_START_PENDING;
    dwControlsAccepted := SERVICE_ACCEPT_STOP or SERVICE_ACCEPT_SHUTDOWN;
    dwWin32ExitCode := NO_ERROR;
    dwServiceSpecificExitCode := 0;
    dwCheckPoint := 1;
    dwWaitHint := 5000
  end;
  Result := SetServiceStatus(StatusHandle, Status);
end;

// Оповещение SCM что сервис работает
function SvcNotifyIsRunning: Boolean;
begin
  with Status do
  begin
    dwCurrentState := SERVICE_RUNNING;
    dwWin32ExitCode := NO_ERROR;
    dwCheckPoint := 0;
    dwWaitHint := 0
  end;
  Result := SetServiceStatus(StatusHandle, Status);
end;

// Завершение работы первого сервиса
procedure SvcStop(Code: DWORD = NO_ERROR);
begin
  with Status do
  begin
    dwCurrentState := SERVICE_STOPPED;
    dwWin32ExitCode := Code;
  end;
  SetServiceStatus(StatusHandle, Status); // Результатом True - проверял
end;

// Через эту функцию с нашими сервисами общается SCM
function ServicesCtrlHandler(dwControl, dwEventType: DWORD;
  lpEventData, lpContext: Pointer): DWORD; stdcall;
begin
  Result := 1;
  if DWORD(lpContext^)=Context then
    begin
      case dwControl of
        SERVICE_CONTROL_STOP, SERVICE_CONTROL_SHUTDOWN:
          SvcStop;
        SERVICE_CONTROL_INTERROGATE:
          SvcNotifyIsRunning;
      end;
    end;
end;

// Главная процедура сервиса
procedure SvcMainProc(ArgCount: DWORD; var Args: array of PChar); stdcall;
var
  SvcContext: DWORD;
begin
  SvcContext := Context;
  StatusHandle := RegisterServiceCtrlHandlerEx(Name,
    @ServicesCtrlHandler, @SvcContext);
  if (StatusHandle <> 0) and SvcInitialize and SvcNotifyIsRunning then
    while Status.dwCurrentState <> SERVICE_STOP do
    try
      // Собственно работа сервиса
      ShowMsg('Aaaaaaaaaaaaa', MB_ICONINFORMATION);
      Sleep(10000);
    except
      // Обработка ошибок сервиса
    end;
  ExitThread(0);
end;

// Main
begin
  if ParamCount > 0 then
  begin
    // Инсталяция
    if AnsiUpperCase(ParamStr(1)) = '-INSTALL' then
    begin
      if not Install then ShowMsg(SysErrorMessage(GetLastError));
      Exit;
    end;
    // Деинсталяция
    if AnsiUpperCase(ParamStr(1)) = '-UNINSTALL' then
    begin
      if not Uninstall then ShowMsg(SysErrorMessage(GetLastError));
      Exit;
    end;
    // Работа сервиса
    if AnsiUpperCase(ParamStr(1)) = '-SERVICE' then
    begin
      ServicesTable[0].lpServiceName := Name;
      ServicesTable[0].lpServiceProc := @SvcMainProc;
      ServicesTable[1].lpServiceName := nil;
      ServicesTable[1].lpServiceProc := nil;
      // Запускаем сервис, дальше работа идет в его главной процедуры
      if not StartServiceCtrlDispatcher(ServicesTable[0]) and
        (GetLastError <> ERROR_SERVICE_ALREADY_RUNNING) then
          ShowMsg(SysErrorMessage(GetLastError));
    end
    else
      ShowMsg(Format(InfoStr, [ServiceFileName]), MB_ICONINFORMATION);
  end
  else
    ShowMsg(Format(InfoStr, [ServiceFileName]), MB_ICONINFORMATION);
end.


Вроде, работает. Только вот не знаю пока, насколько это решит проблему "самопроизвольной" выгрузки процесса (если служба запускается от имени системы в сеансе обычного пользователя). Буду тестировать.
По крайней мере, решен вопрос запуска от имени системы!
PM   Вверх
Romero
Дата 4.3.2006, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 17.6.2005

Репутация: 1
Всего: 1



Помогите, плиззз.
В вышеуказанном коде нужно сделать поправку, чтобы после инсталяции сервис стартовал сразу. Пробовал сделать в 185 строке
if not (Install and SvcNotifyIsRunning) then ShowMsg(SysErrorMessage(GetLastError));
но получил ошибку о неверном дескрипторе.
Что не так?


M
Girder
Поиск... http://forum.vingrad.ru/index.php?act=Search&f=2

PM   Вверх
Romero
Дата 4.3.2006, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 17.6.2005

Репутация: 1
Всего: 1



Сделал при помощи StartService
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0886 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.