Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

How to check EMBG (Unique Master Citizen Number) using regex

In this post, I will share my implementation of how to check if some number looks like EMBG or Unique Master Citizen Number. For those of you who are not aware what is EMBG (Unique Master Citizen Number), please check Unique Master Citizen Number . Long story short, it's a composition of 13 digits, where first 7 digits are representing date in format ddMMyyy, and for the rest of the digits please check the wiki link. The yyy are the last 3 digits of year. The last digit from the 13-digit composition is checksum number, and should be checked outside of regex checking. The following regex should be validating EMBG (Unique Master Citizen Number) for Macedonia, but can be modified to check Unique Master Citizen Number for the rest of exYu countries (except Croatia, which seems that has changed the format according to the wiki article). The regex is validating 20th and 21th century year. Also, it's aware of leap year, and validating 2902 in ddMM input, if applicable.
Here is the regex :

^(?:(?:(?:0[1-9]|1\d|2[0-8])(?:0[1-9]|1[0-2])|(?:29|30)(?:0[13-9]|1[0-2])|31(?:0[13578]|1[02]))[09]\d{2}|2902[09](?:[02468][048]|[13579][26]))4[1-9]\d{4}$

 

And the diagram for the syntax is following:


Here are some tests using powershell:


The usage of this regex can be various, starting from beginner code input testing, to some exchange transport rule or data loss prevention rules. 

Feel free to test, and have some fun.



Checking Cisco WSA For New Updates Availablity

In this post I will share my PowerShell code for querying the availability of new updates for Cisco WSA (Web Security Virtual Appliance). Unfortunately, Cisco has not created API for this product for querying the status, so I've created script with web requests that basically simulate user's interaction for accessing the web page with updates status info, that looks like this :

The column of interest is "New Update".

I will break the code in several sections for easy reading. So, here is the first part, where I'm ignoring the web certificate provided by the Cisco WSA :

add-type -TypeDefinition  @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
        return true;
    }
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

In the next part, I'm collecting the proper credential for checking the updates status, and passing them to the Cisco WSA. In the web request, I'm creating the session variable ses, and collecting the CSRF token and storing it into $csrf variable.

