This commit is contained in:
Zak Bearman
2025-09-24 14:50:06 +12:00
commit bf6f94384f
14 changed files with 1488 additions and 0 deletions

76
Asteroid.ps1 Normal file
View File

@@ -0,0 +1,76 @@
Function Start-AdfsServerTrace {
param (
[string]$ActivityId,
[switch]$IncludeDebug,
[string[]]$ComputerName
)
$jobs = @()
foreach ($computer in $ComputerName) {
$jobs += Start-Job -ScriptBlock {
param ($ActivityId, $IncludeDebug, $computer)
$logNames = @("Security", "Application", "System")
if ($IncludeDebug) { $logNames += "AD FS Tracing/Debug" }
$events = @()
foreach ($log in $logNames) {
try {
$events += Get-WinEvent -ComputerName $computer -LogName $log -ErrorAction SilentlyContinue |
Where-Object { $_.ActivityId -eq $ActivityId }
} catch {
Write-Error "Failed to retrieve events from $computer for log $log"
}
}
return [PSCustomObject]@{
ComputerName = $computer
Events = $events
}
} -ArgumentList $ActivityId, $IncludeDebug, $computer
}
return $jobs
}
Function Receive-AdfsServerTrace {
param (
[Parameter(Mandatory = $true)]
[System.Management.Automation.Job[]]$Jobs
)
$results = @()
foreach ($job in $Jobs) {
$jobResult = Receive-Job -Job $job -Wait -AutoRemoveJob
$results += $jobResult
}
return $results
}
Function Get-AdfsServerTrace {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$ActivityId,
[switch]$IncludeDebug,
[string]$OutHtmlFilePath,
[string[]]$ComputerName = @("localhost")
)
# Start jobs to search all computers in parallel and retrieve results
$jobs = Start-AdfsServerTrace -ActivityId $ActivityId -IncludeDebug:$IncludeDebug -ComputerName $ComputerName
$results = Receive-AdfsServerTrace -Jobs $jobs
if ($OutHtmlFilePath) {
$results | ConvertTo-Html -Property ComputerName, Events | Out-File $OutHtmlFilePath -Force
Write-Output "Report Generated at $OutHtmlFilePath"
Start-Process $OutHtmlFilePath
} else {
Write-Output $results
}
}

51
Binoculars.ps1 Normal file
View File

@@ -0,0 +1,51 @@
## Created by Zak Bearman - Intel - Datacom - For use on any domain that WinRM is enabled and supported for remote log searching##
cls
# Define the username you are searching for
$username = read-host "Please enter users account" # Replace with the username of the locked-out user
# Get the PDC Emulator
$pdcemulator = (Get-ADDomain).PDCEmulator
$DomainControllers = Get-ADDomainController $pdcemulator | Select-Object -ExpandProperty HostName
# Define log file path
$logFile = "C:\Temp\AccountLockoutLog.txt"
# Create the log file if it doesn't exist
if (-not (Test-Path $logFile)) {
New-Item -Path $logFile -ItemType File -Force
}
# Loop indefinitely every 5 minutes
while ($true) {
foreach ($DC in $DomainControllers) {
Write-Host "Searching on: $DC"
Add-Content -Path $logFile -Value "Searching on: $DC - $(Get-Date)"
# Use Invoke-Command to remotely query the domain controller
Invoke-Command -ComputerName $DC -ScriptBlock {
param ($username)
# Query the Security event log for Event ID 4625 (Failed Login Attempt)
$events4625 = Get-EventLog -LogName "Security" -InstanceId 4625 -Newest 1000 | Where-Object { $_.Message -like "*$username*" }
foreach ($event in $events4625) {
$timeGenerated = $event.TimeGenerated
$message = $event.Message
Write-Host "Failed login attempt: $message at $timeGenerated"
Add-Content -Path $using:logFile -Value "Failed login attempt: $message at $timeGenerated"
}
# Query the Security event log for Event ID 4740 (Account Lockout)
$events4740 = Get-EventLog -LogName "Security" -InstanceId 4740 -Newest 1000 | Where-Object { $_.Message -like "*$username*" }
foreach ($event in $events4740) {
$timeGenerated = $event.TimeGenerated
$message = $event.Message
Write-Host "Account locked out: $message at $timeGenerated"
Add-Content -Path $using:logFile -Value "Account locked out: $message at $timeGenerated"
}
} -ArgumentList $username
}
# Wait for 10 seconds (10 seconds)
Start-Sleep -Seconds 10
}

317
Cartographer.ps1 Normal file
View File

