WNetAddConnection2 in Windows 7 with Impersonation and no Error Code - c++

I'm doing some crazy impersonation stuff to get around UAC dialogs in Windows 7 so the user does not have to interact with the UI (I have the admin creds of course).
I have a process running as the Administrator and elevated past UAC. The issue that I'm facing is that when I make a call to WNetAddConnection2, within this process, I am not getting a new mapped net drive. The function returns ERROR_SUCCESS but no net drive is visible. We have another method of adding network drives using 'subst' but this, again, returns successful does does not add a net drive. I have tried to use the default user (which is the Administrator because of process's security context) and I have tried using specific user credentials. I can map the drive just fine through Explorer.
Of course the same functionality works fine in XP/2003. I haven't got around to testing on Vista because of issues with impersonation that are limiting my ability to spin up the process. Are there unique Windows 7 limits on this function? MSDN does not glean any that I can find.
Any help would be greatly appreciated!

The issue was that the process was running as Administrator. Impersonation will not work because WNetAddConnection2 evaluates on processes user. You must start a separate process to accomplish this.

Related

C++: Taking a screenshot of the Windows Logon Screen/UAC Prompts without disabling UAC

I've been looking all over the internet for an answer to this, and it just doesn't seem to be directly answered, so I thought I would ask.
Case scenario: I want to take a screenshot of what is currently on the computer screen. If it's the Windows Logon screen, I want it to be that. If it's the active user's desktop, I want to to be that. If the user elevates their application, and the UAC prompt shows up, I want it to be that.
As per lots of reading and trial and error, my current setup is as follows:
Program runs as a windows service
Gets the active user's token
Runs CreateProcessAsUser with the user's token to generate another instance of itself
Takes a screenshot and transmits it back via pipes.
Right now this is working great for a logged on user, except that screenshot is black when a UAC prompt is enabled.
Also, this method obviously won't work for getting the logon screen.
Fundamentally I am wondering how exactly does TeamViewer go about achieving this sort of thing? It is able to switch between the logon screen and a user's session flawlessly, whilst also capturing UAC prompts. I am immensely curious as to how it achieves this.
Thanks everyone!
As per the advice of Davison, I have figured out how to do this, and it involves multiple steps.
Firstly, one must use CreateProcessAsUser to create a process inside the console session (obtained from WTSGetActiveConsoleSessionId). Something to note is that this process must have administrative privileges, which simply getting a handle to the user's token will not do. The way around this evidently, is to get a handle to a process running with administrative privileges, get this processes' token, duplicate it, and use that with CreateProcessAsUser. The process I used for this was Winlogon.
After this, the rest is quite simple; use OpenInputDesktop to get a handle to the desktop the user is currently seeing (it will be Default for actual desktop, and Winlogon for the UAC Prompt and login screen). After this, use SetThreadDesktop to set your processes' thread to the appropriate desktop, and capture the screen. Assuming that your Process has the privileges to create a handle to the Winlogon desktop, you will be able to capture the login screen/uac prompts and the regular user desktop.
Again, thanks to Davison, who pointed me in the right direction.

How to ask for Administrator privileges in Windows 7?

I wrote an application using Qt under Windows 7. The application starts up with normal user privileges, but I want to gain the Administrator privileges because I want to modify the registry to auto-start the application.
How could I do this?
Take a look at the MSDN sample: UAC self-elevation (CSUACSelfElevation)
Also, Wikipedia actually has a pretty good reference including information on the ShellExecuteEx() "runas" verb and application manifest for elevation requests.
You should embedd correct manifest to your exe:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb756929.aspx.
I know, you said using win32 API, but consider this standard and recommended way.
You do not need administrator privileges to autostart your application.
Simply write the appropriate keys to:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
which does not require administrator privileges (unlike the same path under HKEY_LOCAL_MACHINE).
to auto-startup the application, you don't need admin rights! Instead of adding the registry key under HKLM (where you need admin rights), use HKCU and you're fine.
Note that privileges cannot be changed while the program is running. It has to be killed and restarted with the correct privileges.
To make an application auto start in HKLM, the administrative privilege is needed. But the privilege of an application could not change while running.
So I made a new small application whose task is only write the registry to make the main application auto start.
The main application could call this application with ShellExecuteEx to require administrative privlege.

Under Windows, how can you identify the current console user and then do a logoff against that user?

I need the ability in C++ code to logoff the console user when call from an administrator process or if it is called by that user and maybe a windows service in the future. The issue I am running into is that ExitWindowsEx will only logoff the user that calls it. If an administrator process calls a logoff the console user is unaffected. The only application that I know of that can do this is psShutdown.exe, except that psShutdown can only be run by the administrator. Does anyone know in C++ how to identify the console user and then do a logoff against that user? What is the magic inside psShutdown? I'm looking for something that works in WindowsXP and up. Also I cannot use WMI because some machines are running windows Embeded and do not have WMI.
(The reason psShutdown.exe must be run as administrator is because it installs a service and a normal user does not have the rights to do this.)
Use WTSGetActiveConsoleSessionId to identify the console session, but to go further you are going to need some permissions, you would have to call WTSQueryUserToken (You need to run as SYSTEM to do this) to get a token handle and then CreateProcessAsUser or impersonate and call ExitWindowsEx, or if you are not in a service, call WTSLogoffSession. (I tried calling WTSLogoffSession on my XP box and it did not work, probably because the terminal server service is not running on this system)
I have never actually done this, but it seems like it should be possible with the combination of WTSGetActiveConsoleSessionId() and WTSLogoffSession()

How does Process Explorer enumerate all process names from an XP Guest account?

