Sign in to follow this  
Followers 0
cjconstantine

WMI and RunAs

13 posts in this topic

In a nut shell I was using PSEXEC to start a process as a different user on a remote PC for the sole purpose of creating that user's profile in C:\Documents and Settings. I was told I could no longer use PSEXEC so I've started to experiment with WMI.

At this point I have one script that starts a process on the remote PC:

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ''

#include <String.au3>
#include <File.au3>

MsgBox(0, '', _RemoteStart('U:\AutoIt3\Scripts\Snippets\test.exe', '', 'xxx.xxx.xxx.xxx'))

Func _RemoteStart($exe, $parameters = '', $computer = 'localhost')
    Dim $objWMIService, $objProcess
    Dim $strShell, $objProgram
    Dim $szDrive, $szDir, $szFName, $szExt

    $pid = 0
    $exe = _PathSplit($exe, $szDrive, $szDir, $szFName, $szExt)
    If $parameters <> '' Then $parameters = ' ' & $parameters

; Connect to WMI
    $oWMIService = ObjGet('winmgmts://' & $computer & '/root/cimv2')
    If Not IsObj($oWMIService) Then Return 0

    $colItems = $oWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem ", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) Then
        For $oItem In $colItems
            $systemdir = $oItem.SystemDirectory
        Next
    EndIf
    
    FileCopy($exe[0], '\\' & $computer & '\C$\' & StringTrimLeft($systemdir, 3), 1)

; Obtain the Win32_Process class of object.
    $oProcess = $oWMIService.Get('Win32_Process')
    $oProgram = $oProcess.Methods_('Create' ).InParameters.SpawnInstance_()
    $oProgram.CommandLine = $exe[3] & $exe[4] & $parameters

;Execute the program now at the command line.
    $start = $oWMIService.ExecMethod('Win32_Process', 'Create', $oProgram)
    
    $colItems = $oWMIService.ExecQuery('SELECT * FROM Win32_Process ', 'WQL', $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) Then
        For $oItem In $colItems
            If $oItem.Name = $exe[3] & $exe[4] Then
                $pid = $oItem.ProcessId
                ExitLoop
            EndIf
        Next
    EndIf
    
    Return $pid
EndFunc  ;==>_RemoteStart

And the second part which is supposed to start a process as the other user (Test.exe):

$pid = RunAs($user, $domain, $password, 1, 'C:\Windows\system32\Calc.exe')
FileWriteLine('D:\test.txt', $pid)

I know that Test.exe runs on the remote machine because the text file is updated every time but Calc never starts. Any ideas? Or an easier way to create the other user's profile

Share this post


Link to post
Share on other sites



Are you restricted by not using remote registry as well? Quick and dirty would be to create a script that writes to

"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\defaultusername>defaultpassword>defaultdomainname>Autoadminlogon"

and put a runonce in "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" to clear the keys on logon. So you logon automatically to the desktop at next reboot and then the runonce clears the keys so the next user does not see what is there, you could also set an AT command to schedule a logoff after a set amount of time (long enough for the profile to be created). Not as elegant as your trying to do but if your stuck it should work.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

This is part of a profile copy including files, so rebooting the PC really isn't an option. Not knowing all too much about WMI, is there any reason why RunAs would fail given all the correct credentials?

Edited by cjconstantine

Share this post


Link to post
Share on other sites

<bump> Any reason why RunAs doesn't work with WMI?

Share this post


Link to post
Share on other sites

Try :

$pid = RunAs($user, $domain, $password, 1, 'C:\Windows\system32\Calc.exe')

$pid = RunAs($user, $domain, $password, 2, 'C:\Windows\system32\Calc.exe')

$pid = RunAs($user, $domain, $password, 0, 'C:\Windows\system32\Calc.exe')

$pid = RunAs($user, $domain, $password, 4, 'C:\Windows\system32\Calc.exe')

Share this post


Link to post
Share on other sites

Try :

$pid = RunAs($user, $domain, $password, 1, 'C:\Windows\system32\Calc.exe')

$pid = RunAs($user, $domain, $password, 2, 'C:\Windows\system32\Calc.exe')

$pid = RunAs($user, $domain, $password, 0, 'C:\Windows\system32\Calc.exe')

$pid = RunAs($user, $domain, $password, 4, 'C:\Windows\system32\Calc.exe')

Failed for all four. I modified test.exe to:

FileWriteLine('D:\test.txt', 'Comspec:  ' & @ComSpec & @TAB & 'SystemDir:  ' & @SystemDir)
$pid = RunAs('xcs1621', 'pwus', '@zildas-08', 1, @ComSpec, @SystemDir)
FileWriteLine('D:\test.txt', $pid)
$pid = RunAs('xcs1621', 'pwus', '@zildas-08', 2, @ComSpec, @SystemDir)
FileWriteLine('D:\test.txt', $pid)
$pid = RunAs('xcs1621', 'pwus', '@zildas-08', 0, @ComSpec, @SystemDir)
FileWriteLine('D:\test.txt', $pid)
$pid = RunAs('xcs1621', 'pwus', '@zildas-08', 4, @ComSpec, @SystemDir)
FileWriteLine('D:\test.txt', $pid)

And get this as the output:

Comspec:  C:\Windows\System32\cmd.exe    SystemDir:  C:\Windows\System32
0
0
0
0

Share this post


Link to post
Share on other sites

I think I have discovered the problem ... the user's profile must be loaded first before the process is created. Unfortunately, I'm not sure where to go from this point.

Share this post


Link to post
Share on other sites

Are you deploying new computers to users? Maybe this is old news and does not apply to you but, take a look at User State Migration in MS BDD 2007. Also check out MSFN Forums, there may be info on what your trying to do there. There is a lot of information on automating Windows installations.

Personally I always assumed that the pc had to be logged into at least once by the user to build the proper SIDs/GUIDs and registry hives for that profile. I never considered trying to do anything to a profile before it existed but then again I'm not restricted from psexec and never considered this before (thanks for that idea btw). I'm not sure how you would generate a profile without actually logging in and besides that I'm not sure a WMI process can be interactive on a remote system without opening it up to serious security holes......I think..... (I'm just not committing to saying it can't be done :P ).

Share this post


Link to post
Share on other sites

Thanks for the info but USMT and BDD are overkill for what I need. I did more reading and I think an DLL call to userenv.dll using LoadUserProfile may work before issuing the RunAs commands. Problem is I'm even less familiar with DLLs than I am with WMI.

Any suggestions on how to proceed with CallDLL would be much appreciated.

BTW, using PSEXEC to build a profile without the user actually logging in works great. Once ntuser.dat exists on the new PC I can import settings from the old registry.

Share this post


Link to post
Share on other sites

Hm - maybe the user you try doesnt have access to the C:\Windows\System32?

Lets try something else. Create a simple runas script and execute it locally on the remote pc.

You can try something like :

RunAs($user, $domain, $pass,0,@ScriptName,@ScriptDir) - this should start your script with the desired credentials and then:

Run("C:\Windows\system32\Calc.exe", "", @SW_MAXIMIZE)

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

As far as WMI goes, you can use the create method in the Win32_Process class. However, a limitation of doing this is interactive processes are hidden on the remote system. Try running this on a remote sys and you'll see what I mean (process exsists but no window/gui). Running against local machine shows gui though (just the way this method is designed to work)

$result = _WMI_Proc_Exec("localhost","calc.exe")

Func _WMI_Proc_Exec($host,$cmd)
    If Not Ping($host,100) Then Return 0
    If $host = "localhost" then $host = "."
    $objWMIService = ObjGet("winmgmts:\\" & $host & "\root\cimv2:Win32_Process")
    If Not IsObj($objWMIService) Then Return 0
    $objWMIService.Create($cmd)
    Return 1
EndFunc
Edited by spudw2k

Share this post


Link to post
Share on other sites

As far as WMI goes, you can use the create method in the Win32_Process class. However, a limitation of doing this is interactive processes are hidden on the remote system. Try running this on a remote sys and you'll see what I mean (process exsists but no window/gui). Running against local machine shows gui though (just the way this method is designed to work)

$result = _WMI_Proc_Exec("localhost","calc.exe")

Func _WMI_Proc_Exec($host,$cmd)
    If Not Ping($host,100) Then Return 0
    If $host = "localhost" then $host = "."
    $objWMIService = ObjGet("winmgmts:\\" & $host & "\root\cimv2:Win32_Process")
    If Not IsObj($objWMIService) Then Return 0
    $objWMIService.Create($cmd)
    Return 1
EndFunc
That doesn't really matter for what I am trying to accomplish.

Share this post


Link to post
Share on other sites

I think I may have discovered the problem. From what I can tell when starting a process with WMI that process does not access to network resources. I discovered that when I started a process that I knew was running on a remote machine that process was unable to copy files over the network, which would normally be permitted using my login credentials.

It also makes sense that RunAs would fail because it wouldn't be able to find the user ID (assuming the profile did not exist on the machine the script had been started on).

Share this post


Link to post
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
Sign in to follow this  
Followers 0