$credential = get-credential -username user -Message "Type Credential"
$Req = Invoke-WebRequest 'https://cisco.wsa.url/login' ` -UseBasicParsing -SessionVariable ses
if (-not $? -or $Req.Content -notmatch '<.+csrf.+value=\"(.+)\"') {
                         return
                       }
$Csrf = $Matches[1]

Creating the body for the request, and sending to the login form of Cisco WSA:

$Body = @username = "$($credential.username)"; ` password = "$($Credential.GetNetworkCredential().password)"; ` action = "Login"CSRFKey = "$Csrf"}
$loginp = Invoke-WebRequest -Uri ("https://cisco.wsa.url/login") `  -Method POST -Body $body -WebSession $ses ` -ContentType "application/x-www-form-urlencoded"

After successful login in, I'm making web request to the URL that contains the update info. The content received, I'm converting it from JSON:

$status = Invoke-WebRequest ` -uri ("https://cisco.wsa.url/security_services/url_filters/anti_malware") ` -websession $ses  

if (-not $? -or $status.Content -notmatch '\"https.*GetAvailabilityStatus.*\"') {
  return
}

$UpdateURL = $Matches[0].Replace('"',"")

$updates = Invoke-WebRequest -uri ($UpdateURL-websession $ses

$updates.Content | ConvertFrom-Json

And the output looks like :

Cisco DVS Object Type Rules                                          : Not Available
Cisco DVS Engine                                                     : Not Available
Cisco DVS Malware User Agent Rules                                   : Not Available
Cisco Web Usage Controls - Application Visibility and Control Data   : Not Available
Cisco URL Categories Database                                        : Not Available
Cisco Web Usage Controls - Web Categorization Categories List        : Not Available
Cisco URL Categories Database Incremental Updates                    : Not Available
McAfee Engine Definition                                             : Not Available
L4 Traffic Monitor Anti-Malware Rules                                : Not Available
Web Reputation Rules                                                 : Not Available
Sophos IDE                                                           : Not Available
Web Reputation IP Filters                                            : Not Available
Webroot Anti-Malware Engine                                          : Not Available
Advanced Malware Protection - Engine Definition                      : Not Available
McAfee DATs                                                          : Not Available
Cisco URL Filtering Engine                                           : Not Available
Cisco Web Usage Controls - Dynamic Content Analysis Engine Data      : Not Available
Cisco Web Usage Controls - Web Categorization Engine                 : Not Available
Cisco Web Usage Controls - Application Visibility and Control Engine : Not Available
Cisco Certificate Blacklist                                          : Not Available
Web Reputation Engine                                                : Not Available
Cisco Internal Certificates - Advanced Malware Protection            : Not Available
Time zone rules                                                      : Not Available
Webroot Malware Categories DATs                                      : Not Available
McAfee Anti-Malware Engine                                           : Not Available
Cisco Trusted Root Certificate Bundle                                : Not Available
Webroot Engine Definition                                            : Not Available
Sophos Engine                                                        : Not Available
Advanced Malware Protection - Cloud Configuration and Settings       : Not Available
Cisco Web Usage Controls - Web Categorization URL Keyword Filters    : Not Available
Cisco Web Usage Controls - Web Categorization Prefix Filters         : Not Available
Web Reputation Prefix Filters                                        : Not Available
Cisco Web Usage Controls - Dynamic Content Analysis Engine           : Not Available


I hope you will find this code useful. It can be used in different scenarios when there are no APIs (like this one for example), and you will like to automate some manual tasks.

Happy codding !

Searching For Email Groups Without Members

This is quick one for a reference, searching for AD groups with present email address, but without members using LDAP filter and powershell:
 Get-ADObject -LDAPFilter "(&(objectcategory=group)(!(member=*))(mail=*))" 

Same LDAP filter can be used with Active Directory Users and Computers:


Happy hunting :) 

List MPIO disks active paths

This is a single liner PowerShell for listing active paths on MPIO disk devices:
(gwmi -Namespace root\wmi -Class mpio_disk_info).driveinfo | % {Write-host "Name: $($_.name) Paths: $($_.numberpaths)"}

Tested on Windows Server 2012 R2. This single liner should also work on other Windows Server editions.

And in case if there are multiple servers for checking the active paths on MPIO disk devices, here is the modified single liner (it's presumed that user running the bellow single liner owns the necessary permissions, and there are necessary firewall rules for accessing remote servers):
"server1","server2","server3" | % { write-host $_ -ForegroundColor green  ; (gwmi -ComputerName $_ -Namespace root\wmi -Class mpio_disk_info).driveinfo | % {Write-host "Name: $($_.name) Paths: $($_.numberpaths)"}}

Tested also on Windows Server 2016. 

Searching for AD users with missing email address

In this case, I was searching for AD users with populated proxyaddresses property, but with missing email address from specific domain. For example: a user was having following email addresses: user@domain-a.com and user@domain-c.com, but was missing the user@domain-b.com. I wrote a singleliner PowerShell for listing those users:

Get-ADUser -LDAPFilter "(&(proxyAddresses=*)(!proxyAddresses=smtp:*domain-b.com))" -Properties * | ? {$_.enabled -eq $true } | ft name,proxyaddresses -AutoSize -Wrap
Also, there was one more condition that users with missing email address have to be enabled.

I hope that this singleliner Powershell will help you in a quest for missing email addresses.
 

Finding scripts in GPOs

For this case I wrote a simple PowerShell easy to read script for finding GPOs with scripts and their links to OUs. The script requires domain administrator credential for enumerating GPOs machine startup folder. For populating $dc and $dom variables the script requires online domain controller and domain name. Then the script will start to enumerate policies folders searching for files with vbs,bat, and vbe extensions. It will also filter out with regex the gpo guid found between the curly brackets "{}"in the full file path. Using the gpo guid the script will resolve the gpo name and OUs where that gpo is linked. At the end the script will output the data.

$dc = Read-Host "Online DC (example:dc1)"
$dom = Read-Host "Domain name (example:domain.com)"

dir \\$dc\SYSVOL\$dom\Policies -Include *.vbs,*.bat,*.vbe -Recurse | select -ExpandProperty Fullname | Select-String -Pattern "(?<=\{).*?(?=\})"  | % {

    $id=$_.matches[0].value
    $gpo=get-gpo -guid $id
    $ou =Get-ADOrganizationalUnit -LDAPFilter "(gPLink=*$id*)"

    Write-host $_
    Write-Host "GPOName=" -ForegroundColor Red -NoNewline
    Write-host $gpo.DisplayName -NoNewline
    Write-Host "`tStatus=" -ForegroundColor Yellow -NoNewline
    Write-host $gpo.GpoStatus
    Write-Host "OUlinks=" -ForegroundColor Green -NoNewline
    Write-host $ou.Name
    Write-Host " "

}


