Add startup and persistence analysis tools

Add Get-AutoRun.ps1, Get-ScheduledTasks.ps1, and Get-Services.ps1
for analyzing auto-start programs and persistence mechanisms.

Get-AutoRun: Run/RunOnce keys, Startup folders, startup tasks
Get-ScheduledTasks: Detailed task analysis with filters
Get-Services: Service enumeration using WMI/CIM

Uses Get-CimInstance for reliable service enumeration, avoiding
Get-Service permission issues. Multiple filters and output modes.

Update TODO.md.
This commit is contained in:
2026-02-03 22:39:35 +01:00
parent ce250b9725
commit ed0c1983b3
4 changed files with 409 additions and 4 deletions

View File

@@ -0,0 +1,138 @@
# Get-ScheduledTasks.ps1
# Lists scheduled tasks with details
param(
[ValidateSet("All", "Running", "Ready", "Disabled", "Startup")]
[string]$Filter = "All",
[int]$MaxResults = 50,
[switch]$ShowAll
)
Write-Host "=== Scheduled Tasks ===" -ForegroundColor Cyan
if ($ShowAll) {
$MaxResults = [int]::MaxValue
}
$filterDesc = switch ($Filter) {
"Running" { "Currently running tasks" }
"Ready" { "Tasks ready to run" }
"Disabled" { "Disabled tasks" }
"Startup" { "Tasks that run at startup/logon" }
default { "All scheduled tasks" }
}
Write-Host "$filterDesc`n" -ForegroundColor Yellow
try {
# Get all scheduled tasks
$tasks = Get-ScheduledTask -ErrorAction Stop
# Apply filter
$filteredTasks = switch ($Filter) {
"Running" { $tasks | Where-Object { $_.State -eq "Running" } }
"Ready" { $tasks | Where-Object { $_.State -eq "Ready" } }
"Disabled" { $tasks | Where-Object { $_.State -eq "Disabled" } }
"Startup" {
$tasks | Where-Object {
$_.Triggers.CimClass.CimClassName -contains "MSFT_TaskBootTrigger" -or
$_.Triggers.CimClass.CimClassName -contains "MSFT_TaskLogonTrigger"
}
}
default { $tasks }
}
if ($filteredTasks) {
# Sort by path and name
$sortedTasks = $filteredTasks | Sort-Object TaskPath, TaskName
Write-Host "Found: $($filteredTasks.Count) tasks" -ForegroundColor Green
Write-Host "Showing: $(if ($ShowAll) { "All" } else { "Top $MaxResults" })`n" -ForegroundColor Gray
$count = 0
foreach ($task in ($sortedTasks | Select-Object -First $MaxResults)) {
$count++
# Color based on state
$nameColor = switch ($task.State) {
"Running" { "Green" }
"Ready" { "Cyan" }
"Disabled" { "Gray" }
default { "Yellow" }
}
Write-Host "$count. $($task.TaskPath)$($task.TaskName)" -ForegroundColor $nameColor
Write-Host " State: $($task.State)" -ForegroundColor Gray
# Show triggers
if ($task.Triggers) {
$triggerInfo = @()
foreach ($trigger in $task.Triggers) {
$triggerType = switch ($trigger.CimClass.CimClassName) {
"MSFT_TaskBootTrigger" { "At system startup" }
"MSFT_TaskLogonTrigger" { "At user logon" }
"MSFT_TaskDailyTrigger" { "Daily" }
"MSFT_TaskTimeTrigger" { "At specific time" }
"MSFT_TaskEventTrigger" { "On event" }
"MSFT_TaskIdleTrigger" { "On idle" }
default { $trigger.CimClass.CimClassName -replace "MSFT_Task", "" -replace "Trigger", "" }
}
$triggerInfo += $triggerType
}
Write-Host " Trigger: $($triggerInfo -join ', ')" -ForegroundColor Gray
}
# Show action
if ($task.Actions) {
foreach ($action in $task.Actions) {
if ($action.Execute) {
Write-Host " Execute: $($action.Execute)" -ForegroundColor White
if ($action.Arguments) {
Write-Host " Arguments: $($action.Arguments)" -ForegroundColor Gray
}
if ($action.WorkingDirectory) {
Write-Host " WorkDir: $($action.WorkingDirectory)" -ForegroundColor Gray
}
}
}
}
# Show last/next run time
$taskInfo = Get-ScheduledTaskInfo -TaskName $task.TaskName -TaskPath $task.TaskPath -ErrorAction SilentlyContinue
if ($taskInfo) {
if ($taskInfo.LastRunTime -and $taskInfo.LastRunTime.Year -gt 1) {
Write-Host " Last Run: $($taskInfo.LastRunTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Gray
}
if ($taskInfo.NextRunTime -and $taskInfo.NextRunTime.Year -gt 1) {
Write-Host " Next Run: $($taskInfo.NextRunTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Gray
}
if ($taskInfo.LastTaskResult -ne 0) {
Write-Host " Last Result: 0x$($taskInfo.LastTaskResult.ToString('X'))" -ForegroundColor $(if ($taskInfo.LastTaskResult -eq 0) { "Green" } else { "Red" })
}
}
Write-Host ""
}
if ($filteredTasks.Count -gt $MaxResults -and -not $ShowAll) {
Write-Host "... and $($filteredTasks.Count - $MaxResults) more (use -ShowAll to see all)" -ForegroundColor Gray
}
# Summary
Write-Host "`n=== Summary ===" -ForegroundColor Cyan
$states = $filteredTasks | Group-Object State
foreach ($state in $states) {
Write-Host "$($state.Name): $($state.Count)" -ForegroundColor Green
}
} else {
Write-Host "No tasks found matching filter" -ForegroundColor Gray
}
} catch {
Write-Host "Error: $_" -ForegroundColor Red
Write-Host "Try running as Administrator for full task access" -ForegroundColor Yellow
}
Write-Host "`nFilters: -Filter All|Running|Ready|Disabled|Startup" -ForegroundColor Cyan
Write-Host "Use -ShowAll to see all tasks (default: top $MaxResults)" -ForegroundColor Cyan