.NET Simulate Ctrl+Alt+Del Sendkeys
Asked Answered
S

6

9

all is said in the title, how can I simulate the combination Ctrl+Alt+DEL?

I tried this:

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

But none worked. I am working on VB.NET and Windows XP SP3

Smoot answered 18/2, 2011 at 22:43 Comment(5)
@mdmullinax: Technically, no. He's asking how to simulate the keys, not trap them.Bemean
Do you want to actually simulate the keys, or do you simply want to call up the standard security dialog? If the latter, then you can invoke the WindowsSecurity method on the shell dispatch object.Amphidiploid
No, I wanted to simulate the keys. But I already posted the solution, thanksSmoot
@Smoot What's the difference, if they both end up in the same place (and one is documented and the other isn't)?Amphidiploid
The difference is that I wanted to use this in a service at the logon screen, so that I could logon a certain user automatically (I know about the security issues, but they were not my concern in this case)Smoot
S
1

I finally found this C++ code on CodeProject, which works well when launched as System user. Therefore, I converted the code into a dll, and called the function from my code.

Here is the c++ code (you can use the ErrorExit example function that uses GetLastError from MSDN in case a problem occured):

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

You also need to add a .def file to the project to export the function correctly (the project is named AltCtrlDelCpp) and tell the linker that the definition file of the module is this file

;altctrldel.def
LIBRARY AltCtrlDelCpp

;CODE PRELOAD MOVEABLE DISCARDABLE
;DATA PRELOAD MOVEABLE

EXPORTS
   SimulateAltControlDel

Then, in the .NET solution, you add the dll to the project, configures it so that it is always copied in the output directory, and you just use DllImport to import the function:

C# Code

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

VB.NET Code

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

In VB.NET, you also need to add the attribute to the Sub Main :

<MTAThread()> _
Sub Main()

Then you just have to call the SimulateAltControlDel function and there you go. Please note that I had this work only for a Console Apps, it didn't work in winform apps.

Smoot answered 6/3, 2012 at 11:36 Comment(4)
The above code makes undocumented assumptions about how the Ctrl+Alt+Del hotkey is registered. (It also assumes that there is only one window on the secure desktop that registers a hotkey with ID zero.)Amphidiploid
Well it actually works only when running as System; if you use it as admin, it will not succeed. Please note also that this code is not from me (I posted the link to the page on codeproject) and I am not a C++ developper, so I can't tell if you are right or not :)Smoot
I'm just saying that the above method is not guaranteed to work in future versions of Windows. Just warning anybody who is thinking of using this in their product -- they need to let their customers know that the product is making undocumented assumptions about the system that may stop working in future versions of Windows.Amphidiploid
Ok, indeed this works until Windows XP, I really don't think it will work on Vista and Seven; with those OS you should take a look at SasLibEX for example, but it will not be freeSmoot
T
6

As of Windows Vista, you can use the SendSAS function.


Original answer, now superseded by the above

The function you need is called SimulateSAS. You need to e-mail [email protected] and ask for it. Microsoft don't appear to document this, but just do a websearch for SimulateSAS and you'll see what I mean.

Others have explained why it's actually not a security issue to allow apps to trigger CTRL+ALT+DEL, but you certainly can't do it with SendKeys.

Thulium answered 18/2, 2011 at 22:53 Comment(1)
Update: documented and now generally available as of the Windows 7 SDK, even for Vista.Attain
O
5

You can't. This is done at the device driver level, you can't fake input for the keyboard driver. Also the reason you cannot disable it. Allowing it to be faked would of course be a very serious security flaw.

