List Last Windows Password Change For All Users On A Non-Domain System - windows

I have found an answer to this question for systems that are attached to an AD domain controller. However, this question is for standalone systems where there is no possibility of attaching to a domain controller. Essentially, air-gapped systems.
Short and sweet: Is there a way to list the last time each user changed their Windows password for a non-domain, air-gapped system (either Windows 7 or 10) all at once either as a batch file or PowerShell script?
I know that net user {username} | find /I "Password last set" will do it for them one at a time. However, that would be tedious to run multiple times per machine and we have over 60 systems of this type. So I'm looking for a way to do this in one fell swoop, if possible.
As a caveat, we don't have the option of installing the activedirectory module in PowerShell for this. Also, since the majority of the systems are Windows 7, we don't have access to the Bash command line tools that would be available in Windows 10.
Any and all help with regard to this is appreciated.

Here's one way using the ADSI WinNT provider:
$computerName = [Net.Dns]::GetHostName() # i.e., local computer
$computer = [ADSI] "WinNT://$computerName,Computer"
$childObjects = $computer.Children
foreach ( $childObject in $childObjects ) {
if ( $childObject.Class -eq "User" ) {
if ( $childObject.PasswordAge[0] -gt 0 ) {
$pwdLastSet = (Get-Date).AddSeconds(-$childObject.PasswordAge[0])
}
else {
$pwdLastSet = $null
}
$childObject | Select-Object `
#{Name="AdsPath"; Expression={$_.AdsPath}},
#{Name="PasswordLastSet"; Expression={$pwdLastSet}}
}
}

Related

Trying to back up my Bitlocker Key to ADDS Through Script

I'm trying to automatize the process of storing BitLocker Keys to ADDS.
I wanna be able to run the following script at logon, in order to do that, as the OS is deployed through WDS which already encrypts the drive:
$BitVolume = Get-BitLockerVolume -MountPoint $env:SystemDrive
$RecoveryKey = $BitVolume.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' }
Backup-BitLockerKeyProtector -MountPoint $env:SystemDrive -KeyProtectorId $RecoveryKey.KeyProtectorID
BackupToAAD-BitLockerKeyProtector -MountPoint $env:SystemDrive -KeyProtectorId $RecoveryKey.KeyProtectorID
I always get access denied as this has to run as admin...
Is there any command I can use prior the code to run it as admin?
I've googled but I found no useful info to actually do this...
As for the access denied part... as was already sated, you need to start your PowerShell session as an admin. However, as a point of note about your code, you are only targeting the system/os volume... which may not be the only volume that's encrypted. If you want to programmatically backup all of the encrypted volumes, may I suggest one of the two following options...
One-liner:
Get-BitLockerVolume | where {$_.VolumeStatus -like "FullyEncrypted"} | foreach {foreach($Key in $_.KeyProtector){if($Key -like "RecoveryPassword"){Backup-BitLockerKeyProtector -MountPoint $_.mountpoint -KeyProtectorId $key.KeyProtectorId}}}
Or, if you prefer something a little bit easier to read...
Script Block:
foreach ($BLV in Get-BitLockerVolume){
if ($BLV.VolumeStatus -like "FullyEncrypted"){
foreach ($Key in $BLV.KeyProtector) {
if ($Key -like "RecoveryPassword") {
Backup-BitLockerKeyProtector -MountPoint $BLV.MountPoint -KeyProtectorId $Key.KeyProtectorId
}#if
}#foreach
}#if
}#foreach
Neither is super eloquent... but, with this method it will grab all of the encrypted volumes on the system and add them to AD. You would need to modify the code slightly to add the AAD backup option you cited of course.
P.S. I'm only responding because I recently had to solve this problem of multi-volume backups as a one-liner solution and figured I would share it since your post was a top search result when I looked for a pre-canned solution. Cheers! :)

SCCM 2012 OSD Task Sequence - Rename computer with Service Tag

I am planning to deploy Windows 10 using SCCM 2012. It is working fine, and now I just want to rename the computer to be same as its DELL service tag, and make it as part of Task Sequence. I would ideally like to use Powershell script to do so, however happy to use VBS as well, in case it isn't easy enough with PS.
Following is the Powershell script that does the job, however I can't add it as part of Task Sequence!
$sTag = Get-WmiObject -Class win32_BIOS | Select SerialNumber
$cName = 'DESKTOP' + $sTag.SerialNumber
Rename-Computer -NewName $cName
Can someone please assist?
Thanks in advance.
I think you would be better off not renaming the computer after it is already present in sccm and ad but give it a proper name before it is joined (assuming you use unknown computer support for the osd here)
In this case you should set the SCCM Variable OSDCOmputerName already within the WinPE phase like this (you can find more detailed examples e.g. here):
$sTag = Get-WmiObject -Class win32_BIOS | Select SerialNumber
$OSDComputerName = 'DESKTOP' + $sTag.SerialNumber
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value("OSDComputerName") = $OSDComputerName
If you want to use powershell in PE you will have to modify your boot image (Right click --> Properties --> Optional Components) to include "Windows PowerShell"

WScript.Shell in VBScript not working on Windows RT

In Windows RT on a Surface tablet, I'm running a VB script that fails on the first line which is:
Set WshShell = WScript.CreateObject("WScript.Shell")
The error message says:
Could not create object WScript.Shell with the error code: 80070005
This seems to be a generic error code having to do with access permissions. Any ideas?
I am running with admin privileges.
Windows RT (also known as Windows 8 RT, Windows 8.1 RT, and Surface RT) uses User Mode Code Integrity (UMCI) to restrict the software that is allowed to run.
In the case of VBScript, the Code Integrity component of UMCI only allows creation of "enlightened" COM objects.
"Which COM objects are enlightened?" you ask. Good question. Let's use PowerShell on our Windows RT device to help us find out.
$arrInstances = #(Get-WMIObject -ClassName 'Win32_COMSetting')
$arrCOMObjectProgIDs = #($arrInstances | Where-Object { $null -ne $_.ProgId } |
ForEach-Object { $_.ProgId })
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue
$result = #($arrCOMObjectProgIDs | ForEach-Object { if (New-Object -ComObject $_) { $_ } })
$result
On my fully-patched Surface 2 device, as of today, 2021-Jan-17, the only enlightened COM objects with a ProgID (i.e., the only ones callable from VBScript on Windows RT) are:
Scripting.FileSystemObject
VBScript.RegExp
Scripting.Dictionary
It is not possible to create other VBScript objects (e.g., WScript.Shell, WScript.Network, WinNTSystemInfo, Wbemscripting.SWbemLocator, etc.) on Windows RT due to User Mode Code Integrity (UMCI).
For a more-robust version of the above code, check out my script "Get-COMObjectsProgIDsAllowedToLaunch.ps1" posted to my GitHub repo: https://github.com/franklesniak/PowerShell_Resources
I've seen in a few places people commenting that RT doesn't allow VBScript to run WScript.Shell, though I've not found any official documentation to that effect.
It may just be that the script needs to run with Admin privileges.

Retrieving computers where specified user is in local admin group?

I have windows domain network, i have about 3000 hosts in there. I would like to just check the info which of those hosts having specified technical user account in their local admin groups. I am not that great at power shell, though I know the base things.
I belive that I have to make a list of all hosts across several subnets I have and then run a script that will try to log on those hosts with looking account credentials.
What could be the best solution?
There is a very detailed post on TechNet about listing all computers in domain.
And here's the WMI query part (PowerShell, $aComputerList is a list of computer names):
foreach ($sComputerName in $aComputerList) {
$sUserPattern = 'Win32_UserAccount.Domain="domainname",Name="username"'
$sGroupPattern = 'Win32_Group.Domain="{0}",Name="Administrators"' -f $sComputerName
$oResult = Get-WmiObject -ComputerName $sComputerName -Class Win32_GroupUser | `
Where-Object {
($_.groupcomponent -match $sGroupPattern) -and `
($_.partcomponent -match $sUserPattern)
}
[Bool]$oResult
}
The hard part is that some computers probably won't be reachable (if they're turned off for instance). So you'll need to run your script several times and remove computers from the list as you get responses from them.

PowerShell Script Running as a Service Behaves Strangely

PowerShell Script Running as a Service Behaves Strangely
The Project:
Create a background process that determines if the on board network card is connected. If it is connected, disable the wireless network card. When the onboard network card is not connected, re-enable the wireless card.
Why:
Users hot-dock all the time, getting funky routing tables OR get bound to the wrong DNS servers. When they attempt to access a local resource, say printers, they aren’t able to and then are in my cube (they would file a ticket, but that too would be a local resource). Trying to convince users to disable their own wireless (via switch on laptop) or not hot dock has met with limited success.
The Problem:
The PowerShell script below does run, and does work under my testing conditions. Likely under most testing conditions as the code and wmi queries are pretty generic. Running the script manually yields the expected results, HOWEVER running the script as a service via the only method I could find, srvany.exe, yielded unexpected results and “broke stuff”.
Details:
Running the script as a service, via srvany.exe, works ONCE. When the loop comes back around to test the network connection or tries the method to enable or disable it. The errors indicate that “get-wmiobject” is not a proper Cmdlet. Huh? It works, manually, it works once, but a second time after it disabled the wireless network card it does not. Worse yet MY shell , outside of the service, suddenly can’t do a get-wmiobject, until…. until you go into Device Manager and re-enable the wireless network card yourself.
Debugging attempts:
I rewrote the script and cleaned it up a little to allow for it to get the objects outside of the Do While loop. Nothing changed, but I left the script that way as it seems cleaner anyhow. I enabled “Interact with Desktop” in the service properties and sure enough you can see the script trying to work and getting the before mentioned errors.
Please help. Again the object here is to run a background process, one with enough privileges in Vista or 7 to disable and enable the wireless network card.
#***********************************************************************
# "switch-wifi-srv.ps1"
# This script attempts to identify if a wired network card is in use if
# one is, the Wireless network card is disabled, until the wired network
# card is no longer in use.
#
# Written by Aaron Wurthmann - aaron (AT) wurthmann (DOT) com
#
# 2010.02.10 ver 2 (Service Version)
# If you edit please keep my name or at the very least original author's.
# As of this writing I am unsure if script will work with all scenarios,
# however it has worked for me on Dell laptops running Windows 7 x64.
# -----------------------------------------------------------------------
# This script comes with ABSOLUTELY NO WARRANTY.
# You may redistribute copies of the script under
# the terms of the GNU General Public License.
# -----------------------------------------------------------------------
# Service Installation:
# Aquire and install the Windows 2003 Resource Kit OR the srvany.exe.
# Use sc.exe and srvany.exe to create a service....
# sc create SwitchWifiAuto binPath= "C:\Program Files (x86)\Windows Resource Kits\Tools\srvany.exe" DisplayName= "Switch Wifi Automatically"
# Edit registry entry for SwitchWifiAuto, add a key and a string value...
# HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SwitchWifiAuto\Parameters]
# "Application"="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -ExecutionPolicy RemoteSigned -File C:\\SwitchWifiAuto\\switch-wifi-srv.ps1"
#************************************************************************
$state=""
$wireStatus=""
$wifiStatus=""
# Get Wired and Wireless Card Objects
$objWire=get-wmiobject -class win32_networkadapter -namespace root\CIMV2 | Where-Object {$_.Name -notmatch "Wireless" -and $_.Name -notmatch "Virtual" -and $_.PhysicalAdapter -eq "True"}
$objWifi=get-wmiobject -class win32_networkadapter -namespace root\CIMV2 | where-object {$_.Name -match "Wireless"}
# Get Name of Service to be Used in totally useless Do While Loop
$objService=get-service -display "Switch Wifi Automatically"
# Begin Do While Loop
Do {
# Get status of wired network card. If enabled and connected set $state to Disable (which will later Disable the Wifi network card)
[string]$wireStatus=$objWire | % {$_.NetEnabled}
if($wireStatus -eq "True") {
$state="Disable"
}
# Get Status of wireless card.
if($objWifi){
[string]$wifiStatus=$objWifi | % {$_.NetEnabled}
# If $state is not set to disable and if the wireless card is currently disabled, enable it.
if($state -ne "Disable") {
if($wifiStatus -eq "False") {
Out-Null -InputOject ($objWifi | % {$_.Enable()})
}
# If $state is set to Disable and if wireless card is currently enabled, disable it.
} else {
if($wifiStatus -eq "True") {
Out-Null -InputOject ($objWifi | % {$_.Disable()})
}
}
}
# Reset Checked Variables for good measure
$state=""
$wireStatus=""
$wifiStatus=""
# Sleep for 120 seconds (two minutes)
Start-Sleep -s 120
# Continuing looping (do while) until the service is not running.
# This is of course technically useless as when the service is not running neither is the script to check if the service is not running.
# I made it this way however because I don't like infinite loops and I thought it would be funny to it this way instead of while $var=0
} while ($objService.Status -eq "Running")
Try to remove any output. Service don't have stdout stream. And when the buffer is full strange thing happens. Just a guess ( I never used powershell ).
Debugging attempts: I rewrote the script and cleaned it up a little to
allow for it to get the objects outside of the Do While loop.
You need to include these within the loop or you will not get updated values and the loop will do nothing.

Resources