Запретить доступ к программному процессу киоска - PullRequest
6 голосов
/ 21 марта 2011

У меня есть приложение для киоска, и мне нужно отключить диспетчер задач , чтобы пользователи не могли закрыть программу .
Но некоторым пользователям нужен TaskManager для закрытия зависших программ.

Любая помощь будет присвоена.

Однако я уверен, что в окнах есть функция, предотвращающая закрытие процесса программы, как, например, при попытке уничтожить процесс rundll.exe .Я хочу знать эту функцию, если я могу вызвать ее с помощью DllImport

Может кто-нибудь помочь с трюком?
Взломать?
Функция?
Любое другое решение?

РЕДАКТИРОВАТЬ:

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

РЕДАКТИРОВАТЬ 2: Я пока не могу найти решение

Ответы [ 7 ]

6 голосов
/ 24 июля 2011

Один из подходов, если вы можете получить доступ к идентификатору процесса в административном контексте, - это запретить разрешение PROCESS_TERMINATE на процесс для конечных пользователей.Завершение процесса (с помощью диспетчера задач или других контекстов) по умолчанию предоставляется владельцу, но может быть явно отклонено.Когда отказано, завершение процесса потребует, чтобы владелец вручную изменил ACL, а затем завершил процесс.Если пользователь не является ни администратором, ни владельцем процесса, он не сможет принудительно завершить процесс (например, через диспетчер задач), хотя процессу будет разрешено нормально завершиться.

СледующееВ коде явно запрещен ACE для процесса с PID processid для членов группы «Все».

#include "Aclapi.h"
#include "Sddl.h"
DWORD RestrictTerminateOnProcessId(DWORD processid)
{
    PACL dacl = NULL, newdacl = NULL;
    HANDLE ph = NULL;
    PSECURITY_DESCRIPTOR* desc = NULL;
    PSID everyonesid = NULL;
    ph = OpenProcess(WRITE_DAC | READ_CONTROL, false, processid);
    if (!ph) goto cleanup;

    if (ERROR_SUCCESS != GetSecurityInfo(ph,
            SE_KERNEL_OBJECT,
            DACL_SECURITY_INFORMATION,
            NULL,
            NULL,
            &dacl,
            NULL,
            desc)) goto cleanup;

    SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
    if (!AllocateAndInitializeSid(
            &WorldAuth,1,SECURITY_WORLD_RID,
            0,0,0,0,0,0,0,&everyonesid)) goto cleanup;

    // begin copy dacl
    _ACL_SIZE_INFORMATION si;
    GetAclInformation(dacl,
            &si,
            sizeof(si),
            AclSizeInformation);

    DWORD dwNewAclSize = si.AclBytesInUse +
            (2*sizeof(ACCESS_DENIED_ACE)) + (2*GetLengthSid(everyonesid)) -
            (2*sizeof(DWORD));

    newdacl = (PACL)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            dwNewAclSize);

    if (newdacl == NULL) goto cleanup;

    if (!InitializeAcl(newdacl, dwNewAclSize, ACL_REVISION_DS))
            goto cleanup;

    if (!AddAccessDeniedAce(newdacl,
            ACL_REVISION_DS,
            PROCESS_TERMINATE,
            everyonesid)) goto cleanup;

    for (int i = 0; i < si.AceCount; i++)
    {
            LPVOID pace = NULL;
            if (!GetAce(dacl, i, &pace)) goto cleanup;
            if (!AddAce(newdacl, ACL_REVISION_DS,
                    MAXDWORD, pace, ((PACE_HEADER)pace)->AceSize))
                    goto cleanup;
    }

    // end copy dacl

    if (!SetSecurityInfo(ph,
            SE_KERNEL_OBJECT,
            DACL_SECURITY_INFORMATION,
            NULL,
            NULL,
            newdacl,
            NULL)) goto cleanup;
     SetLastError(0);

cleanup:
    DWORD ret = GetLastError();
    if (desc) LocalFree(desc);
    if (newdacl) HeapFree(GetProcessHeap(), 0, (LPVOID)newdacl);
    if (ph) CloseHandle(ph);
    if (everyonesid) FreeSid(everyonesid);
    return !ret;
}
5 голосов
/ 23 июля 2011

Правильный способ сделать это:

Создайте пользователя для приложения Kiosk. Допустим, KioskUser Создайте других пользователей, которые делают вещи на компьютере. Скажем User1 Никто из них не должен быть администратором. Они не должны быть админами, верно? Конечно, они могут иметь привилегии.

Вы собираетесь использовать учетную запись User1 как обычно. Затем вы запускаете приложение Kiosk как KioskUser. (используйте команду runas) - добавить приложение в сеанс и сделать его видимым (см. аргументы для получения дополнительной информации по этому вопросу)

