Jump to content

Elevate Your Script to the SYSTEM Account


wraithdu
 Share

Recommended Posts

First, thanks to arcker for his Services UDF for making this possible. It works like this:

When launched, the app will install itself as a service, launch the service, then exit. The service runs in the SYSTEM account. To interact with the desktop of the currently logged on user it will get the security information from the winlogon.exe token and the user's environment from the explorer.exe token. The service will relaunch the app with these security settings and environment, then stop. On relaunch, the process will wait for the service to end then uninstall it. The process will now be running in the SYSTEM account in the currently logged on user's session with the user's environment. If you look into the _Svc_Main() function there's a note about how to relaunch the process in Session 0 (same as the service) if you need to do this. In this case it will be running solely in the SYSTEM account in Session 0 with it's own environment.

I've included two more functions for when you need to access certain other user specific items, such as using the @UserName macro, or accessing the HKCU branch of the registry (these things are not taken from the environment, but from the security context of the process). You should test any macros you intend to use to make sure the correct information is returned before running your process for real. _ImpersonateUserStart() and _ImpersonateUserEnd() will enable and disable this impersonation. Keep in mind this alters your security access as well, you will have the same security level as the logged on user during this time.

NOTE: For retrieval of the user environment and user impersonation it is required that explorer.exe is running. If you're using a 3rd party shell replacement, you can edit the UDF to change the requirements to another process, but I can't guarantee it will work.

I've included a stripped down version of arcker's UDF, since not all of it is needed. If I could get some test results from users running XP and Vista/7 with UAC, that would be great too.

Sources:

Link 1

Link 2

ANY SCRIPT USING THESE FUNCTIONS MUST BE COMPILED TO WORK. IT WILL NOT WORK FROM SCITE.

ADMIN RIGHTS REQUIRED AS WELL.

UPDATE 1 (2009/10/29)

- added a function to launch a process as the user of a currently running process in the specified session (ie, to de-elevate a process back to your user account).

UPDATE 2 (2009/10/29)

- fixed a wrong function export which caused problems on XP (thanks trancexxx)

UPDATE 3 (2009/10/30)

- I think I have a stable version now, tested on Win7, XP SP3 VM, and a physical XP SP3 box. As a bonus the service control handler now works in Win7 as well, so we can have a fully functioning service.

_Services_Mini.au3

SystemElevate.au3

Edited by wraithdu
Link to comment
Share on other sites

Excellent

that's how remote installation works :)

(psexec is a good example, or other deployment software )

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Excellent

that's how remote installation works :)

(psexec is a good example, or other deployment software )

What do you mean 'Excellent'? It works for you?

@wraithdu, CreateProcessAsUser function is exported by advapi32.dll.

I got it working, but some funny crashes while. XP SP3.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I don't have XP readily available to test, so if there are problems I'll try to look into it. Anything more specific to offer? Post the contents of the log maybe?

Logs are gone.

This:

$ret = DllCall("kernel32.dll", "int", "CreateProcessAsUserW", "ptr", $hDupToken, "ptr", 0, "wstr", $sAppPath, "ptr", 0, "ptr", 0, "int", 0, _
                    "dword", $dwCreationFlags, "ptr", $pEnvBlock, "ptr", 0, "ptr", DllStructGetPtr($SI), "ptr", DllStructGetPtr($PI))
    If Not @error And $ret[0] Then
...

It's not "kernel32.dll".

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Good catch. Strangely CreateProcessAsUser is also exported by kernel32 on Win7. Guess that's why I didn't notice.

Microsoft have moved lots of the api's that was currently inside different modules into kernel32.dll. This is probably because the speed / efficiency increase is now more important than the memory footprint. The exports in advapi32 and similar are just probably just redirects and are probably there because microsoft doesn't want applications to break on win7 (very strange indeed :)).

Edited by monoceres

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Btw, I found what was/is causing the crash.

It's ProcessWaitClose($CmdLine[2]) you use. It should be:

Case "-run"
            ; as elevated app
            ; wait for service to end and uninstall service (PID passed as $CmdLine[2])
            ProcessClose($CmdLine[2]) ; <- This!
            MsgBox(0, "Hey", "Closed")
            _RemoveService()
...

edit:

Or something like that :)

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

No, it's supposed to be ProcessWaitClose() as the Service will stop itself properly, and the process must wait for it to close before removing it.

That said, I tested on another XP system and did get a crash, but it's a crash in the service, not the newly spawned process. Once you close the crashed app the new process will continue. I still don't know why the service is crashing though.

Edited by wraithdu
Link to comment
Share on other sites

Turns out the problem is stopping the service cleanly in Win7. I can issue a _Service_Stop() command even from in the service in XP and it ends. In 7 that control message is never received so the thing doesn't exit cleanly (leaves a crash log in Event Viewer).

Unless arcker or someone can figure that out, I might just switch to using ProcessClose() to kill the service before removing it. It's ugly and bad, but I don't have another workaround at the moment.

EDIT:

I'm confused again. Now it seems to work OK the way I had it in Vista. Maybe I just need to use _Service_Stop() in XP instead.

Edited by wraithdu
Link to comment
Share on other sites

Turns out the problem is stopping the service cleanly in Win7. I can issue a _Service_Stop() command even from in the service in XP and it ends. In 7 that control message is never received so the thing doesn't exit cleanly (leaves a crash log in Event Viewer).

Unless arcker or someone can figure that out, I might just switch to using ProcessClose() to kill the service before removing it. It's ugly and bad, but I don't have another workaround at the moment.

EDIT:

I'm confused again. Now it seems to work OK the way I had it in Vista. Maybe I just need to use _Service_Stop() in XP instead.

I think there is a problem with logic.

Why don't you exit after successful CreateProcessAsUserW. Don't return if ok, just exit. That makes sense to you?

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Doesn't matter. I tried, but it was still crashing / hanging.

But I've had a breakthrough! I switched to use RegisterServiceCtrlHandlerExW() and a HandlerEx() callback and....it works in Win7! So I'm testing a proper course of events here where the new process stops the service, waits for it to close, then removes it. So far it is working in Win7 and I'm about to do testing in XP.

It also seems that calling the _DebugLog() function at certain times causes a hang, especially if it's called from the child before the server has ended, so we must be careful about that.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...