Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I run my application while a UAC dialog window is showing?

I have an application that I wrote in .NET. It needs to remain running and have access the desktop that the UAC dialog windows open on and interact with that desktop using keyboard and mouse events.

It's sort of like a VNC program. Imagine you are running a VNC program and a UAC window pops up, you want your VNC program to still be able to control the desktop with the UAC window in it so that the user can move the mouse and click the OK button on the UAC dialog. Can anyone tell me how I would go about doing that?

Thanks

like image 591
Ray Avatar asked May 12 '10 18:05

Ray


People also ask

What action triggers a UAC warning?

There are many types of activities that may trigger a UAC prompt: Running a desktop application as an administrator. Making changes to settings and files in the Windows and Program Files folders. Installing or removing drivers and desktop applications.

How do I run UAC as administrator?

Open the Windows Control Panel. Click Administrative Tools > Local Security Policy > Security Settings > Local Policies > Security Options. Double-click Accounts: Administrator account status and select enable.

What is a UAC dialog?

UAC, User Account Control, Windows. The UAC prompt displays the name of the program that is about to make a system change that requires the approval of an administrator, the publisher of that program and the file origin (if you are trying to run a file).

What is the benefit of using UAC?

UAC provides the following benefits: It reduces the number of programs that run with elevated privileges, therefore helping to prevent users from accidentally changing their system settings, and helping to prevent "malware" from gaining system-wide access.


1 Answers

I would suggest you start by reading the documentation. I would guess that maybe you could open the window station and attach your process to it, but I am not very familiar with this area of Windows.

Edit 1:

In Windows XP I was able to access the secure desktop ("winlogon") via OpenDesktop when running as SYSTEM; the ACL on the secure desktop allows access only to the SYSTEM account. After opening it I could enumerate the windows on it, though there were only a handful. Perhaps you could set a window hook and listen for creation of the specific dialog. I'm not sure if Vista changed this model, so maybe it won't work; I don't have a Vista machine in front of me to test against.

Edit 2:

Ok, I got something that mostly works (tested on Windows 7). First you have to have a service running as SYSTEM. From that service, you need to launch a separate application in the user's session. To do this, enumerate all the processes looking for winlogon.exe, open its token, and CreateProcessAsUser. Specify "WinSta0\Winlogon" for the lpDesktop parameter of STARTUPINFO. Now you have a process running as SYSTEM in the user's session on the "Winlogon" desktop. In the new process you can do whatever you want; I did a quick test with EnumDesktopWindows and I was able to get the window class and text for various UAC related windows ("$$$Secure UAP Background Window", "$$$Secure UAP Background Fake Client Window", etc). I'm not sure how to determine when a UAC prompt is being displayed, though; as a quick hack you could just run a loop every 100 ms looking for UAC windows or something. I could paste some code if it would help.

Edit 3:

Ok. I have written a Win32 service that takes the following parameters:

/install - installs the service
/uninstall - uninstalls the service
/service - runs as a service; invoked via SCM
/client - runs as a client; invoked via CreateProcessAsUser

The only interesting code is in the /service and /client modes.

In /service mode it enumerates the running processes via EnumProcesses and GetModuleFileNameEx looking for "winlogon.exe". When it finds one it opens its token and launches itself in /client mode via CreateProcessAsUser:

HANDLE hProcess = ...;
// winlogon.exe runs as SYSTEM in user's session; we need to run the same way
HANDLE hToken = NULL;
if(OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, &hToken))
{
    TCHAR szCommandLine[MAX_PATH];
    GetModuleFileName(NULL, szCommandLine, MAX_PATH);
    PathQuoteSpaces(szCommandLine);
    // run in /client mode
    _tcscat_s(szCommandLine, MAX_PATH, _T(" /client"));
    STARTUPINFO StartupInfo;
    ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
    StartupInfo.cb = sizeof(STARTUPINFO);
    // run on the Winlogon desktop
    StartupInfo.lpDesktop = _T("WinSta0\\Winlogon");
    PROCESS_INFORMATION ProcessInformation;
    ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
    if(CreateProcessAsUser(hToken, NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation))
    {
        CloseHandle(ProcessInformation.hThread);
        ProcessInformation.hThread = NULL;
        CloseHandle(ProcessInformation.hProcess);
        ProcessInformation.hProcess = NULL;
    }
    CloseHandle(hToken);
    hToken = NULL;
}

In /client mode it clicks the "Yes" button on the UAC prompt via a bunch of FindWindow and FindWindowEx calls. You can use Spy++ to figure out the window hierarchy.

HWND hWnd = ...;
HWND hWndButton = FindWindowEx(hWnd, NULL, _T("Button"), NULL);
if(hWndButton != NULL)
{
    // see if this is the "Yes" button
    TCHAR szText[32];
    if(GetWindowText(hWndButton, szText, 32) && _tcsicmp(szText, _T("&Yes")) == 0)
    {
        // click it
        SendMessage(hWndButton, BM_CLICK, 0, 0);
    }
}

The way I test this is to stick a Sleep(5000); in the /client code. Then I start the service and immediately do something that triggers a UAC prompt (i.e. run regedit). After 5 seconds the /client code will wake up and find and click the "Yes" button. You can run other processes on the Winlogon desktop; cmd.exe and spyxx.exe (Spy++) are most useful. Unfortunately, explorer.exe exhibits a lot of problems when running on the Winlogon desktop and isn't very useful. To get to the Winlogon desktop you can run regedit and then Alt+Tab to switch to the other application. If you want to get fancy you can write your own desktop switching utility (using the SwitchDesktop function) so you don't have to trigger a UAC prompt to get to the Winlogon desktop. If you want to get really fancy you can set a global window hook to monitor window creation; when the UAC dialog is about to be displayed you can prepare to click its "Yes" button. I didn't take it quite that far, though.

like image 178
Luke Avatar answered Oct 13 '22 16:10

Luke