@@ -0,0 +1,317 @@
# Cartographer - DNS Record Mapping Tool with GUI - Map - IP to DNS record based on subnet
# Import required assemblies for GUI
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Convert IP addresses to integers for comparison
function Convert-IPToInt {
param (
[string]$IPAddress
)
[array]$octets = $IPAddress.Split('.')
return [int]($octets[0]) * 16777216 + [int]($octets[1]) * 65536 + [int]($octets[2]) * 256 + [int]($octets[3])
}
# Convert integer back to IP address
function Convert-IntToIP {
param (
[int64]$Integer
)
$octet1 = [Math]::Floor($Integer / 16777216)
$remainder = $Integer % 16777216
$octet2 = [Math]::Floor($remainder / 65536)
$remainder = $remainder % 65536
$octet3 = [Math]::Floor($remainder / 256)
$octet4 = $remainder % 256
return "$octet1.$octet2.$octet3.$octet4"
}
# Get subnet range based on IP and mask
function Get-SubnetRange {
param (
[string]$IPAddress
)
# Assuming /24 subnet
$octets = $IPAddress.Split('.')
$networkPrefix = "$($octets[0]).$($octets[1]).$($octets[2])"
$rangeStart = "$networkPrefix.1"
$rangeEnd = "$networkPrefix.254"
return @{
Start = $rangeStart
End = $rangeEnd
}
}
# Get available DNS servers
function Get-AvailableDnsServers {
# $dnsServers = @("localhost")
$clientDnsServers = Get-DnsClientServerAddress |
Where-Object { $_.ServerAddresses -ne $null } |
ForEach-Object {
$_.ServerAddresses | Where-Object { $_ -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$' }
} |
Select-Object -Unique
$dnsServers += $clientDnsServers
# Try to add domain controllers if we're in a domain environment
try {
$domainControllers = Get-ADDomainController -Filter * |
ForEach-Object { $_.HostName }
$dnsServers += $domainControllers
} catch {
# Not in a domain environment or AD module not available, continue without it
}
return $dnsServers | Select-Object -Unique
}
# Query DNS for records
function Search-DnsRecords {
param (
[string]$DnsServer,
[string]$IPRangeStart,
[string]$IPRangeEnd
)
$StartInt = Convert-IPToInt $IPRangeStart
$EndInt = Convert-IPToInt $IPRangeEnd
$Results = @()
try {
$Zones = Get-DnsServerZone -ComputerName $DnsServer -ErrorAction Stop
foreach ($Zone in $Zones) {
$Records = Get-DnsServerResourceRecord -ZoneName $Zone.ZoneName -ComputerName $DnsServer -ErrorAction SilentlyContinue
foreach ($Record in $Records) {
if ($Record.RecordType -eq "A") {
$IPInt = Convert-IPToInt $Record.RecordData.IPv4Address.ToString()
if ($IPInt -ge $StartInt -and $IPInt -le $EndInt) {
$Results += [PSCustomObject]@{
IPAddress = $Record.RecordData.IPv4Address
Hostname = $Record.HostName
Zone = $Zone.ZoneName
}
}
}
}
}
} catch {
[System.Windows.Forms.MessageBox]::Show("Error querying DNS server: $_", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
return $Results
}
# Create the main form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Cartographer - DNS Record Mapping Tool"
$form.Size = New-Object System.Drawing.Size(800, 600)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog
$form.MaximizeBox = $false
# DNS Server selection
$dnsServerLabel = New-Object System.Windows.Forms.Label
$dnsServerLabel.Text = "DNS Server:"
$dnsServerLabel.Location = New-Object System.Drawing.Point(20, 20)
$dnsServerLabel.Size = New-Object System.Drawing.Size(100, 20)
$form.Controls.Add($dnsServerLabel)
$dnsServerComboBox = New-Object System.Windows.Forms.ComboBox
$dnsServerComboBox.Location = New-Object System.Drawing.Point(130, 20)
$dnsServerComboBox.Size = New-Object System.Drawing.Size(200, 20)
$dnsServerComboBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
$form.Controls.Add($dnsServerComboBox)
# Populate DNS Server dropdown
$dnsServers = Get-AvailableDnsServers
foreach ($server in $dnsServers) {
$dnsServerComboBox.Items.Add($server)
}
if ($dnsServerComboBox.Items.Count -gt 0) {
$dnsServerComboBox.SelectedIndex = 0
}
# IP Range Selection Group
$ipRangeGroupBox = New-Object System.Windows.Forms.GroupBox
$ipRangeGroupBox.Text = "IP Range Selection"
$ipRangeGroupBox.Location = New-Object System.Drawing.Point(20, 50)
$ipRangeGroupBox.Size = New-Object System.Drawing.Size(750, 120)
$form.Controls.Add($ipRangeGroupBox)
# Radio buttons for range selection
$subnetRadioButton = New-Object System.Windows.Forms.RadioButton
$subnetRadioButton.Text = "Scan Full /24 Subnet"
$subnetRadioButton.Location = New-Object System.Drawing.Point(20, 20)
$subnetRadioButton.Size = New-Object System.Drawing.Size(150, 20)
$subnetRadioButton.Checked = $true
$ipRangeGroupBox.Controls.Add($subnetRadioButton)
$customRangeRadioButton = New-Object System.Windows.Forms.RadioButton
$customRangeRadioButton.Text = "Custom IP Range"
$customRangeRadioButton.Location = New-Object System.Drawing.Point(20, 50)
$customRangeRadioButton.Size = New-Object System.Drawing.Size(150, 20)
$ipRangeGroupBox.Controls.Add($customRangeRadioButton)
# Subnet IP entry
$subnetIPLabel = New-Object System.Windows.Forms.Label
$subnetIPLabel.Text = "Subnet IP Address:"
$subnetIPLabel.Location = New-Object System.Drawing.Point(180, 20)
$subnetIPLabel.Size = New-Object System.Drawing.Size(120, 20)
$ipRangeGroupBox.Controls.Add($subnetIPLabel)
$subnetIPTextBox = New-Object System.Windows.Forms.TextBox
$subnetIPTextBox.Location = New-Object System.Drawing.Point(300, 20)
$subnetIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
$subnetIPTextBox.Text = "192.168.1.1"
$ipRangeGroupBox.Controls.Add($subnetIPTextBox)
# Custom range IP entries
$startIPLabel = New-Object System.Windows.Forms.Label
$startIPLabel.Text = "Start IP Address:"
$startIPLabel.Location = New-Object System.Drawing.Point(180, 50)
$startIPLabel.Size = New-Object System.Drawing.Size(120, 20)
$ipRangeGroupBox.Controls.Add($startIPLabel)
$startIPTextBox = New-Object System.Windows.Forms.TextBox
$startIPTextBox.Location = New-Object System.Drawing.Point(300, 50)
$startIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
$startIPTextBox.Text = "192.168.1.1"
$startIPTextBox.Enabled = $false
$ipRangeGroupBox.Controls.Add($startIPTextBox)
$endIPLabel = New-Object System.Windows.Forms.Label
$endIPLabel.Text = "End IP Address:"
$endIPLabel.Location = New-Object System.Drawing.Point(460, 50)
$endIPLabel.Size = New-Object System.Drawing.Size(120, 20)
$ipRangeGroupBox.Controls.Add($endIPLabel)
$endIPTextBox = New-Object System.Windows.Forms.TextBox
$endIPTextBox.Location = New-Object System.Drawing.Point(580, 50)
$endIPTextBox.Size = New-Object System.Drawing.Size(150, 20)
$endIPTextBox.Text = "192.168.1.254"
$endIPTextBox.Enabled = $false
$ipRangeGroupBox.Controls.Add($endIPTextBox)
# Radio button event handlers
$subnetRadioButton.Add_CheckedChanged({
if ($subnetRadioButton.Checked) {
$subnetIPTextBox.Enabled = $true
$startIPTextBox.Enabled = $false
$endIPTextBox.Enabled = $false
}
})
$customRangeRadioButton.Add_CheckedChanged({
if ($customRangeRadioButton.Checked) {
$subnetIPTextBox.Enabled = $false
$startIPTextBox.Enabled = $true
$endIPTextBox.Enabled = $true
}
})
# Auto-calculate subnet range from subnet IP
$subnetIPTextBox.Add_TextChanged({
if ($subnetRadioButton.Checked -and $subnetIPTextBox.Text -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$') {
$range = Get-SubnetRange -IPAddress $subnetIPTextBox.Text
$startIPTextBox.Text = $range.Start
$endIPTextBox.Text = $range.End
}
})
# Search Button
$searchButton = New-Object System.Windows.Forms.Button
$searchButton.Text = "Search DNS Records"
$searchButton.Location = New-Object System.Drawing.Point(20, 180)
$searchButton.Size = New-Object System.Drawing.Size(150, 30)
$form.Controls.Add($searchButton)
# Status Label
$statusLabel = New-Object System.Windows.Forms.Label
$statusLabel.Text = "Ready"
$statusLabel.Location = New-Object System.Drawing.Point(180, 185)
$statusLabel.Size = New-Object System.Drawing.Size(590, 20)
$form.Controls.Add($statusLabel)
# Results DataGridView
$resultsDataGridView = New-Object System.Windows.Forms.DataGridView
$resultsDataGridView.Location = New-Object System.Drawing.Point(20, 220)
$resultsDataGridView.Size = New-Object System.Drawing.Size(750, 300)
$resultsDataGridView.AutoSizeColumnsMode = [System.Windows.Forms.DataGridViewAutoSizeColumnsMode]::Fill
$resultsDataGridView.AllowUserToAddRows = $false
$resultsDataGridView.AllowUserToDeleteRows = $false
$resultsDataGridView.ReadOnly = $true
$resultsDataGridView.MultiSelect = $false
$resultsDataGridView.SelectionMode = [System.Windows.Forms.DataGridViewSelectionMode]::FullRowSelect
$form.Controls.Add($resultsDataGridView)
# Export Button
$exportButton = New-Object System.Windows.Forms.Button
$exportButton.Text = "Export Results"
$exportButton.Location = New-Object System.Drawing.Point(20, 530)
$exportButton.Size = New-Object System.Drawing.Size(120, 30)
$exportButton.Enabled = $false
$form.Controls.Add($exportButton)
# Search button click event
$searchButton.Add_Click({
$statusLabel.Text = "Searching DNS records..."
$resultsDataGridView.DataSource = $null
$exportButton.Enabled = $false
$selectedDnsServer = $dnsServerComboBox.SelectedItem.ToString()
$ipRangeStart = ""
$ipRangeEnd = ""
if ($subnetRadioButton.Checked) {
$range = Get-SubnetRange -IPAddress $subnetIPTextBox.Text
$ipRangeStart = $range.Start
$ipRangeEnd = $range.End
} else {
$ipRangeStart = $startIPTextBox.Text
$ipRangeEnd = $endIPTextBox.Text
}
$results = Search-DnsRecords -DnsServer $selectedDnsServer -IPRangeStart $ipRangeStart -IPRangeEnd $ipRangeEnd
if ($results.Count -gt 0) {
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("IPAddress", [string])
$dataTable.Columns.Add("Hostname", [string])
$dataTable.Columns.Add("Zone", [string])
foreach ($result in $results) {
$dataTable.Rows.Add($result.IPAddress.ToString(), $result.Hostname, $result.Zone)
}
$resultsDataGridView.DataSource = $dataTable
$statusLabel.Text = "Found $($results.Count) DNS records"
$exportButton.Enabled = $true
} else {
$statusLabel.Text = "No DNS records found in the specified range"
}
})
# Export button click event
$exportButton.Add_Click({
$saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$saveFileDialog.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"
$saveFileDialog.Title = "Export DNS Records"
$saveFileDialog.FileName = "DNSRecords_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
if ($saveFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$dataTable = $resultsDataGridView.DataSource
$dataTable | Export-Csv -Path $saveFileDialog.FileName -NoTypeInformation
$statusLabel.Text = "Exported to $($saveFileDialog.FileName)"
}
})
# Show the form
[void]$form.ShowDialog()

203
Contrast.ps1 Normal file
View File

@@ -0,0 +1,203 @@
Add-Type -AssemblyName System.Windows.Forms
#Set Domain Controller Variable
$domaincontroller = "fqdn.domain.placeholder" ##################### UPDATE THIS LINE #####################
# Create a form
$form = New-Object Windows.Forms.Form
$form.Text = "Compare AD Group Memberships"
$form.Width = 600
$form.Height = 900
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
# Signature for UPNs
$labelSignature = New-Object Windows.Forms.Label
$labelSignature.Text = "Made by Zak Bearman - Intel"
$labelSignature.Location = New-Object Drawing.Point(10, 832)
$form.Controls.Add($labelSignature)
# Labels and Textboxes for UPNs
$labelPrimaryUser = New-Object Windows.Forms.Label
$labelPrimaryUser.Text = "Primary User UPN:"
$labelPrimaryUser.Location = New-Object Drawing.Point(10, 23)
$form.Controls.Add($labelPrimaryUser)
$textBoxPrimaryUser = New-Object Windows.Forms.TextBox
$textBoxPrimaryUser.Location = New-Object Drawing.Point(120, 20)
$textBoxPrimaryUser.Width = 200
$form.Controls.Add($textBoxPrimaryUser)
# ComboBox for selecting the number of users to compare against
$labelNumUsers = New-Object Windows.Forms.Label
$labelNumUsers.Text = "How many other users?"
$labelNumUsers.Location = New-Object Drawing.Point(10, 50)
$form.Controls.Add($labelNumUsers)
$comboBoxNumUsers = New-Object Windows.Forms.ComboBox
$comboBoxNumUsers.Location = New-Object Drawing.Point(250, 50)
$comboBoxNumUsers.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
$comboBoxNumUsers.Items.Add("1")
$comboBoxNumUsers.Items.Add("2")
$comboBoxNumUsers.Items.Add("3")
$comboBoxNumUsers.SelectedIndex = 0
$form.Controls.Add($comboBoxNumUsers)
# GroupBox for UPNs of users to compare against
$groupBoxUsers = New-Object Windows.Forms.GroupBox
$groupBoxUsers.Text = "Users to Compare Against:"
$groupBoxUsers.Location = New-Object Drawing.Point(10, 80)
$groupBoxUsers.Width = 340
$groupBoxUsers.Height = 100
$form.Controls.Add($groupBoxUsers)
# Textboxes for entering UPNs based on the selected number of users
$textBoxUser1 = New-Object Windows.Forms.TextBox
$textBoxUser1.Location = New-Object Drawing.Point(10, 20)
$textBoxUser1.Width = 200
$groupBoxUsers.Controls.Add($textBoxUser1)
$textBoxUser2 = New-Object Windows.Forms.TextBox
$textBoxUser2.Location = New-Object Drawing.Point(10, 50)
$textBoxUser2.Width = 200
$textBoxUser2.Visible = $false
$groupBoxUsers.Controls.Add($textBoxUser2)
$textBoxUser3 = New-Object Windows.Forms.TextBox
$textBoxUser3.Location = New-Object Drawing.Point(10, 80)
$textBoxUser3.Width = 200
$textBoxUser3.Visible = $false
$groupBoxUsers.Controls.Add($textBoxUser3)
# Button to initiate comparison
$buttonCompare = New-Object Windows.Forms.Button
$buttonCompare.Text = "Compare"
$buttonCompare.Location = New-Object Drawing.Point(120, 195)
$form.Controls.Add($buttonCompare)
# Help button to display usage instructions
$buttonHelp = New-Object Windows.Forms.Button
$buttonHelp.Text = "Click Me"
$buttonHelp.Location = New-Object Drawing.Point(215, 195)
$form.Controls.Add($buttonHelp)
# Scrollable and selectable textbox for displaying output
$textBoxOutput = New-Object Windows.Forms.TextBox
$textBoxOutput.Location = New-Object Drawing.Point(10, 230)
$textBoxOutput.Width = 560
$textBoxOutput.Height = 600
$textBoxOutput.Multiline = $true
$textBoxOutput.ScrollBars = "Vertical"
$textBoxOutput.ReadOnly = $true
$form.Controls.Add($textBoxOutput)
# Event handler for the ComboBox selection change
$comboBoxNumUsers.Add_SelectedIndexChanged({
$numUsers = [int]$comboBoxNumUsers.SelectedItem
# Show/hide textboxes based on the selected number of users
$textBoxUser1.Visible = $numUsers -ge 1
$textBoxUser2.Visible = $numUsers -ge 2
$textBoxUser3.Visible = $numUsers -ge 3
})
# Event handler for the Compare button
$buttonCompare.Add_Click({
# Get the entered UPNs and the selected number of users
$primaryUserUPN = $textBoxPrimaryUser.Text
$numUsers = [int]$comboBoxNumUsers.SelectedItem
# Get the UPNs of the users to compare against based on the selected number
$usersToCompareUPNs = @()
if ($textBoxUser1.Visible) { $usersToCompareUPNs += $textBoxUser1.Text }
if ($textBoxUser2.Visible) { $usersToCompareUPNs += $textBoxUser2.Text }
if ($textBoxUser3.Visible) { $usersToCompareUPNs += $textBoxUser3.Text }
# Function to get group memberships for a user using UPN
function Get-ADUserGroupsByUPN {
param (
[string]$userUPN
)
$user = Get-ADUser -Filter { UserPrincipalName -eq $userUPN } -Server $domaincontroller
if ($user) {
$groups = Get-ADPrincipalGroupMembership -Identity $user -Server $domaincontroller
return $groups | Select-Object -ExpandProperty Name
} else {
Write-Host "User with UPN $userUPN not found."
return $null
}
}
# Get group memberships for the primary user
$primaryUserGroups = Get-ADUserGroupsByUPN -userUPN $primaryUserUPN
if ($primaryUserGroups -ne $null) {
# Compare group memberships for the primary user with other users
$missingGroups = @()
foreach ($userUPN in $usersToCompareUPNs) {
$userGroups = Get-ADUserGroupsByUPN -userUPN $userUPN
if ($userGroups -ne $null) {
foreach ($group in $userGroups) {
if ($primaryUserGroups -notcontains $group -and $missingGroups -notcontains $group) {
$missingGroups += $group
}
}
}
}
# Display the missing groups in the output textbox
if ($missingGroups.Count -gt 0) {
$missingGroupsText = $missingGroups -join "`r`n"
$textBoxOutput.Text = "Groups missing for $primaryUserUPN compared to the other users:`r`n`r`n$missingGroupsText"
} else {
$textBoxOutput.Text = "No missing groups found for $primaryUserUPN."
}
}
})
# Event handler for the Help button
$buttonHelp.Add_Click({
# Display usage instructions in a new window
$helpForm = New-Object Windows.Forms.Form
$helpForm.Text = "Usage Instructions"
$helpForm.Width = 400
$helpForm.Height = 350
$helpLabel = New-Object Windows.Forms.Label
$helpLabel.Text = "Instructions:"
$helpLabel.Location = New-Object Drawing.Point(10, 10)
$helpForm.Controls.Add($helpLabel)
$helpText = @"
1. Enter the UPN of the primary user in the 'Primary User UPN' field.
2. Select the number of users to compare against from the dropdown 1, 2 or 3.
3. Enter the UPNs of the users to compare against in the 'Users to Compare Against' section.
4. Click the 'Compare' button to compare group memberships that the primary user is missing.
5. The results will be displayed in the textbox below. Find the membership that is most likely what they need and apply this in AD.
6. If this is an admin account, Please supply this information to Wintel via the ticket to be actioned accordingly.
"@
$helpTextBox = New-Object Windows.Forms.TextBox
$helpTextBox.Location = New-Object Drawing.Point(10, 40)
$helpTextBox.Width = 360
$helpTextBox.Height = 250
$helpTextBox.Multiline = $true
$helpTextBox.ScrollBars = "Vertical"
$helpTextBox.Text = $helpText
$helpTextBox.ReadOnly = $true
$helpForm.Controls.Add($helpTextBox)
$helpForm.ShowDialog()
})
# Show the form
$form.ShowDialog()
# Disclaimer: TWFkZSBieSBaYWsgQmVhcm1hbiAtIERhdGFjb20gV2ludGVsIC0gUHJvdmlkZWQgYXMgaXMgd2hlcmUgaXMuIElmIGJyb2tlbiB3aWxsIGJlIGxvb2tlZCBhdCBpbiBhIGJlc3QgZWZmb3J0IGF0dGVtcHQ=

80
Conversation.ps1 Normal file
View File

@@ -0,0 +1,80 @@
## After running the powershell scriopt run the following after the fact changing the port number to what you need.
## $msg = Receive-TCPMessage -Port 9999
## from the remote server that you need to send the traffic from. Run the following with the port number you set to listen
## Test-NetConnection win1962 -Port 9999
Function Receive-TCPMessage {
Param (
[Parameter(Mandatory=$true, Position=0)]
[ValidateNotNullOrEmpty()]
[int] $Port
)
Process {
Try {
# Set up endpoint and start listening
$endpoint = new-object System.Net.IPEndPoint([ipaddress]::any,$port)
$listener = new-object System.Net.Sockets.TcpListener $EndPoint
$listener.start()
# Wait for an incoming connection
$data = $listener.AcceptTcpClient()
# Stream setup
$stream = $data.GetStream()
$bytes = New-Object System.Byte[] 1024
# Read data from stream and write it to host
while (($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){
$EncodedText = New-Object System.Text.ASCIIEncoding
$data = $EncodedText.GetString($bytes,0, $i)
Write-Output $data
}
# Close TCP connection and stop listening
$stream.close()
$listener.stop()
}
Catch {
"Receive Message failed with: `n" + $Error[0]
}
}
}

111
Darth-SPooN.ps1 Normal file
View File

@@ -0,0 +1,111 @@
param(
[Parameter(Mandatory = $true)]
[string]$MachineName,
[Parameter(Mandatory = $true)]
[string]$ServiceAccount,
[int]$SqlPort = 1433,
[string[]]$HadrListeners
)
Import-Module ActiveDirectory
Write-Host "=== MSSQLSvc + HADR SPN Validation Tool ===" -ForegroundColor Cyan
Write-Host "Machine: $MachineName"
Write-Host "Service Account: $ServiceAccount"
Write-Host "SQL Port: $SqlPort"
if ($HadrListeners) {
Write-Host "HADR Listener(s): $($HadrListeners -join ', ')"
}
Write-Host "-------------------------------------------"
# Get domain FQDN
$domainFQDN = (Get-ADDomain).DNSRoot
# Lookup service account (user or computer)
try {
$svcObj = Get-ADUser -Identity $ServiceAccount -Properties ServicePrincipalName -ErrorAction Stop
} catch {
try {
$svcObj = Get-ADComputer -Identity $ServiceAccount -Properties ServicePrincipalName -ErrorAction Stop
} catch {
Write-Host "ERROR: Service account '$ServiceAccount' not found in AD." -ForegroundColor Red
exit
}
}
# Build expected MSSQLSvc SPNs for machine and HADR listeners
$namesToCheck = @($MachineName)
if ($HadrListeners) {
$namesToCheck += $HadrListeners
}
$expectedSPNs = foreach ($name in $namesToCheck) {
"MSSQLSvc/${name}.${domainFQDN}:$SqlPort"
"MSSQLSvc/${name}:$SqlPort"
}
Write-Host "`nExpected MSSQLSvc SPNs:" -ForegroundColor Yellow
$expectedSPNs | ForEach-Object { Write-Host " $_" }
# Case-insensitive missing SPN check (fixed grouping)
$missingSPNs = $expectedSPNs | Where-Object {
$expectedLower = $_.ToLower()
-not (( $svcObj.ServicePrincipalName | ForEach-Object { $_.ToLower() } ) -contains $expectedLower)
}
if ($missingSPNs) {
Write-Host "`n[!] Missing MSSQLSvc SPNs on service account:" -ForegroundColor Red
$missingSPNs | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
$addPrompt = Read-Host "`nDo you want to add the missing SPNs now? (Y/N)"
if ($addPrompt -match '^[Yy]$') {
foreach ($spn in $missingSPNs) {
Write-Host "Adding SPN: $spn" -ForegroundColor Green
# Use -S to avoid duplicates, requires running as an account with permission
setspn -S $spn $ServiceAccount
}
Write-Host "`n[OK] Missing SPNs have been added." -ForegroundColor Green
} else {
Write-Host "Skipping SPN creation." -ForegroundColor Yellow
}
} else {
Write-Host "`n[OK] All expected MSSQLSvc SPNs are present." -ForegroundColor Green
}
# Pull all SPNs in the domain
$allSPNs = Get-ADObject -Filter {ServicePrincipalName -like "*"} -Properties ServicePrincipalName |
ForEach-Object {
foreach ($spn in $_.ServicePrincipalName) {
[PSCustomObject]@{
SPN = $spn
ADObject = $_.SamAccountName
DN = $_.DistinguishedName
}
}
}
# Check for duplicates of MSSQLSvc SPNs
Write-Host "`nChecking for duplicate MSSQLSvc SPNs in the domain..." -ForegroundColor Yellow
foreach ($spn in $svcObj.ServicePrincipalName | Where-Object { $_ -like "MSSQLSvc/*" }) {
$owners = $allSPNs | Where-Object { $_.SPN -eq $spn }
if ($owners.Count -gt 1) {
Write-Host "[DUPLICATE] SPN '$spn' is owned by multiple objects:" -ForegroundColor Red
$owners | ForEach-Object { Write-Host " -> $($_.ADObject) ($($_.DN))" }
}
}
# Check for MSSQLSvc SPNs on service account that aren't expected
$expectedLowerList = $expectedSPNs | ForEach-Object { $_.ToLower() }
$wrongSPNs = $svcObj.ServicePrincipalName | Where-Object {
$_ -like "MSSQLSvc/*" -and ($_.ToLower() -notin $expectedLowerList)
}
if ($wrongSPNs) {
Write-Host "`n[!] Warning: Service account has MSSQLSvc SPNs not in expected list:" -ForegroundColor Red
$wrongSPNs | ForEach-Object { Write-Host " $_" }
} else {
Write-Host "`n[OK] No unexpected MSSQLSvc SPNs found." -ForegroundColor Green
}
Write-Host "`n=== MSSQLSvc + HADR SPN Check Complete ==="

132
EggBasket.ps1 Normal file
View File

@@ -0,0 +1,132 @@
# Load required assemblies
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Create the form
$form = New-Object System.Windows.Forms.Form
$form.Text = "MSA Creator - Khan Mayker"
$form.Size = New-Object System.Drawing.Size(400,400)
$form.StartPosition = "CenterScreen"
# Create Labels and Textboxes for Variables
$labelSVCAccount = New-Object System.Windows.Forms.Label
$labelSVCAccount.Text = "Service Account Name:"
$labelSVCAccount.Location = New-Object System.Drawing.Point(10,20)
$labelSVCAccount.Size = New-Object System.Drawing.Size(150,20)
$form.Controls.Add($labelSVCAccount)
$textSVCAccount = New-Object System.Windows.Forms.TextBox
$textSVCAccount.Location = New-Object System.Drawing.Point(180,20)
$textSVCAccount.Size = New-Object System.Drawing.Size(180,20)
$form.Controls.Add($textSVCAccount)
$labelDNS = New-Object System.Windows.Forms.Label
$labelDNS.Text = "DNS Host Name:"
$labelDNS.Location = New-Object System.Drawing.Point(10,60)
$labelDNS.Size = New-Object System.Drawing.Size(150,20)
$form.Controls.Add($labelDNS)
$textDNS = New-Object System.Windows.Forms.TextBox
$textDNS.Location = New-Object System.Drawing.Point(180,60)
$textDNS.Size = New-Object System.Drawing.Size(180,20)
$textDNS.Text = ".domain.placeholder.nz" # Enter your domain "domain.govt.nz" ##################### UPDATE THIS LINE #####################
$textDNS.Enabled = $false
$form.Controls.Add($textDNS)
$labelPath = New-Object System.Windows.Forms.Label
$labelPath.Text = "OU Path:"
$labelPath.Location = New-Object System.Drawing.Point(10,100)
$labelPath.Size = New-Object System.Drawing.Size(150,20)
$form.Controls.Add($labelPath)
$textPath = New-Object System.Windows.Forms.TextBox
$textPath.Location = New-Object System.Drawing.Point(180,100)
$textPath.Size = New-Object System.Drawing.Size(180,20)
$textPath.Text = "OU=grMSA,OU=Service Accounts,OU=_Administration,DC=domain,DC=placeholder,DC=nz" ##################### UPDATE THIS LINE #####################
$textPath.Enabled = $false
$form.Controls.Add($textPath)
$labelMachines = New-Object System.Windows.Forms.Label
$labelMachines.Text = "Machine Names (comma-separated):"
$labelMachines.Location = New-Object System.Drawing.Point(10,140)
$labelMachines.Size = New-Object System.Drawing.Size(220,20)
$form.Controls.Add($labelMachines)
$textMachines = New-Object System.Windows.Forms.TextBox
$textMachines.Location = New-Object System.Drawing.Point(10,170)
$textMachines.Size = New-Object System.Drawing.Size(350,20)
$form.Controls.Add($textMachines)
# Event to update DNS field based on Service Account Name input
$textSVCAccount.Add_TextChanged({
$textDNS.Text = "$($textSVCAccount.Text).domain.placeholder.nz" ##################### UPDATE THIS LINE #####################
})
# Create the Submit Button
$buttonSubmit = New-Object System.Windows.Forms.Button
$buttonSubmit.Text = "Create MSA and AD Group"
$buttonSubmit.Location = New-Object System.Drawing.Point(120, 210)
$buttonSubmit.Size = New-Object System.Drawing.Size(150,30)
$form.Controls.Add($buttonSubmit)
# Action on Submit Button Click
$buttonSubmit.Add_Click({
$SVCAccount = $textSVCAccount.Text
$dns = $textDNS.Text
$path = "OU=grMSA,OU=Service Accounts,OU=_Administration,DC=domain,DC=placeholder,DC=nz" ##################### UPDATE THIS LINE #####################
$machines = $textMachines.Text.Split(',')
if (-not [string]::IsNullOrWhiteSpace($SVCAccount) -and -not [string]::IsNullOrWhiteSpace($dns) -and -not [string]::IsNullOrWhiteSpace($path) -and $machines.Count -gt 0) {
$grMSA = "grMSA_$SVCAccount"
try {
# Create AD Group
New-ADGroup -Name $grMSA -Path $path -GroupScope Global -PassThru -Verbose
# Add Machines to AD Group
foreach ($machine in $machines) {
$machineTrimmed = $machine.Trim() + '$'
Add-AdGroupMember -Identity $grMSA -Members $machineTrimmed -Verbose
}
# Create MSA with the AD Group allowed to retrieve the password
New-ADServiceAccount -Name $SVCAccount -DNSHostName $dns -PrincipalsAllowedToRetrieveManagedPassword $grMSA -Verbose
[System.Windows.Forms.MessageBox]::Show("MSA and AD Group created successfully.", "Success", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
} catch {
[System.Windows.Forms.MessageBox]::Show("Error: $_", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
} else {
[System.Windows.Forms.MessageBox]::Show("Please fill in all fields.", "Input Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
}
})
# Hidden Feature: Click bottom-left corner to open a new window with the message
$form.Add_MouseClick({
param($sender, $e)
# Check if the click is at the bottom-left corner
if ($e.X -eq 0 -and $e.Y -eq $form.ClientSize.Height - 1) {
$hiddenForm = New-Object System.Windows.Forms.Form
$hiddenForm.Text = "Hidden Message"
$hiddenForm.Size = New-Object System.Drawing.Size(500,200)
$hiddenForm.StartPosition = "CenterScreen"
$textBoxMessage = New-Object System.Windows.Forms.TextBox
$textBoxMessage.Multiline = $true
$textBoxMessage.ReadOnly = $true
$textBoxMessage.Text = "dKU0fKP6Ob9ne29wOpCkepUyeV5me20yg2oudV9OdJIxA01khZwbLcs+RqUohKT9YJkoMWLzV2kkelXbPH1khZwbMWLze3LoPmE0dJXveZIselXbPJIxgJIqe25sf3ToPmEyClXbPHUye20oPmEIgJYbepIvOj== d"
$textBoxMessage.Location = New-Object System.Drawing.Point(10,20)
$textBoxMessage.Size = New-Object System.Drawing.Size(460,100)
$textBoxMessage.ScrollBars = "Vertical"
$hiddenForm.Controls.Add($textBoxMessage)
$hiddenForm.ShowDialog()
}
})
# Show the form
$form.Topmost = $true
$form.Add_Shown({$form.Activate()})
[void]$form.ShowDialog()

91
Haystack.ps1 Normal file
View File

@@ -0,0 +1,91 @@
##############################################################
## Change Log #
## 1.0 Initial release #
## 1.1 Added logic for resolved IP to be displayed on screen.#
##############################################################
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Create form controls
$form = New-Object System.Windows.Forms.Form
$form.Text = "Haystack"
$form.ClientSize = New-Object System.Drawing.Size(400, 270)
$dnsNameLabel = New-Object System.Windows.Forms.Label
$dnsNameLabel.Text = "A Record:"
$dnsNameLabel.Location = New-Object System.Drawing.Point(10, 20)
$dnsNameLabel.AutoSize = $true
$dnsNameTextbox = New-Object System.Windows.Forms.TextBox
$dnsNameTextbox.Location = New-Object System.Drawing.Point(120, 20)
$dnsNameTextbox.Size = New-Object System.Drawing.Size(250, 20)
$zoneLabel = New-Object System.Windows.Forms.Label
$zoneLabel.Text = "DNS Zone:"
$zoneLabel.Location = New-Object System.Drawing.Point(10, 50)
$zoneLabel.AutoSize = $true
$zoneTextbox = New-Object System.Windows.Forms.TextBox
$zoneTextbox.Location = New-Object System.Drawing.Point(120, 50)
$zoneTextbox.Size = New-Object System.Drawing.Size(250, 20)
$ipLabel = New-Object System.Windows.Forms.Label
$ipLabel.Text = "IP Address:"
$ipLabel.Location = New-Object System.Drawing.Point(10, 80)
$ipLabel.Size = New-Object System.Drawing.Size(62, 10)
$form.Controls.Add($ipLabel)
$ipTextBox = New-Object System.Windows.Forms.TextBox
$ipTextBox.Location = New-Object System.Drawing.Point(10, 100)
$ipTextBox.ReadOnly = $true
$form.Controls.Add($ipTextBox)
$createButton = New-Object System.Windows.Forms.Button
$createButton.Location = New-Object System.Drawing.Point(120, 80)
$createButton.Size = New-Object System.Drawing.Size(150, 23)
$createButton.Text = "Create Zone and A Record"
$createButton.Add_Click({
# Combine fields and ping DNS name
$combined = $dnsNameTextbox.Text + "." + $zoneTextbox.Text
$pingResult = Test-Connection -ComputerName $combined -Count 1 -Quiet
# Get IP address using Resolve-DnsName
$ipAddress = ""
$dnsResult = Resolve-DnsName -Name $combined -Type A -ErrorAction SilentlyContinue
if ($dnsResult) {
$ipAddress = $dnsResult.IPAddress
}
# If ping failed and Resolve-DnsName didn't return an IP address, show error message and exit
if (!$pingResult -and !$dnsResult) {
[System.Windows.Forms.MessageBox]::Show("Could not resolve DNS name.")
return
}
# Create DNS zone and A record
$zoneName = $zoneTextbox.Text
$aRecord = $dnsNameTextbox.Text
if ($ipAddress) {
$aRecord = $ipAddress
}
Add-DnsServerPrimaryZone -Name $combined -ZoneFile $zoneName
Add-DnsServerResourceRecordA -Name $combined -ZoneName $combined -IPv4Address $aRecord
[System.Windows.Forms.MessageBox]::Show("DNS zone and A record created successfully.")
})
$ipTextBox.Text = $ipAddress
# Add controls to form
$form.Controls.Add($dnsNameLabel)
$form.Controls.Add($dnsNameTextbox)
$form.Controls.Add($zoneLabel)
$form.Controls.Add($zoneTextbox)
$form.Controls.Add($createButton)
$form.Controls.Add($pictureBox)
$form.Controls.Add($ipLabel)
$form.Controls.Add($ipTextBox)
# Show the form
$form.ShowDialog() | Out-Null

29
Ledger.ps1 Normal file
View File

@@ -0,0 +1,29 @@
#This script will read a CSV file with users in samaccountname format in a column named username and query AD for the last password set time based on the day count on line 11.
# Define the path to the CSV file
$csvPath = "C:\temp\password-last-set.csv" # create a CSV file in a specific path with a column named username
# Import the CSV file
$users = Import-Csv -Path $csvPath
# Set the threshold in days
$thresholdDays = 0
# Calculate the threshold date
$thresholdDate = (Get-Date).AddDays(-$thresholdDays)
# Iterate through each user in the CSV
foreach ($user in $users) {
# Get the SamAccountName from the CSV
$samAccountName = $user.username
# Get the user object from Active Directory
$adUser = Get-ADUser -Filter { SamAccountName -eq $samAccountName } -Properties LastLogon
# Check if the PasswordLastSet property exists and compare it with the threshold date
if ($null -eq $adUser.LastLogon) {
Write-Output "$samAccountName Password still unset"
} elseif ($adUser.LastLogon -lt $thresholdDate) {
Write-Output "$samAccountName Password was last set on $($adUser.PasswordLastSet)"
}
}

108
Perfmon-Template.xml Normal file
View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-16"?>
<DataCollectorSet>
<Status>0</Status>
<Duration>0</Duration>
<Description>
</Description>
<DescriptionUnresolved>
</DescriptionUnresolved>
<DisplayName>
</DisplayName>
<DisplayNameUnresolved>
</DisplayNameUnresolved>
<SchedulesEnabled>-1</SchedulesEnabled>
<LatestOutputLocation>
</LatestOutputLocation>
<Name>Overall</Name>
<OutputLocation>C:\temp\Perf\</OutputLocation>
<RootPath>C:\temp\Perf</RootPath>
<Segment>0</Segment>
<SegmentMaxDuration>0</SegmentMaxDuration>
<SegmentMaxSize>0</SegmentMaxSize>
<SerialNumber>1</SerialNumber>
<Server>
</Server>
<Subdirectory>
</Subdirectory>
<SubdirectoryFormat>0</SubdirectoryFormat>
<SubdirectoryFormatPattern>
</SubdirectoryFormatPattern>
<Task>
</Task>
<TaskRunAsSelf>0</TaskRunAsSelf>
<TaskArguments>
</TaskArguments>
<TaskUserTextArguments>
</TaskUserTextArguments>
<UserAccount>local_admin</UserAccount>
<Security>O:BAG:DUD:AI(A;;FA;;;SY)(A;;FA;;;BA)(A;;FR;;;LU)(A;;0x1301ff;;;S-1-5-80-2661322625-712705077-2999183737-3043590567-590698655)(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200ab;;;LU)(A;ID;FR;;;AU)(A;ID;FR;;;LS)(A;ID;FR;;;NS)</Security>
<StopOnCompletion>0</StopOnCompletion>
<PerformanceCounterDataCollector>
<DataCollectorType>0</DataCollectorType>
<Name>System Monitor Log</Name>
<FileName>P2 Performance Log</FileName>
<FileNameFormat>1</FileNameFormat>
<FileNameFormatPattern>
</FileNameFormatPattern>
<LogAppend>0</LogAppend>
<LogCircular>0</LogCircular>
<LogOverwrite>0</LogOverwrite>
<LatestOutputLocation>
</LatestOutputLocation>
<DataSourceName>
</DataSourceName>
<SampleInterval>1</SampleInterval>
<SegmentMaxRecords>0</SegmentMaxRecords>
<LogFileFormat>3</LogFileFormat>
<Counter>\Processor Information(_Total)\% Processor Time</Counter>
<Counter>\LogicalDisk(_Total)\% Disk Time</Counter>
<Counter>\LogicalDisk(_Total)\Avg. Disk Queue Length</Counter>
<Counter>\LogicalDisk(_Total)\Disk Reads/sec</Counter>
<Counter>\LogicalDisk(_Total)\Disk Writes/sec</Counter>
<Counter>\LogicalDisk(_Total)\Avg. Disk sec/Read</Counter>
<Counter>\LogicalDisk(_Total)\Avg. Disk sec/Write</Counter>
<Counter>\Memory\% Committed Bytes In Use</Counter>
<Counter>\Memory\Available MBytes</Counter>
<Counter>\Memory\Cache Faults/sec</Counter>
<Counter>\Memory\Committed Bytes</Counter>
<Counter>\Memory\Pages/sec</Counter>
<Counter>\Processor(*)\% Idle Time</Counter>
<Counter>\Processor(*)\% Privileged Time</Counter>
<Counter>\Processor(_Total)\% Processor Time</Counter>
<Counter>\System\Processor Queue Length</Counter>
<Counter>\System\Context Switches/sec</Counter>
<Counter>\System\System Calls/sec</Counter>
<Counter>\System\Threads</Counter>
<CounterDisplayName>\Processor Information(_Total)\% Processor Time</CounterDisplayName>
<CounterDisplayName>\LogicalDisk(_Total)\% Disk Time</CounterDisplayName>
<CounterDisplayName>\LogicalDisk(_Total)\Avg. Disk Queue Length</CounterDisplayName>
<CounterDisplayName>\LogicalDisk(_Total)\Disk Reads/sec</CounterDisplayName>
<CounterDisplayName>\LogicalDisk(_Total)\Disk Writes/sec</CounterDisplayName>
<CounterDisplayName>\LogicalDisk(_Total)\Avg. Disk sec/Read</CounterDisplayName>
<CounterDisplayName>\LogicalDisk(_Total)\Avg. Disk sec/Write</CounterDisplayName>
<CounterDisplayName>\Memory\% Committed Bytes In Use</CounterDisplayName>
<CounterDisplayName>\Memory\Available MBytes</CounterDisplayName>
<CounterDisplayName>\Memory\Cache Faults/sec</CounterDisplayName>
<CounterDisplayName>\Memory\Committed Bytes</CounterDisplayName>
<CounterDisplayName>\Memory\Pages/sec</CounterDisplayName>
<CounterDisplayName>\Processor(*)\% Idle Time</CounterDisplayName>
<CounterDisplayName>\Processor(*)\% Privileged Time</CounterDisplayName>
<CounterDisplayName>\Processor(_Total)\% Processor Time</CounterDisplayName>
<CounterDisplayName>\System\Processor Queue Length</CounterDisplayName>
<CounterDisplayName>\System\Context Switches/sec</CounterDisplayName>
<CounterDisplayName>\System\System Calls/sec</CounterDisplayName>
<CounterDisplayName>\System\Threads</CounterDisplayName>
</PerformanceCounterDataCollector>
<DataManager>
<Enabled>0</Enabled>
<CheckBeforeRunning>0</CheckBeforeRunning>
<MinFreeDisk>0</MinFreeDisk>
<MaxSize>0</MaxSize>
<MaxFolderCount>0</MaxFolderCount>
<ResourcePolicy>0</ResourcePolicy>
<ReportFileName>report.html</ReportFileName>
<RuleTargetFileName>report.xml</RuleTargetFileName>
<EventsFileName>
</EventsFileName>
</DataManager>
</DataCollectorSet>

58
Scope.ps1 Normal file
View File

@@ -0,0 +1,58 @@
param (
[string]$CAName, # Specify the CA name to search for
[switch]$Valid, # Show only valid certificates
[switch]$Invalid # Show only invalid certificates
)
if (-not $CAName) {
$CAName = "NZGOVTCA*"
}
# Define certificate stores
$rootStore = "Cert:\LocalMachine\Root"
$intermediateStore = "Cert:\LocalMachine\CA"
# Function to check certificate validity
function Check-CertificateValidity {
param ($Cert, $StoreName)
# Get current date
$currentDate = Get-Date
# Check expiration and validity period
$isValid = $currentDate -ge $Cert.NotBefore -and $currentDate -le $Cert.NotAfter
# Prepare result object
[PSCustomObject]@{
Store = $StoreName
Subject = $Cert.Subject
Issuer = $Cert.Issuer
Thumbprint = $Cert.Thumbprint
ValidFrom = $Cert.NotBefore
ValidTo = $Cert.NotAfter
Status = if ($isValid) { "Valid" } else { "Invalid" }
}
}
# Get all root and intermediate certificates issued by the specified CA
$rootCerts = Get-ChildItem -Path $rootStore | Where-Object { $_.Issuer -like "*$CAName*" }
$intermediateCerts = Get-ChildItem -Path $intermediateStore | Where-Object { $_.Issuer -like "*$CAName*" }
# Check certificates
$results = @()
$results += $rootCerts | ForEach-Object { Check-CertificateValidity -Cert $_ -StoreName "Root CA" }
$results += $intermediateCerts | ForEach-Object { Check-CertificateValidity -Cert $_ -StoreName "Intermediate CA" }
# Apply filtering based on switches
if ($Valid) {
$results = $results | Where-Object { $_.Status -eq "Valid" }
} elseif ($Invalid) {
$results = $results | Where-Object { $_.Status -eq "Invalid" }
}
# Output results
if ($results.Count -eq 0) {
Write-Host "No certificates found matching the criteria." -ForegroundColor Red
} else {
$results | Format-Table -AutoSize
}

33
Stacker.ps1 Normal file
View File

@@ -0,0 +1,33 @@
# Variables
$CsrFolder = "C:\Temp\CSRs" # Path to folder with CSR files
$DnsZone = "record.domain.govt.nz" # Your DNS zone (AD-integrated)
$TargetIP = "managementboxIP" # The IP for all A records
$DnsServer = "DC01.example.local" # AD Domain Controller / DNS server
# Loop through CSR files
Get-ChildItem -Path $CsrFolder -Filter *.csr | ForEach-Object {
# Get just the file name without extension
$fqdn = $_.BaseName.Trim()
Write-Host "Processing $fqdn ..."
try {
# If the filename is a full FQDN, strip the zone name
if ($fqdn.ToLower().EndsWith(".$($DnsZone.ToLower())")) {
$hostname = $fqdn.Substring(0, $fqdn.Length - $DnsZone.Length - 1)
} else {
$hostname = $fqdn
}
Write-Host " -> Adding DNS A record for $hostname.$DnsZone -> $TargetIP"
Add-DnsServerResourceRecordA `
-Name $hostname `
-ZoneName $DnsZone `
-IPv4Address $TargetIP `
-ComputerName $DnsServer `
-ErrorAction Stop
} catch {
Write-Warning "Could not add DNS record for $fqdn : $_"
}
}

46
Tentacles.ps1 Normal file
View File

@@ -0,0 +1,46 @@
# Paths
$WacsPath = "C:\ProgramData\Wacs\wacs.exe"
$CsrFolder = "C:\Temp\Renew\Video"
$OutFolder = "C:\Temp\Renew\Output"
# Collect CSR files
$csrFiles = Get-ChildItem -Path $CsrFolder -Include *.csr, *.pem -File -Recurse
if (-not $csrFiles) {
Write-Host "No CSR files found in $CsrFolder"
exit
}
foreach ($csr in $csrFiles) {
# Use the base filename (without extension) as the hostname
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($csr.Name)
$outPath = Join-Path $OutFolder ($baseName + ".pfx")
# Ensure the output directory exists
$outDir = Split-Path $outPath -Parent
if (-not (Test-Path $outDir)) {
New-Item -Path $outDir -ItemType Directory -Force | Out-Null
}
# Build argument array (manual target, hostname from filename)
$args = @(
"--target", "manual",
"--host", $baseName,
"--store", "pfxfile",
"--pfxfilepath", "C:\programdata\wacs\output\",
"--baseuri", "https://acmeprod.domain.govt.nz:9999/acme/rsa/",
"--validation", "selfhosting",
"--validationport", "9998",
"--verbose"
)
# Print command for verification
Write-Host "`nReady to run WACS command for $($csr.Name):"
Write-Host "& $WacsPath $($args -join ' ')"
# Run WACS
& $WacsPath @args
Write-Host "Done processing $($csr.Name)"
}
Write-Host "`nAll CSR filenames processed as hostnames."

153
Warden.ps1 Normal file
View File

@@ -0,0 +1,153 @@
Add-Type -AssemblyName System.Windows.Forms
# Create the form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Instructions"
$form.Size = New-Object System.Drawing.Size(800, 550)
$form.StartPosition = "CenterScreen"
# Create a label to display the instructions
$label = New-Object System.Windows.Forms.Label
$label.Text = @"
This script will read a CSV file with users in samaccountname format in a column named 'username' and will set the -ChangePasswordAtLogon property to $true.
Please select the CSV file.
Clicking Accept will proceed with the operation. Make sure you have confirmed the CSV file is correct before proceeding.
"@
$label.AutoSize = $true
$label.MaximumSize = New-Object System.Drawing.Size(560, 0) # Set maximum width and allow height to adjust
$label.Location = New-Object System.Drawing.Point(10, 80)
$form.Controls.Add($label)
# Define author information
$authorName = "Zak Bearman"
$department = "Wintel Platforms"
$year = "2025"
# Create a label to display the author
$label2 = New-Object System.Windows.Forms.Label
$label2.Text = "Written by $authorName - $department $year."
$label2.AutoSize = $true
$label2.MaximumSize = New-Object System.Drawing.Size(560, 0) # Set maximum width and allow height to adjust
$label2.Location = New-Object System.Drawing.Point(160, 420)
$form.Controls.Add($label2)
# Create a TextBox to display the CSV content
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Multiline = $true
$textBox.ScrollBars = "Vertical"
$textBox.ReadOnly = $true
$textBox.Size = New-Object System.Drawing.Size(200, 500)
$textBox.Location = New-Object System.Drawing.Point(568, 5)
$form.Controls.Add($textBox)
# Create a button to browse for the CSV file
$browseButton = New-Object System.Windows.Forms.Button
$browseButton.Text = "Browse"
$browseButton.Location = New-Object System.Drawing.Point(250, 240)
$script:csvPath = $null
$browseButton.Add_Click({
$script:csvPath = $null
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Filter = "CSV files (*.csv)|*.csv"
if ($openFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$script:csvPath = $openFileDialog.FileName
$textBox.Text = Get-Content -Path $script:csvPath -Raw
}
})
$form.Controls.Add($browseButton)
# Create an Accept button
$acceptButton = New-Object System.Windows.Forms.Button
$acceptButton.Text = "Accept"
$acceptButton.Location = New-Object System.Drawing.Point(200, 300)
$acceptButton.Add_Click({
if (-not $script:csvPath) {
[System.Windows.Forms.MessageBox]::Show("No CSV file selected. Please select a CSV file to proceed.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
return
}
$form.Tag = "Accept"
$form.Close()
})
$form.Controls.Add($acceptButton)
# Create a Cancel button
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Text = "Cancel"
$cancelButton.Location = New-Object System.Drawing.Point(300, 300)
$cancelButton.Add_Click({
$form.Tag = "Cancel"
$form.Close()
})
$form.Controls.Add($cancelButton)
# Show the form
$form.ShowDialog()
# Check the form result
if ($form.Tag -eq "Cancel") {
Write-Output "Operation cancelled by the user."
exit
}
# Import the CSV file
$userList = Import-Csv -Path $script:csvPath
# Check if the path exists, if not create it
$destinationPath = "C:\temp\useroutput\done"
if (-not (Test-Path -Path $destinationPath)) {
New-Item -ItemType Directory -Path $destinationPath | Out-Null
}
# Get today's date
$todaysDate = Get-Date -Format "yyyyMMdd"
# Set the output CSV file path
$outputCsvPath = "$destinationPath\users-done-$todaysDate.csv"
# Loop through each user in the CSV
foreach ($user in $userList) {
$samAccountName = $user.username
try {
# Get the user object by SamAccountName
$userObject = Get-ADUser -Filter {SamAccountName -eq $samAccountName}
if ($null -eq $userObject) {
throw "User '$samAccountName' does not exist."
}
# Set the password to expired
Set-ADUser -Identity $samAccountName -ChangePasswordAtLogon $true
Write-Output "Password for user '$samAccountName' has been set to expired."
}
catch {
Write-Output "Failed to set password for user '$samAccountName': $_"
}
}
catch {
Write-Output "Failed to set password for user '$samAccountName': $_"
}
# Export the updated user list to the new CSV file
$userList | Export-Csv -Path $outputCsvPath -NoTypeInformation
Write-Output "The updated user list has been exported to $outputCsvPath."
# Rename the source CSV file
$originalFileName = [System.IO.Path]::GetFileNameWithoutExtension($script:csvPath)
$originalFileExtension = [System.IO.Path]::GetExtension($script:csvPath)
$directory = [System.IO.Path]::GetDirectoryName($script:csvPath)
$newFileName = "$originalFileName-done-$todaysDate$originalFileExtension"
$newFilePath = [System.IO.Path]::Combine($directory, $newFileName)
Rename-Item -Path $script:csvPath -NewName $newFileName
Write-Output "The original CSV file has been renamed to $newFilePath."
# Open the folder containing the renamed CSV file
Start-Process -FilePath "explorer.exe" -ArgumentList "/select,`"$newFilePath`""
# Clear all variables from active memory
Remove-Variable -Name form, label, label2, textBox, browseButton, acceptButton, cancelButton, csvPath, userList, destinationPath, todaysDate, outputCsvPath, originalFileName, originalFileExtension, directory, newFileName, newFilePath -ErrorAction SilentlyContinue