Does this Last logged user function write anything at all on remote machine

This topic contains 5 replies, has 4 voices, and was last updated by Profile photo of Wei-Yen Tan Wei-Yen Tan 7 months ago.

  • Author
    Posts
  • #38541
    Profile photo of Stuart Mr Aj
    Stuart Mr Aj
    Participant

    Hi, I m very new to PowerShell and just started learning it.
    There is a function I want to run that I found on a website, however I want to confirm that it absolutely does not make any changes to the remote machines that it is run against.
    If possible I just need a bit of a guru to have a look and confirm that its only reading data from the remote machine:

     Function Get-LastLogon 
    
    { 
    
     
    
     
    
    [CmdletBinding()] 
    
    param( 
    
      [Parameter(Position=0,ValueFromPipeline=$true)] 
    
      [Alias("CN","Computer")] 
    
      [String[]]$ComputerName="$env:COMPUTERNAME", 
    
      [String]$FilterSID, 
    
      [String]$WQLFilter="NOT SID = 'S-1-5-18' AND NOT SID = 'S-1-5-19' AND NOT SID = 'S-1-5-20'" 
    
      ) 
    
     
    
    Begin 
    
      { 
    
        #Adjusting ErrorActionPreference to stop on all errors 
    
        $TempErrAct = $ErrorActionPreference 
    
        $ErrorActionPreference = "Stop" 
    
        #Exclude Local System, Local Service & Network Service 
    
      }#End Begin Script Block 
    
     
    
    Process 
    
      { 
    
        Foreach ($Computer in $ComputerName) 
    
          { 
    
            $Computer = $Computer.ToUpper().Trim() 
    
            Try 
    
              { 
    
                #Querying Windows version to determine how to proceed. 
    
                $Win32OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer 
    
                $Build = $Win32OS.BuildNumber 
    
                 
    
                #Win32_UserProfile exist on Windows Vista and above 
    
                If ($Build -ge 6001) 
    
                  { 
    
                    If ($FilterSID) 
    
                      { 
    
                        $WQLFilter = $WQLFilter + " AND NOT SID = `'$FilterSID`'" 
    
                      }#End If ($FilterSID) 
    
                    $Win32User = Get-WmiObject -Class Win32_UserProfile -Filter $WQLFilter -ComputerName $Computer 
    
                    $LastUser = $Win32User | Sort-Object -Property LastUseTime -Descending | Select-Object -First 1 
    
                    $Loaded = $LastUser.Loaded 
    
                    $Script:Time = ([WMI]'').ConvertToDateTime($LastUser.LastUseTime) 
    
                     
    
                    #Convert SID to Account for friendly display 
    
                    $Script:UserSID = New-Object System.Security.Principal.SecurityIdentifier($LastUser.SID) 
    
                    $User = $Script:UserSID.Translate([System.Security.Principal.NTAccount]) 
    
                  }#End If ($Build -ge 6001) 
    
                   
    
                If ($Build -le 6000) 
    
                  { 
    
                    If ($Build -eq 2195) 
    
                      { 
    
                        $SysDrv = $Win32OS.SystemDirectory.ToCharArray()[0] + ":" 
    
                      }#End If ($Build -eq 2195) 
    
                    Else 
    
                      { 
    
                        $SysDrv = $Win32OS.SystemDrive 
    
                      }#End Else 
    
                    $SysDrv = $SysDrv.Replace(":","$") 
    
                    $Script:ProfLoc = "\\$Computer\$SysDrv\Documents and Settings" 
    
                    $Profiles = Get-ChildItem -Path $Script:ProfLoc 
    
                    $Script:NTUserDatLog = $Profiles | ForEach-Object -Process {$_.GetFiles("ntuser.dat.LOG")} 
    
                     
    
                    #Function to grab last profile data, used for allowing -FilterSID to function properly. 
    
                    function GetLastProfData ($InstanceNumber) 
    
                      { 
    
                        $Script:LastProf = ($Script:NTUserDatLog | Sort-Object -Property LastWriteTime -Descending)[$InstanceNumber]               
    
                        $Script:UserName = $Script:LastProf.DirectoryName.Replace("$Script:ProfLoc","").Trim("\").ToUpper() 
    
                        $Script:Time = $Script:LastProf.LastAccessTime 
    
                         
    
                        #Getting the SID of the user from the file ACE to compare 
    
                        $Script:Sddl = $Script:LastProf.GetAccessControl().Sddl 
    
                        $Script:Sddl = $Script:Sddl.split("(") | Select-String -Pattern "[0-9]\)$" | Select-Object -First 1 
    
                        #Formatting SID, assuming the 6th entry will be the users SID. 
    
                        $Script:Sddl = $Script:Sddl.ToString().Split(";")[5].Trim(")") 
    
                         
    
                        #Convert Account to SID to detect if profile is loaded via the remote registry 
    
                        $Script:TranSID = New-Object System.Security.Principal.NTAccount($Script:UserName) 
    
                        $Script:UserSID = $Script:TranSID.Translate([System.Security.Principal.SecurityIdentifier]) 
    
                      }#End function GetLastProfData 
    
                    GetLastProfData -InstanceNumber 0 
    
                     
    
                    #If the FilterSID equals the UserSID, rerun GetLastProfData and select the next instance 
    
                    If ($Script:UserSID -eq $FilterSID) 
    
                      { 
    
                        GetLastProfData -InstanceNumber 1 
    
                      }#End If ($Script:UserSID -eq $FilterSID) 
    
                     
    
                    #If the detected SID via Sddl matches the UserSID, then connect to the registry to detect currently loggedon. 
    
                    If ($Script:Sddl -eq $Script:UserSID) 
    
                      { 
    
                        $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"Users",$Computer) 
    
                        $Loaded = $Reg.GetSubKeyNames() -contains $Script:UserSID.Value 
    
                        #Convert SID to Account for friendly display 
    
                        $Script:UserSID = New-Object System.Security.Principal.SecurityIdentifier($Script:UserSID) 
    
                        $User = $Script:UserSID.Translate([System.Security.Principal.NTAccount]) 
    
                      }#End If ($Script:Sddl -eq $Script:UserSID) 
    
                    Else 
    
                      { 
    
                        $User = $Script:UserName 
    
                        $Loaded = "Unknown" 
    
                      }#End Else 
    
     
    
                  }#End If ($Build -le 6000) 
    
                 
    
                #Creating Custom PSObject For Output 
    
                New-Object -TypeName PSObject -Property @{ 
    
                  Computer=$Computer 
    
                  User=$User 
    
                  SID=$Script:UserSID 
    
                  Time=$Script:Time 
    
                  CurrentlyLoggedOn=$Loaded 
    
                  } | Select-Object Computer, User, SID, Time, CurrentlyLoggedOn 
    
                   
    
              }#End Try 
    
               
    
            Catch 
    
              { 
    
                If ($_.Exception.Message -Like "*Some or all identity references could not be translated*") 
    
                  { 
    
                    Write-Warning "Unable to Translate $Script:UserSID, try filtering the SID `nby using the -FilterSID parameter."   
    
                    Write-Warning "It may be that $Script:UserSID is local to $Computer, Unable to translate remote SID" 
    
                  } 
    
                Else 
    
                  { 
    
                    Write-Warning $_ 
    
                  } 
    
              }#End Catch 
    
               
    
          }#End Foreach ($Computer in $ComputerName) 
    
           
    
      }#End Process 
    
       
    
    End 
    
      { 
    
        #Resetting ErrorActionPref 
    
        $ErrorActionPreference = $TempErrAct 
    
      }#End End 
    
     
    
    }# End Function Get-LastLogon
    
  • #38547
    Profile photo of AK
    AK
    Participant

    Looks like querying and reporting...

  • #38557
    Profile photo of Wei-Yen Tan
    Wei-Yen Tan
    Participant

    It looks like its just querying through WMI and reporting it in a customized manner.

    If you are really concerned look for verbs that say set, remove, new

    With get you can pretty be sure it is safe.

  • #38559
    Profile photo of Stuart Mr Aj
    Stuart Mr Aj
    Participant

    Thank Wei-Yen Tan,

    So I was looking at the verbs and I see these lines that are making a new-object and I am trying to understand exactly what they are doing?

    #Convert Account to SID to detect if profile is loaded via the remote registry

    $Script:TranSID = New-Object System.Security.Principal.NTAccount($Script:UserName)

    $Script:UserSID = $Script:TranSID.Translate([System.Security.Principal.SecurityIdentifier])

  • #38560
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    If you're really in doubt about what's happening run the code one line (or statement) at a time manually and examine the contents of the variables. Look up any cmdlets or .NET classes that you don't understand

    DO THIS IS IN A TEST ENVIRONMENT that you can destroy if things go wrong.

    Its the only way you'll really understand what's happening in the code.

    Its your environment and therefore your responsibility to determine if the code is safe. Other people can tell you that the code looks safe but until you test it in your environment you don't have any guarantees

  • #38561
    Profile photo of Wei-Yen Tan
    Wei-Yen Tan
    Participant

    These type of objects are Seperate to what's in your environment . They don't touch what's in your environment. Objects will create a new representation/view of the data that you already have. It won't modify the data. Just Display what's there. In this case a username.

    As what Richard said. . . If you are really nervous create a seperate environment create a test environment and run the scripts in there.

You must be logged in to reply to this topic.