Thursday 29 June 2017

PerfC Vaccination for ExPetr/Petya/NotPetya Wiper

This is a script I've written to 'vaccinate' our domain against the ExPetr/Petya/NotPetya Wiper.

In short, it finds all computer objects in the domain, with an OS that isn't 'Unknown' or 'Windows Server 2003', and attempts to copy 'perfc' to the C:\Windows directory of each machine. I'm not supplying a copy of the file, only the mechanism to deploy it.

If you wish to test the scripts behaviour on a subset of computers on your domain, I've deliberately left a (commented out) searchbase filter on line 24 -


#$WindowsComputers = (get-adcomputer -server $dc -filter * -SearchBase "ou=SOMEOU,dc=YOUR,dc=DOMAIN,dc=HERE").name

....that you can adjust as necessary. Once you've amended line 24, comment out line 20 -

$WindowsComputers = (Get-ADComputer -Server $DC -filter {}).name



This script is provided 'as-is' without warranty of any kind.

EDIT: Fixed bug where summary reported the successful count as the failed count and vice versa
       


#
# Powershell script to copy PerfC vaccine to computers found in Active Directory
#           by Daniel Shuttleworth 
#                credit to @KieranWalsh for his WannaCry PoSH script that this script makes use of
#


# You must specify a source location for PerfC
$Source = "C:\Windows\Perfc"

# You must specify a domain controller here
$DC = "somedc.your.domain"

# Log directory
$log = Join-Path -Path ([Environment]::GetFolderPath('MyDocuments')) -ChildPath "PerfC presence status for $($ENV:USERDOMAIN).log"

#=========================================================

# Find computer objects in Active Directory
$WindowsComputers = (Get-ADComputer -Server $DC -filter {(OperatingSystem  -notlike 'Windows Server 2003*') -and (OperatingSystem -notlike 'Unknown')}).name | Sort-Object


# If you want to test the script and filter on an OU, I've left the below in..
#$WindowsComputers = (get-adcomputer -server $dc -filter * -SearchBase "ou=SOMEOU,dc=YOUR,dc=DOMAIN,dc=HERE").name

# Count computers found in the domain
$ComputerCount = $WindowsComputers.count
"There are $ComputerCount computers in the domain"

#=========================================================

# Create arrays to deliver counts at the end of processing

$PerfCPresent = @()
$Offline = @()
$CopyFail = @()
$CopySuccess = @()

#=========================================================

# Loop through each computer found in the domain and vaccinate if required 


foreach ($computer in $WindowsComputers)
{
 
 # Check computer is online
 try
 {
  if (Test-Connection $computer -Count 1 -ErrorAction Stop)
  {
   
   # Check if device already has a PerfC file
   $CheckPerfC = Test-Path \\$computer\C$\Windows\Perfc
   
   # If it does, skip to the next computer
   if ($CheckPerfC -eq $true)
   {
    Write-Host -fore Green "File already present, skipping " -NoNewline; write-host -fore White $computer
    $PerfCPresent += $computer
   }
   
   # If it doesn't exist, copy the file and check it copies successfully
   if ($CheckPerfC -eq $false)
   {
    
    write-host -fore Yellow "Copying to " -NoNewline; write-host -fore white $computer
    
    # Copy the file
    Copy-Item C:\Windows\perfc \\$Computer\C$\Windows\
                $CheckPerfCCopy = Test-Path \\$Computer\C$\Windows\perfc
    
    if ($CheckPerfCCopy -eq $true)
    {
     Write-Host -fore Green "File copied successfully to " -NoNewline; write-host -fore White $computer
     $CopySuccess += $computer
    }
    if ($CheckPerfCCopy -eq $false)
    {
     Write-Host -fore Yellow "File not found on " -NoNewline; write-host -fore White $computer -nonewline; write-host -fore Yellow " copy appears to have failed!"
     $CopyFail += $computer
    }
   }
  }
  
 }

 Catch { $Offline+=$Computer }
}


