.NET 模拟 Ctrl+Alt+Del 发送键

Posted

技术标签:

【中文标题】.NET 模拟 Ctrl+Alt+Del 发送键【英文标题】:.NET Simulate Ctrl+Alt+Del Sendkeys 【发布时间】:2011-06-30 03:51:02 【问题描述】:

标题都说了,怎么模拟Ctrl+Alt+DEL的组合?

我试过了:

SendKeys.Send("^(%(DEL))")
SendKeys.Send("^(%DEL)") 
SendKeys.Send("^%DEL")

但没有一个有效。我正在开发 VB.NET 和 Windows XP SP3

【问题讨论】:

@mdmullinax:从技术上讲,没有。他在问如何模拟按键,而不是困住它们。 您想实际模拟密钥,还是只是想调出标准安全对话框?如果是后者,那么您可以在 shell 调度对象上调用 the WindowsSecurity method。 不,我想模拟按键。但是我已经发布了解决方案,谢谢 @GianT971 如果它们最终都在同一个地方(一个有文档而另一个没有),有什么区别? 不同之处在于我想在登录屏幕的服务中使用它,以便我可以自动登录某个用户(我知道安全问题,但它们不是我关心的问题案例) 【参考方案1】:

从 Windows Vista 开始,您可以使用 SendSAS 函数。


原来的答案,现在被上面的取代了

你需要的函数叫做SimulateSAS。您需要发送电子邮件至 saslib@microsoft.com 并索取。 Microsoft 似乎没有记录这一点,但只需对 SimulateSAS 进行网络搜索,您就会明白我的意思。

其他人已经解释了为什么允许应用触发 CTRL+ALT+DEL 实际上不是安全问题,但你当然可以'不要使用SendKeys

【讨论】:

更新:documented 现在从 Windows 7 SDK 开始普遍可用,甚至适用于 Vista。【参考方案2】:

你不能。这是在设备驱动程序级别完成的,您不能伪造键盘驱动程序的输入。也是您无法禁用它的原因。允许它被伪造当然是一个非常严重的安全漏洞。

【讨论】:

logmein 或 gotomypc 是怎么做的? @David:确实如此。这是一个菜单选项。 @Robert 这与您的回答不矛盾吗?我要吃掉我的键盘吗?! @David:是的。这相当复杂。击键被翻译成远程命令,然后连接到远程计算机的键盘、鼠标和显示驱动程序。但是当然,用户必须授予在他的计算机上安装 GotoMyPC 的权限,并且该公司是受信任的。 @Robert 如果另一个应用程序捕获了它,那么他们可能会显示一个虚假的登录对话框并窃取您的凭据。我想这就是安全注意密钥的全部意义所在。【参考方案3】:

最好的办法是下载TightVNC source code, 看看他们是怎么做的。

【讨论】:

你是不是很绝望?!! ;-) @David:嗯,我不知道该怎么做。我不以编写设备驱动程序为生。给我一些代表,该死的! 你去吧,如果汉斯有一些,那你为什么不能呢?!! VNC 使用 SendSAS【参考方案4】:

请参阅此主题以获取一些似乎有用的信息:

Simulate Ctrl+Alt+Delete in VISTA

基本上:

您的程序必须签名 您的程序必须有一个清单来指定所需的权限 您的程序必须位于受保护的文件夹中(需要 UAC 才能写入的文件夹,例如 Program Files 文件夹)

然后您的程序可以使用以下未记录的 API 来调用它:

DWORD dwRet = lpfnWmsgSendMessage(dwSessionId,0x208, 0, (LPARAM)&lParam); //Undocument API.

注意,我只提炼了我链接到的网页,我不知道它是否有效,或者是否还有更多陷阱。

【讨论】:

【参考方案5】:

从 Windows Vista 开始,SendSAS 函数可用。

【讨论】:

【参考方案6】:

我终于在 CodeProject 上找到了this C++ code,它在以系统用户身份启动时运行良好。因此,我将代码转换为dll,并从我的代码中调用了该函数。

这是 c++ 代码(您可以使用 ErrorExit 示例函数,该函数使用 MSDN 中的 GetLastError 以防出现问题):

#include "windows.h"
#include <strsafe.h>

