Run a program with no elevation from a program run as admin

Run a program with no elevation from a program run as admin

Post by Davide Ang » Wed, 29 Jul 2009 01:19:02


Hi to everybody. I've this need :

1. ProgramA.EXE is simply executed with "asInvoker" in his manifest
2. ProgramA.EXE runs with admin elevation ProgramB.EXE using
ShellExecuteEx (lpVerb = 'runas')
3. ProgramA.EXE is terminated
4. ProgramB.EXE re-run ProgramA.EXE with ShellExecuteEx (without
lpVerb) and ProgramA.EXE is run elevated with admin privilege.

How can avoid the admin elevation at point 4? I need to re-run
ProgramA.EXE from ProgramB.EXE with the orginal user rights.

Thank you

Davide Angeli
 
 
 

Run a program with no elevation from a program run as admin

Post by Remy Lebea » Wed, 29 Jul 2009 04:54:41


Try having ProgramA pass its current user token to ProgramB, which would
then use CreateProcessAsUser() to run ProcessA using that same token.

--
Remy Lebeau (TeamB)

 
 
 

Run a program with no elevation from a program run as admin

Post by Paul Baker » Wed, 29 Jul 2009 06:15:44


Can a non-elevated token be created by an elevated processing using
OpenProcessToken and SetTokenInformation with TOKEN_ELEVATION_TYPE?

Paul
 
 
 

Run a program with no elevation from a program run as admin

Post by Remy Lebea » Thu, 30 Jul 2009 07:55:44


"Paul Baker [MVP, Windows Desktop Experience]"




I have no clue. I was thinking more along the lines of having ProgramB
simply use the original token as-is that ProgramA passed to it. ProgramA
can duplicate its token in ProcessB's address space using DuplicateHandle().
Create ProgramB in a suspended state, duplicate the handle, resume the
process and pass the handle to it via any IPC mechanism of your choosing.
On the other hand, I have never used Vista, and likely never will, so I have
no clue what would actually work.

--
Remy Lebeau (TeamB)
 
 
 

Run a program with no elevation from a program run as admin

Post by Paul Baker » Thu, 30 Jul 2009 23:55:30

TOKEN_ELEVATION_TYPE is documented but not mentioned in the documentation
for GetTokenInformation or SetTokenInformation. So effectively, it is not
documented. I would be curious to know if my idea works, just out of
curiousity.

Your idea definitely sounds like it will work, and it guarantees that the
token you use the second time around is the same as the first time around.
This is probably the best idea.

I thought about calling CreateRestrictedToken to create a token that is
restricted in the same way as UAC presumably does for itself, but that
wouldn't work because you couldn't be guaranteed to do it the exact same way
as UAC, especially if the way in which UAC does it is tweeked, which could
cause unexpected behaviour.

Remember the "Run As" verb in Windows XP. It's kind of like UAC :)

Paul
 
 
 

Run a program with no elevation from a program run as admin

Post by Pavel A » Fri, 31 Jul 2009 00:04:22


No it is not like UAC elevation. RunAs starts the process under _other
user_ account so if the process accesses, for example, My Documents
or HKCU, it will see other user's data.

--pa
 
 
 

Run a program with no elevation from a program run as admin

Post by Davide Ang » Fri, 31 Jul 2009 01:19:22


I tried the next solution but it doesn't function :

1. ProgramA creates an event EventA
2. ProgramA runs ProgramB with ShellExecuteEx (runas) passing his
ProcessID in the commandline
3. ProgramA Waits for EventA (WaitForSingleObject)
4. ProgramB open ProgramA process with OpenProcess Api (and ProcessID
from commandline)
5. ProgramB reads ProgramA hToken with OpenProcessToken Api
6. ProgramB fires EventA so ProgramA is closed
7. ProgramB do some stuff and then before closing itself it try to run
ProgramA with CreateProcessAsUser using the hToken rettieved at point
5
8. ProgramB terminate correctly but ProgramA doesn't start because
CreateProcessAsUser returns an 1314 ERROR_PRIVILEGE_NOT_HELD

I've done a lot test and tries but I can't understand why I got that
error calling that api. Have you got an idea?

Davide
 
 
 

Run a program with no elevation from a program run as admin

Post by Davide Ang » Fri, 31 Jul 2009 01:19:35


I tried the next solution but it doesn't function :

1. ProgramA creates an event EventA
2. ProgramA runs ProgramB with ShellExecuteEx (runas) passing his
ProcessID in the commandline
3. ProgramA Waits for EventA (WaitForSingleObject)
4. ProgramB open ProgramA process with OpenProcess Api (and ProcessID
from commandline)
5. ProgramB reads ProgramA hToken with OpenProcessToken Api
6. ProgramB fires EventA so ProgramA is closed
7. ProgramB do some stuff and then before closing itself it try to run
ProgramA with CreateProcessAsUser using the hToken rettieved at point
5
8. ProgramB terminate correctly but ProgramA doesn't start because
CreateProcessAsUser returns an 1314 ERROR_PRIVILEGE_NOT_HELD