Пока пользователь User1 вошел в систему и приложение Kiosk запускается из KioskUser, пользователь User1 не может завершить процесс.

Я бы не советовал «взламывать» систему и не вносить изменения в реестр. Кроме того, вы можете сделать приложение Kiosk сервисом и запускать его под пользователем Kiosk.

5 голосов
/ 23 июля 2011

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

  1. Дайте ему подождать, пока программа продолжит сеанс пользователя.
  2. Запустите его под учетной записью администратора и убедитесь, что пользователи всегда работают с ограниченными учетными записями. Обеспечение привилегий Windows должно заботиться о том, чтобы ваша программа не умирала.

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

Все, что находится за этим, потребует некоторого взлома ядра, как сказал mdm, или погружения на территорию руткитов. Которого я бы посоветовал вам избежать.

Если по какой-либо причине вы все еще используете Windows XP вместо системной службы, вы можете зарегистрировать пакет уведомлений Winlogon . Они в основном неубиваемы, поскольку работают в контексте winlogon.exe, по этой причине они были удалены из Vista и выше.

2 голосов
/ 20 июля 2011

Звучит так, как будто вы не можете предотвратить прекращение процесса - см. этот вопрос и, в частности, ссылку , опубликованную для объяснения .

Однако вы можете запретить пользователю открывать диспетчер задач на панели задач (щелкните правой кнопкой мыши -> открыть диспетчер задач), нажимать Ctrl-Shift-Esc или вводить taskman в командной строке, используя следующий ключ реестра. :

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableTaskMgr 

При значении 1 отключается диспетчер задач, при 0 - снова.

В командной строке отключите его следующим образом:

reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System /v DisableTaskMgr /t REG_DWORD /d 1 /f

И вы можете взять напрокат с помощью этой команды:

reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System /v DisableTaskMgr /t REG_DWORD /d 0 /f

Вам также нужно будет найти способ запретить пользователю записывать этот ключ в реестре - хотя на моем 64-разрядном компьютере под управлением Windows 7 мне пришлось открыть командную строку администратора, прежде чем я мог изменить ключ.

Редактировать

Как предлагается в комментариях, вы можете перехватить системный вызов низкого уровня, чтобы изменить список процессов, о которых сообщается. Этот ответ ускользает от него, вам, в основном, придется написать руткит в режиме ядра - возможно, реализованный как драйвер устройства. Это, вероятно, будет работать только в Windows XP и ниже из-за изменений в ядре, сделанных в Vista и более поздних версиях. Это может быть сделано, однако, мой друг создал прототип этого для его диссертации бакалавра на последнем курсе.

Вам также нужно будет рассмотреть другие методы запросов к процессам - IIRC NtQuerySystemInformation - не единственный способ перечисления процессов.

1 голос
/ 25 мая 2016

Извините, что не опубликовал это как комментарий (недостаточно репутации).Я использую решение drfs, но оно вызывает утечку памяти при использовании метода GetSecurityInfo.Я изменил код и избавился от утечки памяти следующим образом:

Объявление:

PSECURITY_DESCRIPTOR desc = NULL;

Инициализация:

desc = (PSECURITY_DESCRIPTOR)GlobalAlloc(GMEM_FIXED,  sizeof(PSECURITY_DESCRIPTOR));

Очистка:

if (desc) GlobalFree(desc);

Звоните:

GetSecurityInfo(ph, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &dacl, NULL, &desc)

Я также нашел эту статью по этому вопросу: http://i1.blogs.msdn.com/b/oldnewthing/archive/2012/12/12/10376639.aspx

1 голос
/ 25 июля 2011

За исключением защиты вашего приложения Kiosk с помощью руткита / драйвера, который вы не можете ... хотя методы, которые вам необходимо использовать в этом контексте, "вредоносны", так что будьте осторожны ...

Здесь http://blogs.msdn.com/b/oldnewthing/archive/2004/02/16/73780.aspx вы можете видеть, с одной стороны, почему эта задача на самом деле невыполнима, а с другой стороны - несколько возможностей, от которых вам придется защищаться ... которые будут:

отказать в PROCESS_TERMINATE
отказать в PROCESS_CREATE_THREAD
отказать в PROCESS_VM_WRITE
отказать в PROCESS_SUSPEND_RESUME
Плюс любая защита, которую вы можете получить от отладчиков - еще один очень сложный бизнес.

0 голосов
/ 25 июля 2011

Хотя вы не можете запретить авторизованному пользователю уничтожать ваш процесс, вы можете запретить пользователям иметь необходимые разрешения для уничтожения вашего процесса. Тем не менее, местный администратор всегда будет иметь разрешение убить любой процесс Вы надеетесь предотвратить закрытие вашего приложения кем-либо из пользователей или просто не администраторами? В первом случае достаточно просто запустить процесс под выделенной учетной записью пользователя.

...