__declspec(dllexport) BOOL SimulateAltControlDel()

    HDESK   hdeskCurrent;
    HDESK   hdesk;
    HWINSTA hwinstaCurrent;
    HWINSTA hwinsta;

    // 
    // Save the current Window station
    // 
    hwinstaCurrent = GetProcessWindowStation();
    if (hwinstaCurrent == NULL)
        return FALSE;
    // 
    // Save the current desktop
    // 
    hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
    if (hdeskCurrent == NULL)
        return FALSE;
    // 
    // Obtain a handle to WinSta0 - service must be running
    // in the LocalSystem account
    // 
    hwinsta = OpenWindowStation("winsta0", FALSE,
                              WINSTA_ACCESSCLIPBOARD   |
                              WINSTA_ACCESSGLOBALATOMS |
                              WINSTA_CREATEDESKTOP     |
                              WINSTA_ENUMDESKTOPS      |
                              WINSTA_ENUMERATE         |
                              WINSTA_EXITWINDOWS       |
                              WINSTA_READATTRIBUTES    |
                              WINSTA_READSCREEN        |
                              WINSTA_WRITEATTRIBUTES);
    if (hwinsta == NULL)
        return FALSE;
    // 
    // Set the windowstation to be winsta0
    // 

    if (!SetProcessWindowStation(hwinsta))
     return FALSE;

    // 
    // Get the default desktop on winsta0
    // 
    hdesk = OpenDesktop("Winlogon", 0, FALSE,
                        DESKTOP_CREATEMENU |
              DESKTOP_CREATEWINDOW |
                        DESKTOP_ENUMERATE    |
                        DESKTOP_HOOKCONTROL  |
                        DESKTOP_JOURNALPLAYBACK |
                        DESKTOP_JOURNALRECORD |
                        DESKTOP_READOBJECTS |
                        DESKTOP_SWITCHDESKTOP |
                        DESKTOP_WRITEOBJECTS);
    if (hdesk == NULL)
       return FALSE;

    // 
    // Set the desktop to be "default"
    // 
    if (!SetThreadDesktop(hdesk))
       return FALSE;

    PostMessage(HWND_BROADCAST,WM_HOTKEY,0,MAKELPARAM(MOD_ALT|MOD_CONTROL,VK_DELETE));


    // 
    // Reset the Window station and desktop
    // 
    if (!SetProcessWindowStation(hwinstaCurrent))
       return FALSE;

    if (!SetThreadDesktop(hdeskCurrent))
    return FALSE;

    // 
    // Close the windowstation and desktop handles
    // 
    if (!CloseWindowStation(hwinsta))
        return FALSE;
    if (!CloseDesktop(hdesk))
        return FALSE;
    return TRUE;

还需要在工程中添加.def文件才能正确导出函数(工程名为AltCtrlDelCpp)并告诉链接器模块的定义文件就是这个文件

;altctrldel.def
LIBRARY AltCtrlDelCpp

;CODE PRELOAD MOVEABLE DISCARDABLE
;DATA PRELOAD MOVEABLE

EXPORTS
   SimulateAltControlDel

然后,在 .NET 解决方案中,将 dll 添加到项目中,对其进行配置,使其始终复制到输出目录中,然后使用 DllImport 导入函数:

C#代码

[DllImport(@"AltCtrlDelCpp.dll")]
static extern bool SimulateAltControlDel();

VB.NET 代码

<DllImport("AltCtrlDelCpp.dll")> _
Private Function SimulateAltControlDel() As Boolean

在 VB.NET 中,您还需要将属性添加到 Sub Main :

<MTAThread()> _
Sub Main()

然后你只需要调用SimulateAltControlDel 函数就可以了。请注意,我只为 控制台应用程序 使用了这项功能,它不适用于 winform 应用程序。

【讨论】:

以上代码对 Ctrl+Alt+Del 热键的注册方式做出了未记录的假设。 (它还假设安全桌面上只有一个窗口注册了 ID 为 0 的热键。) 它实际上只在作为系统运行时才有效;如果您以管理员身份使用它,它将不会成功。另请注意,此代码不是来自我(我在 codeproject 上发布了该页面的链接)而且我不是 C++ 开发人员,所以我无法判断您是否正确:) 我只是说上述方法不能保证在未来的Windows版本中有效。只是警告任何想在他们的产品中使用它的人 - 他们需要让他们的客户知道该产品正在对系统做出未记录的假设,这些假设可能会在未来的 Windows 版本中停止工作。 好吧,这确实适用于 Windows XP,我真的不认为它适用于 Vista 和 7;对于那些操作系统,你应该看看 SasLibEX,但它不是免费的

以上是关于.NET 模拟 Ctrl+Alt+Del 发送键的主要内容,如果未能解决你的问题,请参考以下文章

centos关闭ctrl+alt+del重启

centos7 取消Ctrl+Alt+Del重启功能

DirectX - 按 ctrl + alt + del 时出错

远程线程注入技术 屏蔽ctrl+alt+del

linux系统初始化--​关闭Ctrl+Alt+Del自动重启的操作关联

如何使用 SetWindowsHookEx api 锁定 CTRL+ALT+DEL?