Advanced Windows PowerShell Scripting Video Training

Advanced Windows PowerShell Scripting Video Training
Advanced Windows PowerShell Scripting Video Training

Wednesday, January 10, 2018

Getting Hacked in Security+

This week we had a little surprise when we were working on the auditing component of our Security+ class here in North Carolina.  The labs this week are built in Azure and I gave each one a public IP address.  On Wednesday afternoon with the VMs online since Monday, we took a look at the failure login attempts.  We got a big surprise with over 11,000 bad logon attempts. 

We then started the second set of VMs fresh.  It took about 10 minutes until we started to see the attempts to access those VMs.  If this does not tell you we operate in a hostile environment, nothing will.  Here is the PowerShell code that we used and the results on the systems online for 10 minutes.

Get-EventLog -LogName Security -InstanceId 4625 |
    Select-Object -Property TimeGenerated,
    @{N="AccountName";E={$_.Message.Split("`n")[12].Replace("Account Name:",$Null).Trim()}},
    @{N="Domain";E={$_.Message.Split("`n")[13].Replace("Account Domain:",$Null).Trim()}},
    @{N="Source";E={$_.Message.Split("`n")[26].Replace("Source Network Address:   ",$Null).Trim()}} 

TimeGenerated        AccountName   Domain Source       
-------------        -----------   ------ ------       
1/10/2018 6:23:36 PM administrator adatum
1/10/2018 6:20:09 PM Administrator Adatum -            
1/10/2018 6:20:09 PM Administrator Adatum -            
1/10/2018 6:13:07 PM ADMINISTRATOR
1/10/2018 6:12:52 PM ADMINISTRATOR
1/10/2018 6:08:53 PM -             -      -            
1/10/2018 6:08:53 PM -             -      -            
1/10/2018 6:05:54 PM Administrator Adatum -            
1/10/2018 6:05:54 PM Administrator Adatum -            
1/10/2018 2:37:23 PM Administrator Adatum -            
1/10/2018 2:37:23 PM Administrator Adatum -  

Let’s find out how many bad logon attempts there were.

Get-EventLog -LogName Security -InstanceId 4625 |
    Select-Object -Property TimeGenerated,
    @{N="AccountName";E={$_.Message.Split("`n")[12].Replace("Account Name:",$Null).Trim()}},
    @{N="Domain";E={$_.Message.Split("`n")[13].Replace("Account Domain:",$Null).Trim()}},
    @{N="Source";E={$_.Message.Split("`n")[26].Replace("Source Network Address:   ",$Null).Trim()}} |

Count    : 13486
Average  :
Sum      :
Maximum  :
Minimum  :
Property : 

Here is the code to provide a list of all attempted user names.

Get-EventLog -LogName Security -InstanceId 4625 |
    Select-Object -Property TimeGenerated,
    @{N="AccountName";E={$_.Message.Split("`n")[12].Replace("Account Name:",$Null).Trim()}},
    @{N="Domain";E={$_.Message.Split("`n")[13].Replace("Account Domain:",$Null).Trim()}},
    @{N="Source";E={$_.Message.Split("`n")[26].Replace("Source Network Address:   ",$Null).Trim()}} |
    Select-object -Property AccountName -Unique |
    Sort-Object -Property AccountName

There was 2137 as of the writing of this article.

Test Generator made with SAPIEN PowerShell Studio

Many of you who read this blog know that I utilize SAPIEN PowerShell Studio when I need a GUI on top of my code.  Here is the latest.  As part of my delivery of Security+ for both the Navy and my civilian business, one item of concern that I hear time and time again is the sheer amount of terminology that students need to memorize.  On the Navy side, we only give them a week to take the course and prep for the exam, which is a huge undertaking.  To help address this issue, I used PowerShell Studio to create a testing engine.

I have always told my PowerShell classes that if the tool does not exist, make it.  This tool continuously repeats questions until the student gets it right.  With several hundred test questions in the pool for the 11 modules that I teach, this test environment is part of the Azure lab environment that I have for each student.  There is another tool to help populate the test engine with questions.  without PowerShell Studio, this would have been very difficult to create with the PowerShell ISE.

Monday, January 8, 2018

What is the difference between –Property and –ExpandProperty in Select-Object

This is often a source of confusion when someone is new to PowerShell.  Since PowerShell is used mostly be non-programers, they often do not understand what an object is.  You need to have a basic understanding of objects to know how these two difference parameters work.  Let me give you an example.
PS C:\> Get-ADUser -Identity AdminUser
DistinguishedName : CN=AdminUser,CN=Users,DC=Adatum,DC=com
Enabled           : True
GivenName         :
Name              : AdminUser
ObjectClass       : user
ObjectGUID        : 696591fc-6697-4d93-b624-3ef7de206ee9
SamAccountName    : AdminUser
SID               : S-1-5-21-817349643-1871075972-606077769-500
Surname           :
UserPrincipalName :
Here you can see a subset of a user object.  This object is displaying 10 properties in the left hand column with their associated values on the right.  Let’s call the Get-Type() method to see the object’s typename.
PS C:\> (Get-ADUser -Identity AdminUser).getType()
IsPublic IsSerial Name    BaseType                                                                       
-------- -------- ----    --------                                                                      
True     False    ADUser  Microsoft.ActiveDirectory.Management.ADAccount 
We can see that this is an ADUser object.  Pipe it to Get-Member
    TypeName: Microsoft.ActiveDirectory.Management.ADUser
Name              MemberType            Definition                                                                                       
----              ----------            ----------                                                                                       
Contains          Method                bool Contains
Equals            Method                bool Equals(S
GetEnumerator     Method                System.Collec
GetHashCode       Method                int GetHashCo
GetType           Method                type GetType(
ToString          Method                string ToStri
Item              ParameterizedProperty Microsoft.Act
DistinguishedName Property              System.String
Enabled           Property              System.Boolea
GivenName         Property              System.String
Name              Property              System.String
ObjectClass       Property              System.String
ObjectGUID        Property              System.Nullab
SamAccountName    Property              System.String
SID               Property              System.Securi
Surname           Property              System.String
UserPrincipalName Property              System.String
Notice again that the entire object is a Microsoft.ActiveDirectory.Management.ADUser object and the property called Name is a System.String object.  Let’s explore the –Property parameter first.
PS C:\> Get-ADUser -Identity AdminUser | Select-Object -Property Name
Now let’s pass this object to Get-Member.
PS C:\> Get-ADUser -Identity AdminUser | Select-Object -Property Name | Get-Member
   TypeName: Selected.Microsoft.ActiveDirectory.Management.ADUser
Name        MemberType   Definition                   
----        ----------   ----------                   
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()            
GetType     Method       type GetType()               
ToString    Method       string ToString()            
Name        NoteProperty string Name=AdminUser     
Notice the TypeName.  It is still a Microsoft.ActiveDirectory.Management.ADUser object, but it is prefixed with Selected.  It is only containing selected information from the original object.  You still see a property called Name with a typename of System.String.  Now let’s look at –ExpandProperty.
PS C:\> Get-ADUser -Identity AdminUser | Select-Object -ExpandProperty Name
You see the user name, but you do not see a column header.  Piping the object to Get-Member reveals the reason why:
PS C:\> Get-ADUser -Identity AdminUser | Select-Object -ExpandProperty Name | Get-Member
   TypeName: System.String
Name             MemberType            Definition                                                                                         
----             ----------            ----------                                                                                        
Clone            Method                System.Object
CompareTo        Method                int CompareTo(
Contains         Method                bool Contains(
CopyTo           Method                void CopyTo(in
EndsWith         Method                bool EndsWith(
Equals           Method                bool Equals(Sy
GetEnumerator    Method                System.CharEnu
GetHashCode      Method                int GetHashCod
GetType          Method                type GetType()
GetTypeCode      Method                System.TypeCod
IndexOf          Method                int IndexOf(ch
IndexOfAny       Method                int IndexOfAny
Insert           Method                string Insert(
IsNormalized     Method                bool IsNormali
LastIndexOf      Method                int LastIndexO
LastIndexOfAny   Method                int LastIndexO
Normalize        Method                string Normali
PadLeft          Method                string PadLeft
PadRight         Method                string PadRigh
Remove           Method                string Remove(
Replace          Method                string Replace
Split            Method                string[] Split
StartsWith       Method                bool StartsWit
Substring        Method                string Substri
ToBoolean        Method                bool IConverti
ToByte           Method                byte IConverti
ToChar           Method                char IConverti
ToCharArray      Method                char[] ToCharA
ToDateTime       Method                datetime IConv
ToDecimal        Method                decimal IConve
ToDouble         Method                double IConver
ToInt16          Method                int16 IConvert
ToInt32          Method                int IConvertib
ToInt64          Method                long IConverti
ToLower          Method                string ToLower
ToLowerInvariant Method                string ToLower
ToSByte          Method                sbyte IConvert
ToSingle         Method                float IConvert
ToString         Method                string ToStrin
ToType           Method                System.Object
ToUInt16         Method                uint16 IConver
ToUInt32         Method                uint32 IConver
ToUInt64         Method                uint64 IConver
ToUpper          Method                string ToUpper
ToUpperInvariant Method                string ToUpper
Trim             Method                string Trim(Pa
TrimEnd          Method                string TrimEnd
TrimStart        Method                string TrimSta
Chars            ParameterizedProperty char Chars(int
Length           Property              int Length {gePS C:\> Get-ADUser -Identity
We are no longer working with the original Microsoft.ActiveDirectory.Management.ADUser object.  We are working with System.String. –ExpandProperty pulled the value of the Name property out of the original object and discarded the original object.  It them placed the value of the Name property in the PowerShell pipeline.  This was a System.String object.
In summary, -Property removed members from an object that you do not want to use and can accept multiple values.  –ExpandProperty removes the original object, but allows the value of the single specified property to continue.

Friday, January 5, 2018

Disconnected PowerShell Web Access Sessions

Today we finished up one of my advanced PowerShell classes.  What was unique about this one is that I ran the labs using Azure which gave the labs internet access.  Because of this, we were able to play around a little bit more and access our PSWA sites on our phones.  That was one cool thing, but the other thing that I never noticed is the ability to have a disconnected session.

Here is our current session:

Notice that I created a variable of $X = 5.  To disconnect, just simply click Save instead of Exit.

Open your web browser again and sign into PowerShell Web Access with the same credentials.  Here is what you get:
From here you can do the following:
  •         Check the current session and select Delete.  This will close the disconnected session.
  •         Click New Session to open a fresh session. 
  •         Click PSWA1.  This is your disconnected session. (You can have multiple disconnected sessions.)

Notice that when you run Get-Variable, your X variable is still present:

Also your history list is preserved.

It’s the little things that you notice from time to time that keeps things interesting.

Wednesday, January 3, 2018

What is the Difference between Get-Help and Get-Command?

Today I am in Columbus, OH delivering a PowerShell class and this question came up once again.  Well, here are a few examples.

Get-Help obviously gives you access to the help system.  The confusion comes when you do this:
Get-Help Update
Get-Command *Update*

Both yield a list of cmdlets that have Update in their name.  Get-Command has a few extra features to help you filter down that list.  For example:
Get-Command -Verb Update

This will list only cmdlets with the verb Help. This next one only list cmdlets with a noun of Help.

Get-Command -Verb Update

You can also filter through specific modules.
Get-Command -Module SmbShare

You can also use these parameters together to help filter cmdlets
PS C:\> Get-Command -Module SmbShare -verb New

CommandType     Name                                               Version    Source             
-----------     ----                                               -------    ------             
Function        New-SmbMapping                               SmbShare           
Function        New-SmbMultichannelConstraint                SmbShare           
Function        New-SmbShare  

Get-Help will show you a list of all possible matches to a query.  If only one result is returned, it automatically opens the help file for what it has found. For example:
Get-Help Hotfix

You will see the help file for Get-Hotfix.  It is the only cmdlet with Hotfix in the name.

Monday, November 6, 2017

How to Compress an NTFS Folder with PowerShell

Yes, I am actually taking a few minutes to write a blog entry.  I was taking a year off but I'm having to much fun teaching my 90th PowerShell class right now.  Here is a quick and easy question.  "How do I compress a folder with PowerShell?"

We have a target of E:\Mod01.  Here is the command.

Get-CimInstance -Query "SELECT * FROM CIM_Directory WHERE Name = 'E:\\Mod01'" |
    Invoke-CimMethod -MethodName Compress

The CIM_Directory class has all that we need.  The filter of 'E:\\Mod01' is not a typo.  We need to escape the backslash with another backslash.  This isolate the target so we do not compress other folders.  This object is passed to Invoke-CimMethod  where we call the Compress method. 

Nice and easy.  Remember to always verify that you are executing methods only against your intended target or really bad things can happen.