unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfMain = class(TForm)
    btnRunProtectedProcess: TButton;
    btnTryTerminateProtectedProcess: TButton;
    btnSetProcessToUnprotectedState: TButton;
    btnRunUnprotectedProcess: TButton;
    btnTerminateUnprotectedProcess: TButton;
    procedure btnRunProtectedProcessClick(Sender: TObject);
    procedure btnTryTerminateProtectedProcessClick(Sender: TObject);
    procedure btnSetProcessToUnprotectedStateClick(Sender: TObject);
    procedure btnRunUnprotectedProcessClick(Sender: TObject);
    procedure btnTerminateUnprotectedProcessClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  SE_OBJECT_TYPE = (SE_UNKNOWN_OBJECT_TYPE, SE_FILE_OBJECT, SE_SERVICE,
    SE_PRINTER, SE_REGISTRY_KEY, SE_LMSHARE, SE_KERNEL_OBJECT,
    SE_WINDOW_OBJECT, SE_DS_OBJECT, SE_DS_OBJECT_ALL,
    SE_PROVIDER_DEFINED_OBJECT, SE_WMIGUID_OBJECT, SE_REGISTRY_WOW64_32KEY);

  PTokenUser = ^_TOKEN_USER;
  _TOKEN_USER = record
    User : TSidAndAttributes;
  end;

var fMain: TfMain;
    pi_prot   : TProcessInformation;
    pi_unprot : TProcessInformation;

const
  WinWorldSid  = 1;
  aclSize      = 1024;
  ACL_REVISION = 2;

function CreateWellKnownSid(WellKnownSidType: Cardinal; DomainSid, Sid: PSID;
  var cbSID: Cardinal): Bool; stdcall; external advapi32 name 'CreateWellKnownSid';

function SetSecurityInfo(handle: THandle; ObjectType: SE_OBJECT_TYPE;
  SecurityInfo: SECURITY_INFORMATION; psidOwner, psidGroup: PSID;
  pDacl, pSacl: PACL): DWORD; stdcall; external advapi32 name 'SetSecurityInfo';

implementation

{$R *.dfm}

procedure TfMain.btnRunProtectedProcessClick(Sender: TObject);
var
  si  : TStartupInfo;
  sa  : TSecurityAttributes;
  sd  : TSecurityDescriptor;
  dacl: PACL;
  SID : PSID;
  SIDLength: Cardinal;
begin
  // Інаціалізуємо дескриптор безпеки
  InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
  GetMem(dacl, aclSize);
  try
    // Інаціалізуємо список керування доступом (DACL)
    InitializeAcl(dacl^, aclSize, ACL_REVISION);
    SIDLength := 0;
    // Отримуємо ідентифікатор секретності (SID)
    CreateWellKnownSid(WinWorldSid, nil, nil, SIDLength);
    GetMem(SID, SIDLength);
    try
      CreateWellKnownSid(WinWorldSid, nil, SID, SIDLength);
      // Додаємо в DACL елемент, який дозволяє всім користувачам
      // будь-який вид доступу крім припинення процесу
      // (PROCESS_TERMINATE)
      AddAccessAllowedAce(dacl^, ACL_REVISION,
        PROCESS_ALL_ACCESS and not PROCESS_TERMINATE, SID);
      // Записуємо інформацію з дескриптора безпеки у DACL
      SetSecurityDescriptorDacl(@sd, true, dacl, false);
      // Створюємо процес
      sa.nLength := SizeOf(TSecurityAttributes);
      sa.lpSecurityDescriptor := @sd;
      sa.bInheritHandle := false;
      FillChar(si, SizeOf(TStartupInfo), 0);
      si.cb := SizeOf(TStartupInfo);
      CreateProcess('C:\WINDOWS\system32\notepad.exe', nil, @sa, nil, false, NORMAL_PRIORITY_CLASS,
        nil, nil, si, pi_prot);
      // Закриваємо непотрібні дескриптори
      CloseHandle(pi_prot.hThread);
      CloseHandle(pi_prot.hProcess);
    finally
      FreeMem(SID);
    end;
  finally
    FreeMem(dacl);
  end;
end;

procedure TfMain.btnTryTerminateProtectedProcessClick(Sender: TObject);
var hProcess : THandle;
begin
  hProcess := OpenProcess(PROCESS_TERMINATE, false, pi_prot.dwProcessId);
  if hProcess <> 0 then TerminateProcess(hProcess, 0) else
    MessageDlg('Неможливо завершити процес!', mtError, [mbCancel], 0);
end;

procedure TfMain.btnTerminateUnprotectedProcessClick(Sender: TObject);
var hProcess: THandle;
begin
  hProcess := OpenProcess(PROCESS_TERMINATE, false, pi_unprot.dwProcessId);
  if hProcess <> 0 then TerminateProcess(hProcess, 0);
end;

procedure TfMain.btnRunUnprotectedProcessClick(Sender: TObject);
var  si : TStartupInfo;
begin
  FillChar(SI, Sizeof(SI), #0);
  si.cb := SizeOf(TStartupInfo);
  CreateProcess('C:\WINDOWS\system32\notepad.exe', nil, nil, nil,
    false, NORMAL_PRIORITY_CLASS, nil, nil, si, pi_unprot);
  CloseHandle(pi_unprot.hThread);
  CloseHandle(pi_unprot.hProcess);
end;

procedure TfMain.btnSetProcessToUnprotectedStateClick(Sender: TObject);
var hProcess: THandle;
begin
  // При відкритті процесу запитуємо право доступу на зміну DACL
  hProcess := OpenProcess(WRITE_DAC, false, pi_prot.dwProcessId);
  if hProcess <> 0 then begin
    // Якщо процес відкрито, обнуляємо вказівник на DACL,
    // роблячи процес незахищеним
    SetSecurityInfo(hProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
      nil, nil, nil, nil);
    CloseHandle(hProcess);
  end;
end;

end.