I'm attempting to enumerate all running process EXE names, and have stumbled when attempting this on the XP Guest account. I am able to enumerate all Process IDs using EnumProcesses, but when I attempt OpenProcess with PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, the function fails.
I fired up Process Explorer under the XP Guest account, and it was able to enumerate all process names (though as expected, most other information from processes outside the Guest user-space was not present).
So, my question is, how can I duplicate the Process Explorer magic to get the process names of services and other processes running outside the Guest account user-space?
I suppose that the Process Explorer use NtQuerySystemInformation with parameter SystemProcessInformation to get the list of processes. For the code example see my old answer. Additionally the function NtQueryInformationProcess will be used to get additional information.
By the way, if you start Process Explorer under Dependency Walker (menu "Profile" / "Start Profiling" or F7) then you will see all functions which Process Explorer really use from NTDLL.DLL. You can see that NtQuerySystemInformation and NtQueryInformationProcess will be really used.
NtQuerySystemInformation is only barely documented and "may be altered or unavailable in future versions of Windows" CreateToolhelp32Snapshot is fully documented and should give you the image name.
When a process starts, it is assigned a basic set of access privileges. Certain API calls require additional privileges to complete successfully. Specifically, OpenProcess can require the SeDebugPrivilege privilege in certain cases. You can find an example of how to modify your process token to enable additional privileges here: Enabling and Disabling Privileges in C++.
GetProcessImageFileName only needs PROCESS_QUERY_LIMITED_INFORMATION starting with Vista, but on XP it does need PROCESS_QUERY_INFORMATION.
You shouldn't need, and definitely shouldn't be able to get from a guest account, PROCESS_VM_READ.

How can a Windows service execute a GUI application?

I have written a Windows service that allows me to remotely run and stop applications. These applications are run using CreateProcess, and this works for me because most of them only perform backend processing. Recently, I need to run applications that present GUI to the current log in user. How do I code in C++ to allow my service to locate the currently active desktop and run the GUI on it?
Roger Lipscombe's answer, to use WTSEnumerateSessions to find the right desktop, then CreateProcessAsUser to start the application on that desktop (you pass it the handle of the desktop as part of the STARTUPINFO structure) is correct.
However, I would strongly recommend against doing this. In some environments, such as Terminal Server hosts with many active users, determining which desktop is the 'active' one isn't easy, and may not even be possible.
But most importantly, if an application will suddenly appear on a user's desktop, this may very well occur at a bad time (either because the user simply isn't expecting it, or because you're trying to launch the app when the session isn't quite initialized yet, in the process of shutting down, or whatever).
A more conventional approach would be to put a shortcut to a small client app for your service in the global startup group. This app will then launch along with every user session, and can be used start other apps (if so desired) without any juggling of user credentials, sessions and/or desktops.
Also, this shortcut can be moved/disabled by administrators as desired, which will make deployment of your application much easier, since it doesn't deviate from the standards used by other Windows apps...
The short answer is "You don't", as opening a GUI program running under another user context is a security vulnerability commonly known as a Shatter Attack.
Take a look at this MSDN article: Interactive Services. It gives some options for a service to interact with a user.
In short you have these options:
Display a dialog box in the user's session using the WTSSendMessage function.
Create a separate hidden GUI application and use the CreateProcessAsUser function to run the application within the context of the interactive user. Design the GUI application to communicate with the service through some method of interprocess communication (IPC), for example, named pipes. The service communicates with the GUI application to tell it when to display the GUI. The application communicates the results of the user interaction back to the service so that the service can take the appropriate action. Note that IPC can expose your service interfaces over the network unless you use an appropriate access control list (ACL).
If this service runs on a multiuser system, add the application to the following key so that it is run in each session: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. If the application uses named pipes for IPC, the server can distinguish between multiple user processes by giving each pipe a unique name based on the session ID.
WTSEnumerateSessions and CreateProcessAsUser.
Several people suggested WTSEnumerateSessions and CreateProcessAsUser. I wonder why no one suggested WTSGetActiveConsoleSessionId, since you said you only want to target one logged in user.
Several people sure are right to suggest CreateProcessAsUser though. If you call plain old CreateProcess the way you said, then the application's GUI will run with your service's privileges instead of the user's privileges.
That problems Session 0 , Interactive Services ,
Windows Service Allow Service To Interact With Desktop
on Windows 7 or Windows Vista
You can read this article
http://www.codeproject.com/KB/vista-security/SubvertingVistaUAC.aspx
I try explained here it's working on Windows 7
On Win2K, XP and Win2K3 the console user is logged on in Session 0, the same session the services live in. If a service is configured as interactive, it'll be able to show the UI on the user's desktop.
However, on Vista, no user can be logged on in Session 0. Showing UI from a service there is a bit trickier. You need to enumerate the active sessions using WTSEnumerateSessions API, find the console session and create the process as that user. Of course, you need also a token or user credentials to be able to do that. You can read more details about this process here.
I think as long as you have only one user logged in, it will automatically display on that user's desktop.
Anyway, be very careful when having a service start an exe.
If the write access to the folder with the exe is not restricted, any user can replace that exe with any other program, which will then be run with sytem rights. Take for example cmd.exe (available on all windows sytems). The next time the service tries to start your exe, you get a command shell with system rights...
If you launch a GUI from your service it will show up on the currently active desktop.
But only if you adjusted the service permissions: You need to allow it to interact with the desktop.
Important Services cannot directly interact with a user as of Windows Vista. Therefore, the techniques mentioned in the section titled Using an Interactive Service should not be used in new code.
This is taken from : http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx