Запретить доступ к программному процессу Kiosk
У меня есть приложение киоск и отключить диспетчер задач всегда предотвратить закрытие программы пользователи .
но некоторым пользователям нужен TaskManager для закрытия зависающих программ.
любая помощь будет присвоено.
Тем не менее , я уверен, что в windows есть функция для предотвращения закрытия процесса программы, как при попытке убить программы rundll.exe
7 ответов
один из подходов, если вы можете получить доступ к идентификатору процесса в административном контексте, - это запретить разрешение PROCESS_TERMINATE на процесс конечным пользователям. Завершение процесса (через Диспетчер задач или другие контексты) по умолчанию предоставляется владельцу, но может быть явно отклонено. Когда это отклонено, завершение процесса потребует от владельца вручную изменить ACL, а затем завершить процесс. Если пользователь не является ни администратором, ни владельцем процесса, он не сможет принудительно завершить процесс (например, через Диспетчер задач), хотя процессу будет разрешено выйти нормально.
следующий код помещает явный Ace deny в процесс с PID processid
для членов группы Everyone.
#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;
}
вы можете создать службу, которая работает при загрузке. Тогда мониторы, когда пользователь регистрирует in и запускает вашу программу. Оттуда у вас есть два варианта:
- пусть он подождет в программе и оживит ее до тех пор, пока сеанс пользователя не исчезнет.
- запустите его под учетной записью администратора и убедитесь, что пользователи всегда работают с ограниченными учетными записями. Применение привилегий Windows должно заботиться о вашей программе, а не умирающий.
Если вы должны разрешить пользователям административные привилегии (и они могут, таким образом, убить вашу службу), убедитесь, что зарегистрировать службу так, чтобы SCM перезагрузки он автоматически.
все, что выходит за рамки этого, потребует взлома ядра, как сказал mdm, или погружения на территорию руткитов. Чего я бы посоветовал вам избегать.
Если вы все еще используете Windows XP, вместо системной службы, вы можете зарегистрировать пакет уведомлений Winlogon. Они в основном неубиваемые, поскольку они работают в контексте winlogon.exe, по этой причине они были удалены из Vista и выше.
правильный способ сделать это:
создайте пользователя для приложения киоска. Скажем, KioskUser Создайте других пользователей, которые делают что-то на компьютере. Допустим Пользователь1 Никто из них не должен быть администратором. Они не должны быть администраторами правильно? Конечно, у них могут быть привилегии.
вы собираетесь использовать учетную запись user1 как обычно. Затем запустите приложение киоска как KioskUser. (используйте команду runas для ) - добавьте приложение в сеанс и сделайте его видимым (см. аргументы для получения дополнительной информации об этом)
пока Пользователь1 входит в систему и приложение киоска работает от KioskUser, Пользователь1 не может убить процесс.
Я бы не рекомендовал "взламывать" систему или что-то менять в реестре. Кроме того, вы можете сделать приложение киоска сервисом и запустить его под пользователем киоска.
похоже, вы не можете предотвратить процесс от убийства-см. этот вопрос и в частности ссылка размещена на объяснение.
однако вы можете запретить пользователю открывать диспетчер задач на панели задач (щелкните правой кнопкой мыши -> открыть Диспетчер задач), нажимать 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
и вы можете renable с этой командой:
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System /v DisableTaskMgr /t REG_DWORD /d 0 /f
Вам также нужно найти способ предотвратить запись пользователя в этот раздел реестра - хотя на моей 64-разрядной машине Windows 7 мне пришлось открыть командную строку администратора, прежде чем я мог изменить ключ.
редактировать
как предложено в комментариях, вы можете перехватить низкий системный вызов уровня для изменения списка сообщаемых процессов. ответ ускользает от него, вам в основном придется написать руткит в режиме ядра-вероятно, реализованный как драйвер устройства. Вероятно, это будет работать только в Windows XP и ниже из-за изменений ядра, сделанных в Vista и далее. Это можно сделать, однако, мой друг создал прототип этого для своей диссертации последнего года BSc.
Вам также придется рассмотреть другие методы запроса процессов - IIRC NtQuerySystemInformation
это не единственный способ перечисления процессов.
не хватает защиты вашего киоска приложения с некоторым руткитом / драйвером, который вы не можете... хотя методы, которые вам нужно будет использовать в этом контексте, являются "вредоносными", поэтому будьте осторожны...
здесь http://blogs.msdn.com/b/oldnewthing/archive/2004/02/16/73780.aspx Вы можете видеть, с одной стороны, почему это задача на самом деле невозможно, а с другой стороны, несколько возможностей, которые вы должны были бы защитить... а именно:
запретить PROCESS_TERMINATE
отрицать PROCESS_CREATE_THREAD
запретить PROCESS_VM_WRITE
запретить PROCESS_SUSPEND_RESUME
Плюс любая защита, которую вы можете получить от отладчиков-еще один очень сложный бизнес.
Извините, что не разместил это в качестве комментария (недостаточно репутации). Я использую решение 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
хотя вы не можете запретить авторизованному пользователю убивать ваш процесс, вы можете запретить пользователям иметь необходимые разрешения для убийства вашего процесса. Тем не менее, у локального администратора всегда будет разрешение убить любой процесс. Ваша надежда предотвратить закрытие вашего приложения любым пользователем или просто не администраторами? Если первый, просто запуск процесса под выделенной учетной записью пользователя может быть достаточно, чтобы сделать трюк.