import depuis ancien GitHub
This commit is contained in:
396
maintenance-ivanti/ExploitBox.ps1
Normal file
396
maintenance-ivanti/ExploitBox.ps1
Normal file
@@ -0,0 +1,396 @@
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
||||
|
||||
|
||||
# ==== Config SQL IVANTI ====
|
||||
$script:IvantiSqlInstance = "serveurIVANTI.domain.lan"
|
||||
$script:IvantiSqlDatabase = "LDMS123"
|
||||
|
||||
# -----------------------------
|
||||
# Form setup (compact & pro)
|
||||
# -----------------------------
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = 'Ops Maintenance Console'
|
||||
$form.Size = New-Object System.Drawing.Size(465,580)
|
||||
$form.StartPosition= 'CenterScreen'
|
||||
$form.FormBorderStyle = 'FixedDialog'
|
||||
$form.MaximizeBox = $false
|
||||
$form.MinimizeBox = $false
|
||||
$form.Font = New-Object System.Drawing.Font('Segoe UI', 9)
|
||||
|
||||
# Status strip (status text + progress)
|
||||
$statusStrip = New-Object System.Windows.Forms.StatusStrip
|
||||
$statusLabel = New-Object System.Windows.Forms.ToolStripStatusLabel
|
||||
$prog = New-Object System.Windows.Forms.ToolStripProgressBar
|
||||
$statusLabel.Spring = $true
|
||||
$prog.Minimum = 0; $prog.Maximum = 1; $prog.Step = 1; $prog.Value = 0
|
||||
[void]$statusStrip.Items.Add($statusLabel)
|
||||
[void]$statusStrip.Items.Add($prog)
|
||||
$form.Controls.Add($statusStrip)
|
||||
|
||||
function Set-Status([string]$text){ $statusLabel.Text = $text }
|
||||
|
||||
# -----------------------------
|
||||
# GroupBox: Task
|
||||
# -----------------------------
|
||||
$gbTask = New-Object System.Windows.Forms.GroupBox
|
||||
$gbTask.Text = 'Task'
|
||||
$gbTask.Location = New-Object System.Drawing.Point(10,8)
|
||||
$gbTask.Size = New-Object System.Drawing.Size(445,80)
|
||||
$form.Controls.Add($gbTask)
|
||||
|
||||
$lblSelect = New-Object System.Windows.Forms.Label
|
||||
$lblSelect.Text = 'Select:'
|
||||
$lblSelect.Location = New-Object System.Drawing.Point(12,30)
|
||||
$lblSelect.AutoSize = $true
|
||||
$gbTask.Controls.Add($lblSelect)
|
||||
|
||||
$comboBox = New-Object System.Windows.Forms.ComboBox
|
||||
$comboBox.Location = New-Object System.Drawing.Point(65,27)
|
||||
$comboBox.Size = New-Object System.Drawing.Size(230,24)
|
||||
$comboBox.DropDownStyle = 'DropDownList'
|
||||
$comboBox.Items.Add('IVANTI Core') | Out-Null
|
||||
$comboBox.Items.Add('IVANTI Console') | Out-Null
|
||||
$comboBox.Items.Add('WSUS') | Out-Null
|
||||
$gbTask.Controls.Add($comboBox)
|
||||
|
||||
$btnRun = New-Object System.Windows.Forms.Button
|
||||
$btnRun.Text = 'Run'
|
||||
$btnRun.Location = New-Object System.Drawing.Point(310,26)
|
||||
$btnRun.Size = New-Object System.Drawing.Size(110,26)
|
||||
$gbTask.Controls.Add($btnRun)
|
||||
$form.AcceptButton = $btnRun
|
||||
|
||||
# -----------------------------
|
||||
# GroupBox: Credentials
|
||||
# -----------------------------
|
||||
$gbCreds = New-Object System.Windows.Forms.GroupBox
|
||||
$gbCreds.Text = 'Credentials (IVANTI Core)'
|
||||
$gbCreds.Location = New-Object System.Drawing.Point(10,95)
|
||||
$gbCreds.Size = New-Object System.Drawing.Size(445,90)
|
||||
$form.Controls.Add($gbCreds)
|
||||
|
||||
$labelUser = New-Object System.Windows.Forms.Label
|
||||
$labelUser.Text = 'Username:'
|
||||
$labelUser.Location = New-Object System.Drawing.Point(12,27)
|
||||
$labelUser.AutoSize = $true
|
||||
$gbCreds.Controls.Add($labelUser)
|
||||
|
||||
$textBoxNom = New-Object System.Windows.Forms.TextBox
|
||||
$textBoxNom.Location = New-Object System.Drawing.Point(90,24)
|
||||
$textBoxNom.Size = New-Object System.Drawing.Size(150,24)
|
||||
$textBoxNom.Enabled = $false
|
||||
$gbCreds.Controls.Add($textBoxNom)
|
||||
|
||||
$labelPwd = New-Object System.Windows.Forms.Label
|
||||
$labelPwd.Text = 'Password:'
|
||||
$labelPwd.Location = New-Object System.Drawing.Point(12,57)
|
||||
$labelPwd.AutoSize = $true
|
||||
$gbCreds.Controls.Add($labelPwd)
|
||||
|
||||
$textBoxPassword = New-Object System.Windows.Forms.TextBox
|
||||
$textBoxPassword.Location = New-Object System.Drawing.Point(90,54)
|
||||
$textBoxPassword.Size = New-Object System.Drawing.Size(150,24)
|
||||
$textBoxPassword.UseSystemPasswordChar = $true
|
||||
$textBoxPassword.Enabled = $false
|
||||
$gbCreds.Controls.Add($textBoxPassword)
|
||||
|
||||
# -----------------------------
|
||||
# GroupBox: Output
|
||||
# -----------------------------
|
||||
$gbOut = New-Object System.Windows.Forms.GroupBox
|
||||
$gbOut.Text = 'Output'
|
||||
$gbOut.Location = New-Object System.Drawing.Point(10,190)
|
||||
$gbOut.Size = New-Object System.Drawing.Size(445,330)
|
||||
$form.Controls.Add($gbOut)
|
||||
|
||||
$outputBox = New-Object System.Windows.Forms.RichTextBox
|
||||
$outputBox.Location = New-Object System.Drawing.Point(12,22)
|
||||
$outputBox.Size = New-Object System.Drawing.Size(420,270)
|
||||
$outputBox.Font = New-Object System.Drawing.Font('Consolas', 9)
|
||||
$outputBox.ReadOnly = $true
|
||||
$outputBox.WordWrap = $false
|
||||
$gbOut.Controls.Add($outputBox)
|
||||
|
||||
$btnClear = New-Object System.Windows.Forms.Button
|
||||
$btnClear.Text= 'Clear'
|
||||
$btnClear.Location = New-Object System.Drawing.Point(322,295)
|
||||
$btnClear.Size = New-Object System.Drawing.Size(110,26)
|
||||
$gbOut.Controls.Add($btnClear)
|
||||
|
||||
# Helper: unified output
|
||||
function Append-Output([string]$text){
|
||||
foreach($line in ($text -split "(`r`n|`n|`r)")){
|
||||
if ([string]::IsNullOrWhiteSpace($line)) { continue }
|
||||
|
||||
$color = [System.Drawing.Color]::Black
|
||||
if ($line -match '\bOK\b') { $color = [System.Drawing.Color]::ForestGreen }
|
||||
elseif ($line -match '\bKO\b') { $color = [System.Drawing.Color]::Crimson }
|
||||
|
||||
$outputBox.SelectionStart = $outputBox.TextLength
|
||||
$outputBox.SelectionLength = 0
|
||||
$outputBox.SelectionColor = $color
|
||||
$outputBox.AppendText($line + [Environment]::NewLine)
|
||||
$outputBox.SelectionColor = $outputBox.ForeColor
|
||||
}
|
||||
$outputBox.ScrollToCaret()
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Logging helper
|
||||
# -----------------------------
|
||||
function Write-Log {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$True)][string]$Message,
|
||||
[Parameter(Mandatory=$False)]
|
||||
[string]$Path = $(if ($MyInvocation.MyCommand.Path) {
|
||||
$MyInvocation.MyCommand.Path -replace '\.ps1$', '.log'
|
||||
} else { "C:\Windows\Temp\exploitbox.log" })
|
||||
)
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
"$timestamp : $script:SelectedOption : $Message" | Out-File -FilePath $Path -Append
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Functions (business)
|
||||
# -----------------------------
|
||||
function Start-WSUS-Maintenance {
|
||||
Write-Host "[STEP] Start-WSUS-Maintenance"
|
||||
Set-Status "WSUS maintenance..."
|
||||
$Aff = ""
|
||||
$FileSQL = Join-Path $PSScriptRoot "WSUSMaintenance.sql"
|
||||
Write-Log -Message "----- Start-WSUS-Maintenance"
|
||||
$Instance = "\\.\pipe\MICROSOFT##WID\tsql\query"
|
||||
$Bdd = "SUSDB"
|
||||
try {
|
||||
Import-Module SqlServer -ErrorAction Stop
|
||||
Invoke-Sqlcmd -ServerInstance $Instance -Database $Bdd -InputFile $FileSQL -ErrorAction Stop -Verbose
|
||||
$Aff = "Maintenance OK"
|
||||
Write-Log -Message "WSUS maintenance OK"
|
||||
Write-Host "[DONE] WSUS maintenance OK"
|
||||
} catch {
|
||||
$Aff = "KO : $($_.Exception.Message)"
|
||||
Write-Log -Message "WSUS maintenance KO ($($_.Exception.Message))"
|
||||
Write-Host "[FAIL] WSUS maintenance KO $($_.Exception.Message)"
|
||||
}
|
||||
return ($Aff + "`r`n")
|
||||
}
|
||||
|
||||
function Start-IVANTI-Maintenance {
|
||||
Write-Host "[STEP] Start-IVANTI-Maintenance"
|
||||
Set-Status "IVANTI SQL maintenance..."
|
||||
$Aff = ""
|
||||
$FileSQL = Join-Path $PSScriptRoot "SQLMaintenance2022.sql"
|
||||
Write-Log -Message "----- Start-IVANTI-Maintenance"
|
||||
|
||||
$username = $textBoxNom.Text
|
||||
$password = $textBoxPassword.Text
|
||||
|
||||
try {
|
||||
Import-Module SqlServer -ErrorAction Stop
|
||||
Invoke-Sqlcmd -ServerInstance $script:IvantiSqlInstance `
|
||||
-Database $script:IvantiSqlDatabase `
|
||||
-Username $username `
|
||||
-Password $password `
|
||||
-InputFile $FileSQL `
|
||||
-ErrorAction Stop -Verbose
|
||||
$Aff = "Maintenance OK"
|
||||
Write-Log -Message "IVANTI SQL maintenance OK"
|
||||
Write-Host "[DONE] IVANTI SQL maintenance OK"
|
||||
} catch {
|
||||
$Aff = "KO : $($_.Exception.Message)"
|
||||
Write-Log -Message "IVANTI SQL maintenance KO ($($_.Exception.Message))"
|
||||
Write-Host "[FAIL] IVANTI SQL maintenance KO $($_.Exception.Message)"
|
||||
}
|
||||
return ($Aff + "`r`n")
|
||||
}
|
||||
|
||||
function Get-RebootStatus {
|
||||
Write-Host "[STEP] Get-RebootStatus"
|
||||
Set-Status "Checking reboot status..."
|
||||
$Aff = ""
|
||||
Write-Log -Message "----- Get-RebootStatus"
|
||||
$rebootRequired = $false
|
||||
$rebootPaths = @(
|
||||
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending',
|
||||
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired'
|
||||
)
|
||||
foreach ($p in $rebootPaths) { if (Test-Path $p) { $rebootRequired = $true; break } }
|
||||
if ($rebootRequired) {
|
||||
$Aff = "Reboot Needed (KO)"; Write-Log -Message $Aff; Write-Host "[INFO] Reboot Needed"
|
||||
} else {
|
||||
$Aff = "No Reboot Needed (OK)"; Write-Log -Message $Aff; Write-Host "[INFO] No Reboot Needed"
|
||||
}
|
||||
return ($Aff + "`r`n")
|
||||
}
|
||||
|
||||
function Cleanup-IIS {
|
||||
Write-Host "[STEP] Cleanup-IIS"
|
||||
Set-Status "Cleaning IIS logs..."
|
||||
$Aff = ""; Write-Log -Message "----- Cleanup-IIS"
|
||||
$LogPath = "C:\inetpub\logs\LogFiles\W3SVC1"
|
||||
if (-not (Test-Path $LogPath)) {
|
||||
$Aff = "PurgeIIS : OK (no log folder)`r`n"
|
||||
Write-Log -Message "PurgeIIS : OK (no log folder)"
|
||||
Write-Host "[DONE] Cleanup-IIS OK (no folder)"
|
||||
return $Aff
|
||||
}
|
||||
$maxDaystoKeep = -30
|
||||
$old = Get-ChildItem -Path $LogPath -File -Filter *.log | Where-Object LastWriteTime -lt ((Get-Date).AddDays($maxDaystoKeep))
|
||||
if ($old.Count -gt 0){ foreach ($i in $old){ Remove-Item $i.FullName -Force -Verbose } }
|
||||
$old = Get-ChildItem -Path $LogPath -File -Filter *.log | Where-Object LastWriteTime -lt ((Get-Date).AddDays($maxDaystoKeep))
|
||||
if ($old.Count -gt 0){ $Aff = "PurgeIIS : KO"; Write-Log -Message $Aff; Write-Host "[FAIL] Cleanup-IIS KO" }
|
||||
else { $Aff = "PurgeIIS : OK"; Write-Log -Message $Aff; Write-Host "[DONE] Cleanup-IIS OK" }
|
||||
return ($Aff + "`r`n")
|
||||
}
|
||||
|
||||
function Check-ldscan {
|
||||
Write-Host "[STEP] Check-ldscan"
|
||||
Set-Status "Checking ldscan folder..."
|
||||
$Aff = ""; Write-Log -Message "----- Check-ldscan"
|
||||
$path = "C:\Program Files\LANDesk\ManagementSuite\ldscan"
|
||||
$count = Get-ChildItem $path -File | Measure-Object | ForEach-Object { $_.Count }
|
||||
if ($count -gt 200) {
|
||||
$Aff = "Countldscan : KO"; Write-Log -Message $Aff; Write-Host "[FAIL] ldscan KO ($count files)"
|
||||
} else {
|
||||
$count = Get-ChildItem $path -Recurse -File | Measure-Object | ForEach-Object { $_.Count }
|
||||
if ($count -gt 200) { $Aff = "Countldscan : WARNING"; Write-Log -Message $Aff; Write-Host "[WARN] ldscan WARNING ($count files)" }
|
||||
else { $Aff = "Countldscan : OK"; Write-Log -Message $Aff; Write-Host "[DONE] ldscan OK ($count files)" }
|
||||
}
|
||||
return ($Aff + "`r`n")
|
||||
}
|
||||
|
||||
|
||||
# PSWindowsUpdate
|
||||
function Install-WindowsUpdate {
|
||||
Write-Host "[STEP] Install-WindowsUpdate (PSWindowsUpdate)"
|
||||
Set-Status "Installing Windows Updates..."
|
||||
$Aff = ""; Write-Log -Message "----- Install-WindowsUpdate (PSWindowsUpdate)"
|
||||
try {
|
||||
if (-not (Get-Module -ListAvailable -Name PSWindowsUpdate)) { throw "Module PSWindowsUpdate not found on this system." }
|
||||
Import-Module PSWindowsUpdate -ErrorAction Stop
|
||||
# Remove -WindowsUpdate to honor WSUS policy
|
||||
$updates = PSWindowsUpdate\Install-WindowsUpdate -WindowsUpdate -AcceptAll -IgnoreReboot -ErrorAction Stop
|
||||
if ($updates) {
|
||||
$Aff += ($updates | Select-Object KB, Title, Result | Format-Table -AutoSize | Out-String)
|
||||
$updates | ForEach-Object { Write-Log -Message ("{0} {1} -> {2}" -f $_.KB, $_.Title, $_.Result) } | Out-Null
|
||||
Write-Host "[DONE] Windows Update processed (OK)"
|
||||
} else {
|
||||
$Aff += "No applicable updates (OK).`r`n"; Write-Log -Message "No applicable updates."; Write-Host "[INFO] No applicable updates"
|
||||
}
|
||||
} catch {
|
||||
$Aff += "PSWindowsUpdate failed (KO): $($_.Exception.Message)`r`n"
|
||||
Write-Log -Message "PSWindowsUpdate failed (KO): $($_.Exception.Message)"
|
||||
Write-Host "[FAIL] Windows Update failed (KO): $($_.Exception.Message)"
|
||||
}
|
||||
return $Aff
|
||||
}
|
||||
|
||||
function Get-WSUS-PatchInGroups {
|
||||
Write-Host "[STEP] Get-WSUS-PatchInGroups"
|
||||
Set-Status "Building WSUS report..."
|
||||
$Aff = ""; Write-Log -Message "----- Get-WSUS-PatchInGroups"
|
||||
$MaxDaysReport = 35; $ListeKB=@()
|
||||
[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | Out-Null
|
||||
$wsusServer = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer()
|
||||
$updates = $wsusServer.GetUpdates()
|
||||
$targetGroups = $wsusServer.GetComputerTargetGroups()
|
||||
foreach ($u in $updates){
|
||||
$approvals = $u.GetUpdateApprovals()
|
||||
foreach ($ap in $approvals){
|
||||
foreach ($tg in $targetGroups){
|
||||
if ($tg.Id -eq $ap.ComputerTargetGroupId) {
|
||||
$days = (New-TimeSpan -Start $ap.goLiveTime -End (Get-Date)).Days
|
||||
$title = $u.Title; $group = $tg.Name
|
||||
if ($days -lt $MaxDaysReport) {
|
||||
$match = 0
|
||||
if (($title -match "Windows 10") -and ($title -match "1809") -and ($title -match " x64")) { $match = 1 }
|
||||
if ($match -eq 1) {
|
||||
$ListeKB += [PSCustomObject]@{ KBTitre=$title; KBGroup=$group; KBChang=$days }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$ListeKB = $ListeKB | Sort-Object KBTitre, KBChang
|
||||
$maxTitle=120; $maxGroup=25; $maxDays=5; $prev="####"
|
||||
foreach ($KB in $ListeKB) {
|
||||
if ($KB.KBTitre -ne $prev) { $Aff += "`r`n"; $prev = $KB.KBTitre }
|
||||
$line = "{0,-$maxTitle} | {1,-$maxGroup} | {2,-$maxDays}" -f $KB.KBTitre, $KB.KBGroup, $KB.KBChang
|
||||
$Aff += "`r`n$line"; Write-Log -Message $line
|
||||
}
|
||||
Write-Host "[DONE] WSUS patch listing generated"
|
||||
return ($Aff + "`r`n")
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Admin check
|
||||
# -----------------------------
|
||||
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
|
||||
Start-Process PowerShell -ArgumentList "-File `"$($MyInvocation.MyCommand.Path)`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# UI events
|
||||
# -----------------------------
|
||||
$comboBox.Add_SelectedIndexChanged({
|
||||
$script:SelectedOption = $comboBox.SelectedItem
|
||||
if ($comboBox.SelectedItem -eq 'IVANTI Core') {
|
||||
$textBoxNom.Enabled = $true; $textBoxPassword.Enabled = $true; $textBoxNom.Text = "admindb"
|
||||
$gbCreds.Enabled = $true
|
||||
} else {
|
||||
$textBoxNom.Enabled = $false; $textBoxPassword.Enabled = $false; $gbCreds.Enabled = $false
|
||||
}
|
||||
})
|
||||
|
||||
$btnClear.Add_Click({ $outputBox.Clear(); Set-Status "Output cleared." })
|
||||
|
||||
$btnRun.Add_Click({
|
||||
$selectedOption = $comboBox.SelectedItem
|
||||
$script:SelectedOption = $selectedOption
|
||||
if (-not $selectedOption) { [System.Windows.Forms.MessageBox]::Show("Please select a task.", "Info", 'OK', 'Information') | Out-Null; return }
|
||||
|
||||
# progress config
|
||||
switch ($selectedOption) {
|
||||
'IVANTI Core' { $prog.Maximum = 6 }
|
||||
'IVANTI Console' { $prog.Maximum = 2 }
|
||||
'WSUS' { $prog.Maximum = 4 }
|
||||
}
|
||||
$prog.Value = 0
|
||||
|
||||
if ($selectedOption -eq "IVANTI Core") {
|
||||
Set-Status "IVANTI Core running..."
|
||||
Append-Output "----- Check ldscan"; Append-Output (Check-ldscan); $prog.PerformStep()
|
||||
Append-Output "----- Clean IIS Log"; Append-Output (Cleanup-IIS); $prog.PerformStep()
|
||||
Append-Output "----- Windows Update"; Append-Output (Install-WindowsUpdate); $prog.PerformStep()
|
||||
Append-Output "----- SQL maintenance"; Append-Output (Start-IVANTI-Maintenance);$prog.PerformStep()
|
||||
Append-Output "----- Get Reboot"; Append-Output (Get-RebootStatus); $prog.PerformStep()
|
||||
Set-Status "IVANTI Core: done."
|
||||
}
|
||||
|
||||
if ($selectedOption -eq "IVANTI Console") {
|
||||
Set-Status "IVANTI Console running..."
|
||||
Append-Output "----- Windows Update"; Append-Output (Install-WindowsUpdate); $prog.PerformStep()
|
||||
Append-Output "----- Get Reboot"; Append-Output (Get-RebootStatus); $prog.PerformStep()
|
||||
Set-Status "IVANTI Console: done."
|
||||
}
|
||||
|
||||
if ($selectedOption -eq "WSUS") {
|
||||
Set-Status "WSUS tasks running..."
|
||||
Append-Output "----- Windows Update"; Append-Output (Install-WindowsUpdate); $prog.PerformStep()
|
||||
Append-Output "----- Get Reboot"; Append-Output (Get-RebootStatus); $prog.PerformStep()
|
||||
Append-Output "----- SQL Maintenance"; Append-Output (Start-WSUS-Maintenance); $prog.PerformStep()
|
||||
Append-Output "----- Deploy"; Append-Output (Get-WSUS-PatchInGroups); $prog.PerformStep()
|
||||
Set-Status "WSUS: done."
|
||||
}
|
||||
})
|
||||
|
||||
# -----------------------------
|
||||
# Run UI
|
||||
# -----------------------------
|
||||
$form.ShowDialog() | Out-Null
|
||||
Reference in New Issue
Block a user