I have some code that used to work, but recently stopped. It's in an Adobe Reader Plugin, and the latest Reader version has a "Protected Mode" which causes my problem.
My plugin can load some of my normal dlls, which load in-process:
MyNormalLib::IMyClassPtr foo;
HRESULT hr = foo.CreateInstance(__uuidof(MyNormalLib::MyClass));
But when I try to get a com pointer to my service (running on the same machine):
MyOtherLib::IMyServicePtr bar;
HRESULT hr = bar.CreateInstance(__uuidof(MyOtherLib::MyService));
I get E_ACCESSDENIED for my HRESULT.
This used to work fine, until Adobe Reader X came along. Without Protected Mode, Adobe runs normally and everything works. With Protected Mode, Adobe spawns another Reader process, with some restrictions on it. Looking at this with Process Explorer, I can see that the Security Tab for the parent Reader process has pretty much everything set to Mandatory; but the child Reader process has most groups set to "Deny, Mandatory", some "Mandatory, Restricted", some are just Mandatory. If this matters, I can provide more details.
All processes (my service and both Reader) are run as the same user -- me. I have admin rights, if that matters.
What can cause an AccessDenied error when trying to reach my own service? What security hoops do I have to jump through to get this to work?
The restricted process does not have admin rights. That's pretty much the point of the exercise - Reader X drops as many rights as it can from its token so that if it is pwned your computer is not.
(That's basically how UAC works too, you have to go to the Kernel to get permission to re-enable your Administrator group once you have disabled it).
Basically you need to look at the privs that Reader X has, and make sure your component can be used with those permissions. Process Monitor is your friend - just filter for DENIED and the problems will pop right out at you!
Related
I have been dabbling with working nicely with UAC for a while and I found about a few things:
With UAC enabled, a program in the Startup folder, that requires to be run as admin (say by an embedded manifest), cannot be run according to this Stack Overflow thread.
Another method of running a program at startup is by creating a key containing the path to that application in: HKLM or HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run or HKLM or HKCU\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run in 64 bit machines.
Yet another method is using the task scheduler setting the Run with highest privileges option. This is the only method that bypasses the problem stated in point 1.
Coming from a Linux background, I had no clue about all these admin rights related problems. If someone can list out scenarios which absolutely need administrator privileges, it would be of great help!
I'm asking this because when I'm developing some application, I keep encountering several problems during implementation mostly because my application required admin rights when it shouldn't.
If I know, at design time, all possible scenarios that require admin rights, I could possibly design a common service for all my applications that takes care of all the administrator tasks (I think services are the Windows way of doing things like this).
There really isn't a list of scenarios or API function calls that require elevation. Your best option will probably be to focus on what API calls require elevation. The reason for this is that it may be required only if certain values are passed to the function. For instance CreateFile can create a file in your home directory without elevation but requires it for creating a file in C:\Windows. If the directory is provided through user input the only way you can know if elevation is required is to check the error code when the call fails. If elevation is required the function will set the error status to ERROR_ACCESS_DENIED and return a value indicating failure.
Ok, so we have a C++ app that runs fine in Windows XP.
It has the following code in the initialization
// Register all OLE server (factories) as running. This enables the
// OLE libraries to create objects from other applications.
COleObjectFactory::RegisterAll();
Now like i said, it works fine in Windows XP, but as far I understand the program tries to register its COM interface Which is fine in XP, but this may be a problem in Windows Vista and Windows 7 because of the UAC. Especially if its is run as a standard user (with no elevated privileges).
If i understand it correctly this is needed for the program to run properly, but it cant execute this code without elevated privileges. If it will run every time the app runs (this usually runs when CWinApp::init() is run)
Before you say just use admin privileges, the user will not have them, there is no way to change that
So, now my questions are:
1) am i correct in my assumptions?
2) if I am correct, what is the best way around this? Can i just remove this? Do i need to set up some other thing? (we changed some VB modules to use a XML file instead of stuff in the registry
PS: the modules compiles into DLLs
PPS: UAC MUST be on
Take note that:
The documentation for these functions makes no mention of any privilege requirements; and
nobody online seems to be having trouble with these functions in limited privilege environments; and
it's 2012, I think someone would have noticed if these functions didn't work under UAC by now.
So (with nothing to suggest otherwise) I'd say It Just Works.
Notwithstanding the above, I looked at the implementation of COleObjectFactory::RegisterAll() and COleObjectFactory::UpdateRegistryAll().
RegisterAll
Ultimately calling RegisterAll ends up in olefact.cpp:135 where CoRegisterClassObject is called. From MSDN:
Registers an EXE class object with OLE so other applications can connect to it.
I believe this registration will be limited to the current user's session and the lifetime of the application. The Remarks section touches on privileges (As of Windows Server 2003...) but doesn't provide anything concrete.
There's an object known as the Running Object Table (ROT) that can be retrieved via GetRunningObjectTable. The documentation has this snippet:
Each workstation has a local ROT that maintains a table of the objects that have been registered as running on that computer.
The COM Elevation Moniker has some more information about the ROT and privileges (it suggests processes of various privilege levels work fine with it). The links on the left-hand side might help, too.
Overall it seems there's nothing to suggest that CoRegisterClassObject requires administrator permissions.
UpdateRegistryAll
This function ends up in olefact.cpp:375 where it opens HKEY_CLASSES_ROOT. At this point the documentation gets a bit better:
Registry functions such as RegOpenKeyEx or RegQueryValueEx allow you to specify the HKEY_CLASSES_ROOT key. When you call these functions from a process running in the interactive user account, the system merges the default settings in HKEY_LOCAL_MACHINE\Software\Classes with the interactive user's settings at HKEY_CURRENT_USER\Software\Classes.
Further on:
If you write keys to a key under HKEY_CLASSES_ROOT, the system stores the information under HKEY_LOCAL_MACHINE\Software\Classes
The documentation doesn't define what happens when you try to write to HKEY_CLASSES_ROOT under limited privileges (i.e. a standard user can't write to HKLM), but I believe that you'll end up writing to HKCU instead.
And finally, note:
Windows Server 2003 and Windows XP/2000: Applications can register dependent COM objects to either the per-machine or per-user COM configuration store (HKEY_LOCAL_MACHINE\Software\Classes or HKEY_CURRENT_USER\Software\Classes).
So if it falls through to HKCU, you should be fine.
Caveat Implementor: Don't rely on implementation details.
I'm building a custom authentication subpackage for MSV1_0 for Windows 7. I've used the msvsubauth sample in from the Windows SDK and I have 2 questions regarding some problems I'm facing with that:
When I'm trying just to make sure that the routine get's invoked and set the Auth0 property in the registry to my package and add a simple code at the end of the Msv1_0SubAuthenticationRoutine that creates a file:
//
// Cleanup up before returning.
//
Cleanup:
hTestFile = CreateFile(
TEXT("C:\\lsa\\lsa.txt"),
GENERIC_READ|GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if(hTestFile != INVALID_HANDLE_VALUE) {
CloseHandle(hTestFile);
}
return Status;
} // Msv1_0SubAuthenticationRoutine
Apparently the package gets invoked because when I enter my password I get an error message from windows "the parameter is incorrect" which is a good sign. But why I'm getting that error? when the exactly same code is executed from a separate .exe file it runs perfectly and creates the test text file. I've checked the permissions and set "full control" for "everyone". Any ideas? the SDK doesn't exactly mention what kind of isolation LSA is creating for code within auth packages.
The second problem is testing the AP. Currently with every change I rebuild the library, copy it to a test VM and then to the System32 folder and reboot it. Is there an easier way to do that?
Thank in advance!
Debugging in Winlogon and LSASS makes for the most time consuming debugging.
To ease your debugging, you could write a proxy AP that exports the same functions. When loaded, you proxy_ap would
Copy the real AP from a known location to a temp locationand.
LoadLibrary that DLL, GetProcAddress of everything, and forward any calls it receives to that newly loaded DLL.
Watch for changes in the directory where the original AP was copied from
When a change occurs (and if your AP changed) FreeLibrary and goto step 2
But you need to keep a tight grip on what happens on your development target, because handling the dll switch while dealing with requests comming from many threads can become a worse nightmare that what you are trying to solve.
LogonUI.exe starts a new instance every time, but LSASS.exe is long lived.
+Have a look at CVSNT source code (http://cvsnt.sourcearchive.com/). They have a pretty nice AP that implements su. Run the sample in the local system account with psexec -s (from Microsoft/SysInternals pstools suite)
Perhaps your problem is Everyone only includes Authenticated users? This is just a guess.
I suggest you use Process Monitor to monitor for Access Denied messages or for your path. It is fantastic for debugging permission/path problems of all kinds.
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
If you experience the issue at the "Unlock Workstation" or "change Password" screens, and it doesn't prevent you logging in, this should be easy to do - set it running, reproduce the problem, log back in and hey presto.
Otherwise you might have to resort to tricks like executing that code path only for certain user accounts, on the Nth try, etc.
On Vista using IE8, I have an instance of IWebBrowser2, which I am using to obtain the current HTML document:
IWebBrowser2* browser;
CComPtr<IDispatch> disp;
HRESULT hr = browser->get_Document(&disp);
When this is executed by an Administrator, the call succeeds. However, when called by a regular user, the call returns an error code of "800706B5" ("The interface is unknown") despite the page being on a "Trusted Site" and "Protected Mode" being off.
This same code worked without problems on IE7 on Vista, and with IE8 on XP.
Does anyone know why this error might be occurring, and what I can do to resolve the issue? Running as administrator is less than ideal, and Jon Skeet is stumped by this one too :)
Update: the question seems to revolve around UAC: turning off UAC completely allows things to work for a regular user (though it's distinctly unsafe)
The error is occurring because on Vista, IE 8 runs in "low integrity" mode, whereas my test code, running as a normal user, runs at "medium integrity". The security model is designed so that code can send instructions to lower integrity components, but data cannot be read from "lower" to "higher" components by default.
More information is available in this document about How the Integrity Mechanism Is Implemented in Windows Vista
Was IE8 installed by the Administrator "For this user only"? I don't know why or if that would give this error, just a hunch.
I'm using QTP 10 together with VMWare to test a Siebel Application.
I'm executing the following code to click on a Save button.
Browser("Siebel").Dialog("Filedownload").WinButton("Save").Click
The code works perfectly fine when I'm connected to the VM via Remote Desktop.
On the other side, when I'm starting the QTP test through the scheduler, without having a Remote Desktop connection, the code above fails without any error message. The WinButton is simply not clicked.
Any idea?
Just to add from my experience.
In some companies I worked for I couldn't change screensaver or standby settings due to security policy. A PC was bringing up screensaver during long synchronization periods (like generating really big report), and execution was broken.
To avoid that I created simple "Anti Sleep" function that slightly "moves" mouse every 5 minutes.
http://automation-beyond.com/2009/08/18/anti-sleep-function/
Private Const SleepTime_Max = 300 ‘ 5 minutes
Public Function AntiSleep()
Dim iter
Dim objTimer
Dim objDeviceReplay
Dim intTimeElapsed
Set objTimer = MercuryTimers(“AntiSleep”)
intTimeElapsed = CInt(objTimer.ElapsedTime/1000)
If intTimeElapsed = 0 Then
MercuryTimers(“AntiSleep”).Start
Exit Function
End If
If intTimeElapsed < SleepTime_Max Then
Exit Function
End If
Set objDeviceReplay = CreateObject(“Mercury.DeviceReplay”)
For iter = 100 To 110
objDeviceReplay.MouseMove iter,300
Next
MercuryTimers(“AntiSleep”).Start
Set objDeviceReplay = Nothing
End Function
Example of using it in a custom synchronization function:
http://automation-beyond.com/2009/08/20/gui-object-synchronization-custom-function/
Thank you,
Albert Gareev
QTP can't interact with a locked desktop, that's why it'll only work for you when logged in interactively either locally or over RDP. It's a well known limitation of QTP, most automation engineers go through this pain at some point. :)
To be more specific, it can't interact with Win32 objects (can't think of a better way of putting it), so it'll interact with basic browser controls on a locked desktop no problem, but browser popups and Windows applications can't be interacted with in those circumstances.
I strongly recommend (if your system policy allows) that you install something like UltraVNC or another VNC variant to interact with your remote machines. That way you can leave the remote machine's desktop logged on and active at all times. Since it's a VM that shouldn't cause you any major security problems either. Make sure you turn off any screen savers and don't auto-lock the desktop too. QTP should work just fine for you if you do that.