6

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

任何帮助都会被挪用。

但是,我确信 Windows 中有一个功能可以防止关闭程序的进程,就像试图杀死rundll.exe进程一样。如果我可以用它调用它,我想知道该函数DllImport

任何人都可以帮忙吗?
黑客?
一个函数?
还有其他解决方案吗?

编辑:

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

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

4

7 回答 7

6

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

下面的代码将显式拒绝 ACE 放置在processid每个人组成员的具有 PID 的进程上。

#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;
}
于 2011-07-24T18:47:59.737 回答
5

您可以创建一个在启动时运行的服务。然后它会监视用户何时登录并启动您的程序。从那里你有两个选择:

  1. 只要用户的会话持续存在,让它等待程序并恢复它。
  2. 在管理员帐户下运行它,并确保用户始终在受限帐户上运行。Windows 的特权实施应该注意您的程序不会死机。

如果您必须允许用户管理权限(因此他们可以杀死您的服务),请确保注册您的服务,以便 SCM自动重新启动它

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

如果您仍然在运行 Windows XP,而不是系统服务,您可以注册一个Winlogon 通知包。它们基本上是无法杀死的,因为它们在 winlogon.exe 的上下文中运行,这就是它们从 Vista 及更高版本中删除的原因。

于 2011-07-23T09:40:12.033 回答
5

这样做的正确方法是:

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

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

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

我不建议“破解”系统,也不建议更改注册表中的某些内容。此外,您可以将 Kiosk 应用程序设为服务,并在 Kiosk 用户下运行它。

于 2011-07-23T18:51:33.540 回答
2

听起来您无法阻止进程被杀死 - 请参阅此问题,特别是发布到说明的链接

但是,您可以阻止用户从任务栏打开任务管理器(右键单击 -> 打开任务管理器)、按 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 位计算机上,我必须先打开一个管理员命令提示符才能更改密钥。

编辑

正如评论中所建议的,您可以拦截低级系统调用以更改报告的进程列表。这个答案没有解决,您基本上必须编写一个内核模式 rootkit - 可能作为设备驱动程序实现。由于在 Vista 及更高版本中进行了内核更改,这可能仅适用于 Windows XP 及更低版本。但是可以做到,我的一个朋友为他的 BSc 毕业论文创建了一个原型。

您还必须考虑查询流程的其他方法 - IIRCNtQuerySystemInformation不是可以枚举流程的唯一方法。

于 2011-07-20T08:06:46.057 回答
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
加上任何您可以针对调试器进行的防御 - 另一个非常棘手的事情。

于 2011-07-24T22:56:52.767 回答
1

很抱歉没有将此作为评论发布(没有足够的声誉)。我正在使用 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

于 2016-05-25T11:02:24.207 回答
0

虽然您无法阻止授权用户终止您的进程,但您可以阻止用户拥有必要的权限来终止您的进程。也就是说,本地管理员将始终有权终止任何进程。您是否希望防止任何用户或非管理员关闭您的应用程序?如果是前者,只需在专用用户帐户下运行该进程就足够了。

于 2011-07-25T14:18:43.430 回答