#=========================================================
 
 # Summarise findings
 
 "Summary for domain: $ENV:USERDNSDOMAIN"
 "PerfC Present ($($PerfCPresent.count)):" | Out-File -FilePath $log -Append
 $PerfCPresent -join (', ') | Out-File -FilePath $log -Append
 '' | Out-File -FilePath $log -Append
 "PerfC Copy Succeeded($($CopySuccess.count)):" | Out-File -FilePath $log -Append
 $CopySuccess -join (', ') | Out-File -FilePath $log -Append
 '' | Out-File -FilePath $log -Append
 "PerfC Copy Failed($($CopyFail.count)):" | Out-File -FilePath $log -Append
 $CopyFail -join (', ') | Out-File -FilePath $log -Append
 '' | Out-File -FilePath $log -Append
 "Offline/Untested($(($Offline).count)):" | Out-File -FilePath $log -Append
 $Offline -join (', ') | Out-File -FilePath $log -Append
 
 "Of the $($WindowsComputers.count) windows computers in active directory, $($Offline.count) were off, $($CopyFail.count) had issues copying PerfC, $($CopySuccess.count) were vaccinated this run and $($PerfCPresent.count) had a PerfC vaccine present already."
 'Full details in the log file.'
 
 try
 {
  Start-Process -FilePath notepad++ -ArgumentList $log
 }
 catch
 {
  Start-Process -FilePath notepad.exe -ArgumentList $log
 }


#=========================================================


 

Thursday 30 March 2017

Opening a CD drive using PowerShell

Whether you want the code because April 1st looms large, or because you're trying to show someone at a remote site which desktop they need to do something with, here it is - 



       

Invoke-Command -ComputerName PC-0101 -ScriptBlock {

$ShApp = New-Object -ComObject "Shell.Application"
$ShApp.Namespace(17).Items() | 
    Where-Object { $_.Type -eq "CD Drive" } | 
        foreach { $_.InvokeVerb("Eject") }
 }

       
 

Tuesday 21 February 2017

Creating and managing licpath.lic files for use with Autodesk Revit/Autocad network licenses


***Clearing out an old blog, repost from four years ago!***


The Licpath.lic file is the fourth location Autodesk applications look in when determining where to go to obtain a license.

Licpath.lic files can be configured per machine or included in an admin image/deployment script.

Licpath files are created using any plain text editor - Notepad should cover the majority of
users out there. 


They MUST be named Licpath.lic and placed in the applications program files directoy. For example:


C:\Program Files\Autodesk\Revit Architecture 2013\Program\Licpath.lic




The licpath.lic file must be in the following format:


SERVER <server name> <Host ID>
USE_SERVER


For example:



SERVER adsk_flex1 010203040506
USE_SERVER








In this example, our server hostname is adsk_flex1 and its MAC address is 010203040506

If for whatever reason you're using a non-standard port, you can also set this in the licpath file:

SERVER adsk_flex2 010203040506 33868
USE_SERVER

The above file would attempt to communicate using port 33868. (Without a port defined, the software will attempt to access the license server via the default port, 27000)







Additional Information



http://usa.autodesk.com/adsk/servlet/ps/dl/item?siteID=123112&id=2887766&linkID=9240617


Creating and managing the adskflex.opt Options File for use with AutoDesk Network License Manager/Flex License Manager

***Clearing out an old blog, repost from four years ago!***


Managing the adskflex.opt Options File




Options files are created using any plain text editor - Notepad should cover the majority of users out there. They MUST be named ADSKFLEX.OPT and placed in the same directory as your license file to take effect.






Options are defined on separate lines and can be as complex or simple as your organisation requires. To insert comments, lines should begin with a #




An example options file used in our environment is as follows:
#Adskflex.opt V1.8
REPORTLOG +"D:\Licenses\Autodesk\REPORT.RL"
MAX 0 71200ACD_2010_0F INTERNET *.*.*.*
MAX 0 85536ACD_2011_0F INTERNET *.*.*.*
MAX 0 85730ACD_2012_0F INTERNET *.*.*.*




#Adskflex.opt V1.8 - This is a comment, as indicated by the # at the start of the line. Use comments regularly to make your file as easy to read as possible.




REPORTLOG +"D:\Licenses\Autodesk\REPORT.RL" -  This line defines the location of the options file report log, useful to check how regularly your options rules are matched






MAX 0 71200ACD_2010_0F INTERNET *.*.*.* 


The above line can be broken up into multiple parts.


Max 0 -  The "Max" option allows us to restrict the maximum license usage. We can restrict by groups of users, IP address, IP address ranges or using the LM_PROJECT variable.


In the rule above, we allow for 0 users of AutoCAD 2010 to obtain a license, with a scope of any IP address