Oona answered 18/2, 2011 at 22:52 Comment(10)
How does logmein or gotomypc do it?Bemean
@David: They do. It is a menu option.Anglophobe
@Robert Doesn't that contradict your answer? And am I going to have to eat my keyboard?!Thulium
You can send CTRL+ALT+DELETE to a remote computer through logmein if the computer is at the login screen, where it says Press CTRL+ALT+DELETE to login. There's an icon to process the key. I use it all the time.Bemean
@David: Yes, it does. I forgot about GotoMyPC.Anglophobe
You can do it whenever, TeamViewer is able to send Ctrl+Alt+Del when the machine is at the desktop, bringing up the "Lock this computer", "Switch user" etc. choices.Mcelrath
@David: Yes. It's fairly complicated. The keystrokes are translated to remote commands, which are then hooked into the remote computer's keyboard, mouse and display drivers. But of course, the user had to give permission to install GotoMyPC on his computer, and the company is trusted.Anglophobe
Faking it is not a security flaw, allowing it to be trapped would be the flaw.Masticate
@Mark: Not sure I understand the distinction.Anglophobe
@Robert If another app trapped it then they could show a fake logon dialog and steal your credentials. That, I guess, is the whole point of secure attention key.Thulium
A
4

Your best bet might be to download the TightVNC source code, and see how they do it.

Anglophobe answered 18/2, 2011 at 23:7 Comment(4)
You are desperate aren't you?!! ;-)Thulium
@David: Well, I don't know how to do it. I don't write device drivers for a living. Gimme some reps, dammit!Anglophobe
There you go, if Hans is having some, then why can't you?!!Thulium
VNC does it with SendSASFerri
M
3

See this thread for some information that seems useful:

Basically:

  • Your program must be signed
  • Your program must have a manifest specifying the privileges needed
  • Your program must be located in a protected folder (one that requires UAC for writing to, like the Program Files folder)
  • Your program can then use the following undocumented API to invoke it:

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

Note, I only distilled the web page I link to, I have no idea if it works, or if there are more gotchas.

Mcelrath answered 18/2, 2011 at 22:43 Comment(0)
S
2

As of Windows Vista, the SendSAS function is available.

Serge answered 16/11, 2015 at 0:21 Comment(0)
S
1

I finally found this C++ code on CodeProject, which works well when launched as System user. Therefore, I converted the code into a dll, and called the function from my code.

Here is the c++ code (you can use the ErrorExit example function that uses GetLastError from MSDN in case a problem occured):

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

You also need to add a .def file to the project to export the function correctly (the project is named AltCtrlDelCpp) and tell the linker that the definition file of the module is this file

;altctrldel.def
LIBRARY AltCtrlDelCpp

;CODE PRELOAD MOVEABLE DISCARDABLE
;DATA PRELOAD MOVEABLE

EXPORTS
   SimulateAltControlDel

Then, in the .NET solution, you add the dll to the project, configures it so that it is always copied in the output directory, and you just use DllImport to import the function:

C# Code

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

VB.NET Code

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

In VB.NET, you also need to add the attribute to the Sub Main :

<MTAThread()> _
Sub Main()

Then you just have to call the SimulateAltControlDel function and there you go. Please note that I had this work only for a Console Apps, it didn't work in winform apps.

Smoot answered 6/3, 2012 at 11:36 Comment(4)
The above code makes undocumented assumptions about how the Ctrl+Alt+Del hotkey is registered. (It also assumes that there is only one window on the secure desktop that registers a hotkey with ID zero.)Amphidiploid
Well it actually works only when running as System; if you use it as admin, it will not succeed. Please note also that this code is not from me (I posted the link to the page on codeproject) and I am not a C++ developper, so I can't tell if you are right or not :)Smoot
I'm just saying that the above method is not guaranteed to work in future versions of Windows. Just warning anybody who is thinking of using this in their product -- they need to let their customers know that the product is making undocumented assumptions about the system that may stop working in future versions of Windows.Amphidiploid
Ok, indeed this works until Windows XP, I really don't think it will work on Vista and Seven; with those OS you should take a look at SasLibEX for example, but it will not be freeSmoot

© 2022 - 2024 — McMap. All rights reserved.