Feel free to customize or modify the script to satisfy your needs.
 

Exchange Powershell in Multi Domain Environment

This is quick one, if you're using Exchange PowerShell for managing environment where exchange recipients are located across multiple domains in forest, you might be wondering why by default you will not be able to manage recipient objects that are located in different domains. The reason for this behavior is that by default, you will be able to manage objects that are located in the domain where Exchange servers are located.
In order to change this behavior, for example to manage recipient objects located across forest Set-AdServerSettings cmdlet is your friend:
Set-AdServerSettings -ViewEntireForest $true
One thing to notice is that, the change of this view scope is only limited to current open session.
 

How to find the latest OS Image from Microsoft Azure Galery

This post is for reference and is intended to simplify the way of finding the latest available operating system image from Azure gallery using PowerShell (I will not get into details how to connect to your azure subscription using PowerShell).
Here is an example of how to get the latest image for Windows Server 2012 R2 Datacenter edition:

$OSImage = (Get-AzureVMImage | where {$_.ImageFamily -like "Windows Server 2012 R2 Datacenter*"} | sort PublishedDate -Descending)[0].ImageName

or Ubuntu Server 14 LTS:

$OSImage = (Get-AzureVMImage | where {$_.ImageFamily -like "Ubuntu Server 14*LTS*"} | sort PublishedDate -Descending)[0].ImageName


The logic in these one liners PowerShell is very simple, the output from Get-AzureVMImage is first filtered by ImageFamily and then sorted descending by PublishedDate. The first listed (latest published) image name is put into $osimage variable. Now, "armed" with latest image of the operating system, you can proceed in creating Azure Virtual Machine.
 

Check Microsoft Exchange Services

In this post I would like to share one liner PowerShell, which I'm using in my Exchange test lab environment to check if all Microsoft Exchange services set to start automatically are running, and if not to start them:
"exserver1","exserver2" | % { get-wmiobject win32_service -computername $_ -filter "startmode = 'auto' and state != 'running' and name like 'MSExchange%'" |  % {write-host $_.PSComputername, $_.name; $_.startservice() | out-null }}

In my case there are two exchange servers exserver1 and exserver2, but you can change them to reflect your environment.
I'm also sharing this one liner PowerShell with my students when I'm teaching Microsoft Exchange courses to easily check MS Exchange services on their lab virtual machines. Sometimes not all necessary MSExchange services are started when the lab virtual machines boots up, and there might be problems during student's testing of lab scenarios. This one liner PowerShell is very simple way to avoid that situation.
 

Hyper V VMs revert to snapshot

I'm writing this post because I would like to share my experience of teaching MOC 20341B Core Solutions of Microsoft Exchange Server 2013 with my fellows MCTs. After each module there is a lab in which students can practice with virtual machines reverted to initially created snapshot. Also, after teaching each module I'm reverting VMs to their initial state, before starting to teach the next module.
In order to simplify this task of reverting VMs to their initial state, I wrote quick single liner powershell in which I'm reverting VMs that are running and their name contains 20341B:

