拒绝访问 Kiosk 程序进程

发布于 2024-10-24 07:22:54 字数 427 浏览 10 评论 0原文

我有一个信息亭应用程序,必须始终禁用任务管理器,以防止用户关闭程序
但有些用户需要任务管理器来关闭挂起的程序。

任何帮助都将被适当。

但是,我确信 Windows 中有一种功能可以防止关闭程序的进程,例如当尝试终止 rundll.exe 进程时。我想知道该函数是否可以使用 DllImport 调用它

任何人都可以帮忙解决一个技巧吗?
黑客攻击?
一个函数?
还有其他解决办法吗?

编辑:

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

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

I have a kiosk app and have to disable task manager always to prevent closing the program by users .

But some users need the TaskManager to close hanging programs.

Any help would be appropriated.

However, I am sure there is a function in windows to prevent closing a program's process , as when one attempt to kill rundll.exe process. I want to know that function if I can call it with DllImport

Can anyone help with a trick?

A hack?

A function?

Any other solution?

EDIT:

At least if there is not a way to prevent the process from being closed, I need a way to hide it from processes list appeared in the task manager.

EDIT 2:
I can't find the solution so far

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

櫻之舞 2024-10-31 07:22:54

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

以下代码对具有 PID processid 的进程显式拒绝 ACE,适用于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;
}

One approach, if you could access the process ID in an administrative context, is to deny the PROCESS_TERMINATE permission on the process to end users. Terminating the process (through task manager or other contexts) is by default granted to the owner, but can be explicitly denied. When it is denied, terminating the process would require the owner to manually change the ACL, and then terminate the process. If the user is neither an administrator nor the owner of the process, he will not be able to forcibly terminate the process (e.g., through Task Manager), although the process will be allowed to exit normally.

The following code puts an explicit deny ACE on the process with the PID processid for members of the Everyone group.

#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;
}
锦爱 2024-10-31 07:22:54

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

  1. 让它等待程序并在用户会话持续时恢复它。
  2. 在管理员帐户下运行它,并确保用户始终在有限的帐户上运行。 Windows 的权限执行应该保证您的程序不死。

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

正如 mdm 所说,任何超出这个范围的事情都需要一些内核黑客攻击,或者深入 rootkit 领域。我建议你避免这样做。

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

You could create a service that runs on boot. It then monitors when the user logs in and starts your program. From there you have two choices:

  1. Have it wait on the program and revive it for as long as the user's session persists.
  2. Run it under an administrator account and make sure the users are always running on limited accounts. Windows' privilege enforcement should take care of your program not dying.

If you must allow the users administrative privileges (and they can thus kill your service), make sure to register your service so that the SCM restarts it automatically.

Anything beyond that would require some kernel hacking, as mdm said, or diving into rootkit territory. Which I would suggest you avoid.

If by any chance you're still running Windows XP, instead of a system service, you can register a Winlogon notification package. They're basically unkillable, as they run in the context of winlogon.exe, which is the reason they were removed from Vista and above.

调妓 2024-10-31 07:22:54

执行此操作的正确方法是:

为 Kiosk 应用程序创建用户。可以说 KioskUser
创建在计算机中执行操作的其他用户。假设用户1
他们都不应该是管理员。他们不需要成为管理员,对吧?他们当然可以拥有特权。

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

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

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

The proper way of doing this is:

Create a user for the Kiosk application. Lets say KioskUser
Create other users that do stuff in the computer. Lets say User1
NONE of them should be administrator. They do not need to be admins right? They can have privileges of course.

You are going to use User1 account as usual.
Then, you run the Kiosk application as the KioskUser. (use runas command)
- add the application to the session and make it visible (see the arguments for more info on this)

While the User1 is loged in and the Kiosk application runs from the KioskUser, the User1 cannot kill the process.

I wouldn't recommend "hacking" the system, nor changing something on the registry.
Also, you can make the Kiosk application a service, and run it under the Kiosk user.

南城旧梦 2024-10-31 07:22:54

听起来你无法阻止进程被杀死 - 请参阅这个问题 特别是发布到解释的链接

但是,您可以阻止用户从任务栏打开任务管理器(右键单击 -> 打开任务管理器)、按 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 及更低版本。然而这是可以做到的,我的一个朋友为他的理学学士最后一年的论文创建了一个原型。

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

It sounds like you can't prevent a process from being killed - see this question and specifically the link posted to an explanation.

You can however prevent the user from opening the task manager from the taskbar (right click -> open task manager), from pressing Ctrl-Shift-Esc, or from typing taskman at the command prompt using the following registry key:

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

Setting it to 1 disables the task manager, 0 enables it again.

From the command prompt, disable it like so:

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

And you can renable with this command:

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

You'll also need to find a way of preventing the user from writing to this key in the registry - although on my Windows 7 64-bit machine I had to open an admin command prompt before I could change the key.

Edit

As suggested in the comments, you could intercept a low level system call to alter the list of processes reported. This answer eludes to it, you will basically have to write a kernel-mode rootkit - probably implemented as a device driver. This will likely only work in Windows XP and below due to kernel changes made in Vista and onwards. It can be done however, a friend of mine created a prototype of this for his BSc final year dissertation.

You'll also have to consider other methods of querying for processes - IIRC NtQuerySystemInformation isn't the only way that processes can be enumerated.

说不完的你爱 2024-10-31 07:22:54

如果没有使用一些 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
再加上您可以针对调试器进行的任何防御 - 另一个非常棘手的事情。

Short of protecting your Kiosk app with some rootkit/driver you can't... although the methods you would need to use in this context are "malware-like" so beware...

Here http://blogs.msdn.com/b/oldnewthing/archive/2004/02/16/73780.aspx you can see on one side why this is a task not really possible and on the other side the several possibilities you would have to defend against... which would be:

deny PROCESS_TERMINATE
deny PROCESS_CREATE_THREAD
deny PROCESS_VM_WRITE
deny PROCESS_SUSPEND_RESUME
Plus any defense you can get your hands on against debuggers - another very tricky business.

做个少女永远怀春 2024-10-31 07:22:54

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

Sorry for not posting this as a comment (not enough reputation).
I'm using drfs solution, but it seems to induce a memory leak with the way GetSecurityInfo is used. I changed the code and got rid of the memory leak like this:

Declaration:

PSECURITY_DESCRIPTOR desc = NULL;

Initialisation:

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

Cleanup:

if (desc) GlobalFree(desc);

Call:

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

I also found this article on the issue: http://i1.blogs.msdn.com/b/oldnewthing/archive/2012/12/12/10376639.aspx

咆哮 2024-10-31 07:22:54

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

While you can't prevent an authorized user from killing your process, you can prevent users from having the necessary permissions to kill your process. That said, a local administrator will always have permission to kill any process. Is your hope to prevent closing of your application by any user or just non-admins? If the former, simply running the process under a dedicated user account may be enough to do the trick.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文