AD Powershell

From ICO wiki

Welcome to the Learn-Power-Shell wiki!

  1. Learn-Power-Shell

Power shell tips collected by Ender Phan

  1. Some useful links:




- It's a part of the AD module which is a part of RSAT (Remote Server Administration Tools).


- ( live with it )

- ( just a blog about Powershell Scripting )

  1. Some useful books for rookies and masters:


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

- PG_PowerShell_XWIPSCRE01_0

  1. Some useful tips:

- To check AMD:


- 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


![Alt text](/image/version.PNG?raw=true "Version")

- List Variables

`dir variable:`

- 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 }`

  1. 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

  1. Services

- To see the services are able to pause or continue

`Get-Service| ? {$_.CanPauseAndContinue}`

- Get commands about SERVICE

`Get-Command -Noun service`

![Alt text](/image/get-command-none-service.PNG?raw=true "None service")

- 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](/image/get-command-none-service.PNG?raw=true "get-member")

  1. Processes

- To start/stop processes

`Start-Process -FilePath notepad -WindowStyle Maximized`

- Kill processes

`Get-Process notepad | kill -WhatIf`

  1. Invoke

- List history using "h"

- Using invoke to remote command thru history ID

`Invoke-History 2`

![Alt text](/image/help.PNG?raw=true "history")

  1. 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

  1. BIOS

- Some:

`Get-WmiObject -class win32_bios`

`Alias: gwmi win32_bios`

  1. Some methods

- Maximum value:

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


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.


  1. Active Directory


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

Link :

LDAP Scan Map:


Mapping ADA





  1. How to upgrade powershell 4.0

1. Download and Install the full package 4.5.1 here

2. Checking for update if needed

3. Download and Install the update package here:

Go to :

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

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

4. Restart the machine if it requires

  1. 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`

  1. To see who is logged on:
   `query user /server:SERVERNAME`
  1. Anatomy LDAP Attributes

Useful Links:

- 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:

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.


- LockoutTime

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

  1. 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

Connecting Through Windows Firewall

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

More here:

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

```html $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"})**

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

===> 3.8481 sec ``` 2.

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

```html 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_

  1. 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: 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 } ```