Get-VM | ? { $_.state -eq 'Running' -and $_.name -like '*20341B*' } | % { Write-host $_.name ; Get-VMSnapshot $_.name | Restore-VMSnapshot -Confirm:$false }

This single liner powershell can be improved and adjusted to your needs, for example revert VMs on all student's Hyper V hosts ...
 

How to find out all locked out accounts in Active Directory using Powershell

This one liner PowerShell for reference, is intended to show how to find out all locked out accounts in Active Directory using Search-ADAccount with LockedOut parameter (ActiveDirectory module is required):
Search-ADAccount -LockedOut
The output from this cmdlet will list all the locked out accounts. Furthermore, if you want to unlock all those accounts, the output of the Search-ADAccount can be piped to Unlock-ADAccount cmdlet (permission for unlocking ad accounts is required) for example:
Search-ADAccount -LockedOut | Unlock-ADAccount

For more info about these powerful cmdlets please check TechNet: Search-ADAccount and Unlock-ADAccount .
 

Finding the currently logged on user using powershell and WMI

This is quick one for reference, here is an example how to find out currently logged on user on remote computer or local computer (administrative permission is required for querying remote computer) using PowerShell single liner:

Get-WmiObject win32_ComputerSystem -ComputerName Remote computer name or IP address | Select username
 
For finding out the currently logged on user, WMI and Win32_ComputerSystem class is used. Win32_ComputerSystem class has username property which contains the currently logged on user. For more information about Win32_ComputerSystem class please check the MSDN article http://msdn.microsoft.com/en-us/library/aa394102(v=vs.85).aspx .

My first thought was to find out the currently logged on user, but what about the users that are logged on and are switching between their profiles ? That's when the things get complicated. Anyway, here is PowerShell script which will list logged on users on remote or local machine, even if they are switching between profiles on same pc (for comp variable add the ip address or computer name of the machine, also administrative permission are required) :

