Skip to content
Ender Loc Phan edited this page Feb 5, 2018 · 37 revisions

Welcome to the Learn-Power-Shell wiki!

Learn-Power-Shell

Power shell tips collected by Ender Phan

Some useful links:

Some useful books for rookies and masters:

Beginners:

  • learn-windows-powershell-3-in-a-month-of-lunches-don-jones-jeffrey-hicks

  • PG_PowerShell_XWIPSCRE01_0

Some useful tips:

  • To check AMD:

    $env:Processor_Architecture

  • Get Service by its variable

    Get-Service | Where-Object {$_.Name -eq "VSS"}

    • Name: is the name of colum
    • VSS: is the name of service
  • Display by specific column

    Get-Service | Where-Object {$_.Name -eq "VSS"} | select Status

  • Outfile

    Get-Service | Where-Object {$_.Status -eq "running"} | Format-list | Out-File .\outhere.txt

  • Responding property variable

    Get-Process | where {$_.Responding -eq "true"}

  • Operator

    Get-Service | Where-Object {($_.Status -eq "running") -and ($_.Name -eq "WSearch")}

  • Whatif command

    Get-Process notepad |Stop-process -whatif

  • Get-EventLog

    Get-EventLog -LogName Application -Newest 10

  • Get-help

    get-help get-process

  • Tracking variable

    ($PSVersionTable).psversion

Alt text

  • List Variables

    dir variable:

  • Get-Alias

    Get-Alias

  • Really detail stuffs

    Get-Process notepad| Format-List * | more

  • Format Table and its property

    Get-Process | Format-Table -Property Name, Starttime

    • Name and starttime are column name ( property )
  • if interested in the column ( property ) which contains starttime

    Get-Process | Where-Object{$_.Starttime}| Format-Table -Property Name, Starttime

    * means if Startiime -eq true { write-host Name, Starttime }

Alias

  • Diffences between process and function to get its alias

    Get-Alias history

    Get-Alias -Definition Where-Object

  • Get specific alias

    Get-alias [?]

    *[?] exactly ? will be listed

Services

  • To see the services are able to pause or continue

    Get-Service| ? {$_.CanPauseAndContinue}

  • Get commands about SERVICE

    Get-Command -Noun service

Alt text

  • To set the service status

    Set-Service -Name LanmanServer -Status Paused ( requires administrator mode )

  • Get properties of Service

    Get-Service | Get-Member

    TypeName: System.ServiceProcess.ServiceController

Alt text

Processes

  • To start/stop processes

    Start-Process -FilePath notepad -WindowStyle Maximized

  • Kill processes

    Get-Process notepad | kill -WhatIf

Invoke

  • List history using "h"

  • Using invoke to remote command thru history ID

    Invoke-History 2

Alt text

Event logs

  • See the available logs

    Get-eventlog -list

  • Newest log of Application log

    Get-EventLog -LogName Application -Newest 5

  • Get the applications logs which its message contains a word "WmiApRpl"

    Get-EventLog -LogName Application | ? {$_.Message -match "WmiApRpl"}

  • Differences between -match and property's values

    1, Get-EventLog -LogName Application -Message "WmiApRpl" : it doesn't allow

    2, Get-EventLog -LogName Application -InstanceId "1001" : it does allow

    Case 2 is allowed because the value "1001" is matched entirely in the property InstanceId

  • Select category with Select

    Get-EventLog -LogName Application -Newest 5| select Source

    ==> it means whith we should use -match to find the containing word in the property. in case if we want to short the command that makes sure the word are contained entirelly in property

BIOS

  • Some:

    Get-WmiObject -class win32_bios

    Alias: gwmi win32_bios

Some methods

  • Maximum value:

    ($array | Measure-Object -Maximum ).Maximum

    !!!!NB:

      Just use Select to select the property. If we want to get exactly the value of that property. Just use dot (.) to print its value
    
  • Convert out-put to String

    $getEvent = Get-EventLog -LogName Application -Newest 19|?{($_.Source -match "SSH") -and ($_.Message -match "user")} |fl -Property Message |out-string

    • Use Out-string to convert
  • Split, In order to split the output we have to convert it to string variable.

    $getEvent.Split(":")

Active Directory

`[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()`

- [System.DirectoryServices.ActiveDirectory.Domain] --> class identifier 
- GetCurrentDomain() --> method

Link : https://blogs.technet.microsoft.com/heyscriptingguy/2006/11/09/how-can-i-use-windows-powershell-to-get-a-list-of-all-my-computers/

https://technet.microsoft.com/en-us/library/ff730967.aspx

LDAP Scan Map:

https://technet.microsoft.com/en-us/library/ff730967.aspx

Bloodhound https://blog.cobaltstrike.com/2016/12/14/my-first-go-with-bloodhound/

Mapping ADA https://msdn.microsoft.com/en-us/library/aa746392(v=vs.85).aspx

CSV: http://www.jhouseconsulting.com/2014/01/06/script-to-create-a-report-on-useraccountcontrol-flags-1088

UserAccountControl: http://www.selfadsi.org/ads-attributes/user-userAccountControl.htm

http://www.netvision.com/ad_useraccountcontrol.php

Param: https://www.experts-exchange.com/questions/28587998/Powershell-require-at-least-one-of-two-parameters-to-be-mandatory.html

Format: https://github.com/zloeber/FormatPowershellCode

How to upgrade powershell 4.0

  1. Download and Install the full package 4.5.1 here

https://www.microsoft.com/en-us/download/details.aspx?id=40779

  1. Checking for update if needed

  2. Download and Install the update package here:

Go to : https://www.microsoft.com/en-us/download/details.aspx?id=40855

Click "Download" then stick on: Windows6.1-KB2819745-x64-MultiPkg.msu and Next

!!! Mention on what OS (x32 or x64) you are using

  1. Restart the machine if it requires

How to install AD cmdlets

Command lines:

Import-Module ServerManager

Add-WindowsFeature RSAT-AD-PowerShell

Install-windowsfeature -name AD-Domain-Services –IncludeManagementTools

Import-module ActiveDirectory

To see who is logged on:

query user /server:SERVERNAME

Anatomy LDAP Attributes

Useful Links: http://www.selfadsi.org/

  • LastLogonTimeStamp and Lastlogon

LastLogonTimeStamp : replicated

Lastlogon: Non-replicated

It is important to note that the intended purpose of the lastLogontimeStamp attribute to help identify inactive computer and user accounts. The lastLogon attribute is not designed to provide real time logon information. With default settings in place the lastLogontimeStamp will be 9-14 days behind the current date

  • Modifytimestamp

This attribute appears in entries that have been modified using the protocol (e.g., using the Modify operation). The value is the time the entry was last modified. More: https://tools.ietf.org/html/rfc4512

This attribute is not replicated. If we want want to query the latest values, we should scan on every each DC's and get the maximum number which means the latest date time values.

ModifyTimestamp is marked as Constructed Attribute (effectively an alias for whenChanged)

  • PASSWD_CANT_CHANGE Flag in userAccountControl (Caution: This bit does not work as expected!)

flag ADS_UF_PASSWD_CANT_CHANGE (0x40) in userAccountControl attribute meanwhile it can’t be queried correctly if improper configuration is set for this flag which means the "user cannot change password" is determined by the access control entry on the user account rather than the ADS_UF_PASSWD_CANT_CHANGE (0x40) bit in the userAccountControl attribute.

More: http://ldapwiki.com/wiki/User-Account-Control%20Attribute

http://www.selfadsi.org/ads-attributes/user-userAccountControl.htm#UF_PASSWD_CANT_CHANGE

  • LockoutTime

http://www.selfadsi.org/ads-attributes/user-userAccountControl.htm

If you are currently connected with a user object via LDAP, you can also examine the attribute msDS-User-Account-Control-Computed. In contrast to the userAccountControl, this shows you in the UF_LOCKOUT whether an account is actually deleted. However, it is a constructed attribute so that it cannot be used as a filter criterion in LDAP search operations.

  • Get-WMIObject ( ERROR: Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) )

Setting DCOM Security to Allow a User to Access a Computer Remotely Security in WMI is related to connecting to a WMI namespace. WMI uses DCOM to handle remote calls. One reason for failure to connect to a remote computer is due to a DCOM failure (error "DCOM Access Denied" decimal -2147024891 or hex 0x80070005). For more information about DCOM security in WMI for C++ applications, see Setting Client Application Process Security.

You can configure DCOM settings for WMI using the DCOM Config utility (DCOMCnfg.exe) found in Administrative Tools in Control Panel. This utility exposes the settings that enable certain users to connect to the computer remotely through DCOM. Members of the Administrators group are allowed to remotely connect to the computer by default. With this utility you can set the security to start, access, and configure the WMI service. The following procedure describes how to grant DCOM remote startup and activation permissions for certain users and groups. If Computer A is connecting remotely to Computer B, you can set these permissions on Computer B to allow a user or group that is not part of the Administrators group on Computer B to execute DCOM startup and activation calls on Computer B.

To grant DCOM remote launch and activation permissions for a user or group

  1. Click Start , click Run , type DCOMCNFG , and then click OK.

  2. In the Component Services dialog box, expand Component Services, expand Computers, and then right-click My Computer and click Properties.

  3. In the My Computer Properties dialog box, click the COM Security tab.

  4. Under Launch and Activation Permissions, click Edit Limits.

  5. In the Launch Permission dialog box, follow these steps if your name or your group does not appear in the Groups or user names list: In the Launch Permission dialog box, click Add.

  6. In the Select Users, Computers, or Groups dialog box, add your name and the group in the Enter the object names to select box, and then click OK.

  7. In the Launch Permission dialog box, select your user and group in the Group or user names box. In the Allow column under Permissions for User, select Remote Launch and select Remote Activation, and then click OK.

The following procedure describes how to grant DCOM remote access permissions for certain users and groups. If Computer A is connecting remotely to Computer B, you can set these permissions on Computer B to allow a user or group that is not part of the Administrators group on Computer B to connect to Computer B.

More here https://msdn.microsoft.com/en-us/library/aa393266.aspx

How to expand the WMI Root Nodes from Domain

Providing DCOM permission on multiple machines can be done by applying group policy

security settings for DCOM computer configuration > windows settings > security settings > Local policies > Security options > DCOM : Machine launch restrictions Please check the following link, that is what we need to do:

Securing a Remote WMI Connection http://msdn.microsoft.com/en-us/library/aa393266%28VS.85%29.aspx

Connecting Through Windows Firewall http://msdn.microsoft.com/en-us/library/aa389286%28VS.85%29.aspx

Acceleration

  • Creating the object with [psCustomObject] helps to speed up the code in powershell, less typing as well :))

More here: http://www.jonathanmedd.net/2011/09/powershell-v3-creating-objects-with-pscustomobject-its-fast.html

For example:

$TestAddMember = {
(0..5000) | ForEach-Object {$CustomObject = New-Object psobject
$CustomObject | Add-Member -Name "Name" -Value "Test Name"
$CustomObject | Add-Member -Name "ID" -Value $_
$CustomObject
}
}
Measure-Command $TestAddMember | Format-Table TotalSeconds -Autosize

This takes 28 second to complete

$TestProperty = {
(0..5000) | ForEach-Object {[pscustomobject]@{Name = "Test Name"; ID = $_}}
}
Measure-Command $TestPSCustomObject | Format-Table TotalSeconds -Autosize

This takes 0,9 second to complete with less typing

  • Where cmdlets

$file.Where({$_.ProcessName -match "winlogon"})

measure-command {$file.Where({$_.ProcessName -match "winlogon"})} |select -ExpandProperty totalmilliseconds

===> 3.8481 sec

$file |? ({$_.ProcessName -match "winlogon"})

measure-command {$file |? ({$_.ProcessName -match "winlogon"})} |select -ExpandProperty totalmilliseconds

===> 9.6128 sec

Reason: Because the [1] does not use the pipe line "|", it's a great functionality but it's really slow

Tips and Tricks

  • Last command: $$

  • Find Command: Get-Command *csv*

  • Get-adgroup: Get-ADGroupMember 'Domain Admins' | Get-ADUser -Properties sAMAccountName|select sAMAccountName

  • tofileTime() (get-date "Wednesday, July 12, 2017 7:10:52 PM").tofiletime()

  • String Encryption

    $Secure = Read-Host -AsSecureString

    $Encrypted = ConvertFrom-SecureString -SecureString $Secure

  • Groups commands

    whoami /groups

ERROR HANDELING

ERROR: The underlying connection was closed: An unexpected error occurred on a receive

if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy').Type)
{
    add-type @"
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;
    }
}
"@
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}

Stupid MS

https://social.technet.microsoft.com/Forums/Lync/en-US/114e5747-dfe9-45af-8020-3255cc77e094/no-value-when-querying-whencreated-and-useraccountcontrol-via-getaduser-powershell-or?forum=winserverDS