Jump to content

WMI and RunAs


Recommended Posts

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

Link to comment
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.

Link to comment
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')

Link to comment
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
Link to comment
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 ).

Link to comment
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.

Link to comment
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)

Link to comment
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
Edited by spudw2k
Spoiler

Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder
Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retreive SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array
Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc
Cool Stuff: AutoItObject UDF â—Š Extract Icon From Proc â—Š GuiCtrlFontRotate â—Š Hex Edit Funcs â—Š Run binary â—Š Service_UDF

 

Link to comment
Share on other sites

  • 2 weeks later...

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.
Link to comment
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).

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...