$comp="computername or ip address"
Get-WmiObject win32_logonsession -ComputerName $comp -Filter "Logontype = '2' or Logontype='11' or logontype='10'" |
foreach {Get-WmiObject win32_loggedonuser -ComputerName $comp -filter "Dependent = '\\\\.\\root\\cimv2:Win32_LogonSession.LogonId=`"$($_.logonid)`"'" | select Antecedent } |
foreach { ($_.antecedent.split('"'))[1] + "\" + ($_.antecedent.split('"'))[3] } | select -unique

WMI is utilized and Win32_LogonSession and Win32_LoggedOnUser classes are used. From Win32_LogonSession I'm filtering for following logontype: Interactive, RemoteInteractive and CachedInteractive, and passing the logonid to Win32_LoggedOnUser class. From Win32_LoggedOnUser class Antecedent property is manipulated to create easy to read output.

For more info about Win32_LogonSession and Win32_LoggedOnUser classes, please check MSDN library : http://msdn.microsoft.com/en-us/library/aa394172(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/aa394189(v=vs.85).aspx .

 

Setting Sleep Option on multiple Windows 8.1 domain computers

This was an easy task that I want to share, and the request was to set the power option when the computer will go into sleep state on a list of Windows 8.1 domain computers. Most of the computers on the list were having the default option of 30 minutes for going into sleep state. And this value of 30 minutes has to be changed into 5 hours, but all computers that were having a changed default setting of 30 minutes into Never must not be set. I was using PowerShell with WMI for achieving this task. And here is the script:

$comps =Get-Content "C:\Temp\Scripts\computers.txt"

foreach ($comp in $comps)
{

if (Test-Connection -ComputerName $comp.Trim() -Quiet)
{
#find the active powerplan
$a = (gwmi win32_powerplan -Namespace root\cimv2\power -ComputerName $comp.Trim() -filter { IsActive = 'True' }).instanceid.split("\")[1]


#find the powersetting for sleep option
$b = (gwmi win32_powersetting -Namespace root\cimv2\power -ComputerName $comp.Trim() -Filter { Elementname = 'Sleep After' }).instanceid.split("\")[1]


#get the value for sleep setting on active power plan
$seconds =  gwmi win32_powersettingdataindex -Namespace root\cimv2\power -ComputerName $comp.Trim() -Filter "InstanceID like '%$a%ac%$b'"

#check if the setting is Never
if ( $seconds.SettingIndexValue -ne 0 )
{


#set the value to 5 hours
    $seconds.SettingIndexValue = 18000
    $seconds.Put()
   
}
else
{

    write-host "$comp has sleep option Never"
}
}
}


The script is easy to understand, but anyway here is the overview:
  • Getting the list of computers from file and looping from each of the computer and checking if the computer is online.
  • In the main part I'm getting the guid for active power plan and guid for sleep option. After that I'm getting the value for sleep option in seconds.
  • And in the last part of the script I'm setting the option for going into sleep after 5 hours if the current value is not 0, which is the value for never put computer into sleep state.

Sweet Dreams :)
 

AD user password expiration

This is quick one for reference, here is an example how to find out when will expire password for some AD user using powershell single liner (replace username with your AD user of interest):

PS C:\Temp> [datetime]::FromFileTime((Get-ADUser username -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed")

Creating Custom Queries For Searching TMG 2010 Logging Databases

In this case I was trying to find out unique client IP addresses that were accessing TMG published web site in last 3 days. TMG server was having locally installed logging database. One way to achieve this task is using SQL Server Management Studio, another way is using powershell. In this article, I'll show how I have found the ip addresses using powershell.
After importing the SQLServerCmdletSnapin100, Invoke-Sqlcmd cmdlet will be available for running:
Add-PSSnapin SQLServerCmdletSnapin100
Now it's time to create the SQL query using here-strings:
$query=@"
SELECT ClientIP as IPAddress from
(SELECT DISTINCT ClientIP
FROM [ISALOG_20130926_WEB_000].[dbo].[WebProxyLog] WHERE [WebProxyLog].[Rule] = 'TMG Rule Name'
UNION
SELECT DISTINCT ClientIP
FROM [ISALOG_20130925_WEB_000].[dbo].[WebProxyLog] WHERE [WebProxyLog].[Rule] = 'TMG Rule Name'
UNION
SELECT DISTINCT ClientIP
FROM [ISALOG_20130924_WEB_000].[dbo].[WebProxyLog] WHERE [WebProxyLog].[Rule] = 'TMG Rule Name')t1;
"@
The SQL query is simple, so I'm not going into details.
Now it's time to execute the query using invoke-sqlcmd :
Invoke-Sqlcmd -Query $query -ServerInstance localhost\msfw -QueryTimeout 300 | ft

The result will contain IP addresses in unfriendly readable format, something like:
C0A8018A-FFFF-0000-0000-000000000000 
The reason for this kind of logging, is that TMG is using same field for logging IPv4 and IPv6 addresses. One way for converting CAA8018A into 192.168.1.138 is using Excel formula which looks like this:

HEX2DEC(MID(A1,1,2)) &"."&HEX2DEC(MID(A1,3,2))&"."&HEX2DEC(MID(A1,5,2))&"."&HEX2DEC(MID(A1,7,2))


Happy IP addresses hunting :)

How to delete printer driver using WMI and powershell

In this case a new network printer was installed on network with ip address w.x.y.z. Unfortunately, this ip address w.x.y.z was belonging to some previously installed network printer that was decommissioned. On network there were client workstations that were using printer driver from the decommissioned printer pointing to w.x.y.z ip address. This situation was causing old spooled documents from clients for the decommissioned printer to print garbage on this new different type of printer with ip address w.x.y.z. The network administrator has provided list of client computers that were trying to empty their spool with old printer driver to the w.x.y.z ip address.
One way to delete this old printer driver pointing to w.x.y.z ip address from clients is using wmi with powershell.
First cancel old print jobs:

PS C:\Temp> (Get-WmiObject win32_printer -computer client1,client2... -filter "Portname = 'IP_w.x.y.z'").cancelalljobs()

Then, delete the print driver :

PS C:\Temp> (Get-WmiObject win32_printer -computer client1,client2... -filter "Portname = 'IP_w.x.y.z'").delete()
 

How to convert string to Base64 and vice versa using Powershell

For debugging purposes I needed a quick way to convert Base64 encoded string. My opinion is that  the easiest way to achieve is to use Powershell.

Here is the example how to convert string "Hello World" to Base64 using ToBase64String method:

PS C:\Temp>$b  = [System.Text.Encoding]::UTF8.GetBytes("Hello World")
PS C:\Temp>[System.Convert]::ToBase64String($b)
SGVsbG8gV29ybGQ=

And here is the example how to decode Base64 string using FromBase64String method:

PS C:\Temp>$b  = [System.Convert]::FromBase64String("SGVsbG8gV29ybGQ=")
PS C:\Temp>[System.Text.Encoding]::UTF8.GetString($b)
Hello World


More about using ToBase64String and FromBase64String methods check:
http://msdn.microsoft.com/en-us/library/system.convert.frombase64string.aspx
http://msdn.microsoft.com/en-us/library/system.convert.tobase64string.aspx
 

How to sign powershell scripts

In order to sign powershell scripts, code signing certificate is needed. Finding code signing certificates from user personal certificate store and storing it to a variable called $signcert can be done using following powershell command:

$signcert = (dir cert:currentuser\my\ -CodeSigningCert)
 
After storing the certificate for signing into $signcert, we can use Set-AuthenticodeSignature to sign the script. I'm running the Set-AuthenticodeSignature with TimeStampServer parameter, that will provide signed script to run even though the signing certificate gets expired. In most cases this scenario will be OK.
There are a lot of TimeStampServer providers, in my example I'll use server from Comodo. So, the signing script cmdlet will look like this :

Set-AuthenticodeSignature .\scripttobesigned.ps1 $signcert -TimestampServer http://timestamp.comodoca.com/authenticode

There is great two part tutorial about signing scripts on:
http://blogs.technet.com/b/heyscriptingguy/archive/2010/06/16/hey-scripting-guy-how-can-i-sign-windows-powershell-scripts-with-an-enterprise-windows-pki-part-1-of-2.aspx

http://blogs.technet.com/b/heyscriptingguy/archive/2010/06/17/hey-scripting-guy-how-can-i-sign-windows-powershell-scripts-with-an-enterprise-windows-pki-part-2-of-2.aspx

 

Generate random alphabetic password with powershell

Following script will generate 15 alphabetic character random string using powershell :

$r = New-Object System.Random
1..15 | % { $pass += [char]$r.next(97,122) }
$pass

 

Scripting Games 2012 Advanced Event 10

Advanced Event 10 :

<#
.DESCRIPTION
    This script creates csv log file for Processor counter set every 2 seconds (10 snapshots).
.LINK
    http://blogs.technet.com/b/heyscriptingguy/archive/2012/04/13/the-2012-scripting-games-advanced-event-10-create-a-csv-log-file.aspx
#>
param (
[string[]]$Computers=$env:computername
)
foreach ($computer in $computers)
{
    $filepath = $env:userprofile + "\Documents\" + $Computer + "_processorCounters.csv"
        Get-Counter -ListSet processor -ComputerName $Computer |
        Get-Counter -ComputerName $Computer -SampleInterval 2 -MaxSamples 10 |
        Export-Counter -path $filepath -FileFormat CSV -Force
}

How to check EMBG (Unique Master Citizen Number) using regex

In this post, I will share my implementation of how to check if some number looks like EMBG or Unique Master Citizen Number. For those of yo...