拒绝访问Kiosk程序流程

时间:2011-03-21 15:41:56

标签: c# c++ windows kiosk win32-process

我有一个自助服务终端应用,必须禁用任务管理器,以防止用户关闭程序。  
但是有些用户需要TaskManager来关闭挂起程序。

任何帮助都会被挪用。

但是,我确信在Windows中有一个函数可以防止关闭程序的进程,就像一次尝试杀死 rundll.exe 进程一样。如果我可以使用DllImport

调用它,我想知道该函数

任何人都可以帮忙解决问题吗?
一个黑客?
一个功能?
任何其他解决方案?

修改

至少如果没有办法阻止进程被关闭,我需要一种方法将其隐藏在任务管理器中出现的进程列表中。

编辑2: 到目前为止我找不到解决方案

7 个答案:

答案 0 :(得分:6)

如果您可以在管理上下文中访问进程ID,则一种方法是拒绝对最终用户的进程的PROCESS_TERMINATE权限。默认情况下,终止进程(通过任务管理器或其他上下文)授予所有者,但可以明确拒绝。拒绝时,终止进程将要求所有者手动更改ACL,然后终止进程。如果用户既不是管理员也不是流程的所有者,他将无法强行终止该流程(例如,通过任务管理器),尽管该流程将被允许正常退出。

以下代码为Everyone组成员的PID processid进程显式拒绝ACE。

#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;
}

答案 1 :(得分:5)

您可以创建在启动时运行的服务。然后monitors when the user logs进入并启动您的程序。从那里你有两个选择:

  1. 让用户等待该程序,并在用户的会话持续存在的情况下恢复该程序。
  2. 在管理员帐户下运行它,并确保用户始终在受限帐户上运行。 Windows的权限执行应该照顾您的程序而不会死亡。
  3. 如果您必须允许用户拥有管理权限(并因此可以终止您的服务),请务必注册您的服务以便SCM restarts it automatically

    除此之外的任何事情都需要一些内核黑客攻击,正如mdm所说,或潜入rootkit领域。我建议你避免使用。

    如果您仍然运行Windows XP而不是系统服务,则可以注册Winlogon notification package。它们基本上是不可杀戮的,因为它们在winlogon.exe的环境中运行,这就是它们从Vista及以上版本removed的原因。

答案 2 :(得分:5)

这样做的正确方法是:

为Kiosk应用程序创建用户。让我们说KioskUser 创建在计算机中执行操作的其他用户。让我们说User1 他们中的任何人都不应该是管理员。他们不需要是管理员吗?他们当然可以享有特权。

您将像往常一样使用User1帐户。 然后,您将Kiosk应用程序作为KioskUser运行。 (使用runas命令) - 将应用程序添加到会话中并使其可见(有关此更多信息,请参阅参数)

当User1进入并且Kiosk应用程序从KioskUser运行时,User1无法终止该进程。

我不建议“黑客”系统,也不建议改变注册表上的内容。 此外,您可以将Kiosk应用程序设为服务,并在Kiosk用户下运行。

答案 3 :(得分:2)

听起来你不能阻止一个进程被杀 - 请参阅this question,特别是link posted to an explanation

但是,您可以阻止用户从任务栏打开任务管理器(右键单击 - >打开任务管理器),按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

您还需要找到一种方法来防止用户在注册表中写入此密钥 - 尽管在我的Windows 7 64位计算机上,我必须先打开管理命令提示符才能更改密钥。< / p>

修改

根据评论中的建议,您可以拦截低级系统调用以更改报告的进程列表。 This answer躲过它,你基本上必须编写一个内核模式rootkit - 可能是作为设备驱动程序实现的。由于在Vista及更高版本中进行内核更改,这可能仅适用于Windows XP及更低版本。然而,可以这样做,我的一个朋友为他的BSc最后一年论文创建了这个原型。

您还必须考虑其他查询流程的方法 - IIRC NtQuerySystemInformation并不是枚举流程的唯一方法。

答案 4 :(得分:1)

使用某些rootkit /驱动程序保护您的Kiosk应用程序是不可能的......虽然您在此上下文中需要使用的方法是“类似恶意软件”,但要注意......

这里http://blogs.msdn.com/b/oldnewthing/archive/2004/02/16/73780.aspx你可以在一方面看到为什么这是一项不太可能的任务,另一方面你需要防范的几种可能性......这将是:

拒绝PROCESS_TERMINATE
拒绝PROCESS_CREATE_THREAD
拒绝PROCESS_VM_WRITE
拒绝PROCESS_SUSPEND_RESUME
再加上任何防御措施,你都可以对抗调试器 - 另一个非常棘手的业务。

答案 5 :(得分:1)

很抱歉不发布此评论(声誉不足)。 我正在使用drfs解决方案,但它似乎通过使用GetSecurityInfo的方式导致内存泄漏。我改变了代码并摆脱了这样的内存泄漏:

声明:

console

初​​始化:

PSECURITY_DESCRIPTOR desc = NULL;

清理:

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

呼叫:

if (desc) GlobalFree(desc);

我还在这个问题上发现了这篇文章:http://i1.blogs.msdn.com/b/oldnewthing/archive/2012/12/12/10376639.aspx

答案 6 :(得分:0)

虽然您无法阻止授权用户终止您的进程,但您可以阻止用户拥有杀死进程所需的权限。也就是说,本地管理员将始终拥有杀死任何进程的权限。您希望阻止任何用户或非管理员关闭您的应用程序吗?如果是前者,只需在专用用户帐户下运行该流程就足以完成这一操作。