I've done a lot test and tries but I can't understand why I got that
error calling that api. Have you got an idea?

Davide
 
 
 

Run a program with no elevation from a program run as admin

Post by Paul Baker » Fri, 31 Jul 2009 02:42:47

What I meant was, doesn't it create a restricted token similar to a UAC
non-elevated token? It could be for a different user, as you mention.

Paul
 
 
 

Run a program with no elevation from a program run as admin

Post by Remy Lebea » Fri, 31 Jul 2009 03:30:10


Did you try the approach I mentioned earlier?


That won't work if ProgramB does not permissions to ProgramA's process.

Also, OpenProcessToken() returns an access token, not a user token, which is
what CreateProcessAsUser() needs.


In other words, the token is likely no longer valid since its process was
closed.


CreateProcessAsUser() requires ASSIGNPRIMARYTOKEN_NAME and
SE_INCREASE_QUOTA_NAME privileges to be enabled for the calling process.
Look at AdjustTokenPrivileges() for that.

--
Remy Lebeau (TeamB)
 
 
 

Run a program with no elevation from a program run as admin

Post by Leo Davids » Fri, 31 Jul 2009 08:36:40

Hi Davide,

Have you considered making ProgramA (non-admin) stick around until
ProgramB (admin) is finished and then have ProgramA handle whatever
non-admin code/launches are required?

You might need to establish a pipe or something so that ProgramB can
pass information back to ProgramA to tell it what needs to be run, but
that shouldn't be a problem. (ProgramB should have access to write to
a pipe resource created by ProgramA unless I'm mistaken.)

In other words, you keep the non-admin process around and use that to
launch another non-admin process (or simply perform the follow-on
actions itself).

It's a shame an easy-to-use API for doing this was not provided like
one was provided for elevation. I suspect it's why a lot of installers
with "run the program" checkboxes at the end still run the programs as
admin (resulting in confusion, broken settings or admin UIs left
running on non-admin desktops waiting for someone to use File Open as
an admin file manager :) ).

Leo
 
 
 

Run a program with no elevation from a program run as admin

Post by Davide Ang » Fri, 31 Jul 2009 16:39:55


I'm doing some tests because is the first time for me approaching the
security windows api.


How can I get the user token? I've tried with DuplicationTokenEx to
create a new primary token but the result is the same. I don't want to
use LogonUser to get then and user token.


I need to close ProgramA because ProgramB should do something on a DLL
used from ProgramA so how can I duplicate the user token of ProgramA
and then pass it ProgramB?


I've tried all of these, I've also set SE_DEBUG_NAME,
SE_SECURITY_NAME,SE_IMPERSONATE_NAME but the result is the same. Maybe
the problem is on the hToken that I'm using.

Maybe a more simple solution to my problem is to pass through a
ProgramC runned from ProgramA with the same rights of ProgramA and
then ProgramC runs ProgramB with admin rights and waits ProgramB end;
after that ProgramC runs ProgramA.
 
 
 

Run a program with no elevation from a program run as admin

Post by Davide Ang » Fri, 31 Jul 2009 16:44:13

On 30 Lug, 01:36, Leo Davidson < XXXX@XXXXX.COM >


ProgramB need to close ProgramA to some stuff, so I'm just thinking
use a third program ProgramC to do what you said and maybe this
solution can be more easy to do what I want.


Davide
 
 
 

Run a program with no elevation from a program run as admin

Post by Remy Lebea » Sat, 01 Aug 2009 04:16:29


My bad. You can ignore this portion.

--
Remy Lebeau (TeamB)
 
 
 

Run a program with no elevation from a program run as admin

Post by Remy Lebea » Sat, 01 Aug 2009 04:25:09


Perhaps it would be easier for you to just have ProgramA load/unload the DLL
dynamically at runtime rather than link to it statically at compile-time.
That way, ProgramB could send a message to ProgramA asking it to unload the
DLL, then do whatever it needs to do with the DLL, and then send another
message telling ProgramA to re-load the DLL again. That way, ProgramA does
not need to be shut down anymore.


Probably.


If you are going to go that route, then I would suggest two alternatives
approaches:

1) have ProgramA run ProgramB with the same rights as ProgramA, then have
ProgramB run ProgramC elevated, and have ProgramC perform the actual tasks
that need to be run on the DLL. ProgramB can then run ProgramA after
ProgramC exits.

2) move the tasks that need to be performed on the DLL into a COM object,
and have ProgramB instantiate it elevated. ProgramB can then be run with
the same rights as ProgramA. Better, if you use a COM object, and let
ProgramA dynamically load/unload the DLL, then ProgramA can instantiate the
elevated COM object directly and you won't need ProgramB at all.

--
Remy Lebeau (TeamB)