71200AC_2010_0F




This defines the feature code of the application we want to control access to. In this case,. the AutoCAD 2010 feature code is defined. A full list of feature codes for the various Autodesk applications can be accessed via the links below:


Autodesk 2010 Product Suite


Autodesk 2011 Product Suite


Autodesk 2012 Product Suite


Autodesk 2013 Product Suite


Internet


This is the scope the option will apply to. In the example above we apply the option to all IP addresses, as indicated by the wildcard *.*.*.* (Any IP address)
Additional Information


http://usa.autodesk.com/adsk/servlet/ps/dl/item?siteID=123112&id=7459915&linkID=9240617

http://www.globes.com/support/utilities/fnp_LicAdmin_11_9_1.pdf







Output all AD user 'scriptpath' attributes to CSV

As the title suggests, a one liner to output all 'scriptpath' attributes currently set within Active Directory.


Get-ADUser -filter * -properties scriptpath | ft Name, Scriptpath > C:\Temp\AD-ScriptPaths.txt


You may wish to expand on your search by filtering out accurate values, say logon\logon.bat. The following would achieve this -


Get-ADUser -filter {scriptpath -notlike "logon\logon.bat"} -properties scriptpath | ft Name, Scriptpath > C:\Temp\AD-ScriptPaths.txt

Add AD users to group, based on email address

This is a short script I wrote to add a user account to a group, using only the email address associated with the account.

As a side note, this is my first post of the year so perhaps a 'Happy New Year!' is required?!!

To use the script, modify $DC, $users and $group. Remember that $users should point to a text file containing mail addresses, if you wish to use it as I did.
       

# Import AD Module

Import-Module ActiveDirectory

# Get Credentials

$Creds = Get-Credential -Credential "$env:USERNAME"

# Domain Controller to use

$DC = "some.dc.network"

# Path to text file containing usernames to be added to the group
$Users = Get-Content "\\here\are\my\users.txt"

# Group name to add users to
$Group = "Some Group"


# Add users to the group
foreach ($user in $users){
write-host -fore white "Finding user.."
$FoundUser = Get-ADUser -Filter {EmailAddress -eq $user} -Credential $Creds
write-host -fore white "Adding $user to $group"
Try{
Add-ADGroupMember $group $founduser.sid -Credential $Creds -server $DC}
Catch {
write-host -fore Red "Failed to add $user to $group"
}

       
 

Thursday 1 September 2016

Importing, looping and looping some more..

I've had some issues deploying PowerShell scripts recently via SCCM because some of our clients remain on old versions of the Windows Management Framework and PS2.0. To get around the issue I wrote a short script that makes the required changes from my own machine - or some other, logged on with the appropriate rights.

The example script imports the contents of a specified CSV file, loops through each computer, loops through each user profile on that computer and manipulates an ini file, if found, within any user profile on the device.

       


$Computers = Get-Content "\\server\some\share\computers.csv"

# Loop through computers

foreach ($computer in $computers)
{
 Write-Host "Connecting to $computer"
 $CheckComp = Test-Path "\\$computer\C$"
 
 #If computer is offline
 if ($CheckComp -eq $False)
 {
  Write-Host -fore Red "Can't contact $computer - is it online?"
  sleep 1
  #exit
 }
 
 #If computer is online
 if ($CheckComp -eq $True)
 {
  # Grab the remote contents of C:\Users
  $users = get-childitem "\\$computer\C$\Users\"
  
  # Loop through the remote users and manipulate the .ini file
  foreach ($user in $users)
  {
   $Path = "\\$computer\C$\Users\$user\AppData\Roaming\SomeApplication\LicenseDetails.ini"
   $PathExists = Test-Path $path
   if ($PathExists -eq $true)
   {
    (Get-Content $Path).replace('proxyUse=-1', 'proxyUse=-0') | set-content $Path
    (Get-Content $Path).replace('proxyHost=proxy.some.company.com', 'proxyHost=') | set-content $Path
    (Get-Content $Path).replace('proxyPort=8080', 'proxyPort=') | set-content $Path
    write-host "$user's license file changed"
   }
  }
  
  }
 }

       
 

PerfC Vaccination for ExPetr/Petya/NotPetya Wiper

This is a script I've written to 'vaccinate' our domain against the ExPetr/Petya/NotPetya Wiper. In short, it finds all comput...